diff options
Diffstat (limited to 'src')
72 files changed, 1142 insertions, 661 deletions
diff --git a/src/common/tree.h b/src/common/tree.h index 3da49e422..9d2d0df4e 100644 --- a/src/common/tree.h +++ b/src/common/tree.h | |||
| @@ -322,7 +322,7 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | |||
| 322 | template <typename Node> | 322 | template <typename Node> |
| 323 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { | 323 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
| 324 | Node* tmp; | 324 | Node* tmp; |
| 325 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root()) { | 325 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { |
| 326 | if (RB_LEFT(parent) == elm) { | 326 | if (RB_LEFT(parent) == elm) { |
| 327 | tmp = RB_RIGHT(parent); | 327 | tmp = RB_RIGHT(parent); |
| 328 | if (RB_IS_RED(tmp)) { | 328 | if (RB_IS_RED(tmp)) { |
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 55b1716e4..602e12606 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -32,7 +32,8 @@ enum class CommandType : u32 { | |||
| 32 | Control = 5, | 32 | Control = 5, |
| 33 | RequestWithContext = 6, | 33 | RequestWithContext = 6, |
| 34 | ControlWithContext = 7, | 34 | ControlWithContext = 7, |
| 35 | Unspecified, | 35 | TIPC_Close = 15, |
| 36 | TIPC_CommandRegion = 16, // Start of TIPC commands, this is an offset. | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | struct CommandHeader { | 39 | struct CommandHeader { |
| @@ -57,6 +58,20 @@ struct CommandHeader { | |||
| 57 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; | 58 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; |
| 58 | BitField<31, 1, u32> enable_handle_descriptor; | 59 | BitField<31, 1, u32> enable_handle_descriptor; |
| 59 | }; | 60 | }; |
| 61 | |||
| 62 | bool IsTipc() const { | ||
| 63 | return type.Value() >= CommandType::TIPC_CommandRegion; | ||
| 64 | } | ||
| 65 | |||
| 66 | bool IsCloseCommand() const { | ||
| 67 | switch (type.Value()) { | ||
| 68 | case CommandType::Close: | ||
| 69 | case CommandType::TIPC_Close: | ||
| 70 | return true; | ||
| 71 | default: | ||
| 72 | return false; | ||
| 73 | } | ||
| 74 | } | ||
| 60 | }; | 75 | }; |
| 61 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); | 76 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); |
| 62 | 77 | ||
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 0906b8cfb..5fed3dbf5 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include "core/hle/ipc.h" | 15 | #include "core/hle/ipc.h" |
| 16 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 17 | #include "core/hle/kernel/k_client_port.h" | 17 | #include "core/hle/kernel/k_client_port.h" |
| 18 | #include "core/hle/kernel/k_process.h" | ||
| 19 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 18 | #include "core/hle/kernel/k_session.h" | 20 | #include "core/hle/kernel/k_session.h" |
| 19 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| 20 | 22 | ||
| @@ -26,7 +28,7 @@ class RequestHelperBase { | |||
| 26 | protected: | 28 | protected: |
| 27 | Kernel::HLERequestContext* context = nullptr; | 29 | Kernel::HLERequestContext* context = nullptr; |
| 28 | u32* cmdbuf; | 30 | u32* cmdbuf; |
| 29 | ptrdiff_t index = 0; | 31 | u32 index = 0; |
| 30 | 32 | ||
| 31 | public: | 33 | public: |
| 32 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} | 34 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} |
| @@ -38,7 +40,7 @@ public: | |||
| 38 | if (set_to_null) { | 40 | if (set_to_null) { |
| 39 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); | 41 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); |
| 40 | } | 42 | } |
| 41 | index += static_cast<ptrdiff_t>(size_in_words); | 43 | index += size_in_words; |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | /** | 46 | /** |
| @@ -51,11 +53,11 @@ public: | |||
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | u32 GetCurrentOffset() const { | 55 | u32 GetCurrentOffset() const { |
| 54 | return static_cast<u32>(index); | 56 | return index; |
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | void SetCurrentOffset(u32 offset) { | 59 | void SetCurrentOffset(u32 offset) { |
| 58 | index = static_cast<ptrdiff_t>(offset); | 60 | index = offset; |
| 59 | } | 61 | } |
| 60 | }; | 62 | }; |
| 61 | 63 | ||
| @@ -69,37 +71,44 @@ public: | |||
| 69 | AlwaysMoveHandles = 1, | 71 | AlwaysMoveHandles = 1, |
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 72 | explicit ResponseBuilder(Kernel::HLERequestContext& context, u32 normal_params_size, | 74 | explicit ResponseBuilder(Kernel::HLERequestContext& ctx, u32 normal_params_size, |
| 73 | u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, | 75 | u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, |
| 74 | Flags flags = Flags::None) | 76 | Flags flags = Flags::None) |
| 75 | : RequestHelperBase(context), normal_params_size(normal_params_size), | 77 | : RequestHelperBase(ctx), normal_params_size(normal_params_size), |
| 76 | num_handles_to_copy(num_handles_to_copy), | 78 | num_handles_to_copy(num_handles_to_copy), |
| 77 | num_objects_to_move(num_objects_to_move), kernel{context.kernel} { | 79 | num_objects_to_move(num_objects_to_move), kernel{ctx.kernel} { |
| 78 | 80 | ||
| 79 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | 81 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); |
| 80 | 82 | ||
| 81 | context.ClearIncomingObjects(); | 83 | ctx.ClearIncomingObjects(); |
| 82 | 84 | ||
| 83 | IPC::CommandHeader header{}; | 85 | IPC::CommandHeader header{}; |
| 84 | 86 | ||
| 85 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | 87 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory |
| 86 | // padding. | 88 | // padding. |
| 87 | u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | 89 | u32 raw_data_size = ctx.IsTipc() |
| 90 | ? normal_params_size - 1 | ||
| 91 | : sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | ||
| 88 | 92 | ||
| 89 | u32 num_handles_to_move{}; | 93 | u32 num_handles_to_move{}; |
| 90 | u32 num_domain_objects{}; | 94 | u32 num_domain_objects{}; |
| 91 | const bool always_move_handles{ | 95 | const bool always_move_handles{ |
| 92 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; | 96 | (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; |
| 93 | if (!context.Session()->IsDomain() || always_move_handles) { | 97 | if (!ctx.Session()->IsDomain() || always_move_handles) { |
| 94 | num_handles_to_move = num_objects_to_move; | 98 | num_handles_to_move = num_objects_to_move; |
| 95 | } else { | 99 | } else { |
| 96 | num_domain_objects = num_objects_to_move; | 100 | num_domain_objects = num_objects_to_move; |
| 97 | } | 101 | } |
| 98 | 102 | ||
| 99 | if (context.Session()->IsDomain()) { | 103 | if (ctx.Session()->IsDomain()) { |
| 100 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | 104 | raw_data_size += static_cast<u32>(sizeof(DomainMessageHeader) / 4 + num_domain_objects); |
| 101 | } | 105 | } |
| 102 | 106 | ||
| 107 | if (ctx.IsTipc()) { | ||
| 108 | header.type.Assign(ctx.GetCommandType()); | ||
| 109 | } | ||
| 110 | |||
| 111 | ctx.data_size = static_cast<u32>(raw_data_size); | ||
| 103 | header.data_size.Assign(static_cast<u32>(raw_data_size)); | 112 | header.data_size.Assign(static_cast<u32>(raw_data_size)); |
| 104 | if (num_handles_to_copy || num_handles_to_move) { | 113 | if (num_handles_to_copy || num_handles_to_move) { |
| 105 | header.enable_handle_descriptor.Assign(1); | 114 | header.enable_handle_descriptor.Assign(1); |
| @@ -111,22 +120,30 @@ public: | |||
| 111 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy); | 120 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy); |
| 112 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); | 121 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); |
| 113 | PushRaw(handle_descriptor_header); | 122 | PushRaw(handle_descriptor_header); |
| 123 | |||
| 124 | ctx.handles_offset = index; | ||
| 125 | |||
| 114 | Skip(num_handles_to_copy + num_handles_to_move, true); | 126 | Skip(num_handles_to_copy + num_handles_to_move, true); |
| 115 | } | 127 | } |
| 116 | 128 | ||
| 117 | AlignWithPadding(); | 129 | if (!ctx.IsTipc()) { |
| 130 | AlignWithPadding(); | ||
| 118 | 131 | ||
| 119 | if (context.Session()->IsDomain() && context.HasDomainMessageHeader()) { | 132 | if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { |
| 120 | IPC::DomainMessageHeader domain_header{}; | 133 | IPC::DomainMessageHeader domain_header{}; |
| 121 | domain_header.num_objects = num_domain_objects; | 134 | domain_header.num_objects = num_domain_objects; |
| 122 | PushRaw(domain_header); | 135 | PushRaw(domain_header); |
| 136 | } | ||
| 137 | |||
| 138 | IPC::DataPayloadHeader data_payload_header{}; | ||
| 139 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 140 | PushRaw(data_payload_header); | ||
| 123 | } | 141 | } |
| 124 | 142 | ||
| 125 | IPC::DataPayloadHeader data_payload_header{}; | 143 | data_payload_index = index; |
| 126 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 127 | PushRaw(data_payload_header); | ||
| 128 | 144 | ||
| 129 | datapayload_index = index; | 145 | ctx.data_payload_offset = index; |
| 146 | ctx.domain_offset = index + raw_data_size / 4; | ||
| 130 | } | 147 | } |
| 131 | 148 | ||
| 132 | template <class T> | 149 | template <class T> |
| @@ -134,6 +151,9 @@ public: | |||
| 134 | if (context->Session()->IsDomain()) { | 151 | if (context->Session()->IsDomain()) { |
| 135 | context->AddDomainObject(std::move(iface)); | 152 | context->AddDomainObject(std::move(iface)); |
| 136 | } else { | 153 | } else { |
| 154 | // kernel.CurrentProcess()->GetResourceLimit()->Reserve( | ||
| 155 | // Kernel::LimitableResource::Sessions, 1); | ||
| 156 | |||
| 137 | auto* session = Kernel::KSession::Create(kernel); | 157 | auto* session = Kernel::KSession::Create(kernel); |
| 138 | session->Initialize(nullptr, iface->GetServiceName()); | 158 | session->Initialize(nullptr, iface->GetServiceName()); |
| 139 | 159 | ||
| @@ -152,7 +172,7 @@ public: | |||
| 152 | const std::size_t num_move_objects = context->NumMoveObjects(); | 172 | const std::size_t num_move_objects = context->NumMoveObjects(); |
| 153 | ASSERT_MSG(!num_domain_objects || !num_move_objects, | 173 | ASSERT_MSG(!num_domain_objects || !num_move_objects, |
| 154 | "cannot move normal handles and domain objects"); | 174 | "cannot move normal handles and domain objects"); |
| 155 | ASSERT_MSG((index - datapayload_index) == normal_params_size, | 175 | ASSERT_MSG((index - data_payload_index) == normal_params_size, |
| 156 | "normal_params_size value is incorrect"); | 176 | "normal_params_size value is incorrect"); |
| 157 | ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, | 177 | ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, |
| 158 | "num_objects_to_move value is incorrect"); | 178 | "num_objects_to_move value is incorrect"); |
| @@ -229,14 +249,14 @@ private: | |||
| 229 | u32 normal_params_size{}; | 249 | u32 normal_params_size{}; |
| 230 | u32 num_handles_to_copy{}; | 250 | u32 num_handles_to_copy{}; |
| 231 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent | 251 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent |
| 232 | std::ptrdiff_t datapayload_index{}; | 252 | u32 data_payload_index{}; |
| 233 | Kernel::KernelCore& kernel; | 253 | Kernel::KernelCore& kernel; |
| 234 | }; | 254 | }; |
| 235 | 255 | ||
| 236 | /// Push /// | 256 | /// Push /// |
| 237 | 257 | ||
| 238 | inline void ResponseBuilder::PushImpl(s32 value) { | 258 | inline void ResponseBuilder::PushImpl(s32 value) { |
| 239 | cmdbuf[index++] = static_cast<u32>(value); | 259 | cmdbuf[index++] = value; |
| 240 | } | 260 | } |
| 241 | 261 | ||
| 242 | inline void ResponseBuilder::PushImpl(u32 value) { | 262 | inline void ResponseBuilder::PushImpl(u32 value) { |
| @@ -341,9 +361,9 @@ class RequestParser : public RequestHelperBase { | |||
| 341 | public: | 361 | public: |
| 342 | explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} | 362 | explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} |
| 343 | 363 | ||
| 344 | explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { | 364 | explicit RequestParser(Kernel::HLERequestContext& ctx) : RequestHelperBase(ctx) { |
| 345 | ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); | 365 | ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete"); |
| 346 | Skip(context.GetDataPayloadOffset(), false); | 366 | Skip(ctx.GetDataPayloadOffset(), false); |
| 347 | // Skip the u64 command id, it's already stored in the context | 367 | // Skip the u64 command id, it's already stored in the context |
| 348 | static constexpr u32 CommandIdSize = 2; | 368 | static constexpr u32 CommandIdSize = 2; |
| 349 | Skip(CommandIdSize, false); | 369 | Skip(CommandIdSize, false); |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index b505d20a6..ce3466df8 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -55,7 +55,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 55 | IPC::RequestParser rp(src_cmdbuf); | 55 | IPC::RequestParser rp(src_cmdbuf); |
| 56 | command_header = rp.PopRaw<IPC::CommandHeader>(); | 56 | command_header = rp.PopRaw<IPC::CommandHeader>(); |
| 57 | 57 | ||
| 58 | if (command_header->type == IPC::CommandType::Close) { | 58 | if (command_header->IsCloseCommand()) { |
| 59 | // Close does not populate the rest of the IPC header | 59 | // Close does not populate the rest of the IPC header |
| 60 | return; | 60 | return; |
| 61 | } | 61 | } |
| @@ -99,39 +99,43 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 99 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 99 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; | 102 | const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; |
| 103 | 103 | ||
| 104 | // Padding to align to 16 bytes | 104 | if (!command_header->IsTipc()) { |
| 105 | rp.AlignWithPadding(); | 105 | // Padding to align to 16 bytes |
| 106 | 106 | rp.AlignWithPadding(); | |
| 107 | if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request || | 107 | |
| 108 | command_header->type == IPC::CommandType::RequestWithContext) || | 108 | if (Session()->IsDomain() && |
| 109 | !incoming)) { | 109 | ((command_header->type == IPC::CommandType::Request || |
| 110 | // If this is an incoming message, only CommandType "Request" has a domain header | 110 | command_header->type == IPC::CommandType::RequestWithContext) || |
| 111 | // All outgoing domain messages have the domain header, if only incoming has it | 111 | !incoming)) { |
| 112 | if (incoming || domain_message_header) { | 112 | // If this is an incoming message, only CommandType "Request" has a domain header |
| 113 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); | 113 | // All outgoing domain messages have the domain header, if only incoming has it |
| 114 | } else { | 114 | if (incoming || domain_message_header) { |
| 115 | if (Session()->IsDomain()) { | 115 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); |
| 116 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | 116 | } else { |
| 117 | if (Session()->IsDomain()) { | ||
| 118 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | ||
| 119 | } | ||
| 117 | } | 120 | } |
| 118 | } | 121 | } |
| 119 | } | ||
| 120 | 122 | ||
| 121 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); | 123 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); |
| 122 | 124 | ||
| 123 | data_payload_offset = rp.GetCurrentOffset(); | 125 | data_payload_offset = rp.GetCurrentOffset(); |
| 124 | 126 | ||
| 125 | if (domain_message_header && domain_message_header->command == | 127 | if (domain_message_header && |
| 126 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { | 128 | domain_message_header->command == |
| 127 | // CloseVirtualHandle command does not have SFC* or any data | 129 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { |
| 128 | return; | 130 | // CloseVirtualHandle command does not have SFC* or any data |
| 129 | } | 131 | return; |
| 132 | } | ||
| 130 | 133 | ||
| 131 | if (incoming) { | 134 | if (incoming) { |
| 132 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); | 135 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); |
| 133 | } else { | 136 | } else { |
| 134 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 137 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); |
| 138 | } | ||
| 135 | } | 139 | } |
| 136 | 140 | ||
| 137 | rp.SetCurrentOffset(buffer_c_offset); | 141 | rp.SetCurrentOffset(buffer_c_offset); |
| @@ -166,84 +170,67 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 166 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, | 170 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, |
| 167 | u32_le* src_cmdbuf) { | 171 | u32_le* src_cmdbuf) { |
| 168 | ParseCommandBuffer(handle_table, src_cmdbuf, true); | 172 | ParseCommandBuffer(handle_table, src_cmdbuf, true); |
| 169 | if (command_header->type == IPC::CommandType::Close) { | 173 | |
| 174 | if (command_header->IsCloseCommand()) { | ||
| 170 | // Close does not populate the rest of the IPC header | 175 | // Close does not populate the rest of the IPC header |
| 171 | return RESULT_SUCCESS; | 176 | return RESULT_SUCCESS; |
| 172 | } | 177 | } |
| 173 | 178 | ||
| 174 | // The data_size already includes the payload header, the padding and the domain header. | 179 | std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); |
| 175 | std::size_t size = data_payload_offset + command_header->data_size - | 180 | |
| 176 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 177 | if (domain_message_header) | ||
| 178 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 179 | std::copy_n(src_cmdbuf, size, cmd_buf.begin()); | ||
| 180 | return RESULT_SUCCESS; | 181 | return RESULT_SUCCESS; |
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& thread) { | 184 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { |
| 184 | auto& owner_process = *thread.GetOwnerProcess(); | 185 | auto current_offset = handles_offset; |
| 186 | auto& owner_process = *requesting_thread.GetOwnerProcess(); | ||
| 185 | auto& handle_table = owner_process.GetHandleTable(); | 187 | auto& handle_table = owner_process.GetHandleTable(); |
| 186 | 188 | ||
| 187 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf; | ||
| 188 | memory.ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), | ||
| 189 | dst_cmdbuf.size() * sizeof(u32)); | ||
| 190 | |||
| 191 | // The header was already built in the internal command buffer. Attempt to parse it to verify | ||
| 192 | // the integrity and then copy it over to the target command buffer. | ||
| 193 | ParseCommandBuffer(handle_table, cmd_buf.data(), false); | ||
| 194 | |||
| 195 | // The data_size already includes the payload header, the padding and the domain header. | 189 | // The data_size already includes the payload header, the padding and the domain header. |
| 196 | std::size_t size = data_payload_offset + command_header->data_size - | 190 | std::size_t size{}; |
| 197 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 198 | if (domain_message_header) | ||
| 199 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 200 | |||
| 201 | std::copy_n(cmd_buf.begin(), size, dst_cmdbuf.data()); | ||
| 202 | 191 | ||
| 203 | if (command_header->enable_handle_descriptor) { | 192 | if (IsTipc()) { |
| 204 | ASSERT_MSG(!move_objects.empty() || !copy_objects.empty(), | 193 | size = cmd_buf.size(); |
| 205 | "Handle descriptor bit set but no handles to translate"); | 194 | } else { |
| 206 | // We write the translated handles at a specific offset in the command buffer, this space | 195 | size = data_payload_offset + data_size - sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; |
| 207 | // was already reserved when writing the header. | 196 | if (Session()->IsDomain()) { |
| 208 | std::size_t current_offset = | 197 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); |
| 209 | (sizeof(IPC::CommandHeader) + sizeof(IPC::HandleDescriptorHeader)) / sizeof(u32); | ||
| 210 | ASSERT_MSG(!handle_descriptor_header->send_current_pid, "Sending PID is not implemented"); | ||
| 211 | |||
| 212 | ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy); | ||
| 213 | ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move); | ||
| 214 | |||
| 215 | // We don't make a distinction between copy and move handles when translating since HLE | ||
| 216 | // services don't deal with handles directly. However, the guest applications might check | ||
| 217 | // for specific values in each of these descriptors. | ||
| 218 | for (auto& object : copy_objects) { | ||
| 219 | ASSERT(object != nullptr); | ||
| 220 | R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object)); | ||
| 221 | } | 198 | } |
| 199 | } | ||
| 222 | 200 | ||
| 223 | for (auto& object : move_objects) { | 201 | for (auto& object : copy_objects) { |
| 224 | ASSERT(object != nullptr); | 202 | Handle handle{}; |
| 225 | R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object)); | 203 | if (object) { |
| 204 | R_TRY(handle_table.Add(&handle, object)); | ||
| 226 | } | 205 | } |
| 206 | cmd_buf[current_offset++] = handle; | ||
| 227 | } | 207 | } |
| 208 | for (auto& object : move_objects) { | ||
| 209 | Handle handle{}; | ||
| 210 | if (object) { | ||
| 211 | R_TRY(handle_table.Add(&handle, object)); | ||
| 228 | 212 | ||
| 229 | // TODO(Subv): Translate the X/A/B/W buffers. | 213 | // Close our reference to the object, as it is being moved to the caller. |
| 214 | object->Close(); | ||
| 215 | } | ||
| 216 | cmd_buf[current_offset++] = handle; | ||
| 217 | } | ||
| 230 | 218 | ||
| 231 | if (Session()->IsDomain() && domain_message_header) { | 219 | // Write the domain objects to the command buffer, these go after the raw untranslated data. |
| 232 | ASSERT(domain_message_header->num_objects == domain_objects.size()); | 220 | // TODO(Subv): This completely ignores C buffers. |
| 233 | // Write the domain objects to the command buffer, these go after the raw untranslated data. | ||
| 234 | // TODO(Subv): This completely ignores C buffers. | ||
| 235 | std::size_t domain_offset = size - domain_message_header->num_objects; | ||
| 236 | 221 | ||
| 222 | if (Session()->IsDomain()) { | ||
| 223 | current_offset = domain_offset - static_cast<u32>(domain_objects.size()); | ||
| 237 | for (const auto& object : domain_objects) { | 224 | for (const auto& object : domain_objects) { |
| 238 | server_session->AppendDomainRequestHandler(object); | 225 | server_session->AppendDomainRequestHandler(object); |
| 239 | dst_cmdbuf[domain_offset++] = | 226 | cmd_buf[current_offset++] = |
| 240 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); | 227 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); |
| 241 | } | 228 | } |
| 242 | } | 229 | } |
| 243 | 230 | ||
| 244 | // Copy the translated command buffer back into the thread's command buffer area. | 231 | // Copy the translated command buffer back into the thread's command buffer area. |
| 245 | memory.WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), | 232 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), |
| 246 | dst_cmdbuf.size() * sizeof(u32)); | 233 | size * sizeof(u32)); |
| 247 | 234 | ||
| 248 | return RESULT_SUCCESS; | 235 | return RESULT_SUCCESS; |
| 249 | } | 236 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index fa031c121..4fba300dc 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -66,7 +66,8 @@ public: | |||
| 66 | * this request (ServerSession, Originator thread, Translated command buffer, etc). | 66 | * this request (ServerSession, Originator thread, Translated command buffer, etc). |
| 67 | * @returns ResultCode the result code of the translate operation. | 67 | * @returns ResultCode the result code of the translate operation. |
| 68 | */ | 68 | */ |
| 69 | virtual ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) = 0; | 69 | virtual ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 70 | Kernel::HLERequestContext& context) = 0; | ||
| 70 | 71 | ||
| 71 | /** | 72 | /** |
| 72 | * Signals that a client has just connected to this HLE handler and keeps the | 73 | * Signals that a client has just connected to this HLE handler and keeps the |
| @@ -126,17 +127,30 @@ public: | |||
| 126 | u32_le* src_cmdbuf); | 127 | u32_le* src_cmdbuf); |
| 127 | 128 | ||
| 128 | /// Writes data from this context back to the requesting process/thread. | 129 | /// Writes data from this context back to the requesting process/thread. |
| 129 | ResultCode WriteToOutgoingCommandBuffer(KThread& thread); | 130 | ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread); |
| 130 | 131 | ||
| 131 | u32_le GetCommand() const { | 132 | u32_le GetHipcCommand() const { |
| 132 | return command; | 133 | return command; |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 136 | u32_le GetTipcCommand() const { | ||
| 137 | return static_cast<u32_le>(command_header->type.Value()) - | ||
| 138 | static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion); | ||
| 139 | } | ||
| 140 | |||
| 141 | u32_le GetCommand() const { | ||
| 142 | return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); | ||
| 143 | } | ||
| 144 | |||
| 145 | bool IsTipc() const { | ||
| 146 | return command_header->IsTipc(); | ||
| 147 | } | ||
| 148 | |||
| 135 | IPC::CommandType GetCommandType() const { | 149 | IPC::CommandType GetCommandType() const { |
| 136 | return command_header->type; | 150 | return command_header->type; |
| 137 | } | 151 | } |
| 138 | 152 | ||
| 139 | unsigned GetDataPayloadOffset() const { | 153 | u32 GetDataPayloadOffset() const { |
| 140 | return data_payload_offset; | 154 | return data_payload_offset; |
| 141 | } | 155 | } |
| 142 | 156 | ||
| @@ -291,8 +305,10 @@ private: | |||
| 291 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; | 305 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; |
| 292 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; | 306 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; |
| 293 | 307 | ||
| 294 | unsigned data_payload_offset{}; | 308 | u32 data_payload_offset{}; |
| 295 | unsigned buffer_c_offset{}; | 309 | u32 handles_offset{}; |
| 310 | u32 domain_offset{}; | ||
| 311 | u32 data_size{}; | ||
| 296 | u32_le command{}; | 312 | u32_le command{}; |
| 297 | 313 | ||
| 298 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | 314 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; |
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 765e46670..bc18582be 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h | |||
| @@ -177,7 +177,7 @@ class KAutoObjectWithListContainer; | |||
| 177 | 177 | ||
| 178 | class KAutoObjectWithList : public KAutoObject { | 178 | class KAutoObjectWithList : public KAutoObject { |
| 179 | public: | 179 | public: |
| 180 | explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_), kernel(kernel_) {} | 180 | explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {} |
| 181 | 181 | ||
| 182 | static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { | 182 | static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { |
| 183 | const u64 lid = lhs.GetId(); | 183 | const u64 lid = lhs.GetId(); |
| @@ -204,11 +204,7 @@ public: | |||
| 204 | private: | 204 | private: |
| 205 | friend class KAutoObjectWithListContainer; | 205 | friend class KAutoObjectWithListContainer; |
| 206 | 206 | ||
| 207 | private: | ||
| 208 | Common::IntrusiveRedBlackTreeNode list_node; | 207 | Common::IntrusiveRedBlackTreeNode list_node; |
| 209 | |||
| 210 | protected: | ||
| 211 | KernelCore& kernel; | ||
| 212 | }; | 208 | }; |
| 213 | 209 | ||
| 214 | template <typename T> | 210 | template <typename T> |
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index b6f1d713f..ad01cf67e 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 16 | KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 17 | KClientPort::~KClientPort() = default; | 17 | KClientPort::~KClientPort() = default; |
| 18 | 18 | ||
| 19 | void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { | 19 | void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { |
| @@ -58,9 +58,9 @@ bool KClientPort::IsSignaled() const { | |||
| 58 | 58 | ||
| 59 | ResultCode KClientPort::CreateSession(KClientSession** out) { | 59 | ResultCode KClientPort::CreateSession(KClientSession** out) { |
| 60 | // Reserve a new session from the resource limit. | 60 | // Reserve a new session from the resource limit. |
| 61 | KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), | 61 | // KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), |
| 62 | LimitableResource::Sessions); | 62 | // LimitableResource::Sessions); |
| 63 | R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); | 63 | // R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); |
| 64 | 64 | ||
| 65 | // Update the session counts. | 65 | // Update the session counts. |
| 66 | { | 66 | { |
| @@ -91,7 +91,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { | |||
| 91 | // Create a new session. | 91 | // Create a new session. |
| 92 | KSession* session = KSession::Create(kernel); | 92 | KSession* session = KSession::Create(kernel); |
| 93 | if (session == nullptr) { | 93 | if (session == nullptr) { |
| 94 | /* Decrement the session count. */ | 94 | // Decrement the session count. |
| 95 | const auto prev = num_sessions--; | 95 | const auto prev = num_sessions--; |
| 96 | if (prev == max_sessions) { | 96 | if (prev == max_sessions) { |
| 97 | this->NotifyAvailable(); | 97 | this->NotifyAvailable(); |
| @@ -104,7 +104,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { | |||
| 104 | session->Initialize(this, parent->GetName()); | 104 | session->Initialize(this, parent->GetName()); |
| 105 | 105 | ||
| 106 | // Commit the session reservation. | 106 | // Commit the session reservation. |
| 107 | session_reservation.Commit(); | 107 | // session_reservation.Commit(); |
| 108 | 108 | ||
| 109 | // Register the session. | 109 | // Register the session. |
| 110 | KSession::Register(kernel, session); | 110 | KSession::Register(kernel, session); |
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index ec1d7e12e..d00ce3ddd 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h | |||
| @@ -21,7 +21,7 @@ class KClientPort final : public KSynchronizationObject { | |||
| 21 | KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); | 21 | KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); |
| 22 | 22 | ||
| 23 | public: | 23 | public: |
| 24 | explicit KClientPort(KernelCore& kernel); | 24 | explicit KClientPort(KernelCore& kernel_); |
| 25 | virtual ~KClientPort() override; | 25 | virtual ~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_); |
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp index 0618dc246..8ad1be762 100644 --- a/src/core/hle/kernel/k_client_session.cpp +++ b/src/core/hle/kernel/k_client_session.cpp | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} | 15 | KClientSession::KClientSession(KernelCore& kernel_) |
| 16 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||
| 16 | KClientSession::~KClientSession() = default; | 17 | KClientSession::~KClientSession() = default; |
| 17 | 18 | ||
| 18 | void KClientSession::Destroy() { | 19 | void KClientSession::Destroy() { |
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 6476a588b..720a8c243 100644 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h | |||
| @@ -33,7 +33,7 @@ class KClientSession final | |||
| 33 | KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); | 33 | KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); |
| 34 | 34 | ||
| 35 | public: | 35 | public: |
| 36 | explicit KClientSession(KernelCore& kernel); | 36 | explicit KClientSession(KernelCore& kernel_); |
| 37 | virtual ~KClientSession(); | 37 | virtual ~KClientSession(); |
| 38 | 38 | ||
| 39 | void Initialize(KSession* parent_, std::string&& name_) { | 39 | void Initialize(KSession* parent_, std::string&& name_) { |
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index f51cf3e7b..ce3bade60 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp | |||
| @@ -254,8 +254,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | // Close threads in the list. | 256 | // Close threads in the list. |
| 257 | for (auto it = thread_list.begin(); it != thread_list.end(); | 257 | for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) { |
| 258 | it = thread_list.erase(kernel, it)) { | ||
| 259 | (*it).Close(); | 258 | (*it).Close(); |
| 260 | } | 259 | } |
| 261 | } | 260 | } |
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index 986355b78..0720efece 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp | |||
| @@ -8,8 +8,9 @@ | |||
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | KEvent::KEvent(KernelCore& kernel) | 11 | KEvent::KEvent(KernelCore& kernel_) |
| 12 | : KAutoObjectWithSlabHeapAndContainer{kernel}, readable_event{kernel}, writable_event{kernel} {} | 12 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, readable_event{kernel_}, writable_event{ |
| 13 | kernel_} {} | ||
| 13 | 14 | ||
| 14 | KEvent::~KEvent() = default; | 15 | KEvent::~KEvent() = default; |
| 15 | 16 | ||
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 4ca869930..9a59ffb70 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h | |||
| @@ -19,7 +19,7 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj | |||
| 19 | KERNEL_AUTOOBJECT_TRAITS(KEvent, KAutoObject); | 19 | KERNEL_AUTOOBJECT_TRAITS(KEvent, KAutoObject); |
| 20 | 20 | ||
| 21 | public: | 21 | public: |
| 22 | explicit KEvent(KernelCore& kernel); | 22 | explicit KEvent(KernelCore& kernel_); |
| 23 | virtual ~KEvent(); | 23 | virtual ~KEvent(); |
| 24 | 24 | ||
| 25 | void Initialize(std::string&& name); | 25 | void Initialize(std::string&& name); |
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h index 500f44685..540e518cd 100644 --- a/src/core/hle/kernel/k_linked_list.h +++ b/src/core/hle/kernel/k_linked_list.h | |||
| @@ -124,7 +124,7 @@ public: | |||
| 124 | 124 | ||
| 125 | ~KLinkedList() { | 125 | ~KLinkedList() { |
| 126 | // Erase all elements. | 126 | // Erase all elements. |
| 127 | for (auto it = this->begin(); it != this->end(); it = this->erase(kernel, it)) { | 127 | for (auto it = begin(); it != end(); it = erase(it)) { |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | // Ensure we succeeded. | 130 | // Ensure we succeeded. |
| @@ -223,7 +223,7 @@ public: | |||
| 223 | this->erase(this->begin()); | 223 | this->erase(this->begin()); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | iterator erase(KernelCore& kernel, const iterator pos) { | 226 | iterator erase(const iterator pos) { |
| 227 | KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); | 227 | KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); |
| 228 | iterator ret = iterator(BaseList::erase(pos.m_base_it)); | 228 | iterator ret = iterator(BaseList::erase(pos.m_base_it)); |
| 229 | KLinkedListNode::Free(kernel, freed_node); | 229 | KLinkedListNode::Free(kernel, freed_node); |
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 4a2d88008..44bfeb0d5 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -17,8 +17,8 @@ KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) | |||
| 17 | KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { | 17 | KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { |
| 18 | auto node{memory_block_tree.begin()}; | 18 | auto node{memory_block_tree.begin()}; |
| 19 | while (node != end()) { | 19 | while (node != end()) { |
| 20 | const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; | 20 | const VAddr node_end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; |
| 21 | if (node->GetAddress() <= addr && end_addr - 1 >= addr) { | 21 | if (node->GetAddress() <= addr && node_end_addr - 1 >= addr) { |
| 22 | return node; | 22 | return node; |
| 23 | } | 23 | } |
| 24 | node = std::next(node); | 24 | node = std::next(node); |
| @@ -67,7 +67,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 67 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, | 67 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, |
| 68 | KMemoryState state, KMemoryPermission perm, | 68 | KMemoryState state, KMemoryPermission perm, |
| 69 | KMemoryAttribute attribute) { | 69 | KMemoryAttribute attribute) { |
| 70 | const VAddr end_addr{addr + num_pages * PageSize}; | 70 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 71 | iterator node{memory_block_tree.begin()}; | 71 | iterator node{memory_block_tree.begin()}; |
| 72 | 72 | ||
| 73 | prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; | 73 | prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; |
| @@ -78,7 +78,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 78 | const VAddr cur_addr{block->GetAddress()}; | 78 | const VAddr cur_addr{block->GetAddress()}; |
| 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 80 | 80 | ||
| 81 | if (addr < cur_end_addr && cur_addr < end_addr) { | 81 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 82 | if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) { | 82 | if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) { |
| 83 | node = next_node; | 83 | node = next_node; |
| 84 | continue; | 84 | continue; |
| @@ -89,8 +89,8 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 89 | memory_block_tree.insert(node, block->Split(addr)); | 89 | memory_block_tree.insert(node, block->Split(addr)); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | if (end_addr < cur_end_addr) { | 92 | if (update_end_addr < cur_end_addr) { |
| 93 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 93 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | new_node->Update(state, perm, attribute); | 96 | new_node->Update(state, perm, attribute); |
| @@ -98,7 +98,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 98 | MergeAdjacent(new_node, next_node); | 98 | MergeAdjacent(new_node, next_node); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | if (cur_end_addr - 1 >= end_addr - 1) { | 101 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 102 | break; | 102 | break; |
| 103 | } | 103 | } |
| 104 | 104 | ||
| @@ -108,7 +108,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 108 | 108 | ||
| 109 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, | 109 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 110 | KMemoryPermission perm, KMemoryAttribute attribute) { | 110 | KMemoryPermission perm, KMemoryAttribute attribute) { |
| 111 | const VAddr end_addr{addr + num_pages * PageSize}; | 111 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 112 | iterator node{memory_block_tree.begin()}; | 112 | iterator node{memory_block_tree.begin()}; |
| 113 | 113 | ||
| 114 | while (node != memory_block_tree.end()) { | 114 | while (node != memory_block_tree.end()) { |
| @@ -117,15 +117,15 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 117 | const VAddr cur_addr{block->GetAddress()}; | 117 | const VAddr cur_addr{block->GetAddress()}; |
| 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 119 | 119 | ||
| 120 | if (addr < cur_end_addr && cur_addr < end_addr) { | 120 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 121 | iterator new_node{node}; | 121 | iterator new_node{node}; |
| 122 | 122 | ||
| 123 | if (addr > cur_addr) { | 123 | if (addr > cur_addr) { |
| 124 | memory_block_tree.insert(node, block->Split(addr)); | 124 | memory_block_tree.insert(node, block->Split(addr)); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | if (end_addr < cur_end_addr) { | 127 | if (update_end_addr < cur_end_addr) { |
| 128 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 128 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | new_node->Update(state, perm, attribute); | 131 | new_node->Update(state, perm, attribute); |
| @@ -133,7 +133,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 133 | MergeAdjacent(new_node, next_node); | 133 | MergeAdjacent(new_node, next_node); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | if (cur_end_addr - 1 >= end_addr - 1) { | 136 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 137 | break; | 137 | break; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| @@ -143,7 +143,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState | |||
| 143 | 143 | ||
| 144 | void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, | 144 | void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, |
| 145 | KMemoryPermission perm) { | 145 | KMemoryPermission perm) { |
| 146 | const VAddr end_addr{addr + num_pages * PageSize}; | 146 | const VAddr update_end_addr{addr + num_pages * PageSize}; |
| 147 | iterator node{memory_block_tree.begin()}; | 147 | iterator node{memory_block_tree.begin()}; |
| 148 | 148 | ||
| 149 | while (node != memory_block_tree.end()) { | 149 | while (node != memory_block_tree.end()) { |
| @@ -152,15 +152,15 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc | |||
| 152 | const VAddr cur_addr{block->GetAddress()}; | 152 | const VAddr cur_addr{block->GetAddress()}; |
| 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| 154 | 154 | ||
| 155 | if (addr < cur_end_addr && cur_addr < end_addr) { | 155 | if (addr < cur_end_addr && cur_addr < update_end_addr) { |
| 156 | iterator new_node{node}; | 156 | iterator new_node{node}; |
| 157 | 157 | ||
| 158 | if (addr > cur_addr) { | 158 | if (addr > cur_addr) { |
| 159 | memory_block_tree.insert(node, block->Split(addr)); | 159 | memory_block_tree.insert(node, block->Split(addr)); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | if (end_addr < cur_end_addr) { | 162 | if (update_end_addr < cur_end_addr) { |
| 163 | new_node = memory_block_tree.insert(node, block->Split(end_addr)); | 163 | new_node = memory_block_tree.insert(node, block->Split(update_end_addr)); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | lock_func(new_node, perm); | 166 | lock_func(new_node, perm); |
| @@ -168,7 +168,7 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc | |||
| 168 | MergeAdjacent(new_node, next_node); | 168 | MergeAdjacent(new_node, next_node); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | if (cur_end_addr - 1 >= end_addr - 1) { | 171 | if (cur_end_addr - 1 >= update_end_addr - 1) { |
| 172 | break; | 172 | break; |
| 173 | } | 173 | } |
| 174 | 174 | ||
diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h index a861c04ab..90ab8fd62 100644 --- a/src/core/hle/kernel/k_memory_region.h +++ b/src/core/hle/kernel/k_memory_region.h | |||
| @@ -82,9 +82,9 @@ public: | |||
| 82 | type_id = type; | 82 | type_id = type; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | constexpr bool Contains(u64 address) const { | 85 | constexpr bool Contains(u64 addr) const { |
| 86 | ASSERT(this->GetEndAddress() != 0); | 86 | ASSERT(this->GetEndAddress() != 0); |
| 87 | return this->GetAddress() <= address && address <= this->GetLastAddress(); | 87 | return this->GetAddress() <= addr && addr <= this->GetLastAddress(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | constexpr bool IsDerivedFrom(u32 type) const { | 90 | constexpr bool IsDerivedFrom(u32 type) const { |
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index 734aa2a8c..feb2bb11f 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | 11 | ||
| 12 | KPort::KPort(KernelCore& kernel) | 12 | KPort::KPort(KernelCore& kernel_) |
| 13 | : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} | 13 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} |
| 14 | 14 | ||
| 15 | KPort::~KPort() = default; | 15 | KPort::~KPort() = default; |
| 16 | 16 | ||
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index f1b2838d8..960f1f3a3 100644 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h | |||
| @@ -21,7 +21,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec | |||
| 21 | KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject); | 21 | KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject); |
| 22 | 22 | ||
| 23 | public: | 23 | public: |
| 24 | explicit KPort(KernelCore& kernel); | 24 | explicit KPort(KernelCore& kernel_); |
| 25 | virtual ~KPort(); | 25 | virtual ~KPort(); |
| 26 | 26 | ||
| 27 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 27 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 174318180..bdcbaeeaa 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -118,11 +118,11 @@ private: | |||
| 118 | std::bitset<num_slot_entries> is_slot_used; | 118 | std::bitset<num_slot_entries> is_slot_used; |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string name, | 121 | ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, |
| 122 | ProcessType type) { | 122 | ProcessType type) { |
| 123 | auto& kernel = system.Kernel(); | 123 | auto& kernel = system.Kernel(); |
| 124 | 124 | ||
| 125 | process->name = std::move(name); | 125 | process->name = std::move(process_name); |
| 126 | 126 | ||
| 127 | process->resource_limit = kernel.GetSystemResourceLimit(); | 127 | process->resource_limit = kernel.GetSystemResourceLimit(); |
| 128 | process->status = ProcessStatus::Created; | 128 | process->status = ProcessStatus::Created; |
| @@ -373,8 +373,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | |||
| 373 | void KProcess::PrepareForTermination() { | 373 | void KProcess::PrepareForTermination() { |
| 374 | ChangeStatus(ProcessStatus::Exiting); | 374 | ChangeStatus(ProcessStatus::Exiting); |
| 375 | 375 | ||
| 376 | const auto stop_threads = [this](const std::vector<KThread*>& thread_list) { | 376 | const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) { |
| 377 | for (auto& thread : thread_list) { | 377 | for (auto& thread : in_thread_list) { |
| 378 | if (thread->GetOwnerProcess() != this) | 378 | if (thread->GetOwnerProcess() != this) |
| 379 | continue; | 379 | continue; |
| 380 | 380 | ||
| @@ -491,10 +491,10 @@ bool KProcess::IsSignaled() const { | |||
| 491 | return is_signaled; | 491 | return is_signaled; |
| 492 | } | 492 | } |
| 493 | 493 | ||
| 494 | KProcess::KProcess(KernelCore& kernel) | 494 | KProcess::KProcess(KernelCore& kernel_) |
| 495 | : KAutoObjectWithSlabHeapAndContainer{kernel}, | 495 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, |
| 496 | page_table{std::make_unique<KPageTable>(kernel.System())}, handle_table{kernel}, | 496 | page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_}, |
| 497 | address_arbiter{kernel.System()}, condition_var{kernel.System()}, state_lock{kernel} {} | 497 | address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {} |
| 498 | 498 | ||
| 499 | KProcess::~KProcess() = default; | 499 | KProcess::~KProcess() = default; |
| 500 | 500 | ||
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 62ab26b05..123d71cd3 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -67,7 +67,7 @@ class KProcess final | |||
| 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); |
| 68 | 68 | ||
| 69 | public: | 69 | public: |
| 70 | explicit KProcess(KernelCore& kernel); | 70 | explicit KProcess(KernelCore& kernel_); |
| 71 | ~KProcess() override; | 71 | ~KProcess() override; |
| 72 | 72 | ||
| 73 | enum : u64 { | 73 | enum : u64 { |
| @@ -90,7 +90,7 @@ public: | |||
| 90 | 90 | ||
| 91 | static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; | 91 | static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; |
| 92 | 92 | ||
| 93 | static ResultCode Initialize(KProcess* process, Core::System& system, std::string name, | 93 | static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name, |
| 94 | ProcessType type); | 94 | ProcessType type); |
| 95 | 95 | ||
| 96 | /// Gets a reference to the process' page table. | 96 | /// Gets a reference to the process' page table. |
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp index 8fef4bb00..0ea2d0275 100644 --- a/src/core/hle/kernel/k_readable_event.cpp +++ b/src/core/hle/kernel/k_readable_event.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 15 | KReadableEvent::KReadableEvent(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 16 | 16 | ||
| 17 | KReadableEvent::~KReadableEvent() = default; | 17 | KReadableEvent::~KReadableEvent() = default; |
| 18 | 18 | ||
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h index 1783ef0b8..33cd1dd3e 100644 --- a/src/core/hle/kernel/k_readable_event.h +++ b/src/core/hle/kernel/k_readable_event.h | |||
| @@ -18,7 +18,7 @@ class KReadableEvent : public KSynchronizationObject { | |||
| 18 | KERNEL_AUTOOBJECT_TRAITS(KReadableEvent, KSynchronizationObject); | 18 | KERNEL_AUTOOBJECT_TRAITS(KReadableEvent, KSynchronizationObject); |
| 19 | 19 | ||
| 20 | public: | 20 | public: |
| 21 | explicit KReadableEvent(KernelCore& kernel); | 21 | explicit KReadableEvent(KernelCore& kernel_); |
| 22 | ~KReadableEvent() override; | 22 | ~KReadableEvent() override; |
| 23 | 23 | ||
| 24 | void Initialize(KEvent* parent_, std::string&& name_) { | 24 | void Initialize(KEvent* parent_, std::string&& name_) { |
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index ad5095bfd..bf20bf7d0 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds | 11 | constexpr s64 DefaultTimeout = 10000000000; // 10 seconds |
| 12 | 12 | ||
| 13 | KResourceLimit::KResourceLimit(KernelCore& kernel) | 13 | KResourceLimit::KResourceLimit(KernelCore& kernel_) |
| 14 | : KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {} | 14 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, lock{kernel_}, cond_var{kernel_} {} |
| 15 | KResourceLimit::~KResourceLimit() = default; | 15 | KResourceLimit::~KResourceLimit() = default; |
| 16 | 16 | ||
| 17 | void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { | 17 | void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { |
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 66ebf32df..0debbbb51 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h | |||
| @@ -36,7 +36,7 @@ class KResourceLimit final | |||
| 36 | KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); | 36 | KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); |
| 37 | 37 | ||
| 38 | public: | 38 | public: |
| 39 | explicit KResourceLimit(KernelCore& kernel); | 39 | explicit KResourceLimit(KernelCore& kernel_); |
| 40 | virtual ~KResourceLimit(); | 40 | virtual ~KResourceLimit(); |
| 41 | 41 | ||
| 42 | void Initialize(const Core::Timing::CoreTiming* core_timing_); | 42 | void Initialize(const Core::Timing::CoreTiming* core_timing_); |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 0115fe6d1..e256e9415 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -259,7 +259,7 @@ void KScheduler::OnThreadAffinityMaskChanged(KernelCore& kernel, KThread* thread | |||
| 259 | } | 259 | } |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | 262 | void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) { |
| 263 | ASSERT(system.GlobalSchedulerContext().IsLocked()); | 263 | ASSERT(system.GlobalSchedulerContext().IsLocked()); |
| 264 | 264 | ||
| 265 | // Get a reference to the priority queue. | 265 | // Get a reference to the priority queue. |
| @@ -267,7 +267,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 267 | auto& priority_queue = GetPriorityQueue(kernel); | 267 | auto& priority_queue = GetPriorityQueue(kernel); |
| 268 | 268 | ||
| 269 | // Rotate the front of the queue to the end. | 269 | // Rotate the front of the queue to the end. |
| 270 | KThread* top_thread = priority_queue.GetScheduledFront(core_id, priority); | 270 | KThread* top_thread = priority_queue.GetScheduledFront(cpu_core_id, priority); |
| 271 | KThread* next_thread = nullptr; | 271 | KThread* next_thread = nullptr; |
| 272 | if (top_thread != nullptr) { | 272 | if (top_thread != nullptr) { |
| 273 | next_thread = priority_queue.MoveToScheduledBack(top_thread); | 273 | next_thread = priority_queue.MoveToScheduledBack(top_thread); |
| @@ -279,7 +279,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 279 | 279 | ||
| 280 | // While we have a suggested thread, try to migrate it! | 280 | // While we have a suggested thread, try to migrate it! |
| 281 | { | 281 | { |
| 282 | KThread* suggested = priority_queue.GetSuggestedFront(core_id, priority); | 282 | KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id, priority); |
| 283 | while (suggested != nullptr) { | 283 | while (suggested != nullptr) { |
| 284 | // Check if the suggested thread is the top thread on its core. | 284 | // Check if the suggested thread is the top thread on its core. |
| 285 | const s32 suggested_core = suggested->GetActiveCore(); | 285 | const s32 suggested_core = suggested->GetActiveCore(); |
| @@ -300,7 +300,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 300 | // to the front of the queue. | 300 | // to the front of the queue. |
| 301 | if (top_on_suggested_core == nullptr || | 301 | if (top_on_suggested_core == nullptr || |
| 302 | top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { | 302 | top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { |
| 303 | suggested->SetActiveCore(core_id); | 303 | suggested->SetActiveCore(cpu_core_id); |
| 304 | priority_queue.ChangeCore(suggested_core, suggested, true); | 304 | priority_queue.ChangeCore(suggested_core, suggested, true); |
| 305 | IncrementScheduledCount(suggested); | 305 | IncrementScheduledCount(suggested); |
| 306 | break; | 306 | break; |
| @@ -308,22 +308,22 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | // Get the next suggestion. | 310 | // Get the next suggestion. |
| 311 | suggested = priority_queue.GetSamePriorityNext(core_id, suggested); | 311 | suggested = priority_queue.GetSamePriorityNext(cpu_core_id, suggested); |
| 312 | } | 312 | } |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | // Now that we might have migrated a thread with the same priority, check if we can do better. | 315 | // Now that we might have migrated a thread with the same priority, check if we can do better. |
| 316 | 316 | ||
| 317 | { | 317 | { |
| 318 | KThread* best_thread = priority_queue.GetScheduledFront(core_id); | 318 | KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id); |
| 319 | if (best_thread == GetCurrentThread()) { | 319 | if (best_thread == GetCurrentThread()) { |
| 320 | best_thread = priority_queue.GetScheduledNext(core_id, best_thread); | 320 | best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread); |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | // If the best thread we can choose has a priority the same or worse than ours, try to | 323 | // If the best thread we can choose has a priority the same or worse than ours, try to |
| 324 | // migrate a higher priority thread. | 324 | // migrate a higher priority thread. |
| 325 | if (best_thread != nullptr && best_thread->GetPriority() >= priority) { | 325 | if (best_thread != nullptr && best_thread->GetPriority() >= priority) { |
| 326 | KThread* suggested = priority_queue.GetSuggestedFront(core_id); | 326 | KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id); |
| 327 | while (suggested != nullptr) { | 327 | while (suggested != nullptr) { |
| 328 | // If the suggestion's priority is the same as ours, don't bother. | 328 | // If the suggestion's priority is the same as ours, don't bother. |
| 329 | if (suggested->GetPriority() >= best_thread->GetPriority()) { | 329 | if (suggested->GetPriority() >= best_thread->GetPriority()) { |
| @@ -342,7 +342,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 342 | if (top_on_suggested_core == nullptr || | 342 | if (top_on_suggested_core == nullptr || |
| 343 | top_on_suggested_core->GetPriority() >= | 343 | top_on_suggested_core->GetPriority() >= |
| 344 | HighestCoreMigrationAllowedPriority) { | 344 | HighestCoreMigrationAllowedPriority) { |
| 345 | suggested->SetActiveCore(core_id); | 345 | suggested->SetActiveCore(cpu_core_id); |
| 346 | priority_queue.ChangeCore(suggested_core, suggested, true); | 346 | priority_queue.ChangeCore(suggested_core, suggested, true); |
| 347 | IncrementScheduledCount(suggested); | 347 | IncrementScheduledCount(suggested); |
| 348 | break; | 348 | break; |
| @@ -350,7 +350,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { | |||
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | // Get the next suggestion. | 352 | // Get the next suggestion. |
| 353 | suggested = priority_queue.GetSuggestedNext(core_id, suggested); | 353 | suggested = priority_queue.GetSuggestedNext(cpu_core_id, suggested); |
| 354 | } | 354 | } |
| 355 | } | 355 | } |
| 356 | } | 356 | } |
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index b789a64a4..13a2414e6 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -141,7 +141,7 @@ private: | |||
| 141 | 141 | ||
| 142 | [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel); | 142 | [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel); |
| 143 | 143 | ||
| 144 | void RotateScheduledQueue(s32 core_id, s32 priority); | 144 | void RotateScheduledQueue(s32 cpu_core_id, s32 priority); |
| 145 | 145 | ||
| 146 | void Schedule() { | 146 | void Schedule() { |
| 147 | ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); | 147 | ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); |
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index 5e44c48e2..8cbde177a 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 17 | KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 18 | KServerPort::~KServerPort() = default; | 18 | KServerPort::~KServerPort() = default; |
| 19 | 19 | ||
| 20 | void KServerPort::Initialize(KPort* parent_, std::string&& name_) { | 20 | void KServerPort::Initialize(KPort* parent_, std::string&& name_) { |
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index 558c8ed4d..e76792253 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h | |||
| @@ -29,7 +29,7 @@ private: | |||
| 29 | using SessionList = boost::intrusive::list<KServerSession>; | 29 | using SessionList = boost::intrusive::list<KServerSession>; |
| 30 | 30 | ||
| 31 | public: | 31 | public: |
| 32 | explicit KServerPort(KernelCore& kernel); | 32 | explicit KServerPort(KernelCore& kernel_); |
| 33 | virtual ~KServerPort() override; | 33 | virtual ~KServerPort() override; |
| 34 | 34 | ||
| 35 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; | 35 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; |
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index c8acaa453..8850d9af5 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | 25 | ||
| 26 | KServerSession::KServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} | 26 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} |
| 27 | 27 | ||
| 28 | KServerSession::~KServerSession() { | 28 | KServerSession::~KServerSession() { |
| 29 | kernel.ReleaseServiceThread(service_thread); | 29 | kernel.ReleaseServiceThread(service_thread); |
| @@ -95,7 +95,7 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co | |||
| 95 | UNREACHABLE(); | 95 | UNREACHABLE(); |
| 96 | return RESULT_SUCCESS; // Ignore error if asserts are off | 96 | return RESULT_SUCCESS; // Ignore error if asserts are off |
| 97 | } | 97 | } |
| 98 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); | 98 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(*this, context); |
| 99 | 99 | ||
| 100 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | 100 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { |
| 101 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | 101 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); |
| @@ -135,7 +135,7 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 135 | // If there is no domain header, the regular session handler is used | 135 | // If there is no domain header, the regular session handler is used |
| 136 | } else if (hle_handler != nullptr) { | 136 | } else if (hle_handler != nullptr) { |
| 137 | // If this ServerSession has an associated HLE handler, forward the request to it. | 137 | // If this ServerSession has an associated HLE handler, forward the request to it. |
| 138 | result = hle_handler->HandleSyncRequest(context); | 138 | result = hle_handler->HandleSyncRequest(*this, context); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | if (convert_to_domain) { | 141 | if (convert_to_domain) { |
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 77095bb85..597d76d38 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -40,7 +40,7 @@ class KServerSession final : public KSynchronizationObject, | |||
| 40 | friend class ServiceThread; | 40 | friend class ServiceThread; |
| 41 | 41 | ||
| 42 | public: | 42 | public: |
| 43 | explicit KServerSession(KernelCore& kernel); | 43 | explicit KServerSession(KernelCore& kernel_); |
| 44 | virtual ~KServerSession() override; | 44 | virtual ~KServerSession() override; |
| 45 | 45 | ||
| 46 | virtual void Destroy() override; | 46 | virtual void Destroy() override; |
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 7b0bc177d..b7ce27a0b 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | 11 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| 14 | KSession::KSession(KernelCore& kernel) | 14 | KSession::KSession(KernelCore& kernel_) |
| 15 | : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} | 15 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {} |
| 16 | KSession::~KSession() = default; | 16 | KSession::~KSession() = default; |
| 17 | 17 | ||
| 18 | void KSession::Initialize(KClientPort* port_, const std::string& name_) { | 18 | void KSession::Initialize(KClientPort* port_, const std::string& name_) { |
| @@ -78,7 +78,7 @@ void KSession::OnClientClosed() { | |||
| 78 | void KSession::PostDestroy(uintptr_t arg) { | 78 | void KSession::PostDestroy(uintptr_t arg) { |
| 79 | // Release the session count resource the owner process holds. | 79 | // Release the session count resource the owner process holds. |
| 80 | KProcess* owner = reinterpret_cast<KProcess*>(arg); | 80 | KProcess* owner = reinterpret_cast<KProcess*>(arg); |
| 81 | owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); | 81 | // owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); |
| 82 | owner->Close(); | 82 | owner->Close(); |
| 83 | } | 83 | } |
| 84 | 84 | ||
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 4321b7885..16901e19c 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -17,7 +17,7 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut | |||
| 17 | KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); | 17 | KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); |
| 18 | 18 | ||
| 19 | public: | 19 | public: |
| 20 | explicit KSession(KernelCore& kernel); | 20 | explicit KSession(KernelCore& kernel_); |
| 21 | virtual ~KSession() override; | 21 | virtual ~KSession() override; |
| 22 | 22 | ||
| 23 | void Initialize(KClientPort* port_, const std::string& name_); | 23 | void Initialize(KClientPort* port_, const std::string& name_); |
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 1da57a4c3..7770b1868 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp | |||
| @@ -12,14 +12,14 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | KSharedMemory::KSharedMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} | 15 | KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 16 | 16 | ||
| 17 | KSharedMemory::~KSharedMemory() { | 17 | KSharedMemory::~KSharedMemory() { |
| 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, | 21 | ResultCode KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, |
| 22 | KProcess* owner_process_, KPageLinkedList&& page_list_, | 22 | KPageLinkedList&& page_list_, |
| 23 | Svc::MemoryPermission owner_permission_, | 23 | Svc::MemoryPermission owner_permission_, |
| 24 | Svc::MemoryPermission user_permission_, | 24 | Svc::MemoryPermission user_permission_, |
| 25 | PAddr physical_address_, std::size_t size_, | 25 | PAddr physical_address_, std::size_t size_, |
| @@ -32,7 +32,7 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de | |||
| 32 | user_permission = user_permission_; | 32 | user_permission = user_permission_; |
| 33 | physical_address = physical_address_; | 33 | physical_address = physical_address_; |
| 34 | size = size_; | 34 | size = size_; |
| 35 | name = name_; | 35 | name = std::move(name_); |
| 36 | 36 | ||
| 37 | // Get the resource limit. | 37 | // Get the resource limit. |
| 38 | KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); | 38 | KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); |
| @@ -67,9 +67,9 @@ void KSharedMemory::Finalize() { | |||
| 67 | KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize(); | 67 | KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize(); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t size, | 70 | ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, |
| 71 | Svc::MemoryPermission permissions) { | 71 | Svc::MemoryPermission permissions) { |
| 72 | const u64 page_count{(size + PageSize - 1) / PageSize}; | 72 | const u64 page_count{(map_size + PageSize - 1) / PageSize}; |
| 73 | 73 | ||
| 74 | if (page_list.GetNumPages() != page_count) { | 74 | if (page_list.GetNumPages() != page_count) { |
| 75 | UNIMPLEMENTED_MSG("Page count does not match"); | 75 | UNIMPLEMENTED_MSG("Page count does not match"); |
| @@ -86,8 +86,8 @@ ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size | |||
| 86 | ConvertToKMemoryPermission(permissions)); | 86 | ConvertToKMemoryPermission(permissions)); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t size) { | 89 | ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { |
| 90 | const u64 page_count{(size + PageSize - 1) / PageSize}; | 90 | const u64 page_count{(unmap_size + PageSize - 1) / PageSize}; |
| 91 | 91 | ||
| 92 | if (page_list.GetNumPages() != page_count) { | 92 | if (page_list.GetNumPages() != page_count) { |
| 93 | UNIMPLEMENTED_MSG("Page count does not match"); | 93 | UNIMPLEMENTED_MSG("Page count does not match"); |
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 28939c93c..553a56327 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h | |||
| @@ -24,12 +24,11 @@ class KSharedMemory final | |||
| 24 | KERNEL_AUTOOBJECT_TRAITS(KSharedMemory, KAutoObject); | 24 | KERNEL_AUTOOBJECT_TRAITS(KSharedMemory, KAutoObject); |
| 25 | 25 | ||
| 26 | public: | 26 | public: |
| 27 | explicit KSharedMemory(KernelCore& kernel); | 27 | explicit KSharedMemory(KernelCore& kernel_); |
| 28 | ~KSharedMemory() override; | 28 | ~KSharedMemory() override; |
| 29 | 29 | ||
| 30 | ResultCode Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, | 30 | ResultCode Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, |
| 31 | KProcess* owner_process_, KPageLinkedList&& page_list_, | 31 | KPageLinkedList&& page_list_, Svc::MemoryPermission owner_permission_, |
| 32 | Svc::MemoryPermission owner_permission_, | ||
| 33 | Svc::MemoryPermission user_permission_, PAddr physical_address_, | 32 | Svc::MemoryPermission user_permission_, PAddr physical_address_, |
| 34 | std::size_t size_, std::string name_); | 33 | std::size_t size_, std::string name_); |
| 35 | 34 | ||
| @@ -37,19 +36,19 @@ public: | |||
| 37 | * Maps a shared memory block to an address in the target process' address space | 36 | * Maps a shared memory block to an address in the target process' address space |
| 38 | * @param target_process Process on which to map the memory block | 37 | * @param target_process Process on which to map the memory block |
| 39 | * @param address Address in system memory to map shared memory block to | 38 | * @param address Address in system memory to map shared memory block to |
| 40 | * @param size Size of the shared memory block to map | 39 | * @param map_size Size of the shared memory block to map |
| 41 | * @param permissions Memory block map permissions (specified by SVC field) | 40 | * @param permissions Memory block map permissions (specified by SVC field) |
| 42 | */ | 41 | */ |
| 43 | ResultCode Map(KProcess& target_process, VAddr address, std::size_t size, | 42 | ResultCode Map(KProcess& target_process, VAddr address, std::size_t map_size, |
| 44 | Svc::MemoryPermission permissions); | 43 | Svc::MemoryPermission permissions); |
| 45 | 44 | ||
| 46 | /** | 45 | /** |
| 47 | * Unmaps a shared memory block from an address in the target process' address space | 46 | * Unmaps a shared memory block from an address in the target process' address space |
| 48 | * @param target_process Process on which to unmap the memory block | 47 | * @param target_process Process on which to unmap the memory block |
| 49 | * @param address Address in system memory to unmap shared memory block | 48 | * @param address Address in system memory to unmap shared memory block |
| 50 | * @param size Size of the shared memory block to unmap | 49 | * @param unmap_size Size of the shared memory block to unmap |
| 51 | */ | 50 | */ |
| 52 | ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t size); | 51 | ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size); |
| 53 | 52 | ||
| 54 | /** | 53 | /** |
| 55 | * Gets a pointer to the shared memory block | 54 | * Gets a pointer to the shared memory block |
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 460b8a714..45380dea0 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp | |||
| @@ -18,18 +18,18 @@ void KSynchronizationObject::Finalize() { | |||
| 18 | KAutoObject::Finalize(); | 18 | KAutoObject::Finalize(); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | 21 | ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, |
| 22 | KSynchronizationObject** objects, const s32 num_objects, | 22 | KSynchronizationObject** objects, const s32 num_objects, |
| 23 | s64 timeout) { | 23 | s64 timeout) { |
| 24 | // Allocate space on stack for thread nodes. | 24 | // Allocate space on stack for thread nodes. |
| 25 | std::vector<ThreadListNode> thread_nodes(num_objects); | 25 | std::vector<ThreadListNode> thread_nodes(num_objects); |
| 26 | 26 | ||
| 27 | // Prepare for wait. | 27 | // Prepare for wait. |
| 28 | KThread* thread = kernel.CurrentScheduler()->GetCurrentThread(); | 28 | KThread* thread = kernel_ctx.CurrentScheduler()->GetCurrentThread(); |
| 29 | 29 | ||
| 30 | { | 30 | { |
| 31 | // Setup the scheduling lock and sleep. | 31 | // Setup the scheduling lock and sleep. |
| 32 | KScopedSchedulerLockAndSleep slp{kernel, thread, timeout}; | 32 | KScopedSchedulerLockAndSleep slp{kernel_ctx, thread, timeout}; |
| 33 | 33 | ||
| 34 | // Check if any of the objects are already signaled. | 34 | // Check if any of the objects are already signaled. |
| 35 | for (auto i = 0; i < num_objects; ++i) { | 35 | for (auto i = 0; i < num_objects; ++i) { |
| @@ -94,13 +94,13 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | |||
| 94 | thread->SetWaitObjectsForDebugging({}); | 94 | thread->SetWaitObjectsForDebugging({}); |
| 95 | 95 | ||
| 96 | // Cancel the timer as needed. | 96 | // Cancel the timer as needed. |
| 97 | kernel.TimeManager().UnscheduleTimeEvent(thread); | 97 | kernel_ctx.TimeManager().UnscheduleTimeEvent(thread); |
| 98 | 98 | ||
| 99 | // Get the wait result. | 99 | // Get the wait result. |
| 100 | ResultCode wait_result{RESULT_SUCCESS}; | 100 | ResultCode wait_result{RESULT_SUCCESS}; |
| 101 | s32 sync_index = -1; | 101 | s32 sync_index = -1; |
| 102 | { | 102 | { |
| 103 | KScopedSchedulerLock lock(kernel); | 103 | KScopedSchedulerLock lock(kernel_ctx); |
| 104 | KSynchronizationObject* synced_obj; | 104 | KSynchronizationObject* synced_obj; |
| 105 | wait_result = thread->GetWaitResult(std::addressof(synced_obj)); | 105 | wait_result = thread->GetWaitResult(std::addressof(synced_obj)); |
| 106 | 106 | ||
| @@ -135,7 +135,8 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, | |||
| 135 | return wait_result; | 135 | return wait_result; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : KAutoObjectWithList{kernel} {} | 138 | KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_) |
| 139 | : KAutoObjectWithList{kernel_} {} | ||
| 139 | 140 | ||
| 140 | KSynchronizationObject::~KSynchronizationObject() = default; | 141 | KSynchronizationObject::~KSynchronizationObject() = default; |
| 141 | 142 | ||
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index ef6dfeeca..e3f08f256 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -60,8 +60,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, | |||
| 60 | 60 | ||
| 61 | namespace Kernel { | 61 | namespace Kernel { |
| 62 | 62 | ||
| 63 | KThread::KThread(KernelCore& kernel) | 63 | KThread::KThread(KernelCore& kernel_) |
| 64 | : KAutoObjectWithSlabHeapAndContainer{kernel}, activity_pause_lock{kernel} {} | 64 | : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {} |
| 65 | KThread::~KThread() = default; | 65 | KThread::~KThread() = default; |
| 66 | 66 | ||
| 67 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, | 67 | ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, |
| @@ -479,7 +479,7 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m | |||
| 479 | return RESULT_SUCCESS; | 479 | return RESULT_SUCCESS; |
| 480 | } | 480 | } |
| 481 | 481 | ||
| 482 | ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | 482 | ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) { |
| 483 | ASSERT(parent != nullptr); | 483 | ASSERT(parent != nullptr); |
| 484 | ASSERT(v_affinity_mask != 0); | 484 | ASSERT(v_affinity_mask != 0); |
| 485 | KScopedLightLock lk{activity_pause_lock}; | 485 | KScopedLightLock lk{activity_pause_lock}; |
| @@ -491,18 +491,18 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 491 | ASSERT(num_core_migration_disables >= 0); | 491 | ASSERT(num_core_migration_disables >= 0); |
| 492 | 492 | ||
| 493 | // If the core id is no-update magic, preserve the ideal core id. | 493 | // If the core id is no-update magic, preserve the ideal core id. |
| 494 | if (core_id == Svc::IdealCoreNoUpdate) { | 494 | if (cpu_core_id == Svc::IdealCoreNoUpdate) { |
| 495 | core_id = virtual_ideal_core_id; | 495 | cpu_core_id = virtual_ideal_core_id; |
| 496 | R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, ResultInvalidCombination); | 496 | R_UNLESS(((1ULL << cpu_core_id) & v_affinity_mask) != 0, ResultInvalidCombination); |
| 497 | } | 497 | } |
| 498 | 498 | ||
| 499 | // Set the virtual core/affinity mask. | 499 | // Set the virtual core/affinity mask. |
| 500 | virtual_ideal_core_id = core_id; | 500 | virtual_ideal_core_id = cpu_core_id; |
| 501 | virtual_affinity_mask = v_affinity_mask; | 501 | virtual_affinity_mask = v_affinity_mask; |
| 502 | 502 | ||
| 503 | // Translate the virtual core to a physical core. | 503 | // Translate the virtual core to a physical core. |
| 504 | if (core_id >= 0) { | 504 | if (cpu_core_id >= 0) { |
| 505 | core_id = Core::Hardware::VirtualToPhysicalCoreMap[core_id]; | 505 | cpu_core_id = Core::Hardware::VirtualToPhysicalCoreMap[cpu_core_id]; |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | // Translate the virtual affinity mask to a physical one. | 508 | // Translate the virtual affinity mask to a physical one. |
| @@ -517,7 +517,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 517 | const KAffinityMask old_mask = physical_affinity_mask; | 517 | const KAffinityMask old_mask = physical_affinity_mask; |
| 518 | 518 | ||
| 519 | // Set our new ideals. | 519 | // Set our new ideals. |
| 520 | physical_ideal_core_id = core_id; | 520 | physical_ideal_core_id = cpu_core_id; |
| 521 | physical_affinity_mask.SetAffinityMask(p_affinity_mask); | 521 | physical_affinity_mask.SetAffinityMask(p_affinity_mask); |
| 522 | 522 | ||
| 523 | if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { | 523 | if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { |
| @@ -535,7 +535,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { | |||
| 535 | } | 535 | } |
| 536 | } else { | 536 | } else { |
| 537 | // Otherwise, we edit the original affinity for restoration later. | 537 | // Otherwise, we edit the original affinity for restoration later. |
| 538 | original_physical_ideal_core_id = core_id; | 538 | original_physical_ideal_core_id = cpu_core_id; |
| 539 | original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); | 539 | original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); |
| 540 | } | 540 | } |
| 541 | } | 541 | } |
| @@ -851,8 +851,8 @@ void KThread::RemoveWaiterImpl(KThread* thread) { | |||
| 851 | thread->SetLockOwner(nullptr); | 851 | thread->SetLockOwner(nullptr); |
| 852 | } | 852 | } |
| 853 | 853 | ||
| 854 | void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | 854 | void KThread::RestorePriority(KernelCore& kernel_ctx, KThread* thread) { |
| 855 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 855 | ASSERT(kernel_ctx.GlobalSchedulerContext().IsLocked()); |
| 856 | 856 | ||
| 857 | while (true) { | 857 | while (true) { |
| 858 | // We want to inherit priority where possible. | 858 | // We want to inherit priority where possible. |
| @@ -868,7 +868,7 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | |||
| 868 | 868 | ||
| 869 | // Ensure we don't violate condition variable red black tree invariants. | 869 | // Ensure we don't violate condition variable red black tree invariants. |
| 870 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { | 870 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { |
| 871 | BeforeUpdatePriority(kernel, cv_tree, thread); | 871 | BeforeUpdatePriority(kernel_ctx, cv_tree, thread); |
| 872 | } | 872 | } |
| 873 | 873 | ||
| 874 | // Change the priority. | 874 | // Change the priority. |
| @@ -877,11 +877,11 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { | |||
| 877 | 877 | ||
| 878 | // Restore the condition variable, if relevant. | 878 | // Restore the condition variable, if relevant. |
| 879 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { | 879 | if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { |
| 880 | AfterUpdatePriority(kernel, cv_tree, thread); | 880 | AfterUpdatePriority(kernel_ctx, cv_tree, thread); |
| 881 | } | 881 | } |
| 882 | 882 | ||
| 883 | // Update the scheduler. | 883 | // Update the scheduler. |
| 884 | KScheduler::OnThreadPriorityChanged(kernel, thread, old_priority); | 884 | KScheduler::OnThreadPriorityChanged(kernel_ctx, thread, old_priority); |
| 885 | 885 | ||
| 886 | // Keep the lock owner up to date. | 886 | // Keep the lock owner up to date. |
| 887 | KThread* lock_owner = thread->GetLockOwner(); | 887 | KThread* lock_owner = thread->GetLockOwner(); |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 4145ef56c..4abfc2b49 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -111,7 +111,7 @@ public: | |||
| 111 | static constexpr s32 DefaultThreadPriority = 44; | 111 | static constexpr s32 DefaultThreadPriority = 44; |
| 112 | static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; | 112 | static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; |
| 113 | 113 | ||
| 114 | explicit KThread(KernelCore& kernel); | 114 | explicit KThread(KernelCore& kernel_); |
| 115 | ~KThread() override; | 115 | ~KThread() override; |
| 116 | 116 | ||
| 117 | public: | 117 | public: |
| @@ -318,7 +318,7 @@ public: | |||
| 318 | 318 | ||
| 319 | [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); | 319 | [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); |
| 320 | 320 | ||
| 321 | [[nodiscard]] ResultCode SetCoreMask(s32 core_id, u64 v_affinity_mask); | 321 | [[nodiscard]] ResultCode SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); |
| 322 | 322 | ||
| 323 | [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); | 323 | [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); |
| 324 | 324 | ||
| @@ -649,7 +649,7 @@ private: | |||
| 649 | std::function<void(void*)>&& init_func, | 649 | std::function<void(void*)>&& init_func, |
| 650 | void* init_func_parameter); | 650 | void* init_func_parameter); |
| 651 | 651 | ||
| 652 | static void RestorePriority(KernelCore& kernel, KThread* thread); | 652 | static void RestorePriority(KernelCore& kernel_ctx, KThread* thread); |
| 653 | 653 | ||
| 654 | // For core KThread implementation | 654 | // For core KThread implementation |
| 655 | ThreadContext32 thread_context_32{}; | 655 | ThreadContext32 thread_context_32{}; |
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index 201617d32..5bc33706d 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | 11 | ||
| 12 | KTransferMemory::KTransferMemory(KernelCore& kernel) | 12 | KTransferMemory::KTransferMemory(KernelCore& kernel_) |
| 13 | : KAutoObjectWithSlabHeapAndContainer{kernel} {} | 13 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 14 | 14 | ||
| 15 | KTransferMemory::~KTransferMemory() = default; | 15 | KTransferMemory::~KTransferMemory() = default; |
| 16 | 16 | ||
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index f56398b9c..838fd2b18 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h | |||
| @@ -26,7 +26,7 @@ class KTransferMemory final | |||
| 26 | KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject); | 26 | KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject); |
| 27 | 27 | ||
| 28 | public: | 28 | public: |
| 29 | explicit KTransferMemory(KernelCore& kernel); | 29 | explicit KTransferMemory(KernelCore& kernel_); |
| 30 | virtual ~KTransferMemory() override; | 30 | virtual ~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_); |
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp index a430e0661..b7b83c151 100644 --- a/src/core/hle/kernel/k_writable_event.cpp +++ b/src/core/hle/kernel/k_writable_event.cpp | |||
| @@ -8,7 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | KWritableEvent::KWritableEvent(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} | 11 | KWritableEvent::KWritableEvent(KernelCore& kernel_) |
| 12 | : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||
| 12 | 13 | ||
| 13 | KWritableEvent::~KWritableEvent() = default; | 14 | KWritableEvent::~KWritableEvent() = default; |
| 14 | 15 | ||
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h index 154d2382c..607b0eadb 100644 --- a/src/core/hle/kernel/k_writable_event.h +++ b/src/core/hle/kernel/k_writable_event.h | |||
| @@ -18,7 +18,7 @@ class KWritableEvent final | |||
| 18 | KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); | 18 | KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); |
| 19 | 19 | ||
| 20 | public: | 20 | 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 | virtual void Destroy() override; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 32bbf2d9b..8b55df82e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include "core/hle/kernel/time_manager.h" | 44 | #include "core/hle/kernel/time_manager.h" |
| 45 | #include "core/hle/lock.h" | 45 | #include "core/hle/lock.h" |
| 46 | #include "core/hle/result.h" | 46 | #include "core/hle/result.h" |
| 47 | #include "core/hle/service/sm/sm.h" | ||
| 47 | #include "core/memory.h" | 48 | #include "core/memory.h" |
| 48 | 49 | ||
| 49 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | 50 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); |
| @@ -51,11 +52,11 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | |||
| 51 | namespace Kernel { | 52 | namespace Kernel { |
| 52 | 53 | ||
| 53 | struct KernelCore::Impl { | 54 | struct KernelCore::Impl { |
| 54 | explicit Impl(Core::System& system, KernelCore& kernel) | 55 | explicit Impl(Core::System& system_, KernelCore& kernel_) |
| 55 | : time_manager{system}, object_list_container{kernel}, system{system} {} | 56 | : time_manager{system_}, object_list_container{kernel_}, system{system_} {} |
| 56 | 57 | ||
| 57 | void SetMulticore(bool is_multicore) { | 58 | void SetMulticore(bool is_multi) { |
| 58 | this->is_multicore = is_multicore; | 59 | is_multicore = is_multi; |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | void Initialize(KernelCore& kernel) { | 62 | void Initialize(KernelCore& kernel) { |
| @@ -599,19 +600,19 @@ struct KernelCore::Impl { | |||
| 599 | irs_shared_mem = KSharedMemory::Create(system.Kernel()); | 600 | irs_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 600 | time_shared_mem = KSharedMemory::Create(system.Kernel()); | 601 | time_shared_mem = KSharedMemory::Create(system.Kernel()); |
| 601 | 602 | ||
| 602 | hid_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, | 603 | hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 603 | {hid_phys_addr, hid_size / PageSize}, | 604 | {hid_phys_addr, hid_size / PageSize}, |
| 604 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, | 605 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 605 | hid_phys_addr, hid_size, "HID:SharedMemory"); | 606 | hid_phys_addr, hid_size, "HID:SharedMemory"); |
| 606 | font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, | 607 | font_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 607 | {font_phys_addr, font_size / PageSize}, | 608 | {font_phys_addr, font_size / PageSize}, |
| 608 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, | 609 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 609 | font_phys_addr, font_size, "Font:SharedMemory"); | 610 | font_phys_addr, font_size, "Font:SharedMemory"); |
| 610 | irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, | 611 | irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 611 | {irs_phys_addr, irs_size / PageSize}, | 612 | {irs_phys_addr, irs_size / PageSize}, |
| 612 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, | 613 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 613 | irs_phys_addr, irs_size, "IRS:SharedMemory"); | 614 | irs_phys_addr, irs_size, "IRS:SharedMemory"); |
| 614 | time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, | 615 | time_shared_mem->Initialize(system.DeviceMemory(), nullptr, |
| 615 | {time_phys_addr, time_size / PageSize}, | 616 | {time_phys_addr, time_size / PageSize}, |
| 616 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, | 617 | Svc::MemoryPermission::None, Svc::MemoryPermission::Read, |
| 617 | time_phys_addr, time_size, "Time:SharedMemory"); | 618 | time_phys_addr, time_size, "Time:SharedMemory"); |
| @@ -656,6 +657,7 @@ struct KernelCore::Impl { | |||
| 656 | 657 | ||
| 657 | /// Map of named ports managed by the kernel, which can be retrieved using | 658 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 658 | /// the ConnectToPort SVC. | 659 | /// the ConnectToPort SVC. |
| 660 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; | ||
| 659 | NamedPortTable named_ports; | 661 | NamedPortTable named_ports; |
| 660 | 662 | ||
| 661 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 663 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| @@ -844,18 +846,17 @@ void KernelCore::PrepareReschedule(std::size_t id) { | |||
| 844 | // TODO: Reimplement, this | 846 | // TODO: Reimplement, this |
| 845 | } | 847 | } |
| 846 | 848 | ||
| 847 | void KernelCore::AddNamedPort(std::string name, KClientPort* port) { | 849 | void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) { |
| 848 | port->Open(); | 850 | impl->service_interface_factory.emplace(std::move(name), factory); |
| 849 | impl->named_ports.emplace(std::move(name), port); | ||
| 850 | } | 851 | } |
| 851 | 852 | ||
| 852 | KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) { | 853 | KClientPort* KernelCore::CreateNamedServicePort(std::string name) { |
| 853 | return impl->named_ports.find(name); | 854 | auto search = impl->service_interface_factory.find(name); |
| 854 | } | 855 | if (search == impl->service_interface_factory.end()) { |
| 855 | 856 | UNIMPLEMENTED(); | |
| 856 | KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort( | 857 | return {}; |
| 857 | const std::string& name) const { | 858 | } |
| 858 | return impl->named_ports.find(name); | 859 | return &search->second(impl->system.ServiceManager(), impl->system); |
| 859 | } | 860 | } |
| 860 | 861 | ||
| 861 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 862 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 51aaccbc7..2d01e1ae0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -27,6 +27,10 @@ class CoreTiming; | |||
| 27 | struct EventType; | 27 | struct EventType; |
| 28 | } // namespace Core::Timing | 28 | } // namespace Core::Timing |
| 29 | 29 | ||
| 30 | namespace Service::SM { | ||
| 31 | class ServiceManager; | ||
| 32 | } | ||
| 33 | |||
| 30 | namespace Kernel { | 34 | namespace Kernel { |
| 31 | 35 | ||
| 32 | class KClientPort; | 36 | class KClientPort; |
| @@ -51,6 +55,9 @@ class ServiceThread; | |||
| 51 | class Synchronization; | 55 | class Synchronization; |
| 52 | class TimeManager; | 56 | class TimeManager; |
| 53 | 57 | ||
| 58 | using ServiceInterfaceFactory = | ||
| 59 | std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; | ||
| 60 | |||
| 54 | namespace Init { | 61 | namespace Init { |
| 55 | struct KSlabResourceCounts; | 62 | struct KSlabResourceCounts; |
| 56 | } | 63 | } |
| @@ -172,14 +179,11 @@ public: | |||
| 172 | 179 | ||
| 173 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | 180 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); |
| 174 | 181 | ||
| 175 | /// Adds a port to the named port table | 182 | /// Registers a named HLE service, passing a factory used to open a port to that service. |
| 176 | void AddNamedPort(std::string name, KClientPort* port); | 183 | void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory); |
| 177 | |||
| 178 | /// Finds a port within the named port table with the given name. | ||
| 179 | NamedPortTable::iterator FindNamedPort(const std::string& name); | ||
| 180 | 184 | ||
| 181 | /// Finds a port within the named port table with the given name. | 185 | /// Opens a port to a service previously registered with RegisterNamedService. |
| 182 | NamedPortTable::const_iterator FindNamedPort(const std::string& name) const; | 186 | KClientPort* CreateNamedServicePort(std::string name); |
| 183 | 187 | ||
| 184 | /// Determines whether or not the given port is a valid named port. | 188 | /// Determines whether or not the given port is a valid named port. |
| 185 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 189 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h index 0c5995db0..d0f7f084b 100644 --- a/src/core/hle/kernel/slab_helpers.h +++ b/src/core/hle/kernel/slab_helpers.h | |||
| @@ -67,11 +67,11 @@ class KAutoObjectWithSlabHeapAndContainer : public Base { | |||
| 67 | 67 | ||
| 68 | private: | 68 | private: |
| 69 | static Derived* Allocate(KernelCore& kernel) { | 69 | static Derived* Allocate(KernelCore& kernel) { |
| 70 | return kernel.SlabHeap<Derived>().AllocateWithKernel(kernel); | 70 | return new Derived(kernel); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static void Free(KernelCore& kernel, Derived* obj) { | 73 | static void Free(KernelCore& kernel, Derived* obj) { |
| 74 | kernel.SlabHeap<Derived>().Free(obj); | 74 | delete obj; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | public: | 77 | public: |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 52011be9c..6b445677e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -284,12 +284,11 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr po | |||
| 284 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 284 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 285 | 285 | ||
| 286 | // Find the client port. | 286 | // Find the client port. |
| 287 | const auto it = kernel.FindNamedPort(port_name); | 287 | auto port = kernel.CreateNamedServicePort(port_name); |
| 288 | if (!kernel.IsValidNamedPort(it)) { | 288 | if (!port) { |
| 289 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); | 289 | LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name); |
| 290 | return ResultNotFound; | 290 | return ResultNotFound; |
| 291 | } | 291 | } |
| 292 | auto port = it->second; | ||
| 293 | 292 | ||
| 294 | // Reserve a handle for the port. | 293 | // Reserve a handle for the port. |
| 295 | // NOTE: Nintendo really does write directly to the output handle here. | 294 | // NOTE: Nintendo really does write directly to the output handle here. |
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp deleted file mode 100644 index 1dd65468d..000000000 --- a/src/core/hle/kernel/transfer_memory.cpp +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_page_table.h" | ||
| 6 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | ||
| 8 | #include "core/hle/kernel/process.h" | ||
| 9 | #include "core/hle/kernel/transfer_memory.h" | ||
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "core/memory.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | TransferMemory::TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory) | ||
| 16 | : Object{kernel}, memory{memory} {} | ||
| 17 | |||
| 18 | TransferMemory::~TransferMemory() { | ||
| 19 | // Release memory region when transfer memory is destroyed | ||
| 20 | Reset(); | ||
| 21 | owner_process->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); | ||
| 22 | } | ||
| 23 | |||
| 24 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, | ||
| 25 | Core::Memory::Memory& memory, | ||
| 26 | VAddr base_address, std::size_t size, | ||
| 27 | KMemoryPermission permissions) { | ||
| 28 | std::shared_ptr<TransferMemory> transfer_memory{ | ||
| 29 | std::make_shared<TransferMemory>(kernel, memory)}; | ||
| 30 | |||
| 31 | transfer_memory->base_address = base_address; | ||
| 32 | transfer_memory->size = size; | ||
| 33 | transfer_memory->owner_permissions = permissions; | ||
| 34 | transfer_memory->owner_process = kernel.CurrentProcess(); | ||
| 35 | |||
| 36 | return transfer_memory; | ||
| 37 | } | ||
| 38 | |||
| 39 | u8* TransferMemory::GetPointer() { | ||
| 40 | return memory.GetPointer(base_address); | ||
| 41 | } | ||
| 42 | |||
| 43 | const u8* TransferMemory::GetPointer() const { | ||
| 44 | return memory.GetPointer(base_address); | ||
| 45 | } | ||
| 46 | |||
| 47 | ResultCode TransferMemory::Reserve() { | ||
| 48 | return owner_process->PageTable().ReserveTransferMemory(base_address, size, owner_permissions); | ||
| 49 | } | ||
| 50 | |||
| 51 | ResultCode TransferMemory::Reset() { | ||
| 52 | return owner_process->PageTable().ResetTransferMemory(base_address, size); | ||
| 53 | } | ||
| 54 | |||
| 55 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h deleted file mode 100644 index 59328c0fe..000000000 --- a/src/core/hle/kernel/transfer_memory.h +++ /dev/null | |||
| @@ -1,96 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "core/hle/kernel/k_memory_block.h" | ||
| 10 | #include "core/hle/kernel/object.h" | ||
| 11 | #include "core/hle/kernel/physical_memory.h" | ||
| 12 | |||
| 13 | union ResultCode; | ||
| 14 | |||
| 15 | namespace Core::Memory { | ||
| 16 | class Memory; | ||
| 17 | } | ||
| 18 | |||
| 19 | namespace Kernel { | ||
| 20 | |||
| 21 | class KernelCore; | ||
| 22 | class Process; | ||
| 23 | |||
| 24 | /// Defines the interface for transfer memory objects. | ||
| 25 | /// | ||
| 26 | /// Transfer memory is typically used for the purpose of | ||
| 27 | /// transferring memory between separate process instances, | ||
| 28 | /// thus the name. | ||
| 29 | /// | ||
| 30 | class TransferMemory final : public Object { | ||
| 31 | public: | ||
| 32 | explicit TransferMemory(KernelCore& kernel, Core::Memory::Memory& memory); | ||
| 33 | ~TransferMemory() override; | ||
| 34 | |||
| 35 | static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; | ||
| 36 | |||
| 37 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory, | ||
| 38 | VAddr base_address, std::size_t size, | ||
| 39 | KMemoryPermission permissions); | ||
| 40 | |||
| 41 | TransferMemory(const TransferMemory&) = delete; | ||
| 42 | TransferMemory& operator=(const TransferMemory&) = delete; | ||
| 43 | |||
| 44 | TransferMemory(TransferMemory&&) = delete; | ||
| 45 | TransferMemory& operator=(TransferMemory&&) = delete; | ||
| 46 | |||
| 47 | std::string GetTypeName() const override { | ||
| 48 | return "TransferMemory"; | ||
| 49 | } | ||
| 50 | |||
| 51 | std::string GetName() const override { | ||
| 52 | return GetTypeName(); | ||
| 53 | } | ||
| 54 | |||
| 55 | HandleType GetHandleType() const override { | ||
| 56 | return HANDLE_TYPE; | ||
| 57 | } | ||
| 58 | |||
| 59 | /// Gets a pointer to the backing block of this instance. | ||
| 60 | u8* GetPointer(); | ||
| 61 | |||
| 62 | /// Gets a pointer to the backing block of this instance. | ||
| 63 | const u8* GetPointer() const; | ||
| 64 | |||
| 65 | /// Gets the size of the memory backing this instance in bytes. | ||
| 66 | constexpr std::size_t GetSize() const { | ||
| 67 | return size; | ||
| 68 | } | ||
| 69 | |||
| 70 | /// Reserves the region to be used for the transfer memory, called after the transfer memory is | ||
| 71 | /// created. | ||
| 72 | ResultCode Reserve(); | ||
| 73 | |||
| 74 | /// Resets the region previously used for the transfer memory, called after the transfer memory | ||
| 75 | /// is closed. | ||
| 76 | ResultCode Reset(); | ||
| 77 | |||
| 78 | void Finalize() override {} | ||
| 79 | |||
| 80 | private: | ||
| 81 | /// The base address for the memory managed by this instance. | ||
| 82 | VAddr base_address{}; | ||
| 83 | |||
| 84 | /// Size of the memory, in bytes, that this instance manages. | ||
| 85 | std::size_t size{}; | ||
| 86 | |||
| 87 | /// The memory permissions that are applied to this instance. | ||
| 88 | KMemoryPermission owner_permissions{}; | ||
| 89 | |||
| 90 | /// The process that this transfer memory instance was created under. | ||
| 91 | Process* owner_process{}; | ||
| 92 | |||
| 93 | Core::Memory::Memory& memory; | ||
| 94 | }; | ||
| 95 | |||
| 96 | } // namespace Kernel | ||
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 513bd3730..65887011f 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -169,10 +169,9 @@ private: | |||
| 169 | 169 | ||
| 170 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 170 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
| 171 | public: | 171 | public: |
| 172 | explicit IAudioDevice(Core::System& system_, u32_le revision_num) | 172 | explicit IAudioDevice(Core::System& system_, Kernel::KEvent& buffer_event_, u32_le revision_) |
| 173 | : ServiceFramework{system_, "IAudioDevice"}, revision{revision_num}, | 173 | : ServiceFramework{system_, "IAudioDevice"}, buffer_event{buffer_event_}, revision{ |
| 174 | buffer_event{system.Kernel()}, audio_input_device_switch_event{system.Kernel()}, | 174 | revision_} { |
| 175 | audio_output_device_switch_event{system.Kernel()} { | ||
| 176 | static const FunctionInfo functions[] = { | 175 | static const FunctionInfo functions[] = { |
| 177 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, | 176 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, |
| 178 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, | 177 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, |
| @@ -189,18 +188,6 @@ public: | |||
| 189 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, | 188 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, |
| 190 | }; | 189 | }; |
| 191 | RegisterHandlers(functions); | 190 | RegisterHandlers(functions); |
| 192 | |||
| 193 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); | ||
| 194 | buffer_event.Initialize("IAudioOutBufferReleasedEvent"); | ||
| 195 | |||
| 196 | // Should be similar to audio_output_device_switch_event | ||
| 197 | Kernel::KAutoObject::Create(std::addressof(audio_input_device_switch_event)); | ||
| 198 | audio_input_device_switch_event.Initialize("IAudioDevice:AudioInputDeviceSwitchedEvent"); | ||
| 199 | |||
| 200 | // Should only be signalled when an audio output device has been changed, example: speaker | ||
| 201 | // to headset | ||
| 202 | Kernel::KAutoObject::Create(std::addressof(audio_output_device_switch_event)); | ||
| 203 | audio_output_device_switch_event.Initialize("IAudioDevice:AudioOutputDeviceSwitchedEvent"); | ||
| 204 | } | 191 | } |
| 205 | 192 | ||
| 206 | private: | 193 | private: |
| @@ -310,7 +297,7 @@ private: | |||
| 310 | 297 | ||
| 311 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 298 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 312 | rb.Push(RESULT_SUCCESS); | 299 | rb.Push(RESULT_SUCCESS); |
| 313 | rb.PushCopyObjects(audio_input_device_switch_event.GetReadableEvent()); | 300 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 314 | } | 301 | } |
| 315 | 302 | ||
| 316 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { | 303 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { |
| @@ -318,17 +305,16 @@ private: | |||
| 318 | 305 | ||
| 319 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 306 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 320 | rb.Push(RESULT_SUCCESS); | 307 | rb.Push(RESULT_SUCCESS); |
| 321 | rb.PushCopyObjects(audio_output_device_switch_event.GetReadableEvent()); | 308 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 322 | } | 309 | } |
| 323 | 310 | ||
| 311 | Kernel::KEvent& buffer_event; | ||
| 324 | u32_le revision = 0; | 312 | u32_le revision = 0; |
| 325 | Kernel::KEvent buffer_event; | 313 | }; |
| 326 | Kernel::KEvent audio_input_device_switch_event; | ||
| 327 | Kernel::KEvent audio_output_device_switch_event; | ||
| 328 | 314 | ||
| 329 | }; // namespace Audio | 315 | AudRenU::AudRenU(Core::System& system_) |
| 316 | : ServiceFramework{system_, "audren:u"}, buffer_event{system.Kernel()} { | ||
| 330 | 317 | ||
| 331 | AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} { | ||
| 332 | // clang-format off | 318 | // clang-format off |
| 333 | static const FunctionInfo functions[] = { | 319 | static const FunctionInfo functions[] = { |
| 334 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, | 320 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, |
| @@ -340,6 +326,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} | |||
| 340 | // clang-format on | 326 | // clang-format on |
| 341 | 327 | ||
| 342 | RegisterHandlers(functions); | 328 | RegisterHandlers(functions); |
| 329 | |||
| 330 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); | ||
| 331 | buffer_event.Initialize("IAudioOutBufferReleasedEvent"); | ||
| 343 | } | 332 | } |
| 344 | 333 | ||
| 345 | AudRenU::~AudRenU() = default; | 334 | AudRenU::~AudRenU() = default; |
| @@ -662,7 +651,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { | |||
| 662 | // always assumes the initial release revision (REV1). | 651 | // always assumes the initial release revision (REV1). |
| 663 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 652 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 664 | rb.Push(RESULT_SUCCESS); | 653 | rb.Push(RESULT_SUCCESS); |
| 665 | rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); | 654 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, Common::MakeMagic('R', 'E', 'V', '1')); |
| 666 | } | 655 | } |
| 667 | 656 | ||
| 668 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { | 657 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { |
| @@ -684,7 +673,7 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c | |||
| 684 | 673 | ||
| 685 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 674 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 686 | rb.Push(RESULT_SUCCESS); | 675 | rb.Push(RESULT_SUCCESS); |
| 687 | rb.PushIpcInterface<IAudioDevice>(system, revision); | 676 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, revision); |
| 688 | } | 677 | } |
| 689 | 678 | ||
| 690 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { | 679 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 37e8b4716..0ee6f9542 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -31,6 +32,7 @@ private: | |||
| 31 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); | 32 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); |
| 32 | 33 | ||
| 33 | std::size_t audren_instance_count = 0; | 34 | std::size_t audren_instance_count = 0; |
| 35 | Kernel::KEvent buffer_event; | ||
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | // Describes a particular audio feature that may be supported in a particular revision. | 38 | // Describes a particular audio feature that may be supported in a particular revision. |
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index bb77d8959..9e5df3bb7 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/math_util.h" | ||
| 8 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 9 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 10 | #include "core/frontend/emu_window.h" | 9 | #include "core/frontend/emu_window.h" |
| @@ -12,10 +11,19 @@ | |||
| 12 | 11 | ||
| 13 | namespace Service::HID { | 12 | namespace Service::HID { |
| 14 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; | 13 | constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; |
| 15 | constexpr f32 angle_threshold = 0.08f; | ||
| 16 | constexpr f32 pinch_threshold = 100.0f; | ||
| 17 | 14 | ||
| 18 | Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase{system_} {} | 15 | // HW is around 700, value is set to 400 to make it easier to trigger with mouse |
| 16 | constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s | ||
| 17 | constexpr f32 angle_threshold = 0.015f; // Threshold in radians | ||
| 18 | constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels | ||
| 19 | constexpr f32 press_delay = 0.5f; // Time in seconds | ||
| 20 | constexpr f32 double_tap_delay = 0.35f; // Time in seconds | ||
| 21 | |||
| 22 | constexpr f32 Square(s32 num) { | ||
| 23 | return static_cast<f32>(num * num); | ||
| 24 | } | ||
| 25 | |||
| 26 | Controller_Gesture::Controller_Gesture(Core::System& system) : ControllerBase(system) {} | ||
| 19 | Controller_Gesture::~Controller_Gesture() = default; | 27 | Controller_Gesture::~Controller_Gesture() = default; |
| 20 | 28 | ||
| 21 | void Controller_Gesture::OnInit() { | 29 | void Controller_Gesture::OnInit() { |
| @@ -24,6 +32,8 @@ void Controller_Gesture::OnInit() { | |||
| 24 | keyboard_finger_id[id] = MAX_POINTS; | 32 | keyboard_finger_id[id] = MAX_POINTS; |
| 25 | udp_finger_id[id] = MAX_POINTS; | 33 | udp_finger_id[id] = MAX_POINTS; |
| 26 | } | 34 | } |
| 35 | shared_memory.header.entry_count = 0; | ||
| 36 | force_update = true; | ||
| 27 | } | 37 | } |
| 28 | 38 | ||
| 29 | void Controller_Gesture::OnRelease() {} | 39 | void Controller_Gesture::OnRelease() {} |
| @@ -38,17 +48,23 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 38 | shared_memory.header.last_entry_index = 0; | 48 | shared_memory.header.last_entry_index = 0; |
| 39 | return; | 49 | return; |
| 40 | } | 50 | } |
| 41 | shared_memory.header.entry_count = 16; | ||
| 42 | 51 | ||
| 43 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 52 | ReadTouchInput(); |
| 44 | shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; | ||
| 45 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 46 | 53 | ||
| 47 | cur_entry.sampling_number = last_entry.sampling_number + 1; | 54 | GestureProperties gesture = GetGestureProperties(); |
| 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 55 | f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) / |
| 56 | (1000 * 1000 * 1000); | ||
| 49 | 57 | ||
| 50 | // TODO(german77): Implement all gesture types | 58 | // Only update if necesary |
| 59 | if (!ShouldUpdateGesture(gesture, time_difference)) { | ||
| 60 | return; | ||
| 61 | } | ||
| 51 | 62 | ||
| 63 | last_update_timestamp = shared_memory.header.timestamp; | ||
| 64 | UpdateGestureSharedMemory(data, size, gesture, time_difference); | ||
| 65 | } | ||
| 66 | |||
| 67 | void Controller_Gesture::ReadTouchInput() { | ||
| 52 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); | 68 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); |
| 53 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); | 69 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); |
| 54 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { | 70 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { |
| @@ -63,50 +79,71 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 63 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); | 79 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); |
| 64 | } | 80 | } |
| 65 | } | 81 | } |
| 82 | } | ||
| 66 | 83 | ||
| 67 | TouchType type = TouchType::Idle; | 84 | bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture, |
| 68 | Attribute attributes{}; | 85 | f32 time_difference) { |
| 69 | GestureProperties gesture = GetGestureProperties(); | 86 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 70 | if (last_gesture.active_points != gesture.active_points) { | 87 | if (force_update) { |
| 71 | ++last_gesture.detection_count; | 88 | force_update = false; |
| 89 | return true; | ||
| 72 | } | 90 | } |
| 73 | if (gesture.active_points > 0) { | ||
| 74 | if (last_gesture.active_points == 0) { | ||
| 75 | attributes.is_new_touch.Assign(true); | ||
| 76 | last_gesture.average_distance = gesture.average_distance; | ||
| 77 | last_gesture.angle = gesture.angle; | ||
| 78 | } | ||
| 79 | 91 | ||
| 80 | type = TouchType::Touch; | 92 | // Update if coordinates change |
| 81 | if (gesture.mid_point.x != last_entry.x || gesture.mid_point.y != last_entry.y) { | 93 | for (size_t id = 0; id < MAX_POINTS; id++) { |
| 82 | type = TouchType::Pan; | 94 | if (gesture.points[id].x != last_gesture.points[id].x || |
| 83 | } | 95 | gesture.points[id].y != last_gesture.points[id].y) { |
| 84 | if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) { | 96 | return true; |
| 85 | type = TouchType::Pinch; | ||
| 86 | } | ||
| 87 | if (std::abs(gesture.angle - last_gesture.angle) > angle_threshold) { | ||
| 88 | type = TouchType::Rotate; | ||
| 89 | } | 97 | } |
| 98 | } | ||
| 99 | |||
| 100 | // Update on press and hold event after 0.5 seconds | ||
| 101 | if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 && | ||
| 102 | time_difference > press_delay) { | ||
| 103 | return enable_press_and_tap; | ||
| 104 | } | ||
| 105 | |||
| 106 | return false; | ||
| 107 | } | ||
| 108 | |||
| 109 | void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size, | ||
| 110 | GestureProperties& gesture, | ||
| 111 | f32 time_difference) { | ||
| 112 | TouchType type = TouchType::Idle; | ||
| 113 | Attribute attributes{}; | ||
| 114 | |||
| 115 | const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 116 | shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17; | ||
| 117 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 90 | 118 | ||
| 91 | cur_entry.delta_x = gesture.mid_point.x - last_entry.x; | 119 | if (shared_memory.header.entry_count < 16) { |
| 92 | cur_entry.delta_y = gesture.mid_point.y - last_entry.y; | 120 | shared_memory.header.entry_count++; |
| 93 | // TODO: Find how velocities are calculated | 121 | } |
| 94 | cur_entry.vel_x = static_cast<float>(cur_entry.delta_x) * 150.1f; | ||
| 95 | cur_entry.vel_y = static_cast<float>(cur_entry.delta_y) * 150.1f; | ||
| 96 | 122 | ||
| 97 | // Slowdown the rate of change for less flapping | 123 | cur_entry.sampling_number = last_entry.sampling_number + 1; |
| 98 | last_gesture.average_distance = | 124 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 99 | (last_gesture.average_distance * 0.9f) + (gesture.average_distance * 0.1f); | ||
| 100 | last_gesture.angle = (last_gesture.angle * 0.9f) + (gesture.angle * 0.1f); | ||
| 101 | 125 | ||
| 126 | // Reset values to default | ||
| 127 | cur_entry.delta_x = 0; | ||
| 128 | cur_entry.delta_y = 0; | ||
| 129 | cur_entry.vel_x = 0; | ||
| 130 | cur_entry.vel_y = 0; | ||
| 131 | cur_entry.direction = Direction::None; | ||
| 132 | cur_entry.rotation_angle = 0; | ||
| 133 | cur_entry.scale = 0; | ||
| 134 | |||
| 135 | if (gesture.active_points > 0) { | ||
| 136 | if (last_gesture.active_points == 0) { | ||
| 137 | NewGesture(gesture, type, attributes); | ||
| 138 | } else { | ||
| 139 | UpdateExistingGesture(gesture, type, time_difference); | ||
| 140 | } | ||
| 102 | } else { | 141 | } else { |
| 103 | cur_entry.delta_x = 0; | 142 | EndGesture(gesture, last_gesture, type, attributes, time_difference); |
| 104 | cur_entry.delta_y = 0; | ||
| 105 | cur_entry.vel_x = 0; | ||
| 106 | cur_entry.vel_y = 0; | ||
| 107 | } | 143 | } |
| 108 | last_gesture.active_points = gesture.active_points; | 144 | |
| 109 | cur_entry.detection_count = last_gesture.detection_count; | 145 | // Apply attributes |
| 146 | cur_entry.detection_count = gesture.detection_count; | ||
| 110 | cur_entry.type = type; | 147 | cur_entry.type = type; |
| 111 | cur_entry.attributes = attributes; | 148 | cur_entry.attributes = attributes; |
| 112 | cur_entry.x = gesture.mid_point.x; | 149 | cur_entry.x = gesture.mid_point.x; |
| @@ -116,12 +153,190 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u | |||
| 116 | cur_entry.points[id].x = gesture.points[id].x; | 153 | cur_entry.points[id].x = gesture.points[id].x; |
| 117 | cur_entry.points[id].y = gesture.points[id].y; | 154 | cur_entry.points[id].y = gesture.points[id].y; |
| 118 | } | 155 | } |
| 119 | cur_entry.rotation_angle = 0; | 156 | last_gesture = gesture; |
| 120 | cur_entry.scale = 0; | ||
| 121 | 157 | ||
| 122 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); | 158 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); |
| 123 | } | 159 | } |
| 124 | 160 | ||
| 161 | void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type, | ||
| 162 | Attribute& attributes) { | ||
| 163 | const auto& last_entry = | ||
| 164 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 165 | gesture.detection_count++; | ||
| 166 | type = TouchType::Touch; | ||
| 167 | |||
| 168 | // New touch after cancel is not considered new | ||
| 169 | if (last_entry.type != TouchType::Cancel) { | ||
| 170 | attributes.is_new_touch.Assign(1); | ||
| 171 | enable_press_and_tap = true; | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type, | ||
| 176 | f32 time_difference) { | ||
| 177 | const auto& last_entry = | ||
| 178 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 179 | |||
| 180 | // Promote to pan type if touch moved | ||
| 181 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 182 | if (gesture.points[id].x != last_gesture.points[id].x || | ||
| 183 | gesture.points[id].y != last_gesture.points[id].y) { | ||
| 184 | type = TouchType::Pan; | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | // Number of fingers changed cancel the last event and clear data | ||
| 190 | if (gesture.active_points != last_gesture.active_points) { | ||
| 191 | type = TouchType::Cancel; | ||
| 192 | enable_press_and_tap = false; | ||
| 193 | gesture.active_points = 0; | ||
| 194 | gesture.mid_point = {}; | ||
| 195 | for (size_t id = 0; id < MAX_POINTS; id++) { | ||
| 196 | gesture.points[id].x = 0; | ||
| 197 | gesture.points[id].y = 0; | ||
| 198 | } | ||
| 199 | return; | ||
| 200 | } | ||
| 201 | |||
| 202 | // Calculate extra parameters of panning | ||
| 203 | if (type == TouchType::Pan) { | ||
| 204 | UpdatePanEvent(gesture, last_gesture, type, time_difference); | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | // Promote to press type | ||
| 209 | if (last_entry.type == TouchType::Touch) { | ||
| 210 | type = TouchType::Press; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | void Controller_Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 215 | TouchType& type, Attribute& attributes, f32 time_difference) { | ||
| 216 | const auto& last_entry = | ||
| 217 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 218 | if (last_gesture.active_points != 0) { | ||
| 219 | switch (last_entry.type) { | ||
| 220 | case TouchType::Touch: | ||
| 221 | if (enable_press_and_tap) { | ||
| 222 | SetTapEvent(gesture, last_gesture, type, attributes); | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | type = TouchType::Cancel; | ||
| 226 | force_update = true; | ||
| 227 | break; | ||
| 228 | case TouchType::Press: | ||
| 229 | case TouchType::Tap: | ||
| 230 | case TouchType::Swipe: | ||
| 231 | case TouchType::Pinch: | ||
| 232 | case TouchType::Rotate: | ||
| 233 | type = TouchType::Complete; | ||
| 234 | force_update = true; | ||
| 235 | break; | ||
| 236 | case TouchType::Pan: | ||
| 237 | EndPanEvent(gesture, last_gesture, type, time_difference); | ||
| 238 | break; | ||
| 239 | default: | ||
| 240 | break; | ||
| 241 | } | ||
| 242 | return; | ||
| 243 | } | ||
| 244 | if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) { | ||
| 245 | gesture.detection_count++; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void Controller_Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 250 | TouchType& type, Attribute& attributes) { | ||
| 251 | type = TouchType::Tap; | ||
| 252 | gesture = last_gesture; | ||
| 253 | force_update = true; | ||
| 254 | f32 tap_time_difference = | ||
| 255 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | ||
| 256 | last_tap_timestamp = last_update_timestamp; | ||
| 257 | if (tap_time_difference < double_tap_delay) { | ||
| 258 | attributes.is_double_tap.Assign(1); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 263 | TouchType& type, f32 time_difference) { | ||
| 264 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 265 | const auto& last_entry = | ||
| 266 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 267 | cur_entry.delta_x = gesture.mid_point.x - last_entry.x; | ||
| 268 | cur_entry.delta_y = gesture.mid_point.y - last_entry.y; | ||
| 269 | |||
| 270 | cur_entry.vel_x = static_cast<f32>(cur_entry.delta_x) / time_difference; | ||
| 271 | cur_entry.vel_y = static_cast<f32>(cur_entry.delta_y) / time_difference; | ||
| 272 | last_pan_time_difference = time_difference; | ||
| 273 | |||
| 274 | // Promote to pinch type | ||
| 275 | if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) { | ||
| 276 | type = TouchType::Pinch; | ||
| 277 | cur_entry.scale = gesture.average_distance / last_gesture.average_distance; | ||
| 278 | } | ||
| 279 | |||
| 280 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture.angle) / | ||
| 281 | (1 + (gesture.angle * last_gesture.angle))); | ||
| 282 | // Promote to rotate type | ||
| 283 | if (std::abs(angle_between_two_lines) > angle_threshold) { | ||
| 284 | type = TouchType::Rotate; | ||
| 285 | cur_entry.scale = 0; | ||
| 286 | cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 291 | TouchType& type, f32 time_difference) { | ||
| 292 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 293 | const auto& last_entry = | ||
| 294 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 295 | cur_entry.vel_x = | ||
| 296 | static_cast<f32>(last_entry.delta_x) / (last_pan_time_difference + time_difference); | ||
| 297 | cur_entry.vel_y = | ||
| 298 | static_cast<f32>(last_entry.delta_y) / (last_pan_time_difference + time_difference); | ||
| 299 | const f32 curr_vel = | ||
| 300 | std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y)); | ||
| 301 | |||
| 302 | // Set swipe event with parameters | ||
| 303 | if (curr_vel > swipe_threshold) { | ||
| 304 | SetSwipeEvent(gesture, last_gesture, type); | ||
| 305 | return; | ||
| 306 | } | ||
| 307 | |||
| 308 | // End panning without swipe | ||
| 309 | type = TouchType::Complete; | ||
| 310 | cur_entry.vel_x = 0; | ||
| 311 | cur_entry.vel_y = 0; | ||
| 312 | force_update = true; | ||
| 313 | } | ||
| 314 | |||
| 315 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 316 | TouchType& type) { | ||
| 317 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | ||
| 318 | const auto& last_entry = | ||
| 319 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | ||
| 320 | type = TouchType::Swipe; | ||
| 321 | gesture = last_gesture; | ||
| 322 | force_update = true; | ||
| 323 | cur_entry.delta_x = last_entry.delta_x; | ||
| 324 | cur_entry.delta_y = last_entry.delta_y; | ||
| 325 | if (std::abs(cur_entry.delta_x) > std::abs(cur_entry.delta_y)) { | ||
| 326 | if (cur_entry.delta_x > 0) { | ||
| 327 | cur_entry.direction = Direction::Right; | ||
| 328 | return; | ||
| 329 | } | ||
| 330 | cur_entry.direction = Direction::Left; | ||
| 331 | return; | ||
| 332 | } | ||
| 333 | if (cur_entry.delta_y > 0) { | ||
| 334 | cur_entry.direction = Direction::Down; | ||
| 335 | return; | ||
| 336 | } | ||
| 337 | cur_entry.direction = Direction::Up; | ||
| 338 | } | ||
| 339 | |||
| 125 | void Controller_Gesture::OnLoadInputDevices() { | 340 | void Controller_Gesture::OnLoadInputDevices() { |
| 126 | touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); | 341 | touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); |
| 127 | touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); | 342 | touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); |
| @@ -183,23 +398,33 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() | |||
| 183 | 398 | ||
| 184 | for (size_t id = 0; id < gesture.active_points; ++id) { | 399 | for (size_t id = 0; id < gesture.active_points; ++id) { |
| 185 | gesture.points[id].x = | 400 | gesture.points[id].x = |
| 186 | static_cast<int>(active_fingers[id].x * Layout::ScreenUndocked::Width); | 401 | static_cast<s32>(active_fingers[id].x * Layout::ScreenUndocked::Width); |
| 187 | gesture.points[id].y = | 402 | gesture.points[id].y = |
| 188 | static_cast<int>(active_fingers[id].y * Layout::ScreenUndocked::Height); | 403 | static_cast<s32>(active_fingers[id].y * Layout::ScreenUndocked::Height); |
| 189 | gesture.mid_point.x += static_cast<int>(gesture.points[id].x / gesture.active_points); | 404 | |
| 190 | gesture.mid_point.y += static_cast<int>(gesture.points[id].y / gesture.active_points); | 405 | // Hack: There is no touch in docked but games still allow it |
| 406 | if (Settings::values.use_docked_mode.GetValue()) { | ||
| 407 | gesture.points[id].x = | ||
| 408 | static_cast<s32>(active_fingers[id].x * Layout::ScreenDocked::Width); | ||
| 409 | gesture.points[id].y = | ||
| 410 | static_cast<s32>(active_fingers[id].y * Layout::ScreenDocked::Height); | ||
| 411 | } | ||
| 412 | |||
| 413 | gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points); | ||
| 414 | gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points); | ||
| 191 | } | 415 | } |
| 192 | 416 | ||
| 193 | for (size_t id = 0; id < gesture.active_points; ++id) { | 417 | for (size_t id = 0; id < gesture.active_points; ++id) { |
| 194 | const double distance = | 418 | const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) + |
| 195 | std::pow(static_cast<float>(gesture.mid_point.x - gesture.points[id].x), 2) + | 419 | Square(gesture.mid_point.y - gesture.points[id].y)); |
| 196 | std::pow(static_cast<float>(gesture.mid_point.y - gesture.points[id].y), 2); | 420 | gesture.average_distance += distance / static_cast<f32>(gesture.active_points); |
| 197 | gesture.average_distance += | ||
| 198 | static_cast<float>(distance) / static_cast<float>(gesture.active_points); | ||
| 199 | } | 421 | } |
| 200 | 422 | ||
| 201 | gesture.angle = std::atan2(static_cast<float>(gesture.mid_point.y - gesture.points[0].y), | 423 | gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y), |
| 202 | static_cast<float>(gesture.mid_point.x - gesture.points[0].x)); | 424 | static_cast<f32>(gesture.mid_point.x - gesture.points[0].x)); |
| 425 | |||
| 426 | gesture.detection_count = last_gesture.detection_count; | ||
| 427 | |||
| 203 | return gesture; | 428 | return gesture; |
| 204 | } | 429 | } |
| 205 | 430 | ||
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 7c357b977..18110a6ad 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -7,7 +7,6 @@ | |||
| 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/swap.h" | ||
| 11 | #include "core/frontend/input.h" | 10 | #include "core/frontend/input.h" |
| 12 | #include "core/hle/service/hid/controllers/controller_base.h" | 11 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 13 | 12 | ||
| @@ -35,10 +34,10 @@ private: | |||
| 35 | 34 | ||
| 36 | enum class TouchType : u32 { | 35 | enum class TouchType : u32 { |
| 37 | Idle, // Nothing touching the screen | 36 | Idle, // Nothing touching the screen |
| 38 | Complete, // Unknown. End of touch? | 37 | Complete, // Set at the end of a touch event |
| 39 | Cancel, // Never triggered | 38 | Cancel, // Set when the number of fingers change |
| 40 | Touch, // Pressing without movement | 39 | Touch, // A finger just touched the screen |
| 41 | Press, // Never triggered | 40 | Press, // Set if last type is touch and the finger hasn't moved |
| 42 | Tap, // Fast press then release | 41 | Tap, // Fast press then release |
| 43 | Pan, // All points moving together across the screen | 42 | Pan, // All points moving together across the screen |
| 44 | Swipe, // Fast press movement and release of a single point | 43 | Swipe, // Fast press movement and release of a single point |
| @@ -58,8 +57,8 @@ private: | |||
| 58 | union { | 57 | union { |
| 59 | u32_le raw{}; | 58 | u32_le raw{}; |
| 60 | 59 | ||
| 61 | BitField<0, 1, u32> is_new_touch; | 60 | BitField<4, 1, u32> is_new_touch; |
| 62 | BitField<1, 1, u32> is_double_tap; | 61 | BitField<8, 1, u32> is_double_tap; |
| 63 | }; | 62 | }; |
| 64 | }; | 63 | }; |
| 65 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); | 64 | static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); |
| @@ -73,10 +72,9 @@ private: | |||
| 73 | struct GestureState { | 72 | struct GestureState { |
| 74 | s64_le sampling_number; | 73 | s64_le sampling_number; |
| 75 | s64_le sampling_number2; | 74 | s64_le sampling_number2; |
| 76 | |||
| 77 | s64_le detection_count; | 75 | s64_le detection_count; |
| 78 | TouchType type; | 76 | TouchType type; |
| 79 | Direction dir; | 77 | Direction direction; |
| 80 | s32_le x; | 78 | s32_le x; |
| 81 | s32_le y; | 79 | s32_le y; |
| 82 | s32_le delta_x; | 80 | s32_le delta_x; |
| @@ -84,8 +82,8 @@ private: | |||
| 84 | f32 vel_x; | 82 | f32 vel_x; |
| 85 | f32 vel_y; | 83 | f32 vel_y; |
| 86 | Attribute attributes; | 84 | Attribute attributes; |
| 87 | u32 scale; | 85 | f32 scale; |
| 88 | u32 rotation_angle; | 86 | f32 rotation_angle; |
| 89 | s32_le point_count; | 87 | s32_le point_count; |
| 90 | std::array<Points, 4> points; | 88 | std::array<Points, 4> points; |
| 91 | }; | 89 | }; |
| @@ -109,10 +107,46 @@ private: | |||
| 109 | Points mid_point{}; | 107 | Points mid_point{}; |
| 110 | s64_le detection_count{}; | 108 | s64_le detection_count{}; |
| 111 | u64_le delta_time{}; | 109 | u64_le delta_time{}; |
| 112 | float average_distance{}; | 110 | f32 average_distance{}; |
| 113 | float angle{}; | 111 | f32 angle{}; |
| 114 | }; | 112 | }; |
| 115 | 113 | ||
| 114 | // Reads input from all available input engines | ||
| 115 | void ReadTouchInput(); | ||
| 116 | |||
| 117 | // Returns true if gesture state needs to be updated | ||
| 118 | bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference); | ||
| 119 | |||
| 120 | // Updates the shared memory to the next state | ||
| 121 | void UpdateGestureSharedMemory(u8* data, std::size_t size, GestureProperties& gesture, | ||
| 122 | f32 time_difference); | ||
| 123 | |||
| 124 | // Initializes new gesture | ||
| 125 | void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes); | ||
| 126 | |||
| 127 | // Updates existing gesture state | ||
| 128 | void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); | ||
| 129 | |||
| 130 | // Terminates exiting gesture | ||
| 131 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | ||
| 132 | Attribute& attributes, f32 time_difference); | ||
| 133 | |||
| 134 | // Set current event to a tap event | ||
| 135 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | ||
| 136 | Attribute& attributes); | ||
| 137 | |||
| 138 | // Calculates and set the extra parameters related to a pan event | ||
| 139 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 140 | TouchType& type, f32 time_difference); | ||
| 141 | |||
| 142 | // Terminates the pan event | ||
| 143 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | ||
| 144 | f32 time_difference); | ||
| 145 | |||
| 146 | // Set current event to a swipe event | ||
| 147 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture, | ||
| 148 | TouchType& type); | ||
| 149 | |||
| 116 | // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned | 150 | // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned |
| 117 | std::optional<size_t> GetUnusedFingerID() const; | 151 | std::optional<size_t> GetUnusedFingerID() const; |
| 118 | 152 | ||
| @@ -134,6 +168,11 @@ private: | |||
| 134 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; | 168 | std::array<size_t, MAX_FINGERS> keyboard_finger_id; |
| 135 | std::array<size_t, MAX_FINGERS> udp_finger_id; | 169 | std::array<size_t, MAX_FINGERS> udp_finger_id; |
| 136 | std::array<Finger, MAX_POINTS> fingers; | 170 | std::array<Finger, MAX_POINTS> fingers; |
| 137 | GestureProperties last_gesture; | 171 | GestureProperties last_gesture{}; |
| 172 | s64_le last_update_timestamp{}; | ||
| 173 | s64_le last_tap_timestamp{}; | ||
| 174 | f32 last_pan_time_difference{}; | ||
| 175 | bool force_update{false}; | ||
| 176 | bool enable_press_and_tap{false}; | ||
| 138 | }; | 177 | }; |
| 139 | } // namespace Service::HID | 178 | } // namespace Service::HID |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 00e683c2f..2c9b2ce6d 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -111,7 +111,7 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) | |||
| 111 | port_installed = true; | 111 | port_installed = true; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) { | 114 | Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) { |
| 115 | const auto guard = LockService(); | 115 | const auto guard = LockService(); |
| 116 | 116 | ||
| 117 | ASSERT(!port_installed); | 117 | ASSERT(!port_installed); |
| @@ -119,9 +119,10 @@ void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) { | |||
| 119 | auto* port = Kernel::KPort::Create(kernel); | 119 | auto* port = Kernel::KPort::Create(kernel); |
| 120 | port->Initialize(max_sessions, false, service_name); | 120 | port->Initialize(max_sessions, false, service_name); |
| 121 | port->GetServerPort().SetHleHandler(shared_from_this()); | 121 | port->GetServerPort().SetHleHandler(shared_from_this()); |
| 122 | kernel.AddNamedPort(service_name, &port->GetClientPort()); | ||
| 123 | 122 | ||
| 124 | port_installed = true; | 123 | port_installed = true; |
| 124 | |||
| 125 | return port->GetClientPort(); | ||
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { | 128 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { |
| @@ -132,6 +133,16 @@ void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* function | |||
| 132 | } | 133 | } |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 136 | void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, | ||
| 137 | std::size_t n) { | ||
| 138 | handlers_tipc.reserve(handlers_tipc.size() + n); | ||
| 139 | for (std::size_t i = 0; i < n; ++i) { | ||
| 140 | // Usually this array is sorted by id already, so hint to insert at the end | ||
| 141 | handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, | ||
| 142 | functions[i]); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 135 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, | 146 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, |
| 136 | const FunctionInfoBase* info) { | 147 | const FunctionInfoBase* info) { |
| 137 | auto cmd_buf = ctx.CommandBuffer(); | 148 | auto cmd_buf = ctx.CommandBuffer(); |
| @@ -166,33 +177,55 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { | |||
| 166 | handler_invoker(this, info->handler_callback, ctx); | 177 | handler_invoker(this, info->handler_callback, ctx); |
| 167 | } | 178 | } |
| 168 | 179 | ||
| 169 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) { | 180 | void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { |
| 181 | boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; | ||
| 182 | |||
| 183 | itr = handlers_tipc.find(ctx.GetCommand()); | ||
| 184 | |||
| 185 | const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; | ||
| 186 | if (info == nullptr || info->handler_callback == nullptr) { | ||
| 187 | return ReportUnimplementedFunction(ctx, info); | ||
| 188 | } | ||
| 189 | |||
| 190 | LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); | ||
| 191 | handler_invoker(this, info->handler_callback, ctx); | ||
| 192 | } | ||
| 193 | |||
| 194 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | ||
| 195 | Kernel::HLERequestContext& ctx) { | ||
| 170 | const auto guard = LockService(); | 196 | const auto guard = LockService(); |
| 171 | 197 | ||
| 172 | switch (context.GetCommandType()) { | 198 | switch (ctx.GetCommandType()) { |
| 173 | case IPC::CommandType::Close: { | 199 | case IPC::CommandType::Close: |
| 174 | IPC::ResponseBuilder rb{context, 2}; | 200 | case IPC::CommandType::TIPC_Close: { |
| 201 | session.Close(); | ||
| 202 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 175 | rb.Push(RESULT_SUCCESS); | 203 | rb.Push(RESULT_SUCCESS); |
| 176 | return IPC::ERR_REMOTE_PROCESS_DEAD; | 204 | return IPC::ERR_REMOTE_PROCESS_DEAD; |
| 177 | } | 205 | } |
| 178 | case IPC::CommandType::ControlWithContext: | 206 | case IPC::CommandType::ControlWithContext: |
| 179 | case IPC::CommandType::Control: { | 207 | case IPC::CommandType::Control: { |
| 180 | system.ServiceManager().InvokeControlRequest(context); | 208 | system.ServiceManager().InvokeControlRequest(ctx); |
| 181 | break; | 209 | break; |
| 182 | } | 210 | } |
| 183 | case IPC::CommandType::RequestWithContext: | 211 | case IPC::CommandType::RequestWithContext: |
| 184 | case IPC::CommandType::Request: { | 212 | case IPC::CommandType::Request: { |
| 185 | InvokeRequest(context); | 213 | InvokeRequest(ctx); |
| 186 | break; | 214 | break; |
| 187 | } | 215 | } |
| 188 | default: | 216 | default: |
| 189 | UNIMPLEMENTED_MSG("command_type={}", context.GetCommandType()); | 217 | if (ctx.IsTipc()) { |
| 218 | InvokeRequestTipc(ctx); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 222 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); | ||
| 190 | } | 223 | } |
| 191 | 224 | ||
| 192 | // If emulation was shutdown, we are closing service threads, do not write the response back to | 225 | // If emulation was shutdown, we are closing service threads, do not write the response back to |
| 193 | // memory that may be shutting down as well. | 226 | // memory that may be shutting down as well. |
| 194 | if (system.IsPoweredOn()) { | 227 | if (system.IsPoweredOn()) { |
| 195 | context.WriteToOutgoingCommandBuffer(context.GetThread()); | 228 | ctx.WriteToOutgoingCommandBuffer(ctx.GetThread()); |
| 196 | } | 229 | } |
| 197 | 230 | ||
| 198 | return RESULT_SUCCESS; | 231 | return RESULT_SUCCESS; |
| @@ -207,7 +240,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system | |||
| 207 | 240 | ||
| 208 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | 241 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); |
| 209 | 242 | ||
| 210 | SM::ServiceManager::InstallInterfaces(sm, system); | 243 | system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); |
| 211 | 244 | ||
| 212 | Account::InstallInterfaces(system); | 245 | Account::InstallInterfaces(system); |
| 213 | AM::InstallInterfaces(*sm, *nv_flinger, system); | 246 | AM::InstallInterfaces(*sm, *nv_flinger, system); |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 884951428..3dfb0740a 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -21,7 +21,9 @@ class System; | |||
| 21 | 21 | ||
| 22 | namespace Kernel { | 22 | namespace Kernel { |
| 23 | class HLERequestContext; | 23 | class HLERequestContext; |
| 24 | } | 24 | class KClientPort; |
| 25 | class KServerSession; | ||
| 26 | } // namespace Kernel | ||
| 25 | 27 | ||
| 26 | namespace Service { | 28 | namespace Service { |
| 27 | 29 | ||
| @@ -64,12 +66,19 @@ public: | |||
| 64 | 66 | ||
| 65 | /// Creates a port pair and registers this service with the given ServiceManager. | 67 | /// Creates a port pair and registers this service with the given ServiceManager. |
| 66 | void InstallAsService(SM::ServiceManager& service_manager); | 68 | void InstallAsService(SM::ServiceManager& service_manager); |
| 67 | /// Creates a port pair and registers it on the kernel's global port registry. | 69 | |
| 68 | void InstallAsNamedPort(Kernel::KernelCore& kernel); | 70 | /// Invokes a service request routine using the HIPC protocol. |
| 69 | /// Invokes a service request routine. | ||
| 70 | void InvokeRequest(Kernel::HLERequestContext& ctx); | 71 | void InvokeRequest(Kernel::HLERequestContext& ctx); |
| 72 | |||
| 73 | /// Invokes a service request routine using the HIPC protocol. | ||
| 74 | void InvokeRequestTipc(Kernel::HLERequestContext& ctx); | ||
| 75 | |||
| 76 | /// Creates a port pair and registers it on the kernel's global port registry. | ||
| 77 | Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); | ||
| 78 | |||
| 71 | /// Handles a synchronization request for the service. | 79 | /// Handles a synchronization request for the service. |
| 72 | ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) override; | 80 | ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 81 | Kernel::HLERequestContext& context) override; | ||
| 73 | 82 | ||
| 74 | protected: | 83 | protected: |
| 75 | /// Member-function pointer type of SyncRequest handlers. | 84 | /// Member-function pointer type of SyncRequest handlers. |
| @@ -102,6 +111,7 @@ private: | |||
| 102 | ~ServiceFrameworkBase() override; | 111 | ~ServiceFrameworkBase() override; |
| 103 | 112 | ||
| 104 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); | 113 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); |
| 114 | void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); | ||
| 105 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); | 115 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); |
| 106 | 116 | ||
| 107 | /// Identifier string used to connect to the service. | 117 | /// Identifier string used to connect to the service. |
| @@ -116,6 +126,7 @@ private: | |||
| 116 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. | 126 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. |
| 117 | InvokerFn* handler_invoker; | 127 | InvokerFn* handler_invoker; |
| 118 | boost::container::flat_map<u32, FunctionInfoBase> handlers; | 128 | boost::container::flat_map<u32, FunctionInfoBase> handlers; |
| 129 | boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc; | ||
| 119 | 130 | ||
| 120 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. | 131 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. |
| 121 | Common::SpinLock lock_service; | 132 | Common::SpinLock lock_service; |
| @@ -183,6 +194,20 @@ protected: | |||
| 183 | RegisterHandlersBase(functions, n); | 194 | RegisterHandlersBase(functions, n); |
| 184 | } | 195 | } |
| 185 | 196 | ||
| 197 | /// Registers handlers in the service. | ||
| 198 | template <std::size_t N> | ||
| 199 | void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) { | ||
| 200 | RegisterHandlersTipc(functions, N); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Registers handlers in the service. Usually prefer using the other RegisterHandlers | ||
| 205 | * overload in order to avoid needing to specify the array size. | ||
| 206 | */ | ||
| 207 | void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) { | ||
| 208 | RegisterHandlersBaseTipc(functions, n); | ||
| 209 | } | ||
| 210 | |||
| 186 | private: | 211 | private: |
| 187 | /** | 212 | /** |
| 188 | * This function is used to allow invocation of pointers to handlers stored in the base class | 213 | * This function is used to allow invocation of pointers to handlers stored in the base class |
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index ee026e22f..de530cbfb 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp | |||
| @@ -26,15 +26,23 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | |||
| 26 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong | 26 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong |
| 27 | // and that we probably want to actually make an entirely new Session, but we still need to | 27 | // and that we probably want to actually make an entirely new Session, but we still need to |
| 28 | // verify this on hardware. | 28 | // verify this on hardware. |
| 29 | |||
| 29 | LOG_DEBUG(Service, "called"); | 30 | LOG_DEBUG(Service, "called"); |
| 30 | 31 | ||
| 32 | auto session = ctx.Session()->GetParent(); | ||
| 33 | |||
| 34 | // Open a reference to the session to simulate a new one being created. | ||
| 35 | session->Open(); | ||
| 36 | session->GetClientSession().Open(); | ||
| 37 | session->GetServerSession().Open(); | ||
| 38 | |||
| 31 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 39 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 32 | rb.Push(RESULT_SUCCESS); | 40 | rb.Push(RESULT_SUCCESS); |
| 33 | rb.PushMoveObjects(ctx.Session()->GetParent()->GetClientSession()); | 41 | rb.PushMoveObjects(session->GetClientSession()); |
| 34 | } | 42 | } |
| 35 | 43 | ||
| 36 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { | 44 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { |
| 37 | LOG_WARNING(Service, "(STUBBED) called, using CloneCurrentObject"); | 45 | LOG_DEBUG(Service, "called"); |
| 38 | 46 | ||
| 39 | CloneCurrentObject(ctx); | 47 | CloneCurrentObject(ctx); |
| 40 | } | 48 | } |
| @@ -44,7 +52,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 44 | 52 | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | 53 | IPC::ResponseBuilder rb{ctx, 3}; |
| 46 | rb.Push(RESULT_SUCCESS); | 54 | rb.Push(RESULT_SUCCESS); |
| 47 | rb.Push<u16>(0x1000); | 55 | rb.Push<u16>(0x8000); |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 50 | // https://switchbrew.org/wiki/IPC_Marshalling | 58 | // https://switchbrew.org/wiki/IPC_Marshalling |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 568effbc9..8cc9aee8a 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/hle/kernel/k_client_port.h" | 9 | #include "core/hle/kernel/k_client_port.h" |
| 10 | #include "core/hle/kernel/k_client_session.h" | 10 | #include "core/hle/kernel/k_client_session.h" |
| 11 | #include "core/hle/kernel/k_port.h" | 11 | #include "core/hle/kernel/k_port.h" |
| 12 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 12 | #include "core/hle/kernel/k_server_port.h" | 13 | #include "core/hle/kernel/k_server_port.h" |
| 13 | #include "core/hle/kernel/k_server_session.h" | 14 | #include "core/hle/kernel/k_server_session.h" |
| 14 | #include "core/hle/kernel/k_session.h" | 15 | #include "core/hle/kernel/k_session.h" |
| @@ -18,6 +19,7 @@ | |||
| 18 | 19 | ||
| 19 | namespace Service::SM { | 20 | namespace Service::SM { |
| 20 | 21 | ||
| 22 | constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2); | ||
| 21 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); | 23 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); |
| 22 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); | 24 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); |
| 23 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); | 25 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); |
| @@ -34,20 +36,17 @@ static ResultCode ValidateServiceName(const std::string& name) { | |||
| 34 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); | 36 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); |
| 35 | return ERR_INVALID_NAME; | 37 | return ERR_INVALID_NAME; |
| 36 | } | 38 | } |
| 37 | if (name.rfind('\0') != std::string::npos) { | ||
| 38 | LOG_ERROR(Service_SM, "A non null terminated service was passed"); | ||
| 39 | return ERR_INVALID_NAME; | ||
| 40 | } | ||
| 41 | return RESULT_SUCCESS; | 39 | return RESULT_SUCCESS; |
| 42 | } | 40 | } |
| 43 | 41 | ||
| 44 | void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { | 42 | Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { |
| 45 | ASSERT(self->sm_interface.expired()); | 43 | ASSERT(self.sm_interface.expired()); |
| 46 | 44 | ||
| 47 | auto sm = std::make_shared<SM>(self, system); | 45 | auto sm = std::make_shared<SM>(self, system); |
| 48 | sm->InstallAsNamedPort(system.Kernel()); | 46 | self.sm_interface = sm; |
| 49 | self->sm_interface = sm; | 47 | self.controller_interface = std::make_unique<Controller>(system); |
| 50 | self->controller_interface = std::make_unique<Controller>(system); | 48 | |
| 49 | return sm->CreatePort(system.Kernel()); | ||
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | 52 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, |
| @@ -107,33 +106,68 @@ SM::~SM() = default; | |||
| 107 | void SM::Initialize(Kernel::HLERequestContext& ctx) { | 106 | void SM::Initialize(Kernel::HLERequestContext& ctx) { |
| 108 | LOG_DEBUG(Service_SM, "called"); | 107 | LOG_DEBUG(Service_SM, "called"); |
| 109 | 108 | ||
| 109 | is_initialized = true; | ||
| 110 | |||
| 110 | IPC::ResponseBuilder rb{ctx, 2}; | 111 | IPC::ResponseBuilder rb{ctx, 2}; |
| 111 | rb.Push(RESULT_SUCCESS); | 112 | rb.Push(RESULT_SUCCESS); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | void SM::GetService(Kernel::HLERequestContext& ctx) { | 115 | void SM::GetService(Kernel::HLERequestContext& ctx) { |
| 115 | IPC::RequestParser rp{ctx}; | 116 | auto result = GetServiceImpl(ctx); |
| 117 | if (result.Succeeded()) { | ||
| 118 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 119 | rb.Push(result.Code()); | ||
| 120 | rb.PushMoveObjects(result.Unwrap()); | ||
| 121 | } else { | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(result.Code()); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { | ||
| 128 | auto result = GetServiceImpl(ctx); | ||
| 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 130 | rb.Push(result.Code()); | ||
| 131 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | ||
| 132 | } | ||
| 133 | |||
| 134 | static std::string PopServiceName(IPC::RequestParser& rp) { | ||
| 116 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); | 135 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); |
| 117 | auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | 136 | std::string result; |
| 137 | for (const auto& c : name_buf) { | ||
| 138 | if (c >= ' ' && c <= '~') { | ||
| 139 | result.push_back(c); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return result; | ||
| 143 | } | ||
| 118 | 144 | ||
| 119 | std::string name(name_buf.begin(), end); | 145 | ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) { |
| 146 | if (!is_initialized) { | ||
| 147 | return ERR_NOT_INITIALIZED; | ||
| 148 | } | ||
| 149 | |||
| 150 | IPC::RequestParser rp{ctx}; | ||
| 151 | std::string name(PopServiceName(rp)); | ||
| 120 | 152 | ||
| 121 | auto result = service_manager->GetServicePort(name); | 153 | auto result = service_manager.GetServicePort(name); |
| 122 | if (result.Failed()) { | 154 | if (result.Failed()) { |
| 123 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 124 | rb.Push(result.Code()); | ||
| 125 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); | 155 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); |
| 126 | if (name.length() == 0) | 156 | return result.Code(); |
| 127 | return; // LibNX Fix | ||
| 128 | UNIMPLEMENTED(); | ||
| 129 | return; | ||
| 130 | } | 157 | } |
| 131 | 158 | ||
| 132 | auto* port = result.Unwrap(); | 159 | auto* port = result.Unwrap(); |
| 133 | 160 | ||
| 161 | // Kernel::KScopedResourceReservation session_reservation( | ||
| 162 | // kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions); | ||
| 163 | // R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached); | ||
| 164 | |||
| 134 | auto* session = Kernel::KSession::Create(kernel); | 165 | auto* session = Kernel::KSession::Create(kernel); |
| 135 | session->Initialize(&port->GetClientPort(), std::move(name)); | 166 | session->Initialize(&port->GetClientPort(), std::move(name)); |
| 136 | 167 | ||
| 168 | // Commit the session reservation. | ||
| 169 | // session_reservation.Commit(); | ||
| 170 | |||
| 137 | if (port->GetServerPort().GetHLEHandler()) { | 171 | if (port->GetServerPort().GetHLEHandler()) { |
| 138 | port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession()); | 172 | port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession()); |
| 139 | } else { | 173 | } else { |
| @@ -141,18 +175,12 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { | |||
| 141 | } | 175 | } |
| 142 | 176 | ||
| 143 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); | 177 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
| 144 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 178 | return MakeResult(&session->GetClientSession()); |
| 145 | rb.Push(RESULT_SUCCESS); | ||
| 146 | rb.PushMoveObjects(session->GetClientSession()); | ||
| 147 | } | 179 | } |
| 148 | 180 | ||
| 149 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { | 181 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { |
| 150 | IPC::RequestParser rp{ctx}; | 182 | IPC::RequestParser rp{ctx}; |
| 151 | 183 | std::string name(PopServiceName(rp)); | |
| 152 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 153 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 154 | |||
| 155 | const std::string name(name_buf.begin(), end); | ||
| 156 | 184 | ||
| 157 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); | 185 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); |
| 158 | const auto max_session_count = rp.PopRaw<u32>(); | 186 | const auto max_session_count = rp.PopRaw<u32>(); |
| @@ -160,7 +188,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 160 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, | 188 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, |
| 161 | max_session_count, is_light); | 189 | max_session_count, is_light); |
| 162 | 190 | ||
| 163 | auto handle = service_manager->RegisterService(name, max_session_count); | 191 | auto handle = service_manager.RegisterService(name, max_session_count); |
| 164 | if (handle.Failed()) { | 192 | if (handle.Failed()) { |
| 165 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", | 193 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", |
| 166 | handle.Code().raw); | 194 | handle.Code().raw); |
| @@ -178,28 +206,31 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 178 | 206 | ||
| 179 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | 207 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { |
| 180 | IPC::RequestParser rp{ctx}; | 208 | IPC::RequestParser rp{ctx}; |
| 209 | std::string name(PopServiceName(rp)); | ||
| 181 | 210 | ||
| 182 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 183 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 184 | |||
| 185 | const std::string name(name_buf.begin(), end); | ||
| 186 | LOG_DEBUG(Service_SM, "called with name={}", name); | 211 | LOG_DEBUG(Service_SM, "called with name={}", name); |
| 187 | 212 | ||
| 188 | IPC::ResponseBuilder rb{ctx, 2}; | 213 | IPC::ResponseBuilder rb{ctx, 2}; |
| 189 | rb.Push(service_manager->UnregisterService(name)); | 214 | rb.Push(service_manager.UnregisterService(name)); |
| 190 | } | 215 | } |
| 191 | 216 | ||
| 192 | SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) | 217 | SM::SM(ServiceManager& service_manager_, Core::System& system_) |
| 193 | : ServiceFramework{system_, "sm:", 4}, | 218 | : ServiceFramework{system_, "sm:", 4}, |
| 194 | service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { | 219 | service_manager{service_manager_}, kernel{system_.Kernel()} { |
| 195 | static const FunctionInfo functions[] = { | 220 | RegisterHandlers({ |
| 196 | {0, &SM::Initialize, "Initialize"}, | 221 | {0, &SM::Initialize, "Initialize"}, |
| 197 | {1, &SM::GetService, "GetService"}, | 222 | {1, &SM::GetService, "GetService"}, |
| 198 | {2, &SM::RegisterService, "RegisterService"}, | 223 | {2, &SM::RegisterService, "RegisterService"}, |
| 199 | {3, &SM::UnregisterService, "UnregisterService"}, | 224 | {3, &SM::UnregisterService, "UnregisterService"}, |
| 200 | {4, nullptr, "DetachClient"}, | 225 | {4, nullptr, "DetachClient"}, |
| 201 | }; | 226 | }); |
| 202 | RegisterHandlers(functions); | 227 | RegisterHandlersTipc({ |
| 228 | {0, &SM::Initialize, "Initialize"}, | ||
| 229 | {1, &SM::GetServiceTipc, "GetService"}, | ||
| 230 | {2, &SM::RegisterService, "RegisterService"}, | ||
| 231 | {3, &SM::UnregisterService, "UnregisterService"}, | ||
| 232 | {4, nullptr, "DetachClient"}, | ||
| 233 | }); | ||
| 203 | } | 234 | } |
| 204 | 235 | ||
| 205 | } // namespace Service::SM | 236 | } // namespace Service::SM |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index af5010c3b..60f0b3f8a 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -34,22 +34,26 @@ class Controller; | |||
| 34 | /// Interface to "sm:" service | 34 | /// Interface to "sm:" service |
| 35 | class SM final : public ServiceFramework<SM> { | 35 | class SM final : public ServiceFramework<SM> { |
| 36 | public: | 36 | public: |
| 37 | explicit SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_); | 37 | explicit SM(ServiceManager& service_manager_, Core::System& system_); |
| 38 | ~SM() override; | 38 | ~SM() override; |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | void Initialize(Kernel::HLERequestContext& ctx); | 41 | void Initialize(Kernel::HLERequestContext& ctx); |
| 42 | void GetService(Kernel::HLERequestContext& ctx); | 42 | void GetService(Kernel::HLERequestContext& ctx); |
| 43 | void GetServiceTipc(Kernel::HLERequestContext& ctx); | ||
| 43 | void RegisterService(Kernel::HLERequestContext& ctx); | 44 | void RegisterService(Kernel::HLERequestContext& ctx); |
| 44 | void UnregisterService(Kernel::HLERequestContext& ctx); | 45 | void UnregisterService(Kernel::HLERequestContext& ctx); |
| 45 | 46 | ||
| 46 | std::shared_ptr<ServiceManager> service_manager; | 47 | ResultVal<Kernel::KClientSession*> GetServiceImpl(Kernel::HLERequestContext& ctx); |
| 48 | |||
| 49 | ServiceManager& service_manager; | ||
| 50 | bool is_initialized{}; | ||
| 47 | Kernel::KernelCore& kernel; | 51 | Kernel::KernelCore& kernel; |
| 48 | }; | 52 | }; |
| 49 | 53 | ||
| 50 | class ServiceManager { | 54 | class ServiceManager { |
| 51 | public: | 55 | public: |
| 52 | static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system); | 56 | static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); |
| 53 | 57 | ||
| 54 | explicit ServiceManager(Kernel::KernelCore& kernel_); | 58 | explicit ServiceManager(Kernel::KernelCore& kernel_); |
| 55 | ~ServiceManager(); | 59 | ~ServiceManager(); |
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index dc2baca4a..2c8899ae0 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp | |||
| @@ -10,6 +10,11 @@ | |||
| 10 | 10 | ||
| 11 | namespace Service::SSL { | 11 | namespace Service::SSL { |
| 12 | 12 | ||
| 13 | enum class CertificateFormat : u32 { | ||
| 14 | Pem = 1, | ||
| 15 | Der = 2, | ||
| 16 | }; | ||
| 17 | |||
| 13 | class ISslConnection final : public ServiceFramework<ISslConnection> { | 18 | class ISslConnection final : public ServiceFramework<ISslConnection> { |
| 14 | public: | 19 | public: |
| 15 | explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { | 20 | explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { |
| @@ -58,8 +63,8 @@ public: | |||
| 58 | {1, nullptr, "GetOption"}, | 63 | {1, nullptr, "GetOption"}, |
| 59 | {2, &ISslContext::CreateConnection, "CreateConnection"}, | 64 | {2, &ISslContext::CreateConnection, "CreateConnection"}, |
| 60 | {3, nullptr, "GetConnectionCount"}, | 65 | {3, nullptr, "GetConnectionCount"}, |
| 61 | {4, nullptr, "ImportServerPki"}, | 66 | {4, &ISslContext::ImportServerPki, "ImportServerPki"}, |
| 62 | {5, nullptr, "ImportClientPki"}, | 67 | {5, &ISslContext::ImportClientPki, "ImportClientPki"}, |
| 63 | {6, nullptr, "RemoveServerPki"}, | 68 | {6, nullptr, "RemoveServerPki"}, |
| 64 | {7, nullptr, "RemoveClientPki"}, | 69 | {7, nullptr, "RemoveClientPki"}, |
| 65 | {8, nullptr, "RegisterInternalPki"}, | 70 | {8, nullptr, "RegisterInternalPki"}, |
| @@ -94,6 +99,39 @@ private: | |||
| 94 | rb.Push(RESULT_SUCCESS); | 99 | rb.Push(RESULT_SUCCESS); |
| 95 | rb.PushIpcInterface<ISslConnection>(system); | 100 | rb.PushIpcInterface<ISslConnection>(system); |
| 96 | } | 101 | } |
| 102 | |||
| 103 | void ImportServerPki(Kernel::HLERequestContext& ctx) { | ||
| 104 | IPC::RequestParser rp{ctx}; | ||
| 105 | const auto certificate_format = rp.PopEnum<CertificateFormat>(); | ||
| 106 | const auto pkcs_12_certificates = ctx.ReadBuffer(0); | ||
| 107 | |||
| 108 | constexpr u64 server_id = 0; | ||
| 109 | |||
| 110 | LOG_WARNING(Service_SSL, "(STUBBED) called, certificate_format={}", certificate_format); | ||
| 111 | |||
| 112 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 113 | rb.Push(RESULT_SUCCESS); | ||
| 114 | rb.Push(server_id); | ||
| 115 | } | ||
| 116 | |||
| 117 | void ImportClientPki(Kernel::HLERequestContext& ctx) { | ||
| 118 | const auto pkcs_12_certificate = ctx.ReadBuffer(0); | ||
| 119 | const auto ascii_password = [&ctx] { | ||
| 120 | if (ctx.CanReadBuffer(1)) { | ||
| 121 | return ctx.ReadBuffer(1); | ||
| 122 | } | ||
| 123 | |||
| 124 | return std::vector<u8>{}; | ||
| 125 | }(); | ||
| 126 | |||
| 127 | constexpr u64 client_id = 0; | ||
| 128 | |||
| 129 | LOG_WARNING(Service_SSL, "(STUBBED) called"); | ||
| 130 | |||
| 131 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 132 | rb.Push(RESULT_SUCCESS); | ||
| 133 | rb.Push(client_id); | ||
| 134 | } | ||
| 97 | }; | 135 | }; |
| 98 | 136 | ||
| 99 | class SSL final : public ServiceFramework<SSL> { | 137 | class SSL final : public ServiceFramework<SSL> { |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 7c4e7dd3b..7399c3648 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -153,6 +153,11 @@ struct InputSubsystem::Impl { | |||
| 153 | // TODO return the correct motion device | 153 | // TODO return the correct motion device |
| 154 | return {}; | 154 | return {}; |
| 155 | } | 155 | } |
| 156 | #ifdef HAVE_SDL2 | ||
| 157 | if (params.Get("class", "") == "sdl") { | ||
| 158 | return sdl->GetMotionMappingForDevice(params); | ||
| 159 | } | ||
| 160 | #endif | ||
| 156 | return {}; | 161 | return {}; |
| 157 | } | 162 | } |
| 158 | 163 | ||
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 42bbf14d4..b5d41bba4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -37,6 +37,9 @@ public: | |||
| 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { | 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { |
| 38 | return {}; | 38 | return {}; |
| 39 | } | 39 | } |
| 40 | virtual MotionMapping GetMotionMappingForDevice(const Common::ParamPackage&) { | ||
| 41 | return {}; | ||
| 42 | } | ||
| 40 | }; | 43 | }; |
| 41 | 44 | ||
| 42 | class NullState : public State { | 45 | class NullState : public State { |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index f682a6db4..822d0b555 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #include "common/logging/log.h" | 31 | #include "common/logging/log.h" |
| 32 | #include "common/math_util.h" | ||
| 32 | #include "common/param_package.h" | 33 | #include "common/param_package.h" |
| 33 | #include "common/settings_input.h" | 34 | #include "common/settings_input.h" |
| 34 | #include "common/threadsafe_queue.h" | 35 | #include "common/threadsafe_queue.h" |
| @@ -68,13 +69,57 @@ public: | |||
| 68 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | 69 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |
| 69 | SDL_GameController* game_controller) | 70 | SDL_GameController* game_controller) |
| 70 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | 71 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, |
| 71 | sdl_controller{game_controller, &SDL_GameControllerClose} {} | 72 | sdl_controller{game_controller, &SDL_GameControllerClose} { |
| 73 | EnableMotion(); | ||
| 74 | } | ||
| 75 | |||
| 76 | void EnableMotion() { | ||
| 77 | if (sdl_controller) { | ||
| 78 | SDL_GameController* controller = sdl_controller.get(); | ||
| 79 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { | ||
| 80 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); | ||
| 81 | has_accel = true; | ||
| 82 | } | ||
| 83 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { | ||
| 84 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); | ||
| 85 | has_gyro = true; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 72 | 89 | ||
| 73 | void SetButton(int button, bool value) { | 90 | void SetButton(int button, bool value) { |
| 74 | std::lock_guard lock{mutex}; | 91 | std::lock_guard lock{mutex}; |
| 75 | state.buttons.insert_or_assign(button, value); | 92 | state.buttons.insert_or_assign(button, value); |
| 76 | } | 93 | } |
| 77 | 94 | ||
| 95 | void SetMotion(SDL_ControllerSensorEvent event) { | ||
| 96 | constexpr float gravity_constant = 9.80665f; | ||
| 97 | std::lock_guard lock{mutex}; | ||
| 98 | u64 time_difference = event.timestamp - last_motion_update; | ||
| 99 | last_motion_update = event.timestamp; | ||
| 100 | switch (event.sensor) { | ||
| 101 | case SDL_SENSOR_ACCEL: { | ||
| 102 | const Common::Vec3f acceleration = {-event.data[0], event.data[2], -event.data[1]}; | ||
| 103 | motion.SetAcceleration(acceleration / gravity_constant); | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | case SDL_SENSOR_GYRO: { | ||
| 107 | const Common::Vec3f gyroscope = {event.data[0], -event.data[2], event.data[1]}; | ||
| 108 | motion.SetGyroscope(gyroscope / (Common::PI * 2)); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | // Ignore duplicated timestamps | ||
| 114 | if (time_difference == 0) { | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | motion.SetGyroThreshold(0.0001f); | ||
| 119 | motion.UpdateRotation(time_difference * 1000); | ||
| 120 | motion.UpdateOrientation(time_difference * 1000); | ||
| 121 | } | ||
| 122 | |||
| 78 | bool GetButton(int button) const { | 123 | bool GetButton(int button) const { |
| 79 | std::lock_guard lock{mutex}; | 124 | std::lock_guard lock{mutex}; |
| 80 | return state.buttons.at(button); | 125 | return state.buttons.at(button); |
| @@ -121,6 +166,14 @@ public: | |||
| 121 | return std::make_tuple(x, y); | 166 | return std::make_tuple(x, y); |
| 122 | } | 167 | } |
| 123 | 168 | ||
| 169 | bool HasGyro() const { | ||
| 170 | return has_gyro; | ||
| 171 | } | ||
| 172 | |||
| 173 | bool HasAccel() const { | ||
| 174 | return has_accel; | ||
| 175 | } | ||
| 176 | |||
| 124 | const MotionInput& GetMotion() const { | 177 | const MotionInput& GetMotion() const { |
| 125 | return motion; | 178 | return motion; |
| 126 | } | 179 | } |
| @@ -173,8 +226,11 @@ private: | |||
| 173 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 226 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 174 | mutable std::mutex mutex; | 227 | mutable std::mutex mutex; |
| 175 | 228 | ||
| 176 | // Motion is initialized without PID values as motion input is not aviable for SDL2 | 229 | // Motion is initialized with the PID values |
| 177 | MotionInput motion{0.0f, 0.0f, 0.0f}; | 230 | MotionInput motion{0.3f, 0.005f, 0.0f}; |
| 231 | u64 last_motion_update{}; | ||
| 232 | bool has_gyro{false}; | ||
| 233 | bool has_accel{false}; | ||
| 178 | }; | 234 | }; |
| 179 | 235 | ||
| 180 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | 236 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { |
| @@ -296,6 +352,12 @@ void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 296 | } | 352 | } |
| 297 | break; | 353 | break; |
| 298 | } | 354 | } |
| 355 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 356 | if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 357 | joystick->SetMotion(event.csensor); | ||
| 358 | } | ||
| 359 | break; | ||
| 360 | } | ||
| 299 | case SDL_JOYDEVICEREMOVED: | 361 | case SDL_JOYDEVICEREMOVED: |
| 300 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); | 362 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); |
| 301 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); | 363 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); |
| @@ -449,6 +511,18 @@ private: | |||
| 449 | std::shared_ptr<SDLJoystick> joystick; | 511 | std::shared_ptr<SDLJoystick> joystick; |
| 450 | }; | 512 | }; |
| 451 | 513 | ||
| 514 | class SDLMotion final : public Input::MotionDevice { | ||
| 515 | public: | ||
| 516 | explicit SDLMotion(std::shared_ptr<SDLJoystick> joystick_) : joystick(std::move(joystick_)) {} | ||
| 517 | |||
| 518 | Input::MotionStatus GetStatus() const override { | ||
| 519 | return joystick->GetMotion().GetMotion(); | ||
| 520 | } | ||
| 521 | |||
| 522 | private: | ||
| 523 | std::shared_ptr<SDLJoystick> joystick; | ||
| 524 | }; | ||
| 525 | |||
| 452 | class SDLDirectionMotion final : public Input::MotionDevice { | 526 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 453 | public: | 527 | public: |
| 454 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 528 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -658,6 +732,10 @@ public: | |||
| 658 | 732 | ||
| 659 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 733 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 660 | 734 | ||
| 735 | if (params.Has("motion")) { | ||
| 736 | return std::make_unique<SDLMotion>(joystick); | ||
| 737 | } | ||
| 738 | |||
| 661 | if (params.Has("hat")) { | 739 | if (params.Has("hat")) { |
| 662 | const int hat = params.Get("hat", 0); | 740 | const int hat = params.Get("hat", 0); |
| 663 | const std::string direction_name = params.Get("direction", ""); | 741 | const std::string direction_name = params.Get("direction", ""); |
| @@ -717,6 +795,17 @@ SDLState::SDLState() { | |||
| 717 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | 795 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); |
| 718 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 796 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 719 | 797 | ||
| 798 | // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers | ||
| 799 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); | ||
| 800 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); | ||
| 801 | |||
| 802 | // Tell SDL2 to use the hidapi driver. This will allow joycons to be detected as a | ||
| 803 | // GameController and not a generic one | ||
| 804 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1"); | ||
| 805 | |||
| 806 | // Turn off Pro controller home led | ||
| 807 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0"); | ||
| 808 | |||
| 720 | // If the frontend is going to manage the event loop, then we don't start one here | 809 | // If the frontend is going to manage the event loop, then we don't start one here |
| 721 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; | 810 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; |
| 722 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { | 811 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { |
| @@ -853,6 +942,13 @@ Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s | |||
| 853 | return params; | 942 | return params; |
| 854 | } | 943 | } |
| 855 | 944 | ||
| 945 | Common::ParamPackage BuildMotionParam(int port, std::string guid) { | ||
| 946 | Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}}); | ||
| 947 | params.Set("port", port); | ||
| 948 | params.Set("guid", std::move(guid)); | ||
| 949 | return params; | ||
| 950 | } | ||
| 951 | |||
| 856 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | 952 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { |
| 857 | switch (event.type) { | 953 | switch (event.type) { |
| 858 | case SDL_JOYAXISMOTION: { | 954 | case SDL_JOYAXISMOTION: { |
| @@ -907,6 +1003,35 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve | |||
| 907 | } | 1003 | } |
| 908 | break; | 1004 | break; |
| 909 | } | 1005 | } |
| 1006 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 1007 | bool is_motion_shaking = false; | ||
| 1008 | constexpr float gyro_threshold = 5.0f; | ||
| 1009 | constexpr float accel_threshold = 11.0f; | ||
| 1010 | if (event.csensor.sensor == SDL_SENSOR_ACCEL) { | ||
| 1011 | const Common::Vec3f acceleration = {-event.csensor.data[0], event.csensor.data[2], | ||
| 1012 | -event.csensor.data[1]}; | ||
| 1013 | if (acceleration.Length() > accel_threshold) { | ||
| 1014 | is_motion_shaking = true; | ||
| 1015 | } | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | if (event.csensor.sensor == SDL_SENSOR_GYRO) { | ||
| 1019 | const Common::Vec3f gyroscope = {event.csensor.data[0], -event.csensor.data[2], | ||
| 1020 | event.csensor.data[1]}; | ||
| 1021 | if (gyroscope.Length() > gyro_threshold) { | ||
| 1022 | is_motion_shaking = true; | ||
| 1023 | } | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | if (!is_motion_shaking) { | ||
| 1027 | break; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 1031 | return BuildMotionParam(joystick->GetPort(), joystick->GetGUID()); | ||
| 1032 | } | ||
| 1033 | break; | ||
| 1034 | } | ||
| 910 | } | 1035 | } |
| 911 | return {}; | 1036 | return {}; |
| 912 | } | 1037 | } |
| @@ -1036,6 +1161,27 @@ AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& pa | |||
| 1036 | return mapping; | 1161 | return mapping; |
| 1037 | } | 1162 | } |
| 1038 | 1163 | ||
| 1164 | MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& params) { | ||
| 1165 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 1166 | return {}; | ||
| 1167 | } | ||
| 1168 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 1169 | auto* controller = joystick->GetSDLGameController(); | ||
| 1170 | if (controller == nullptr) { | ||
| 1171 | return {}; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | joystick->EnableMotion(); | ||
| 1175 | |||
| 1176 | if (!joystick->HasGyro() && !joystick->HasAccel()) { | ||
| 1177 | return {}; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | MotionMapping mapping = {}; | ||
| 1181 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1182 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1183 | return mapping; | ||
| 1184 | } | ||
| 1039 | namespace Polling { | 1185 | namespace Polling { |
| 1040 | class SDLPoller : public InputCommon::Polling::DevicePoller { | 1186 | class SDLPoller : public InputCommon::Polling::DevicePoller { |
| 1041 | public: | 1187 | public: |
| @@ -1149,6 +1295,7 @@ public: | |||
| 1149 | [[fallthrough]]; | 1295 | [[fallthrough]]; |
| 1150 | case SDL_JOYBUTTONUP: | 1296 | case SDL_JOYBUTTONUP: |
| 1151 | case SDL_JOYHATMOTION: | 1297 | case SDL_JOYHATMOTION: |
| 1298 | case SDL_CONTROLLERSENSORUPDATE: | ||
| 1152 | return {SDLEventToMotionParamPackage(state, event)}; | 1299 | return {SDLEventToMotionParamPackage(state, event)}; |
| 1153 | } | 1300 | } |
| 1154 | return std::nullopt; | 1301 | return std::nullopt; |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 8b7363f56..121e01913 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -57,6 +57,7 @@ public: | |||
| 57 | 57 | ||
| 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; |
| 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; |
| 60 | MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; | ||
| 60 | 61 | ||
| 61 | private: | 62 | private: |
| 62 | void InitJoystick(int joystick_index); | 63 | void InitJoystick(int joystick_index); |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 623b43d8a..ffe9edc1b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -543,8 +543,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, |
| 546 | const std::array<Offset2D, 2>& dst_region, | 546 | const Region2D& dst_region, const Region2D& src_region, |
| 547 | const std::array<Offset2D, 2>& src_region, | ||
| 548 | Tegra::Engines::Fermi2D::Filter filter, | 547 | Tegra::Engines::Fermi2D::Filter filter, |
| 549 | Tegra::Engines::Fermi2D::Operation operation) { | 548 | Tegra::Engines::Fermi2D::Operation operation) { |
| 550 | state_tracker.NotifyScissor0(); | 549 | state_tracker.NotifyScissor0(); |
| @@ -560,9 +559,9 @@ void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | |||
| 560 | const GLbitfield buffer_bits = dst->BufferBits(); | 559 | const GLbitfield buffer_bits = dst->BufferBits(); |
| 561 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; | 560 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; |
| 562 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 561 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| 563 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region[0].x, src_region[0].y, | 562 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region.start.x, src_region.start.y, |
| 564 | src_region[1].x, src_region[1].y, dst_region[0].x, dst_region[0].y, | 563 | src_region.end.x, src_region.end.y, dst_region.start.x, |
| 565 | dst_region[1].x, dst_region[1].y, buffer_bits, | 564 | dst_region.start.y, dst_region.end.x, dst_region.end.y, buffer_bits, |
| 566 | is_linear ? GL_LINEAR : GL_NEAREST); | 565 | is_linear ? GL_LINEAR : GL_NEAREST); |
| 567 | } | 566 | } |
| 568 | 567 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3c871541b..df8be12ff 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -28,7 +28,7 @@ using VideoCommon::ImageId; | |||
| 28 | using VideoCommon::ImageViewId; | 28 | using VideoCommon::ImageViewId; |
| 29 | using VideoCommon::ImageViewType; | 29 | using VideoCommon::ImageViewType; |
| 30 | using VideoCommon::NUM_RT; | 30 | using VideoCommon::NUM_RT; |
| 31 | using VideoCommon::Offset2D; | 31 | using VideoCommon::Region2D; |
| 32 | using VideoCommon::RenderTargets; | 32 | using VideoCommon::RenderTargets; |
| 33 | 33 | ||
| 34 | struct ImageBufferMap { | 34 | struct ImageBufferMap { |
| @@ -73,10 +73,8 @@ public: | |||
| 73 | 73 | ||
| 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 75 | 75 | ||
| 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, const Region2D& dst_region, |
| 77 | const std::array<Offset2D, 2>& dst_region, | 77 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 78 | const std::array<Offset2D, 2>& src_region, | ||
| 79 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 80 | Tegra::Engines::Fermi2D::Operation operation); | 78 | Tegra::Engines::Fermi2D::Operation operation); |
| 81 | 79 | ||
| 82 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, | 80 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 1f6a169ae..b7f5b8bc2 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -289,16 +289,15 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri | |||
| 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); | 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, |
| 293 | const std::array<Offset2D, 2>& dst_region, | 293 | const Region2D& src_region) { |
| 294 | const std::array<Offset2D, 2>& src_region) { | ||
| 295 | const VkOffset2D offset{ | 294 | const VkOffset2D offset{ |
| 296 | .x = std::min(dst_region[0].x, dst_region[1].x), | 295 | .x = std::min(dst_region.start.x, dst_region.end.x), |
| 297 | .y = std::min(dst_region[0].y, dst_region[1].y), | 296 | .y = std::min(dst_region.start.y, dst_region.end.y), |
| 298 | }; | 297 | }; |
| 299 | const VkExtent2D extent{ | 298 | const VkExtent2D extent{ |
| 300 | .width = static_cast<u32>(std::abs(dst_region[1].x - dst_region[0].x)), | 299 | .width = static_cast<u32>(std::abs(dst_region.end.x - dst_region.start.x)), |
| 301 | .height = static_cast<u32>(std::abs(dst_region[1].y - dst_region[0].y)), | 300 | .height = static_cast<u32>(std::abs(dst_region.end.y - dst_region.start.y)), |
| 302 | }; | 301 | }; |
| 303 | const VkViewport viewport{ | 302 | const VkViewport viewport{ |
| 304 | .x = static_cast<float>(offset.x), | 303 | .x = static_cast<float>(offset.x), |
| @@ -313,11 +312,12 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | |||
| 313 | .offset = offset, | 312 | .offset = offset, |
| 314 | .extent = extent, | 313 | .extent = extent, |
| 315 | }; | 314 | }; |
| 316 | const float scale_x = static_cast<float>(src_region[1].x - src_region[0].x); | 315 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x); |
| 317 | const float scale_y = static_cast<float>(src_region[1].y - src_region[0].y); | 316 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y); |
| 318 | const PushConstants push_constants{ | 317 | const PushConstants push_constants{ |
| 319 | .tex_scale = {scale_x, scale_y}, | 318 | .tex_scale = {scale_x, scale_y}, |
| 320 | .tex_offset = {static_cast<float>(src_region[0].x), static_cast<float>(src_region[0].y)}, | 319 | .tex_offset = {static_cast<float>(src_region.start.x), |
| 320 | static_cast<float>(src_region.start.y)}, | ||
| 321 | }; | 321 | }; |
| 322 | cmdbuf.SetViewport(0, viewport); | 322 | cmdbuf.SetViewport(0, viewport); |
| 323 | cmdbuf.SetScissor(0, scissor); | 323 | cmdbuf.SetScissor(0, scissor); |
| @@ -353,8 +353,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 353 | BlitImageHelper::~BlitImageHelper() = default; | 353 | BlitImageHelper::~BlitImageHelper() = default; |
| 354 | 354 | ||
| 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 356 | const std::array<Offset2D, 2>& dst_region, | 356 | const Region2D& dst_region, const Region2D& src_region, |
| 357 | const std::array<Offset2D, 2>& src_region, | ||
| 358 | Tegra::Engines::Fermi2D::Filter filter, | 357 | Tegra::Engines::Fermi2D::Filter filter, |
| 359 | Tegra::Engines::Fermi2D::Operation operation) { | 358 | Tegra::Engines::Fermi2D::Operation operation) { |
| 360 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 359 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| @@ -383,8 +382,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 383 | 382 | ||
| 384 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | 383 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, |
| 385 | VkImageView src_depth_view, VkImageView src_stencil_view, | 384 | VkImageView src_depth_view, VkImageView src_stencil_view, |
| 386 | const std::array<Offset2D, 2>& dst_region, | 385 | const Region2D& dst_region, const Region2D& src_region, |
| 387 | const std::array<Offset2D, 2>& src_region, | ||
| 388 | Tegra::Engines::Fermi2D::Filter filter, | 386 | Tegra::Engines::Fermi2D::Filter filter, |
| 389 | Tegra::Engines::Fermi2D::Operation operation) { | 387 | Tegra::Engines::Fermi2D::Operation operation) { |
| 390 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); | 388 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 43fd3d737..0d81a06ed 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Vulkan { | 14 | namespace Vulkan { |
| 15 | 15 | ||
| 16 | using VideoCommon::Offset2D; | 16 | using VideoCommon::Region2D; |
| 17 | 17 | ||
| 18 | class Device; | 18 | class Device; |
| 19 | class Framebuffer; | 19 | class Framebuffer; |
| @@ -35,15 +35,13 @@ public: | |||
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 38 | const std::array<Offset2D, 2>& dst_region, | 38 | const Region2D& dst_region, const Region2D& src_region, |
| 39 | const std::array<Offset2D, 2>& src_region, | ||
| 40 | Tegra::Engines::Fermi2D::Filter filter, | 39 | Tegra::Engines::Fermi2D::Filter filter, |
| 41 | Tegra::Engines::Fermi2D::Operation operation); | 40 | Tegra::Engines::Fermi2D::Operation operation); |
| 42 | 41 | ||
| 43 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, | 42 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, |
| 44 | VkImageView src_stencil_view, const std::array<Offset2D, 2>& dst_region, | 43 | VkImageView src_stencil_view, const Region2D& dst_region, |
| 45 | const std::array<Offset2D, 2>& src_region, | 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 46 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 47 | Tegra::Engines::Fermi2D::Operation operation); | 45 | Tegra::Engines::Fermi2D::Operation operation); |
| 48 | 46 | ||
| 49 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); | 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 017348e05..bdd0ce8bc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -490,8 +490,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 490 | write_barrier); | 490 | write_barrier); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const std::array<Offset2D, 2>& dst_region, | 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, |
| 494 | const std::array<Offset2D, 2>& src_region, | ||
| 495 | const VkImageSubresourceLayers& dst_layers, | 494 | const VkImageSubresourceLayers& dst_layers, |
| 496 | const VkImageSubresourceLayers& src_layers) { | 495 | const VkImageSubresourceLayers& src_layers) { |
| 497 | return VkImageBlit{ | 496 | return VkImageBlit{ |
| @@ -499,13 +498,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 499 | .srcOffsets = | 498 | .srcOffsets = |
| 500 | { | 499 | { |
| 501 | { | 500 | { |
| 502 | .x = src_region[0].x, | 501 | .x = src_region.start.x, |
| 503 | .y = src_region[0].y, | 502 | .y = src_region.start.y, |
| 504 | .z = 0, | 503 | .z = 0, |
| 505 | }, | 504 | }, |
| 506 | { | 505 | { |
| 507 | .x = src_region[1].x, | 506 | .x = src_region.end.x, |
| 508 | .y = src_region[1].y, | 507 | .y = src_region.end.y, |
| 509 | .z = 1, | 508 | .z = 1, |
| 510 | }, | 509 | }, |
| 511 | }, | 510 | }, |
| @@ -513,42 +512,42 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 513 | .dstOffsets = | 512 | .dstOffsets = |
| 514 | { | 513 | { |
| 515 | { | 514 | { |
| 516 | .x = dst_region[0].x, | 515 | .x = dst_region.start.x, |
| 517 | .y = dst_region[0].y, | 516 | .y = dst_region.start.y, |
| 518 | .z = 0, | 517 | .z = 0, |
| 519 | }, | 518 | }, |
| 520 | { | 519 | { |
| 521 | .x = dst_region[1].x, | 520 | .x = dst_region.end.x, |
| 522 | .y = dst_region[1].y, | 521 | .y = dst_region.end.y, |
| 523 | .z = 1, | 522 | .z = 1, |
| 524 | }, | 523 | }, |
| 525 | }, | 524 | }, |
| 526 | }; | 525 | }; |
| 527 | } | 526 | } |
| 528 | 527 | ||
| 529 | [[nodiscard]] VkImageResolve MakeImageResolve(const std::array<Offset2D, 2>& dst_region, | 528 | [[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, |
| 530 | const std::array<Offset2D, 2>& src_region, | 529 | const Region2D& src_region, |
| 531 | const VkImageSubresourceLayers& dst_layers, | 530 | const VkImageSubresourceLayers& dst_layers, |
| 532 | const VkImageSubresourceLayers& src_layers) { | 531 | const VkImageSubresourceLayers& src_layers) { |
| 533 | return VkImageResolve{ | 532 | return VkImageResolve{ |
| 534 | .srcSubresource = src_layers, | 533 | .srcSubresource = src_layers, |
| 535 | .srcOffset = | 534 | .srcOffset = |
| 536 | { | 535 | { |
| 537 | .x = src_region[0].x, | 536 | .x = src_region.start.x, |
| 538 | .y = src_region[0].y, | 537 | .y = src_region.start.y, |
| 539 | .z = 0, | 538 | .z = 0, |
| 540 | }, | 539 | }, |
| 541 | .dstSubresource = dst_layers, | 540 | .dstSubresource = dst_layers, |
| 542 | .dstOffset = | 541 | .dstOffset = |
| 543 | { | 542 | { |
| 544 | .x = dst_region[0].x, | 543 | .x = dst_region.start.x, |
| 545 | .y = dst_region[0].y, | 544 | .y = dst_region.start.y, |
| 546 | .z = 0, | 545 | .z = 0, |
| 547 | }, | 546 | }, |
| 548 | .extent = | 547 | .extent = |
| 549 | { | 548 | { |
| 550 | .width = static_cast<u32>(dst_region[1].x - dst_region[0].x), | 549 | .width = static_cast<u32>(dst_region.end.x - dst_region.start.x), |
| 551 | .height = static_cast<u32>(dst_region[1].y - dst_region[0].y), | 550 | .height = static_cast<u32>(dst_region.end.y - dst_region.start.y), |
| 552 | .depth = 1, | 551 | .depth = 1, |
| 553 | }, | 552 | }, |
| 554 | }; | 553 | }; |
| @@ -602,8 +601,7 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 602 | } | 601 | } |
| 603 | 602 | ||
| 604 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 603 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 605 | const std::array<Offset2D, 2>& dst_region, | 604 | const Region2D& dst_region, const Region2D& src_region, |
| 606 | const std::array<Offset2D, 2>& src_region, | ||
| 607 | Tegra::Engines::Fermi2D::Filter filter, | 605 | Tegra::Engines::Fermi2D::Filter filter, |
| 608 | Tegra::Engines::Fermi2D::Operation operation) { | 606 | Tegra::Engines::Fermi2D::Operation operation) { |
| 609 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); | 607 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 628785d5e..4a57d378b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -16,7 +16,7 @@ namespace Vulkan { | |||
| 16 | 16 | ||
| 17 | using VideoCommon::ImageId; | 17 | using VideoCommon::ImageId; |
| 18 | using VideoCommon::NUM_RT; | 18 | using VideoCommon::NUM_RT; |
| 19 | using VideoCommon::Offset2D; | 19 | using VideoCommon::Region2D; |
| 20 | using VideoCommon::RenderTargets; | 20 | using VideoCommon::RenderTargets; |
| 21 | using VideoCore::Surface::PixelFormat; | 21 | using VideoCore::Surface::PixelFormat; |
| 22 | 22 | ||
| @@ -71,8 +71,7 @@ struct TextureCacheRuntime { | |||
| 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); |
| 72 | 72 | ||
| 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 74 | const std::array<Offset2D, 2>& dst_region, | 74 | const Region2D& dst_region, const Region2D& src_region, |
| 75 | const std::array<Offset2D, 2>& src_region, | ||
| 76 | Tegra::Engines::Fermi2D::Filter filter, | 75 | Tegra::Engines::Fermi2D::Filter filter, |
| 77 | Tegra::Engines::Fermi2D::Operation operation); | 76 | Tegra::Engines::Fermi2D::Operation operation); |
| 78 | 77 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 98e33c3a0..59b7c678b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -148,7 +148,9 @@ public: | |||
| 148 | /// Blit an image with the given parameters | 148 | /// Blit an image with the given parameters |
| 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 150 | const Tegra::Engines::Fermi2D::Surface& src, | 150 | const Tegra::Engines::Fermi2D::Surface& src, |
| 151 | const Tegra::Engines::Fermi2D::Config& copy); | 151 | const Tegra::Engines::Fermi2D::Config& copy, |
| 152 | std::optional<Region2D> src_region_override = {}, | ||
| 153 | std::optional<Region2D> dst_region_override = {}); | ||
| 152 | 154 | ||
| 153 | /// Invalidate the contents of the color buffer index | 155 | /// Invalidate the contents of the color buffer index |
| 154 | /// These contents become unspecified, the cache can assume aggressive optimizations. | 156 | /// These contents become unspecified, the cache can assume aggressive optimizations. |
| @@ -615,7 +617,9 @@ void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | |||
| 615 | template <class P> | 617 | template <class P> |
| 616 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 618 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 617 | const Tegra::Engines::Fermi2D::Surface& src, | 619 | const Tegra::Engines::Fermi2D::Surface& src, |
| 618 | const Tegra::Engines::Fermi2D::Config& copy) { | 620 | const Tegra::Engines::Fermi2D::Config& copy, |
| 621 | std::optional<Region2D> src_override, | ||
| 622 | std::optional<Region2D> dst_override) { | ||
| 619 | const BlitImages images = GetBlitImages(dst, src); | 623 | const BlitImages images = GetBlitImages(dst, src); |
| 620 | const ImageId dst_id = images.dst_id; | 624 | const ImageId dst_id = images.dst_id; |
| 621 | const ImageId src_id = images.src_id; | 625 | const ImageId src_id = images.src_id; |
| @@ -631,20 +635,42 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 631 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); | 635 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); |
| 632 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); | 636 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); |
| 633 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); | 637 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); |
| 634 | const std::array src_region{ | 638 | |
| 635 | Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, | 639 | // out of bounds texture blit checking |
| 636 | Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, | 640 | const bool use_override = src_override.has_value(); |
| 641 | const s32 src_x0 = copy.src_x0 >> src_samples_x; | ||
| 642 | s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x; | ||
| 643 | const s32 src_y0 = copy.src_y0 >> src_samples_y; | ||
| 644 | const s32 src_y1 = copy.src_y1 >> src_samples_y; | ||
| 645 | |||
| 646 | const auto src_width = static_cast<s32>(src_image.info.size.width); | ||
| 647 | const bool width_oob = src_x1 > src_width; | ||
| 648 | const auto width_diff = width_oob ? src_x1 - src_width : 0; | ||
| 649 | if (width_oob) { | ||
| 650 | src_x1 = src_width; | ||
| 651 | } | ||
| 652 | |||
| 653 | const Region2D src_dimensions{ | ||
| 654 | Offset2D{.x = src_x0, .y = src_y0}, | ||
| 655 | Offset2D{.x = src_x1, .y = src_y1}, | ||
| 637 | }; | 656 | }; |
| 657 | const auto src_region = use_override ? *src_override : src_dimensions; | ||
| 638 | 658 | ||
| 639 | const std::optional src_base = src_image.TryFindBase(src.Address()); | 659 | const std::optional src_base = src_image.TryFindBase(src.Address()); |
| 640 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; | 660 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; |
| 641 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); | 661 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); |
| 642 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); | 662 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); |
| 643 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); | 663 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); |
| 644 | const std::array dst_region{ | 664 | |
| 645 | Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, | 665 | const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; |
| 646 | Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, | 666 | const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; |
| 667 | const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; | ||
| 668 | const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; | ||
| 669 | const Region2D dst_dimensions{ | ||
| 670 | Offset2D{.x = dst_x0, .y = dst_y0}, | ||
| 671 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, | ||
| 647 | }; | 672 | }; |
| 673 | const auto dst_region = use_override ? *dst_override : dst_dimensions; | ||
| 648 | 674 | ||
| 649 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. | 675 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. |
| 650 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; | 676 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; |
| @@ -661,6 +687,21 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 661 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, | 687 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, |
| 662 | copy.operation); | 688 | copy.operation); |
| 663 | } | 689 | } |
| 690 | |||
| 691 | if (width_oob) { | ||
| 692 | // Continue copy of the oob region of the texture on the next row | ||
| 693 | auto oob_src = src; | ||
| 694 | oob_src.height++; | ||
| 695 | const Region2D src_region_override{ | ||
| 696 | Offset2D{.x = 0, .y = src_y0 + 1}, | ||
| 697 | Offset2D{.x = width_diff, .y = src_y1 + 1}, | ||
| 698 | }; | ||
| 699 | const Region2D dst_region_override{ | ||
| 700 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y0}, | ||
| 701 | Offset2D{.x = dst_x1, .y = dst_y1}, | ||
| 702 | }; | ||
| 703 | BlitImage(dst, oob_src, copy, src_region_override, dst_region_override); | ||
| 704 | } | ||
| 664 | } | 705 | } |
| 665 | 706 | ||
| 666 | template <class P> | 707 | template <class P> |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 2ad2d72a6..c9571f7e4 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -64,6 +64,13 @@ struct Offset3D { | |||
| 64 | s32 z; | 64 | s32 z; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct Region2D { | ||
| 68 | constexpr auto operator<=>(const Region2D&) const noexcept = default; | ||
| 69 | |||
| 70 | Offset2D start; | ||
| 71 | Offset2D end; | ||
| 72 | }; | ||
| 73 | |||
| 67 | struct Extent2D { | 74 | struct Extent2D { |
| 68 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; | 75 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; |
| 69 | 76 | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index c9318c562..ab3512810 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -153,6 +153,10 @@ QString ButtonToText(const Common::ParamPackage& param) { | |||
| 153 | return QObject::tr("Button %1").arg(button_str); | 153 | return QObject::tr("Button %1").arg(button_str); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | if (param.Has("motion")) { | ||
| 157 | return QObject::tr("SDL Motion"); | ||
| 158 | } | ||
| 159 | |||
| 156 | return {}; | 160 | return {}; |
| 157 | } | 161 | } |
| 158 | 162 | ||
| @@ -1245,12 +1249,16 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { | |||
| 1245 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 1249 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; |
| 1246 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 1250 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); |
| 1247 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 1251 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); |
| 1252 | auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); | ||
| 1248 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { | 1253 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { |
| 1249 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | 1254 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; |
| 1250 | } | 1255 | } |
| 1251 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { | 1256 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { |
| 1252 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | 1257 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; |
| 1253 | } | 1258 | } |
| 1259 | for (std::size_t i = 0; i < motions_param.size(); ++i) { | ||
| 1260 | motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]; | ||
| 1261 | } | ||
| 1254 | 1262 | ||
| 1255 | UpdateUI(); | 1263 | UpdateUI(); |
| 1256 | } | 1264 | } |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index f35c89e04..0cdaea8a4 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -46,6 +46,7 @@ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::Configur | |||
| 46 | SetConfiguration(); | 46 | SetConfiguration(); |
| 47 | 47 | ||
| 48 | // Force game list reload if any of the relevant settings are changed. | 48 | // Force game list reload if any of the relevant settings are changed. |
| 49 | connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); | ||
| 49 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 50 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
| 50 | &ConfigureUi::RequestGameListUpdate); | 51 | &ConfigureUi::RequestGameListUpdate); |
| 51 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 52 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9e72acbf7..30bb1aac7 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2751,24 +2751,19 @@ void GMainWindow::MigrateConfigFiles() { | |||
| 2751 | 2751 | ||
| 2752 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, | 2752 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, |
| 2753 | const std::string& title_version) { | 2753 | const std::string& title_version) { |
| 2754 | const auto full_name = std::string(Common::g_build_fullname); | ||
| 2755 | const auto branch_name = std::string(Common::g_scm_branch); | 2754 | const auto branch_name = std::string(Common::g_scm_branch); |
| 2756 | const auto description = std::string(Common::g_scm_desc); | 2755 | const auto description = std::string(Common::g_scm_desc); |
| 2757 | const auto build_id = std::string(Common::g_build_id); | 2756 | const auto build_id = std::string(Common::g_build_id); |
| 2758 | 2757 | ||
| 2759 | const auto date = | 2758 | const auto yuzu_title = fmt::format("yuzu | {}-{}", branch_name, description); |
| 2760 | QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd")).toStdString(); | 2759 | const auto override_title = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 2760 | const auto window_title = override_title.empty() ? yuzu_title : override_title; | ||
| 2761 | 2761 | ||
| 2762 | if (title_name.empty()) { | 2762 | if (title_name.empty()) { |
| 2763 | const auto fmt = std::string(Common::g_title_bar_format_idle); | 2763 | setWindowTitle(QString::fromStdString(window_title)); |
| 2764 | setWindowTitle(QString::fromStdString(fmt::format(fmt.empty() ? "yuzu {0}| {1}-{2}" : fmt, | ||
| 2765 | full_name, branch_name, description, | ||
| 2766 | std::string{}, date, build_id))); | ||
| 2767 | } else { | 2764 | } else { |
| 2768 | const auto fmt = std::string(Common::g_title_bar_format_running); | 2765 | const auto run_title = fmt::format("{} | {} | {}", window_title, title_name, title_version); |
| 2769 | setWindowTitle(QString::fromStdString( | 2766 | setWindowTitle(QString::fromStdString(run_title)); |
| 2770 | fmt::format(fmt.empty() ? "yuzu {0}| {3} | {6} | {1}-{2}" : fmt, full_name, branch_name, | ||
| 2771 | description, title_name, date, build_id, title_version))); | ||
| 2772 | } | 2767 | } |
| 2773 | } | 2768 | } |
| 2774 | 2769 | ||