diff options
Diffstat (limited to 'src')
68 files changed, 1020 insertions, 517 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 13f915a01..ba0acfb72 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -43,6 +43,7 @@ namespace Log { | |||
| 43 | SUB(HW, LCD) \ | 43 | SUB(HW, LCD) \ |
| 44 | SUB(HW, GPU) \ | 44 | SUB(HW, GPU) \ |
| 45 | SUB(HW, AES) \ | 45 | SUB(HW, AES) \ |
| 46 | CLS(IPC) \ | ||
| 46 | CLS(Frontend) \ | 47 | CLS(Frontend) \ |
| 47 | CLS(Render) \ | 48 | CLS(Render) \ |
| 48 | SUB(Render, Software) \ | 49 | SUB(Render, Software) \ |
| @@ -91,8 +92,8 @@ const char* GetLevelName(Level log_level) { | |||
| 91 | 92 | ||
| 92 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | 93 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, |
| 93 | const char* function, const char* format, va_list args) { | 94 | const char* function, const char* format, va_list args) { |
| 94 | using std::chrono::steady_clock; | ||
| 95 | using std::chrono::duration_cast; | 95 | using std::chrono::duration_cast; |
| 96 | using std::chrono::steady_clock; | ||
| 96 | 97 | ||
| 97 | static steady_clock::time_point time_origin = steady_clock::now(); | 98 | static steady_clock::time_point time_origin = steady_clock::now(); |
| 98 | 99 | ||
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 35b5af3cb..57021037a 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -60,6 +60,7 @@ enum class Class : ClassType { | |||
| 60 | HW_LCD, ///< LCD register emulation | 60 | HW_LCD, ///< LCD register emulation |
| 61 | HW_GPU, ///< GPU control emulation | 61 | HW_GPU, ///< GPU control emulation |
| 62 | HW_AES, ///< AES engine emulation | 62 | HW_AES, ///< AES engine emulation |
| 63 | IPC, ///< IPC interface | ||
| 63 | Frontend, ///< Emulator UI | 64 | Frontend, ///< Emulator UI |
| 64 | Render, ///< Emulator video output and hardware acceleration | 65 | Render, ///< Emulator video output and hardware acceleration |
| 65 | Render_Software, ///< Software renderer backend | 66 | Render_Software, ///< Software renderer backend |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index aa4d92ab1..e77261dc4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -37,6 +37,8 @@ set(SRCS | |||
| 37 | hle/kernel/wait_object.cpp | 37 | hle/kernel/wait_object.cpp |
| 38 | hle/lock.cpp | 38 | hle/lock.cpp |
| 39 | hle/romfs.cpp | 39 | hle/romfs.cpp |
| 40 | hle/service/acc/acc.cpp | ||
| 41 | hle/service/acc/acc_u0.cpp | ||
| 40 | hle/service/am/am.cpp | 42 | hle/service/am/am.cpp |
| 41 | hle/service/am/applet_oe.cpp | 43 | hle/service/am/applet_oe.cpp |
| 42 | hle/service/aoc/aoc_u.cpp | 44 | hle/service/aoc/aoc_u.cpp |
| @@ -48,15 +50,14 @@ set(SRCS | |||
| 48 | hle/service/nvdrv/devices/nvdisp_disp0.cpp | 50 | hle/service/nvdrv/devices/nvdisp_disp0.cpp |
| 49 | hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 51 | hle/service/nvdrv/devices/nvhost_as_gpu.cpp |
| 50 | hle/service/nvdrv/devices/nvmap.cpp | 52 | hle/service/nvdrv/devices/nvmap.cpp |
| 53 | hle/service/nvdrv/interface.cpp | ||
| 51 | hle/service/nvdrv/nvdrv.cpp | 54 | hle/service/nvdrv/nvdrv.cpp |
| 52 | hle/service/nvdrv/nvdrv_a.cpp | ||
| 53 | hle/service/pctl/pctl.cpp | 55 | hle/service/pctl/pctl.cpp |
| 54 | hle/service/pctl/pctl_a.cpp | 56 | hle/service/pctl/pctl_a.cpp |
| 55 | hle/service/service.cpp | 57 | hle/service/service.cpp |
| 56 | hle/service/sm/controller.cpp | 58 | hle/service/sm/controller.cpp |
| 57 | hle/service/sm/sm.cpp | 59 | hle/service/sm/sm.cpp |
| 58 | hle/service/time/time.cpp | 60 | hle/service/time/time.cpp |
| 59 | hle/service/time/time_s.cpp | ||
| 60 | hle/service/vi/vi.cpp | 61 | hle/service/vi/vi.cpp |
| 61 | hle/service/vi/vi_m.cpp | 62 | hle/service/vi/vi_m.cpp |
| 62 | hle/shared_page.cpp | 63 | hle/shared_page.cpp |
| @@ -125,6 +126,8 @@ set(HEADERS | |||
| 125 | hle/lock.h | 126 | hle/lock.h |
| 126 | hle/result.h | 127 | hle/result.h |
| 127 | hle/romfs.h | 128 | hle/romfs.h |
| 129 | hle/service/acc/acc.h | ||
| 130 | hle/service/acc/acc_u0.h | ||
| 128 | hle/service/am/am.h | 131 | hle/service/am/am.h |
| 129 | hle/service/am/applet_oe.h | 132 | hle/service/am/applet_oe.h |
| 130 | hle/service/aoc/aoc_u.h | 133 | hle/service/aoc/aoc_u.h |
| @@ -137,15 +140,14 @@ set(HEADERS | |||
| 137 | hle/service/nvdrv/devices/nvdisp_disp0.h | 140 | hle/service/nvdrv/devices/nvdisp_disp0.h |
| 138 | hle/service/nvdrv/devices/nvhost_as_gpu.h | 141 | hle/service/nvdrv/devices/nvhost_as_gpu.h |
| 139 | hle/service/nvdrv/devices/nvmap.h | 142 | hle/service/nvdrv/devices/nvmap.h |
| 143 | hle/service/nvdrv/interface.h | ||
| 140 | hle/service/nvdrv/nvdrv.h | 144 | hle/service/nvdrv/nvdrv.h |
| 141 | hle/service/nvdrv/nvdrv_a.h | ||
| 142 | hle/service/pctl/pctl.h | 145 | hle/service/pctl/pctl.h |
| 143 | hle/service/pctl/pctl_a.h | 146 | hle/service/pctl/pctl_a.h |
| 144 | hle/service/service.h | 147 | hle/service/service.h |
| 145 | hle/service/sm/controller.h | 148 | hle/service/sm/controller.h |
| 146 | hle/service/sm/sm.h | 149 | hle/service/sm/sm.h |
| 147 | hle/service/time/time.h | 150 | hle/service/time/time.h |
| 148 | hle/service/time/time_s.h | ||
| 149 | hle/service/vi/vi.h | 151 | hle/service/vi/vi.h |
| 150 | hle/service/vi/vi_m.h | 152 | hle/service/vi/vi_m.h |
| 151 | hle/shared_page.h | 153 | hle/shared_page.h |
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 531875006..5ae60214e 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -39,7 +39,8 @@ public: | |||
| 39 | Run(1); | 39 | Run(1); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, Kernel::VMAPermission perms) {} | 42 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, |
| 43 | Kernel::VMAPermission perms) {} | ||
| 43 | 44 | ||
| 44 | /// Clear all instruction cache | 45 | /// Clear all instruction cache |
| 45 | virtual void ClearInstructionCache() = 0; | 46 | virtual void ClearInstructionCache() = 0; |
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 13f6c658c..fd64eab39 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include "core/hle/kernel/svc.h" | 11 | #include "core/hle/kernel/svc.h" |
| 12 | 12 | ||
| 13 | // Load Unicorn DLL once on Windows using RAII | 13 | // Load Unicorn DLL once on Windows using RAII |
| 14 | #ifdef _WIN32 | 14 | #ifdef _MSC_VER |
| 15 | #include <unicorn_dynload.h> | 15 | #include <unicorn_dynload.h> |
| 16 | struct LoadDll { | 16 | struct LoadDll { |
| 17 | private: | 17 | private: |
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index dedbd4bdf..05c872d89 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -905,7 +905,7 @@ void ToggleServer(bool status) { | |||
| 905 | server_enabled = status; | 905 | server_enabled = status; |
| 906 | 906 | ||
| 907 | // Start server | 907 | // Start server |
| 908 | if (!IsConnected() && Core::System().GetInstance().IsPoweredOn()) { | 908 | if (!IsConnected() && Core::System::GetInstance().IsPoweredOn()) { |
| 909 | Init(); | 909 | Init(); |
| 910 | } | 910 | } |
| 911 | } else { | 911 | } else { |
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index ec08be0f4..1840fac12 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -19,7 +19,6 @@ constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); | |||
| 19 | // TODO(yuriks): These will probably go away once translation is implemented inside the kernel. | 19 | // TODO(yuriks): These will probably go away once translation is implemented inside the kernel. |
| 20 | constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; | 20 | constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; |
| 21 | 21 | ||
| 22 | |||
| 23 | enum class ControlCommand : u32 { | 22 | enum class ControlCommand : u32 { |
| 24 | ConvertSessionToDomain = 0, | 23 | ConvertSessionToDomain = 0, |
| 25 | ConvertDomainToSession = 1, | 24 | ConvertDomainToSession = 1, |
| @@ -81,13 +80,13 @@ struct BufferDescriptorX { | |||
| 81 | u32_le address_bits_0_31; | 80 | u32_le address_bits_0_31; |
| 82 | 81 | ||
| 83 | u32_le Counter() const { | 82 | u32_le Counter() const { |
| 84 | u32_le counter{ counter_bits_0_5 }; | 83 | u32_le counter{counter_bits_0_5}; |
| 85 | counter |= counter_bits_9_11 << 9; | 84 | counter |= counter_bits_9_11 << 9; |
| 86 | return counter; | 85 | return counter; |
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | VAddr Address() const { | 88 | VAddr Address() const { |
| 90 | VAddr address{ address_bits_0_31 }; | 89 | VAddr address{address_bits_0_31}; |
| 91 | address |= static_cast<VAddr>(address_bits_32_35) << 32; | 90 | address |= static_cast<VAddr>(address_bits_32_35) << 32; |
| 92 | address |= static_cast<VAddr>(address_bits_36_38) << 36; | 91 | address |= static_cast<VAddr>(address_bits_36_38) << 36; |
| 93 | return address; | 92 | return address; |
| @@ -107,14 +106,14 @@ struct BufferDescriptorABW { | |||
| 107 | }; | 106 | }; |
| 108 | 107 | ||
| 109 | VAddr Address() const { | 108 | VAddr Address() const { |
| 110 | VAddr address{ address_bits_0_31 }; | 109 | VAddr address{address_bits_0_31}; |
| 111 | address |= static_cast<VAddr>(address_bits_32_35) << 32; | 110 | address |= static_cast<VAddr>(address_bits_32_35) << 32; |
| 112 | address |= static_cast<VAddr>(address_bits_36_38) << 36; | 111 | address |= static_cast<VAddr>(address_bits_36_38) << 36; |
| 113 | return address; | 112 | return address; |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | u64 Size() const { | 115 | u64 Size() const { |
| 117 | u64 size{ size_bits_0_31 }; | 116 | u64 size{size_bits_0_31}; |
| 118 | size |= static_cast<u64>(size_bits_32_35) << 32; | 117 | size |= static_cast<u64>(size_bits_32_35) << 32; |
| 119 | return size; | 118 | return size; |
| 120 | } | 119 | } |
| @@ -130,7 +129,7 @@ struct BufferDescriptorC { | |||
| 130 | }; | 129 | }; |
| 131 | 130 | ||
| 132 | VAddr Address() const { | 131 | VAddr Address() const { |
| 133 | VAddr address{ address_bits_0_31 }; | 132 | VAddr address{address_bits_0_31}; |
| 134 | address |= static_cast<VAddr>(address_bits_32_47) << 32; | 133 | address |= static_cast<VAddr>(address_bits_32_47) << 32; |
| 135 | return address; | 134 | return address; |
| 136 | } | 135 | } |
| @@ -144,6 +143,11 @@ struct DataPayloadHeader { | |||
| 144 | static_assert(sizeof(DataPayloadHeader) == 8, "DataPayloadRequest size is incorrect"); | 143 | static_assert(sizeof(DataPayloadHeader) == 8, "DataPayloadRequest size is incorrect"); |
| 145 | 144 | ||
| 146 | struct DomainMessageHeader { | 145 | struct DomainMessageHeader { |
| 146 | enum class CommandType : u32_le { | ||
| 147 | SendMessage = 1, | ||
| 148 | CloseVirtualHandle = 2, | ||
| 149 | }; | ||
| 150 | |||
| 147 | union { | 151 | union { |
| 148 | // Used when responding to an IPC request, Server -> Client. | 152 | // Used when responding to an IPC request, Server -> Client. |
| 149 | struct { | 153 | struct { |
| @@ -154,7 +158,7 @@ struct DomainMessageHeader { | |||
| 154 | // Used when performing an IPC request, Client -> Server. | 158 | // Used when performing an IPC request, Client -> Server. |
| 155 | struct { | 159 | struct { |
| 156 | union { | 160 | union { |
| 157 | BitField<0, 8, u32_le> command; | 161 | BitField<0, 8, CommandType> command; |
| 158 | BitField<16, 16, u32_le> size; | 162 | BitField<16, 16, u32_le> size; |
| 159 | }; | 163 | }; |
| 160 | u32_le object_id; | 164 | u32_le object_id; |
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 0f1077d9e..25530a3c8 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -9,10 +9,13 @@ | |||
| 9 | #include <type_traits> | 9 | #include <type_traits> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include "core/hle/ipc.h" | 11 | #include "core/hle/ipc.h" |
| 12 | #include "core/hle/kernel/client_port.h" | ||
| 13 | #include "core/hle/kernel/client_session.h" | ||
| 12 | #include "core/hle/kernel/domain.h" | 14 | #include "core/hle/kernel/domain.h" |
| 13 | #include "core/hle/kernel/handle_table.h" | 15 | #include "core/hle/kernel/handle_table.h" |
| 14 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 15 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 18 | #include "core/hle/kernel/server_port.h" | ||
| 16 | 19 | ||
| 17 | namespace IPC { | 20 | namespace IPC { |
| 18 | 21 | ||
| @@ -63,13 +66,20 @@ public: | |||
| 63 | : RequestHelperBase(context) { | 66 | : RequestHelperBase(context) { |
| 64 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | 67 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); |
| 65 | 68 | ||
| 69 | context.ClearIncomingObjects(); | ||
| 70 | |||
| 66 | IPC::CommandHeader header{}; | 71 | IPC::CommandHeader header{}; |
| 67 | 72 | ||
| 68 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | 73 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory |
| 69 | // padding. | 74 | // padding. |
| 70 | u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | 75 | u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; |
| 71 | if (context.IsDomain()) | 76 | if (context.IsDomain()) { |
| 72 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | 77 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; |
| 78 | } else { | ||
| 79 | // If we're not in a domain, turn the domain object parameters into move handles. | ||
| 80 | num_handles_to_move += num_domain_objects; | ||
| 81 | num_domain_objects = 0; | ||
| 82 | } | ||
| 73 | 83 | ||
| 74 | header.data_size.Assign(raw_data_size); | 84 | header.data_size.Assign(raw_data_size); |
| 75 | if (num_handles_to_copy || num_handles_to_move) { | 85 | if (num_handles_to_copy || num_handles_to_move) { |
| @@ -100,7 +110,15 @@ public: | |||
| 100 | 110 | ||
| 101 | template <class T, class... Args> | 111 | template <class T, class... Args> |
| 102 | void PushIpcInterface(Args&&... args) { | 112 | void PushIpcInterface(Args&&... args) { |
| 103 | context->AddDomainObject(std::make_shared<T>(std::forward<Args>(args)...)); | 113 | auto iface = std::make_shared<T>(std::forward<Args>(args)...); |
| 114 | if (context->IsDomain()) { | ||
| 115 | context->AddDomainObject(std::move(iface)); | ||
| 116 | } else { | ||
| 117 | auto port = iface->CreatePort(); | ||
| 118 | auto session = port->Connect(); | ||
| 119 | ASSERT(session.Succeeded()); | ||
| 120 | context->AddMoveObject(std::move(session).Unwrap()); | ||
| 121 | } | ||
| 104 | } | 122 | } |
| 105 | 123 | ||
| 106 | // Validate on destruction, as there shouldn't be any case where we don't want it | 124 | // Validate on destruction, as there shouldn't be any case where we don't want it |
diff --git a/src/core/hle/kernel/domain.cpp b/src/core/hle/kernel/domain.cpp index 7ebb4b9c7..5035e9c08 100644 --- a/src/core/hle/kernel/domain.cpp +++ b/src/core/hle/kernel/domain.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 5 | #include "core/hle/kernel/client_port.h" | 7 | #include "core/hle/kernel/client_port.h" |
| 6 | #include "core/hle/kernel/domain.h" | 8 | #include "core/hle/kernel/domain.h" |
| 7 | #include "core/hle/kernel/handle_table.h" | 9 | #include "core/hle/kernel/handle_table.h" |
| @@ -36,7 +38,24 @@ ResultCode Domain::SendSyncRequest(SharedPtr<Thread> thread) { | |||
| 36 | if (domain_message_header) { | 38 | if (domain_message_header) { |
| 37 | // If there is a DomainMessageHeader, then this is CommandType "Request" | 39 | // If there is a DomainMessageHeader, then this is CommandType "Request" |
| 38 | const u32 object_id{context.GetDomainMessageHeader()->object_id}; | 40 | const u32 object_id{context.GetDomainMessageHeader()->object_id}; |
| 39 | return request_handlers[object_id - 1]->HandleSyncRequest(context); | 41 | switch (domain_message_header->command) { |
| 42 | case IPC::DomainMessageHeader::CommandType::SendMessage: | ||
| 43 | return request_handlers[object_id - 1]->HandleSyncRequest(context); | ||
| 44 | |||
| 45 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | ||
| 46 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id); | ||
| 47 | |||
| 48 | request_handlers[object_id - 1] = nullptr; | ||
| 49 | |||
| 50 | IPC::RequestBuilder rb{context, 2}; | ||
| 51 | rb.Push(RESULT_SUCCESS); | ||
| 52 | |||
| 53 | return RESULT_SUCCESS; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | LOG_CRITICAL(IPC, "Unknown domain command=%d", domain_message_header->command.Value()); | ||
| 58 | UNIMPLEMENTED(); | ||
| 40 | } | 59 | } |
| 41 | return request_handlers.front()->HandleSyncRequest(context); | 60 | return request_handlers.front()->HandleSyncRequest(context); |
| 42 | } | 61 | } |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index afa09b404..ac62a0d5a 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -102,13 +102,21 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 102 | data_payload_header = | 102 | data_payload_header = |
| 103 | std::make_unique<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>()); | 103 | std::make_unique<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>()); |
| 104 | 104 | ||
| 105 | data_payload_offset = rp.GetCurrentOffset(); | ||
| 106 | |||
| 107 | if (domain_message_header && | ||
| 108 | domain_message_header->command == | ||
| 109 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { | ||
| 110 | // CloseVirtualHandle command does not have SFC* or any data | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 105 | if (incoming) { | 114 | if (incoming) { |
| 106 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); | 115 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); |
| 107 | } else { | 116 | } else { |
| 108 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 117 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); |
| 109 | } | 118 | } |
| 110 | 119 | ||
| 111 | data_payload_offset = rp.GetCurrentOffset(); | ||
| 112 | command = rp.Pop<u32_le>(); | 120 | command = rp.Pop<u32_le>(); |
| 113 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. | 121 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. |
| 114 | } | 122 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 09caa43df..6dceb766d 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -151,13 +151,13 @@ public: | |||
| 151 | return domain != nullptr; | 151 | return domain != nullptr; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | template<typename T> | 154 | template <typename T> |
| 155 | SharedPtr<T> GetCopyObject(size_t index) { | 155 | SharedPtr<T> GetCopyObject(size_t index) { |
| 156 | ASSERT(index < copy_objects.size()); | 156 | ASSERT(index < copy_objects.size()); |
| 157 | return DynamicObjectCast<T>(copy_objects[index]); | 157 | return DynamicObjectCast<T>(copy_objects[index]); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | template<typename T> | 160 | template <typename T> |
| 161 | SharedPtr<T> GetMoveObject(size_t index) { | 161 | SharedPtr<T> GetMoveObject(size_t index) { |
| 162 | ASSERT(index < move_objects.size()); | 162 | ASSERT(index < move_objects.size()); |
| 163 | return DynamicObjectCast<T>(move_objects[index]); | 163 | return DynamicObjectCast<T>(move_objects[index]); |
| @@ -175,6 +175,14 @@ public: | |||
| 175 | domain_objects.emplace_back(std::move(object)); | 175 | domain_objects.emplace_back(std::move(object)); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | /// Clears the list of objects so that no lingering objects are written accidentally to the | ||
| 179 | /// response buffer. | ||
| 180 | void ClearIncomingObjects() { | ||
| 181 | move_objects.clear(); | ||
| 182 | copy_objects.clear(); | ||
| 183 | domain_objects.clear(); | ||
| 184 | } | ||
| 185 | |||
| 178 | private: | 186 | private: |
| 179 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | 187 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; |
| 180 | SharedPtr<Kernel::Domain> domain; | 188 | SharedPtr<Kernel::Domain> domain; |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index df3b4083e..4d9549e45 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -105,7 +105,6 @@ public: | |||
| 105 | UNREACHABLE(); | 105 | UNREACHABLE(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | |||
| 109 | public: | 108 | public: |
| 110 | static unsigned int next_object_id; | 109 | static unsigned int next_object_id; |
| 111 | 110 | ||
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index d990d0569..d2600cdd7 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp | |||
| @@ -95,10 +95,8 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) { | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) { | 98 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {} |
| 99 | } | ||
| 100 | 99 | ||
| 101 | void MapSharedPages(VMManager& address_space) { | 100 | void MapSharedPages(VMManager& address_space) {} |
| 102 | } | ||
| 103 | 101 | ||
| 104 | } // namespace Kernel | 102 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 49b6b454e..38db21005 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -41,9 +41,9 @@ public: | |||
| 41 | return HANDLE_TYPE; | 41 | return HANDLE_TYPE; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | u32 priority; ///< The priority of the mutex, used for priority inheritance. | 44 | u32 priority; ///< The priority of the mutex, used for priority inheritance. |
| 45 | std::string name; ///< Name of mutex (optional) | 45 | std::string name; ///< Name of mutex (optional) |
| 46 | VAddr guest_addr; ///< Address of the guest mutex value | 46 | VAddr guest_addr; ///< Address of the guest mutex value |
| 47 | 47 | ||
| 48 | /** | 48 | /** |
| 49 | * Elevate the mutex priority to the best priority | 49 | * Elevate the mutex priority to the best priority |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 20b4e401c..add98472f 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -131,6 +131,8 @@ public: | |||
| 131 | /// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse | 131 | /// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse |
| 132 | /// this value from the process header. | 132 | /// this value from the process header. |
| 133 | u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK; | 133 | u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK; |
| 134 | u32 allowed_thread_priority_mask = 0xFFFFFFFF; | ||
| 135 | u32 is_virtual_address_memory_enabled = 0; | ||
| 134 | /// Current status of the process | 136 | /// Current status of the process |
| 135 | ProcessStatus status; | 137 | ProcessStatus status; |
| 136 | 138 | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9c60576c1..6401af35a 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -255,9 +255,8 @@ static ResultCode CancelSynchronization(Handle thread_handle) { | |||
| 255 | /// Attempts to locks a mutex, creating it if it does not already exist | 255 | /// Attempts to locks a mutex, creating it if it does not already exist |
| 256 | static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr, | 256 | static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr, |
| 257 | Handle requesting_thread_handle) { | 257 | Handle requesting_thread_handle) { |
| 258 | LOG_TRACE(Kernel_SVC, | 258 | LOG_TRACE(Kernel_SVC, "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " |
| 259 | "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " | 259 | "requesting_current_thread_handle=0x%08X", |
| 260 | "requesting_current_thread_handle=0x%08X", | ||
| 261 | holding_thread_handle, mutex_addr, requesting_thread_handle); | 260 | holding_thread_handle, mutex_addr, requesting_thread_handle); |
| 262 | 261 | ||
| 263 | SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); | 262 | SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); |
| @@ -305,14 +304,27 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 305 | LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, | 304 | LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, |
| 306 | info_sub_id, handle); | 305 | info_sub_id, handle); |
| 307 | 306 | ||
| 308 | ASSERT(handle == 0 || handle == CurrentProcess); | ||
| 309 | |||
| 310 | auto& vm_manager = g_current_process->vm_manager; | 307 | auto& vm_manager = g_current_process->vm_manager; |
| 311 | 308 | ||
| 312 | switch (static_cast<GetInfoType>(info_id)) { | 309 | switch (static_cast<GetInfoType>(info_id)) { |
| 313 | case GetInfoType::AllowedCpuIdBitmask: | 310 | case GetInfoType::AllowedCpuIdBitmask: |
| 314 | *result = g_current_process->allowed_processor_mask; | 311 | *result = g_current_process->allowed_processor_mask; |
| 315 | break; | 312 | break; |
| 313 | case GetInfoType::AllowedThreadPrioBitmask: | ||
| 314 | *result = g_current_process->allowed_thread_priority_mask; | ||
| 315 | break; | ||
| 316 | case GetInfoType::MapRegionBaseAddr: | ||
| 317 | *result = vm_manager.GetAddressSpaceBaseAddr(); | ||
| 318 | break; | ||
| 319 | case GetInfoType::MapRegionSize: | ||
| 320 | *result = vm_manager.GetAddressSpaceSize(); | ||
| 321 | break; | ||
| 322 | case GetInfoType::HeapRegionBaseAddr: | ||
| 323 | *result = vm_manager.GetNewMapRegionBaseAddr() + vm_manager.GetNewMapRegionSize(); | ||
| 324 | break; | ||
| 325 | case GetInfoType::HeapRegionSize: | ||
| 326 | *result = Memory::HEAP_SIZE; | ||
| 327 | break; | ||
| 316 | case GetInfoType::TotalMemoryUsage: | 328 | case GetInfoType::TotalMemoryUsage: |
| 317 | *result = vm_manager.GetTotalMemoryUsage(); | 329 | *result = vm_manager.GetTotalMemoryUsage(); |
| 318 | break; | 330 | break; |
| @@ -334,6 +346,18 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 334 | case GetInfoType::NewMapRegionSize: | 346 | case GetInfoType::NewMapRegionSize: |
| 335 | *result = vm_manager.GetNewMapRegionSize(); | 347 | *result = vm_manager.GetNewMapRegionSize(); |
| 336 | break; | 348 | break; |
| 349 | case GetInfoType::IsVirtualAddressMemoryEnabled: | ||
| 350 | *result = g_current_process->is_virtual_address_memory_enabled; | ||
| 351 | break; | ||
| 352 | case GetInfoType::TitleId: | ||
| 353 | LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); | ||
| 354 | *result = 0; | ||
| 355 | break; | ||
| 356 | case GetInfoType::PrivilegedProcessId: | ||
| 357 | LOG_WARNING(Kernel_SVC, | ||
| 358 | "(STUBBED) Attempted to query priviledged process id bounds, returned 0"); | ||
| 359 | *result = 0; | ||
| 360 | break; | ||
| 337 | default: | 361 | default: |
| 338 | UNIMPLEMENTED(); | 362 | UNIMPLEMENTED(); |
| 339 | } | 363 | } |
| @@ -522,9 +546,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V | |||
| 522 | 546 | ||
| 523 | Core::System::GetInstance().PrepareReschedule(); | 547 | Core::System::GetInstance().PrepareReschedule(); |
| 524 | 548 | ||
| 525 | LOG_TRACE(Kernel_SVC, | 549 | LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " |
| 526 | "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 550 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", |
| 527 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", | ||
| 528 | entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); | 551 | entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); |
| 529 | 552 | ||
| 530 | return RESULT_SUCCESS; | 553 | return RESULT_SUCCESS; |
| @@ -709,6 +732,11 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 | |||
| 709 | return RESULT_SUCCESS; | 732 | return RESULT_SUCCESS; |
| 710 | } | 733 | } |
| 711 | 734 | ||
| 735 | static ResultCode SetThreadCoreMask(u64, u64, u64) { | ||
| 736 | LOG_WARNING(Kernel_SVC, "(STUBBED) called"); | ||
| 737 | return RESULT_SUCCESS; | ||
| 738 | } | ||
| 739 | |||
| 712 | namespace { | 740 | namespace { |
| 713 | struct FunctionDef { | 741 | struct FunctionDef { |
| 714 | using Func = void(); | 742 | using Func = void(); |
| @@ -735,7 +763,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 735 | {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, | 763 | {0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"}, |
| 736 | {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, | 764 | {0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"}, |
| 737 | {0x0E, nullptr, "GetThreadCoreMask"}, | 765 | {0x0E, nullptr, "GetThreadCoreMask"}, |
| 738 | {0x0F, nullptr, "SetThreadCoreMask"}, | 766 | {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, |
| 739 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, | 767 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, |
| 740 | {0x11, nullptr, "SignalEvent"}, | 768 | {0x11, nullptr, "SignalEvent"}, |
| 741 | {0x12, nullptr, "ClearEvent"}, | 769 | {0x12, nullptr, "ClearEvent"}, |
diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index 610cd1d7d..42cc41da3 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h | |||
| @@ -24,14 +24,28 @@ struct PageInfo { | |||
| 24 | enum class GetInfoType : u64 { | 24 | enum class GetInfoType : u64 { |
| 25 | // 1.0.0+ | 25 | // 1.0.0+ |
| 26 | AllowedCpuIdBitmask = 0, | 26 | AllowedCpuIdBitmask = 0, |
| 27 | AllowedThreadPrioBitmask = 1, | ||
| 28 | MapRegionBaseAddr = 2, | ||
| 29 | MapRegionSize = 3, | ||
| 30 | HeapRegionBaseAddr = 4, | ||
| 31 | HeapRegionSize = 5, | ||
| 27 | TotalMemoryUsage = 6, | 32 | TotalMemoryUsage = 6, |
| 28 | TotalHeapUsage = 7, | 33 | TotalHeapUsage = 7, |
| 34 | IsCurrentProcessBeingDebugged = 8, | ||
| 35 | ResourceHandleLimit = 9, | ||
| 36 | IdleTickCount = 10, | ||
| 29 | RandomEntropy = 11, | 37 | RandomEntropy = 11, |
| 38 | PerformanceCounter = 0xF0000002, | ||
| 30 | // 2.0.0+ | 39 | // 2.0.0+ |
| 31 | AddressSpaceBaseAddr = 12, | 40 | AddressSpaceBaseAddr = 12, |
| 32 | AddressSpaceSize = 13, | 41 | AddressSpaceSize = 13, |
| 33 | NewMapRegionBaseAddr = 14, | 42 | NewMapRegionBaseAddr = 14, |
| 34 | NewMapRegionSize = 15, | 43 | NewMapRegionSize = 15, |
| 44 | // 3.0.0+ | ||
| 45 | IsVirtualAddressMemoryEnabled = 16, | ||
| 46 | TitleId = 18, | ||
| 47 | // 4.0.0+ | ||
| 48 | PrivilegedProcessId = 19, | ||
| 35 | }; | 49 | }; |
| 36 | 50 | ||
| 37 | void CallSVC(u32 immediate); | 51 | void CallSVC(u32 immediate); |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index dca637dde..bf261699e 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -6,9 +6,9 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/arm/arm_interface.h" | 8 | #include "core/arm/arm_interface.h" |
| 9 | #include "core/core.h" | ||
| 9 | #include "core/hle/kernel/errors.h" | 10 | #include "core/hle/kernel/errors.h" |
| 10 | #include "core/hle/kernel/vm_manager.h" | 11 | #include "core/hle/kernel/vm_manager.h" |
| 11 | #include "core/core.h" | ||
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | #include "core/memory_setup.h" | 13 | #include "core/memory_setup.h" |
| 14 | #include "core/mmio.h" | 14 | #include "core/mmio.h" |
| @@ -86,7 +86,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | |||
| 86 | VirtualMemoryArea& final_vma = vma_handle->second; | 86 | VirtualMemoryArea& final_vma = vma_handle->second; |
| 87 | ASSERT(final_vma.size == size); | 87 | ASSERT(final_vma.size == size); |
| 88 | 88 | ||
| 89 | Core::CPU().MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute); | 89 | Core::CPU().MapBackingMemory(target, size, block->data() + offset, |
| 90 | VMAPermission::ReadWriteExecute); | ||
| 90 | 91 | ||
| 91 | final_vma.type = VMAType::AllocatedMemoryBlock; | 92 | final_vma.type = VMAType::AllocatedMemoryBlock; |
| 92 | final_vma.permissions = VMAPermission::ReadWrite; | 93 | final_vma.permissions = VMAPermission::ReadWrite; |
| @@ -356,12 +357,12 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { | |||
| 356 | 357 | ||
| 357 | u64 VMManager::GetTotalMemoryUsage() { | 358 | u64 VMManager::GetTotalMemoryUsage() { |
| 358 | LOG_WARNING(Kernel, "(STUBBED) called"); | 359 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 359 | return 0x400000; | 360 | return 0xBE000000; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | u64 VMManager::GetTotalHeapUsage() { | 363 | u64 VMManager::GetTotalHeapUsage() { |
| 363 | LOG_WARNING(Kernel, "(STUBBED) called"); | 364 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 364 | return 0x10000; | 365 | return 0x0; |
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | VAddr VMManager::GetAddressSpaceBaseAddr() { | 368 | VAddr VMManager::GetAddressSpaceBaseAddr() { |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp new file mode 100644 index 000000000..5716577d6 --- /dev/null +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/acc/acc.h" | ||
| 6 | #include "core/hle/service/acc/acc_u0.h" | ||
| 7 | |||
| 8 | namespace Service { | ||
| 9 | namespace Account { | ||
| 10 | |||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||
| 12 | std::make_shared<ACC_U0>()->InstallAsService(service_manager); | ||
| 13 | } | ||
| 14 | |||
| 15 | } // namespace Account | ||
| 16 | } // namespace Service | ||
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h new file mode 100644 index 000000000..44d024f48 --- /dev/null +++ b/src/core/hle/service/acc/acc.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 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 "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | namespace Account { | ||
| 11 | |||
| 12 | /// Registers all ACC services with the specified service manager. | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | ||
| 14 | |||
| 15 | } // namespace Account | ||
| 16 | } // namespace Service | ||
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp new file mode 100644 index 000000000..147f4e62e --- /dev/null +++ b/src/core/hle/service/acc/acc_u0.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 7 | #include "core/hle/service/acc/acc_u0.h" | ||
| 8 | |||
| 9 | namespace Service { | ||
| 10 | namespace Account { | ||
| 11 | |||
| 12 | void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { | ||
| 13 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 14 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 15 | rb.Push(RESULT_SUCCESS); | ||
| 16 | } | ||
| 17 | |||
| 18 | ACC_U0::ACC_U0() : ServiceFramework("acc:u0") { | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, | ||
| 21 | }; | ||
| 22 | RegisterHandlers(functions); | ||
| 23 | } | ||
| 24 | |||
| 25 | } // namespace Account | ||
| 26 | } // namespace Service | ||
diff --git a/src/core/hle/service/time/time_s.h b/src/core/hle/service/acc/acc_u0.h index 073227910..ac243d5b8 100644 --- a/src/core/hle/service/time/time_s.h +++ b/src/core/hle/service/acc/acc_u0.h | |||
| @@ -4,20 +4,19 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/hle_ipc.h" | ||
| 8 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 9 | 8 | ||
| 10 | namespace Service { | 9 | namespace Service { |
| 11 | namespace Time { | 10 | namespace Account { |
| 12 | 11 | ||
| 13 | class TimeS final : public ServiceFramework<TimeS> { | 12 | class ACC_U0 final : public ServiceFramework<ACC_U0> { |
| 14 | public: | 13 | public: |
| 15 | TimeS(); | 14 | ACC_U0(); |
| 16 | ~TimeS() = default; | 15 | ~ACC_U0() = default; |
| 17 | 16 | ||
| 18 | private: | 17 | private: |
| 19 | void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); | 18 | void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); |
| 20 | }; | 19 | }; |
| 21 | 20 | ||
| 22 | } // namespace Time | 21 | } // namespace Account |
| 23 | } // namespace Service | 22 | } // namespace Service |
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index f65d6b9f5..b360e7e5f 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/event.h" | 7 | #include "core/hle/kernel/event.h" |
| 8 | #include "core/hle/service/am/applet_oe.h" | 8 | #include "core/hle/service/am/applet_oe.h" |
| 9 | #include "core/hle/service/apm/apm.h" | ||
| 9 | 10 | ||
| 10 | namespace Service { | 11 | namespace Service { |
| 11 | namespace AM { | 12 | namespace AM { |
| @@ -54,7 +55,14 @@ class ISelfController final : public ServiceFramework<ISelfController> { | |||
| 54 | public: | 55 | public: |
| 55 | ISelfController() : ServiceFramework("ISelfController") { | 56 | ISelfController() : ServiceFramework("ISelfController") { |
| 56 | static const FunctionInfo functions[] = { | 57 | static const FunctionInfo functions[] = { |
| 58 | {11, &ISelfController::SetOperationModeChangedNotification, | ||
| 59 | "SetOperationModeChangedNotification"}, | ||
| 60 | {12, &ISelfController::SetPerformanceModeChangedNotification, | ||
| 61 | "SetPerformanceModeChangedNotification"}, | ||
| 57 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, | 62 | {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, |
| 63 | {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, | ||
| 64 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, | ||
| 65 | "SetOutOfFocusSuspendingEnabled"}, | ||
| 58 | }; | 66 | }; |
| 59 | RegisterHandlers(functions); | 67 | RegisterHandlers(functions); |
| 60 | } | 68 | } |
| @@ -64,11 +72,62 @@ private: | |||
| 64 | // Takes 3 input u8s with each field located immediately after the previous u8, these are | 72 | // Takes 3 input u8s with each field located immediately after the previous u8, these are |
| 65 | // bool flags. No output. | 73 | // bool flags. No output. |
| 66 | 74 | ||
| 75 | IPC::RequestParser rp{ctx}; | ||
| 76 | |||
| 77 | struct FocusHandlingModeParams { | ||
| 78 | u8 unknown0; | ||
| 79 | u8 unknown1; | ||
| 80 | u8 unknown2; | ||
| 81 | }; | ||
| 82 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 83 | |||
| 84 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(RESULT_SUCCESS); | ||
| 86 | |||
| 87 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 88 | } | ||
| 89 | |||
| 90 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { | ||
| 67 | IPC::RequestBuilder rb{ctx, 2}; | 91 | IPC::RequestBuilder rb{ctx, 2}; |
| 68 | rb.Push(RESULT_SUCCESS); | 92 | rb.Push(RESULT_SUCCESS); |
| 69 | 93 | ||
| 70 | LOG_WARNING(Service, "(STUBBED) called"); | 94 | LOG_WARNING(Service, "(STUBBED) called"); |
| 71 | } | 95 | } |
| 96 | |||
| 97 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||
| 98 | IPC::RequestParser rp{ctx}; | ||
| 99 | |||
| 100 | bool flag = rp.Pop<bool>(); | ||
| 101 | |||
| 102 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 103 | rb.Push(RESULT_SUCCESS); | ||
| 104 | |||
| 105 | LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||
| 106 | } | ||
| 107 | |||
| 108 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||
| 109 | IPC::RequestParser rp{ctx}; | ||
| 110 | |||
| 111 | bool flag = rp.Pop<bool>(); | ||
| 112 | |||
| 113 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 114 | rb.Push(RESULT_SUCCESS); | ||
| 115 | |||
| 116 | LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||
| 117 | } | ||
| 118 | |||
| 119 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { | ||
| 120 | // Takes 3 input u8s with each field located immediately after the previous u8, these are | ||
| 121 | // bool flags. No output. | ||
| 122 | IPC::RequestParser rp{ctx}; | ||
| 123 | |||
| 124 | bool enabled = rp.Pop<bool>(); | ||
| 125 | |||
| 126 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(RESULT_SUCCESS); | ||
| 128 | |||
| 129 | LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); | ||
| 130 | } | ||
| 72 | }; | 131 | }; |
| 73 | 132 | ||
| 74 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 133 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
| @@ -77,6 +136,8 @@ public: | |||
| 77 | static const FunctionInfo functions[] = { | 136 | static const FunctionInfo functions[] = { |
| 78 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | 137 | {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, |
| 79 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | 138 | {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, |
| 139 | {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||
| 140 | {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||
| 80 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | 141 | {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, |
| 81 | }; | 142 | }; |
| 82 | RegisterHandlers(functions); | 143 | RegisterHandlers(functions); |
| @@ -85,6 +146,16 @@ public: | |||
| 85 | } | 146 | } |
| 86 | 147 | ||
| 87 | private: | 148 | private: |
| 149 | enum class FocusState : u8 { | ||
| 150 | InFocus = 1, | ||
| 151 | NotInFocus = 2, | ||
| 152 | }; | ||
| 153 | |||
| 154 | enum class OperationMode : u8 { | ||
| 155 | Handheld = 0, | ||
| 156 | Docked = 1, | ||
| 157 | }; | ||
| 158 | |||
| 88 | void GetEventHandle(Kernel::HLERequestContext& ctx) { | 159 | void GetEventHandle(Kernel::HLERequestContext& ctx) { |
| 89 | event->Signal(); | 160 | event->Signal(); |
| 90 | 161 | ||
| @@ -106,7 +177,23 @@ private: | |||
| 106 | void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { | 177 | void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { |
| 107 | IPC::RequestBuilder rb{ctx, 3}; | 178 | IPC::RequestBuilder rb{ctx, 3}; |
| 108 | rb.Push(RESULT_SUCCESS); | 179 | rb.Push(RESULT_SUCCESS); |
| 109 | rb.Push<u32>(1); // 1: In focus, 2/3: Out of focus(running in "background") | 180 | rb.Push(static_cast<u8>(FocusState::InFocus)); |
| 181 | |||
| 182 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 183 | } | ||
| 184 | |||
| 185 | void GetOperationMode(Kernel::HLERequestContext& ctx) { | ||
| 186 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 187 | rb.Push(RESULT_SUCCESS); | ||
| 188 | rb.Push(static_cast<u8>(OperationMode::Handheld)); | ||
| 189 | |||
| 190 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 191 | } | ||
| 192 | |||
| 193 | void GetPerformanceMode(Kernel::HLERequestContext& ctx) { | ||
| 194 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 195 | rb.Push(RESULT_SUCCESS); | ||
| 196 | rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld)); | ||
| 110 | 197 | ||
| 111 | LOG_WARNING(Service, "(STUBBED) called"); | 198 | LOG_WARNING(Service, "(STUBBED) called"); |
| 112 | } | 199 | } |
| @@ -119,6 +206,10 @@ public: | |||
| 119 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { | 206 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { |
| 120 | static const FunctionInfo functions[] = { | 207 | static const FunctionInfo functions[] = { |
| 121 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | 208 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, |
| 209 | {66, &IApplicationFunctions::InitializeGamePlayRecording, | ||
| 210 | "InitializeGamePlayRecording"}, | ||
| 211 | {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||
| 212 | {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||
| 122 | }; | 213 | }; |
| 123 | RegisterHandlers(functions); | 214 | RegisterHandlers(functions); |
| 124 | } | 215 | } |
| @@ -136,6 +227,27 @@ private: | |||
| 136 | 227 | ||
| 137 | LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); | 228 | LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); |
| 138 | } | 229 | } |
| 230 | |||
| 231 | void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { | ||
| 232 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 233 | rb.Push(RESULT_SUCCESS); | ||
| 234 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 235 | } | ||
| 236 | |||
| 237 | void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { | ||
| 238 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 239 | rb.Push(RESULT_SUCCESS); | ||
| 240 | |||
| 241 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 242 | } | ||
| 243 | |||
| 244 | void NotifyRunning(Kernel::HLERequestContext& ctx) { | ||
| 245 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 246 | rb.Push(RESULT_SUCCESS); | ||
| 247 | rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||
| 248 | |||
| 249 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 250 | } | ||
| 139 | }; | 251 | }; |
| 140 | 252 | ||
| 141 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | 253 | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { |
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index f70b9fc10..66d94ff52 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp | |||
| @@ -13,13 +13,54 @@ void InstallInterfaces(SM::ServiceManager& service_manager) { | |||
| 13 | std::make_shared<APM>()->InstallAsService(service_manager); | 13 | std::make_shared<APM>()->InstallAsService(service_manager); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | class ISession final : public ServiceFramework<ISession> { | ||
| 17 | public: | ||
| 18 | ISession() : ServiceFramework("ISession") { | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, | ||
| 21 | {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, | ||
| 22 | }; | ||
| 23 | RegisterHandlers(functions); | ||
| 24 | } | ||
| 25 | |||
| 26 | private: | ||
| 27 | void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||
| 28 | IPC::RequestParser rp{ctx}; | ||
| 29 | |||
| 30 | auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||
| 31 | u32 config = rp.Pop<u32>(); | ||
| 32 | |||
| 33 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 34 | rb.Push(RESULT_SUCCESS); | ||
| 35 | |||
| 36 | LOG_WARNING(Service, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), config); | ||
| 37 | } | ||
| 38 | |||
| 39 | void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||
| 40 | IPC::RequestParser rp{ctx}; | ||
| 41 | |||
| 42 | auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||
| 43 | |||
| 44 | IPC::RequestBuilder rb{ctx, 3}; | ||
| 45 | rb.Push(RESULT_SUCCESS); | ||
| 46 | rb.Push<u32>(0); // Performance configuration | ||
| 47 | |||
| 48 | LOG_WARNING(Service, "(STUBBED) called mode=%u", static_cast<u32>(mode)); | ||
| 49 | } | ||
| 50 | }; | ||
| 51 | |||
| 16 | APM::APM() : ServiceFramework("apm") { | 52 | APM::APM() : ServiceFramework("apm") { |
| 17 | static const FunctionInfo functions[] = { | 53 | static const FunctionInfo functions[] = { |
| 18 | {0x00000000, nullptr, "OpenSession"}, | 54 | {0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"}, |
| 19 | {0x00000001, nullptr, "GetPerformanceMode"}, | ||
| 20 | }; | 55 | }; |
| 21 | RegisterHandlers(functions); | 56 | RegisterHandlers(functions); |
| 22 | } | 57 | } |
| 23 | 58 | ||
| 59 | void APM::OpenSession(Kernel::HLERequestContext& ctx) { | ||
| 60 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 61 | rb.Push(RESULT_SUCCESS); | ||
| 62 | rb.PushIpcInterface<ISession>(); | ||
| 63 | } | ||
| 64 | |||
| 24 | } // namespace APM | 65 | } // namespace APM |
| 25 | } // namespace Service | 66 | } // namespace Service |
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h index 377db71a4..90a1afbbc 100644 --- a/src/core/hle/service/apm/apm.h +++ b/src/core/hle/service/apm/apm.h | |||
| @@ -9,10 +9,18 @@ | |||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | namespace APM { | 10 | namespace APM { |
| 11 | 11 | ||
| 12 | enum class PerformanceMode : u8 { | ||
| 13 | Handheld = 0, | ||
| 14 | Docked = 1, | ||
| 15 | }; | ||
| 16 | |||
| 12 | class APM final : public ServiceFramework<APM> { | 17 | class APM final : public ServiceFramework<APM> { |
| 13 | public: | 18 | public: |
| 14 | APM(); | 19 | APM(); |
| 15 | ~APM() = default; | 20 | ~APM() = default; |
| 21 | |||
| 22 | private: | ||
| 23 | void OpenSession(Kernel::HLERequestContext& ctx); | ||
| 16 | }; | 24 | }; |
| 17 | 25 | ||
| 18 | /// Registers all AM services with the specified service manager. | 26 | /// Registers all AM services with the specified service manager. |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 3c4259d27..be7a6ff65 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -18,9 +18,9 @@ namespace HID { | |||
| 18 | 18 | ||
| 19 | // Updating period for each HID device. | 19 | // Updating period for each HID device. |
| 20 | // TODO(shinyquagsire23): These need better values. | 20 | // TODO(shinyquagsire23): These need better values. |
| 21 | constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 234; | 21 | constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 10000; |
| 22 | constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 104; | 22 | constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 10000; |
| 23 | constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 101; | 23 | constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 10000; |
| 24 | 24 | ||
| 25 | class IAppletResource final : public ServiceFramework<IAppletResource> { | 25 | class IAppletResource final : public ServiceFramework<IAppletResource> { |
| 26 | public: | 26 | public: |
| @@ -65,44 +65,71 @@ private: | |||
| 65 | if (is_device_reload_pending.exchange(false)) | 65 | if (is_device_reload_pending.exchange(false)) |
| 66 | LoadInputDevices(); | 66 | LoadInputDevices(); |
| 67 | 67 | ||
| 68 | // TODO(shinyquagsire23): This is a hack! | 68 | // Set up controllers as neon red+blue Joy-Con attached to console |
| 69 | ControllerPadState& state = | 69 | ControllerHeader& controller_header = mem->controllers[Controller_Handheld].header; |
| 70 | mem->controllers[Controller_Handheld].layouts[Layout_Default].entries[0].buttons; | 70 | controller_header.type = ControllerType_Handheld | ControllerType_JoyconPair; |
| 71 | using namespace Settings::NativeButton; | 71 | controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent; |
| 72 | state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); | 72 | controller_header.right_color_body = JOYCON_BODY_NEON_RED; |
| 73 | state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); | 73 | controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED; |
| 74 | state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); | 74 | controller_header.left_color_body = JOYCON_BODY_NEON_BLUE; |
| 75 | state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); | 75 | controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE; |
| 76 | state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); | 76 | |
| 77 | state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); | 77 | for (int layoutIdx = 0; layoutIdx < HID_NUM_LAYOUTS; layoutIdx++) { |
| 78 | state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); | 78 | ControllerLayout& layout = mem->controllers[Controller_Handheld].layouts[layoutIdx]; |
| 79 | state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); | 79 | layout.header.num_entries = HID_NUM_ENTRIES; |
| 80 | state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); | 80 | layout.header.max_entry_index = HID_NUM_ENTRIES - 1; |
| 81 | state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); | 81 | |
| 82 | state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); | 82 | // HID shared memory stores the state of the past 17 samples in a circlular buffer, |
| 83 | state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); | 83 | // each with a timestamp in number of samples since boot. |
| 84 | 84 | layout.header.timestamp_ticks = CoreTiming::GetTicks(); | |
| 85 | state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); | 85 | layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES; |
| 86 | state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); | 86 | |
| 87 | state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); | 87 | ControllerInputEntry& entry = layout.entries[layout.header.latest_entry]; |
| 88 | state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); | 88 | entry.connection_state = ConnectionState_Connected | ConnectionState_Wired; |
| 89 | 89 | entry.timestamp++; | |
| 90 | state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); | 90 | entry.timestamp_2++; // TODO(shinyquagsire23): Is this always identical to timestamp? |
| 91 | state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); | 91 | |
| 92 | state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); | 92 | // TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future? |
| 93 | state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); | 93 | // For now everything is just the default handheld layout, but split Joy-Con will |
| 94 | 94 | // rotate the face buttons and directions for certain layouts. | |
| 95 | state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); | 95 | ControllerPadState& state = entry.buttons; |
| 96 | state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); | 96 | using namespace Settings::NativeButton; |
| 97 | state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); | 97 | state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); |
| 98 | state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); | 98 | state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); |
| 99 | 99 | state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); | |
| 100 | state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); | 100 | state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); |
| 101 | state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); | 101 | state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); |
| 102 | 102 | state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); | |
| 103 | // TODO(shinyquagsire23): Analog stick vals | 103 | state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); |
| 104 | 104 | state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); | |
| 105 | // TODO(shinyquagsire23): Update pad info proper, (circular buffers, timestamps, layouts) | 105 | state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); |
| 106 | state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 107 | state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 108 | state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 109 | |||
| 110 | state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 111 | state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 112 | state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 113 | state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 114 | |||
| 115 | state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 116 | state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 117 | state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 118 | state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 119 | |||
| 120 | state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 121 | state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 122 | state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 123 | state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 124 | |||
| 125 | state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 126 | state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); | ||
| 127 | |||
| 128 | // TODO(shinyquagsire23): Analog stick vals | ||
| 129 | |||
| 130 | // TODO(shinyquagsire23): Update pad info proper, (circular buffers, timestamps, | ||
| 131 | // layouts) | ||
| 132 | } | ||
| 106 | 133 | ||
| 107 | // TODO(shinyquagsire23): Update touch info | 134 | // TODO(shinyquagsire23): Update touch info |
| 108 | 135 | ||
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 486e64800..3de9adb4b 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -12,6 +12,16 @@ namespace HID { | |||
| 12 | 12 | ||
| 13 | // Begin enums and output structs | 13 | // Begin enums and output structs |
| 14 | 14 | ||
| 15 | constexpr u32 HID_NUM_ENTRIES = 17; | ||
| 16 | constexpr u32 HID_NUM_LAYOUTS = 7; | ||
| 17 | constexpr s32 HID_JOYSTICK_MAX = 0x8000; | ||
| 18 | constexpr s32 HID_JOYSTICK_MIN = -0x8000; | ||
| 19 | |||
| 20 | constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; | ||
| 21 | constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; | ||
| 22 | constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; | ||
| 23 | constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; | ||
| 24 | |||
| 15 | enum ControllerType : u32 { | 25 | enum ControllerType : u32 { |
| 16 | ControllerType_ProController = 1 << 0, | 26 | ControllerType_ProController = 1 << 0, |
| 17 | ControllerType_Handheld = 1 << 1, | 27 | ControllerType_Handheld = 1 << 1, |
| @@ -57,10 +67,10 @@ enum ControllerID { | |||
| 57 | // Begin TouchScreen | 67 | // Begin TouchScreen |
| 58 | 68 | ||
| 59 | struct TouchScreenHeader { | 69 | struct TouchScreenHeader { |
| 60 | u64 timestampTicks; | 70 | u64 timestamp_ticks; |
| 61 | u64 numEntries; | 71 | u64 num_entries; |
| 62 | u64 latestEntry; | 72 | u64 latest_entry; |
| 63 | u64 maxEntryIndex; | 73 | u64 max_entry_index; |
| 64 | u64 timestamp; | 74 | u64 timestamp; |
| 65 | }; | 75 | }; |
| 66 | static_assert(sizeof(TouchScreenHeader) == 0x28, | 76 | static_assert(sizeof(TouchScreenHeader) == 0x28, |
| @@ -68,7 +78,7 @@ static_assert(sizeof(TouchScreenHeader) == 0x28, | |||
| 68 | 78 | ||
| 69 | struct TouchScreenEntryHeader { | 79 | struct TouchScreenEntryHeader { |
| 70 | u64 timestamp; | 80 | u64 timestamp; |
| 71 | u64 numTouches; | 81 | u64 num_touches; |
| 72 | }; | 82 | }; |
| 73 | static_assert(sizeof(TouchScreenEntryHeader) == 0x10, | 83 | static_assert(sizeof(TouchScreenEntryHeader) == 0x10, |
| 74 | "HID touch screen entry header structure has incorrect size"); | 84 | "HID touch screen entry header structure has incorrect size"); |
| @@ -76,11 +86,11 @@ static_assert(sizeof(TouchScreenEntryHeader) == 0x10, | |||
| 76 | struct TouchScreenEntryTouch { | 86 | struct TouchScreenEntryTouch { |
| 77 | u64 timestamp; | 87 | u64 timestamp; |
| 78 | u32 padding; | 88 | u32 padding; |
| 79 | u32 touchIndex; | 89 | u32 touch_index; |
| 80 | u32 x; | 90 | u32 x; |
| 81 | u32 y; | 91 | u32 y; |
| 82 | u32 diameterX; | 92 | u32 diameter_x; |
| 83 | u32 diameterY; | 93 | u32 diameter_y; |
| 84 | u32 angle; | 94 | u32 angle; |
| 85 | u32 padding_2; | 95 | u32 padding_2; |
| 86 | }; | 96 | }; |
| @@ -107,10 +117,10 @@ static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has inc | |||
| 107 | // Begin Mouse | 117 | // Begin Mouse |
| 108 | 118 | ||
| 109 | struct MouseHeader { | 119 | struct MouseHeader { |
| 110 | u64 timestampTicks; | 120 | u64 timestamp_ticks; |
| 111 | u64 numEntries; | 121 | u64 num_entries; |
| 112 | u64 latestEntry; | 122 | u64 latest_entry; |
| 113 | u64 maxEntryIndex; | 123 | u64 max_entry_index; |
| 114 | }; | 124 | }; |
| 115 | static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size"); | 125 | static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size"); |
| 116 | 126 | ||
| @@ -132,10 +142,10 @@ struct MouseEntry { | |||
| 132 | u64 timestamp_2; | 142 | u64 timestamp_2; |
| 133 | u32 x; | 143 | u32 x; |
| 134 | u32 y; | 144 | u32 y; |
| 135 | u32 velocityX; | 145 | u32 velocity_x; |
| 136 | u32 velocityY; | 146 | u32 velocity_y; |
| 137 | u32 scrollVelocityX; | 147 | u32 scroll_velocity_x; |
| 138 | u32 scrollVelocityY; | 148 | u32 scroll_velocity_y; |
| 139 | MouseButtonState buttons; | 149 | MouseButtonState buttons; |
| 140 | }; | 150 | }; |
| 141 | static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); | 151 | static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); |
| @@ -152,10 +162,10 @@ static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size"); | |||
| 152 | // Begin Keyboard | 162 | // Begin Keyboard |
| 153 | 163 | ||
| 154 | struct KeyboardHeader { | 164 | struct KeyboardHeader { |
| 155 | u64 timestampTicks; | 165 | u64 timestamp_ticks; |
| 156 | u64 numEntries; | 166 | u64 num_entries; |
| 157 | u64 latestEntry; | 167 | u64 latest_entry; |
| 158 | u64 maxEntryIndex; | 168 | u64 max_entry_index; |
| 159 | }; | 169 | }; |
| 160 | static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); | 170 | static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); |
| 161 | 171 | ||
| @@ -207,24 +217,24 @@ static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has i | |||
| 207 | 217 | ||
| 208 | struct ControllerHeader { | 218 | struct ControllerHeader { |
| 209 | u32 type; | 219 | u32 type; |
| 210 | u32 isHalf; | 220 | u32 is_half; |
| 211 | u32 singleColorsDescriptor; | 221 | u32 single_colors_descriptor; |
| 212 | u32 singleColorBody; | 222 | u32 single_color_body; |
| 213 | u32 singleColorButtons; | 223 | u32 single_color_buttons; |
| 214 | u32 splitColorsDescriptor; | 224 | u32 split_colors_descriptor; |
| 215 | u32 leftColorBody; | 225 | u32 left_color_body; |
| 216 | u32 leftColorButtons; | 226 | u32 left_color_buttons; |
| 217 | u32 rightColorBody; | 227 | u32 right_color_body; |
| 218 | u32 rightColorbuttons; | 228 | u32 right_color_buttons; |
| 219 | }; | 229 | }; |
| 220 | static_assert(sizeof(ControllerHeader) == 0x28, | 230 | static_assert(sizeof(ControllerHeader) == 0x28, |
| 221 | "HID controller header structure has incorrect size"); | 231 | "HID controller header structure has incorrect size"); |
| 222 | 232 | ||
| 223 | struct ControllerLayoutHeader { | 233 | struct ControllerLayoutHeader { |
| 224 | u64 timestampTicks; | 234 | u64 timestamp_ticks; |
| 225 | u64 numEntries; | 235 | u64 num_entries; |
| 226 | u64 latestEntry; | 236 | u64 latest_entry; |
| 227 | u64 maxEntryIndex; | 237 | u64 max_entry_index; |
| 228 | }; | 238 | }; |
| 229 | static_assert(sizeof(ControllerLayoutHeader) == 0x20, | 239 | static_assert(sizeof(ControllerLayoutHeader) == 0x20, |
| 230 | "HID controller layout header structure has incorrect size"); | 240 | "HID controller layout header structure has incorrect size"); |
| @@ -274,11 +284,11 @@ struct ControllerInputEntry { | |||
| 274 | u64 timestamp; | 284 | u64 timestamp; |
| 275 | u64 timestamp_2; | 285 | u64 timestamp_2; |
| 276 | ControllerPadState buttons; | 286 | ControllerPadState buttons; |
| 277 | u32 joystickLeftX; | 287 | u32 joystick_left_x; |
| 278 | u32 joystickLeftY; | 288 | u32 joystick_left_y; |
| 279 | u32 joystickRightX; | 289 | u32 joystick_right_x; |
| 280 | u32 joystickRightY; | 290 | u32 joystick_right_y; |
| 281 | u64 connectionState; | 291 | u64 connection_state; |
| 282 | }; | 292 | }; |
| 283 | static_assert(sizeof(ControllerInputEntry) == 0x30, | 293 | static_assert(sizeof(ControllerInputEntry) == 0x30, |
| 284 | "HID controller input entry structure has incorrect size"); | 294 | "HID controller input entry structure has incorrect size"); |
| @@ -294,8 +304,8 @@ struct Controller { | |||
| 294 | ControllerHeader header; | 304 | ControllerHeader header; |
| 295 | std::array<ControllerLayout, 7> layouts; | 305 | std::array<ControllerLayout, 7> layouts; |
| 296 | std::array<u8, 0x2a70> unk_1; | 306 | std::array<u8, 0x2a70> unk_1; |
| 297 | ControllerMAC macLeft; | 307 | ControllerMAC mac_left; |
| 298 | ControllerMAC macRight; | 308 | ControllerMAC mac_right; |
| 299 | std::array<u8, 0xdf8> unk_2; | 309 | std::array<u8, 0xdf8> unk_2; |
| 300 | }; | 310 | }; |
| 301 | static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size"); | 311 | static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size"); |
| @@ -307,17 +317,17 @@ struct SharedMemory { | |||
| 307 | TouchScreen touchscreen; | 317 | TouchScreen touchscreen; |
| 308 | Mouse mouse; | 318 | Mouse mouse; |
| 309 | Keyboard keyboard; | 319 | Keyboard keyboard; |
| 310 | std::array<u8, 0x400> unkSection1; | 320 | std::array<u8, 0x400> unk_section_1; |
| 311 | std::array<u8, 0x400> unkSection2; | 321 | std::array<u8, 0x400> unk_section_2; |
| 312 | std::array<u8, 0x400> unkSection3; | 322 | std::array<u8, 0x400> unk_section_3; |
| 313 | std::array<u8, 0x400> unkSection4; | 323 | std::array<u8, 0x400> unk_section_4; |
| 314 | std::array<u8, 0x200> unkSection5; | 324 | std::array<u8, 0x200> unk_section_5; |
| 315 | std::array<u8, 0x200> unkSection6; | 325 | std::array<u8, 0x200> unk_section_6; |
| 316 | std::array<u8, 0x200> unkSection7; | 326 | std::array<u8, 0x200> unk_section_7; |
| 317 | std::array<u8, 0x800> unkSection8; | 327 | std::array<u8, 0x800> unk_section_8; |
| 318 | std::array<u8, 0x4000> controllerSerials; | 328 | std::array<u8, 0x4000> controller_serials; |
| 319 | std::array<Controller, 10> controllers; | 329 | std::array<Controller, 10> controllers; |
| 320 | std::array<u8, 0x4600> unkSection9; | 330 | std::array<u8, 0x4600> unk_section_9; |
| 321 | }; | 331 | }; |
| 322 | static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); | 332 | static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); |
| 323 | 333 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 1ee2787c6..5ee33b3d6 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | 9 | ||
| 10 | namespace Service { | 10 | namespace Service { |
| 11 | namespace NVDRV { | 11 | namespace Nvidia { |
| 12 | namespace Devices { | 12 | namespace Devices { |
| 13 | 13 | ||
| 14 | /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to | 14 | /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to |
| @@ -29,5 +29,5 @@ public: | |||
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | } // namespace Devices | 31 | } // namespace Devices |
| 32 | } // namespace NVDRV | 32 | } // namespace Nvidia |
| 33 | } // namespace Service | 33 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 992f70b45..b65d79f11 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -4,13 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | ||
| 7 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 8 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| 8 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 9 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 10 | #include "video_core/video_core.h" | 11 | #include "video_core/video_core.h" |
| 11 | 12 | ||
| 12 | namespace Service { | 13 | namespace Service { |
| 13 | namespace NVDRV { | 14 | namespace Nvidia { |
| 14 | namespace Devices { | 15 | namespace Devices { |
| 15 | 16 | ||
| 16 | u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | 17 | u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { |
| @@ -28,9 +29,11 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 28 | using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; | 29 | using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; |
| 29 | const RendererBase::FramebufferInfo framebuffer_info{ | 30 | const RendererBase::FramebufferInfo framebuffer_info{ |
| 30 | addr, offset, width, height, stride, static_cast<PixelFormat>(format)}; | 31 | addr, offset, width, height, stride, static_cast<PixelFormat>(format)}; |
| 32 | |||
| 33 | Core::System::GetInstance().perf_stats.EndGameFrame(); | ||
| 31 | VideoCore::g_renderer->SwapBuffers(framebuffer_info); | 34 | VideoCore::g_renderer->SwapBuffers(framebuffer_info); |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | } // namespace Devices | 37 | } // namespace Devices |
| 35 | } // namespace NVDRV | 38 | } // namespace Nvidia |
| 36 | } // namespace Service | 39 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 601068af1..f5f9de3f4 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 11 | 11 | ||
| 12 | namespace Service { | 12 | namespace Service { |
| 13 | namespace NVDRV { | 13 | namespace Nvidia { |
| 14 | namespace Devices { | 14 | namespace Devices { |
| 15 | 15 | ||
| 16 | class nvmap; | 16 | class nvmap; |
| @@ -30,5 +30,5 @@ private: | |||
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | } // namespace Devices | 32 | } // namespace Devices |
| 33 | } // namespace NVDRV | 33 | } // namespace Nvidia |
| 34 | } // namespace Service | 34 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index c7bf79050..9db08339a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | 7 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" |
| 8 | 8 | ||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | namespace NVDRV { | 10 | namespace Nvidia { |
| 11 | namespace Devices { | 11 | namespace Devices { |
| 12 | 12 | ||
| 13 | u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | 13 | u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { |
| @@ -16,5 +16,5 @@ u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector< | |||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | } // namespace Devices | 18 | } // namespace Devices |
| 19 | } // namespace NVDRV | 19 | } // namespace Nvidia |
| 20 | } // namespace Service | 20 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 6f441b020..01f8861c8 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace NVDRV { | 12 | namespace Nvidia { |
| 13 | namespace Devices { | 13 | namespace Devices { |
| 14 | 14 | ||
| 15 | class nvhost_as_gpu final : public nvdevice { | 15 | class nvhost_as_gpu final : public nvdevice { |
| @@ -21,5 +21,5 @@ public: | |||
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | } // namespace Devices | 23 | } // namespace Devices |
| 24 | } // namespace NVDRV | 24 | } // namespace Nvidia |
| 25 | } // namespace Service | 25 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 2d6f30e3e..d37b5b159 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 10 | 10 | ||
| 11 | namespace Service { | 11 | namespace Service { |
| 12 | namespace NVDRV { | 12 | namespace Nvidia { |
| 13 | namespace Devices { | 13 | namespace Devices { |
| 14 | 14 | ||
| 15 | VAddr nvmap::GetObjectAddress(u32 handle) const { | 15 | VAddr nvmap::GetObjectAddress(u32 handle) const { |
| @@ -151,5 +151,5 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | } // namespace Devices | 153 | } // namespace Devices |
| 154 | } // namespace NVDRV | 154 | } // namespace Nvidia |
| 155 | } // namespace Service | 155 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index e74f356e5..6954c0324 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 13 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 14 | 14 | ||
| 15 | namespace Service { | 15 | namespace Service { |
| 16 | namespace NVDRV { | 16 | namespace Nvidia { |
| 17 | namespace Devices { | 17 | namespace Devices { |
| 18 | 18 | ||
| 19 | class nvmap final : public nvdevice { | 19 | class nvmap final : public nvdevice { |
| @@ -104,5 +104,5 @@ private: | |||
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | } // namespace Devices | 106 | } // namespace Devices |
| 107 | } // namespace NVDRV | 107 | } // namespace Nvidia |
| 108 | } // namespace Service | 108 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.cpp b/src/core/hle/service/nvdrv/interface.cpp index 84d89cb49..848615fa7 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -4,35 +4,27 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 7 | #include "core/hle/service/nvdrv/interface.h" |
| 8 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||
| 10 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 11 | #include "core/hle/service/nvdrv/nvdrv.h" | 8 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 12 | #include "core/hle/service/nvdrv/nvdrv_a.h" | ||
| 13 | 9 | ||
| 14 | namespace Service { | 10 | namespace Service { |
| 15 | namespace NVDRV { | 11 | namespace Nvidia { |
| 16 | 12 | ||
| 17 | void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { | 13 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { |
| 18 | LOG_WARNING(Service, "(STUBBED) called"); | 14 | LOG_WARNING(Service, "(STUBBED) called"); |
| 19 | 15 | ||
| 20 | auto buffer = ctx.BufferDescriptorA()[0]; | 16 | auto buffer = ctx.BufferDescriptorA()[0]; |
| 21 | 17 | ||
| 22 | std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); | 18 | std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); |
| 23 | 19 | ||
| 24 | auto device = devices[device_name]; | 20 | u32 fd = nvdrv->Open(device_name); |
| 25 | u32 fd = next_fd++; | ||
| 26 | |||
| 27 | open_files[fd] = device; | ||
| 28 | |||
| 29 | IPC::RequestBuilder rb{ctx, 4}; | 21 | IPC::RequestBuilder rb{ctx, 4}; |
| 30 | rb.Push(RESULT_SUCCESS); | 22 | rb.Push(RESULT_SUCCESS); |
| 31 | rb.Push<u32>(fd); | 23 | rb.Push<u32>(fd); |
| 32 | rb.Push<u32>(0); | 24 | rb.Push<u32>(0); |
| 33 | } | 25 | } |
| 34 | 26 | ||
| 35 | void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | 27 | void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { |
| 36 | LOG_WARNING(Service, "(STUBBED) called"); | 28 | LOG_WARNING(Service, "(STUBBED) called"); |
| 37 | 29 | ||
| 38 | IPC::RequestParser rp{ctx}; | 30 | IPC::RequestParser rp{ctx}; |
| @@ -46,11 +38,8 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | |||
| 46 | std::vector<u8> output(output_buffer.Size()); | 38 | std::vector<u8> output(output_buffer.Size()); |
| 47 | 39 | ||
| 48 | Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); | 40 | Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); |
| 49 | auto itr = open_files.find(fd); | ||
| 50 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||
| 51 | 41 | ||
| 52 | auto device = itr->second; | 42 | u32 nv_result = nvdrv->Ioctl(fd, command, input, output); |
| 53 | u32 nv_result = device->ioctl(command, input, output); | ||
| 54 | 43 | ||
| 55 | Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); | 44 | Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); |
| 56 | 45 | ||
| @@ -59,26 +48,35 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | |||
| 59 | rb.Push(nv_result); | 48 | rb.Push(nv_result); |
| 60 | } | 49 | } |
| 61 | 50 | ||
| 62 | void NVDRV_A::Initialize(Kernel::HLERequestContext& ctx) { | 51 | void NVDRV::Close(Kernel::HLERequestContext& ctx) { |
| 52 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 53 | |||
| 54 | IPC::RequestParser rp{ctx}; | ||
| 55 | u32 fd = rp.Pop<u32>(); | ||
| 56 | |||
| 57 | auto result = nvdrv->Close(fd); | ||
| 58 | |||
| 59 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 60 | rb.Push(result); | ||
| 61 | } | ||
| 62 | |||
| 63 | void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { | ||
| 63 | LOG_WARNING(Service, "(STUBBED) called"); | 64 | LOG_WARNING(Service, "(STUBBED) called"); |
| 64 | IPC::RequestBuilder rb{ctx, 3}; | 65 | IPC::RequestBuilder rb{ctx, 3}; |
| 65 | rb.Push(RESULT_SUCCESS); | 66 | rb.Push(RESULT_SUCCESS); |
| 66 | rb.Push<u32>(0); | 67 | rb.Push<u32>(0); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { | 70 | NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) |
| 71 | : ServiceFramework(name), nvdrv(std::move(nvdrv)) { | ||
| 70 | static const FunctionInfo functions[] = { | 72 | static const FunctionInfo functions[] = { |
| 71 | {0, &NVDRV_A::Open, "Open"}, | 73 | {0, &NVDRV::Open, "Open"}, |
| 72 | {1, &NVDRV_A::Ioctl, "Ioctl"}, | 74 | {1, &NVDRV::Ioctl, "Ioctl"}, |
| 73 | {3, &NVDRV_A::Initialize, "Initialize"}, | 75 | {2, &NVDRV::Close, "Close"}, |
| 76 | {3, &NVDRV::Initialize, "Initialize"}, | ||
| 74 | }; | 77 | }; |
| 75 | RegisterHandlers(functions); | 78 | RegisterHandlers(functions); |
| 76 | |||
| 77 | auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||
| 78 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||
| 79 | devices["/dev/nvmap"] = nvmap_dev; | ||
| 80 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | } // namespace NVDRV | 81 | } // namespace Nvidia |
| 84 | } // namespace Service | 82 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h new file mode 100644 index 000000000..1b9aa9938 --- /dev/null +++ b/src/core/hle/service/nvdrv/interface.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright 2018 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 | #include <string> | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace Nvidia { | ||
| 14 | |||
| 15 | class NVDRV final : public ServiceFramework<NVDRV> { | ||
| 16 | public: | ||
| 17 | NVDRV(std::shared_ptr<Module> nvdrv, const char* name); | ||
| 18 | ~NVDRV() = default; | ||
| 19 | |||
| 20 | private: | ||
| 21 | void Open(Kernel::HLERequestContext& ctx); | ||
| 22 | void Ioctl(Kernel::HLERequestContext& ctx); | ||
| 23 | void Close(Kernel::HLERequestContext& ctx); | ||
| 24 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 25 | |||
| 26 | std::shared_ptr<Module> nvdrv; | ||
| 27 | }; | ||
| 28 | |||
| 29 | } // namespace Nvidia | ||
| 30 | } // namespace Service | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index c874e6395..9b73886bb 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -2,19 +2,62 @@ | |||
| 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 "core/hle/ipc_helpers.h" | ||
| 6 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||
| 7 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||
| 8 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||
| 9 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 5 | #include "core/hle/service/nvdrv/nvdrv.h" | 10 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 6 | #include "core/hle/service/nvdrv/nvdrv_a.h" | 11 | #include "core/hle/service/nvdrv/interface.h" |
| 7 | 12 | ||
| 8 | namespace Service { | 13 | namespace Service { |
| 9 | namespace NVDRV { | 14 | namespace Nvidia { |
| 10 | 15 | ||
| 11 | std::weak_ptr<NVDRV_A> nvdrv_a; | 16 | std::weak_ptr<Module> nvdrv; |
| 12 | 17 | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 18 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
| 14 | auto nvdrv = std::make_shared<NVDRV_A>(); | 19 | auto module_ = std::make_shared<Module>(); |
| 15 | nvdrv->InstallAsService(service_manager); | 20 | std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager); |
| 16 | nvdrv_a = nvdrv; | 21 | std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager); |
| 22 | nvdrv = module_; | ||
| 17 | } | 23 | } |
| 18 | 24 | ||
| 19 | } // namespace NVDRV | 25 | Module::Module() { |
| 26 | auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||
| 27 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||
| 28 | devices["/dev/nvmap"] = nvmap_dev; | ||
| 29 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||
| 30 | } | ||
| 31 | |||
| 32 | u32 Module::Open(std::string device_name) { | ||
| 33 | ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device %s", | ||
| 34 | device_name.c_str()); | ||
| 35 | |||
| 36 | auto device = devices[device_name]; | ||
| 37 | u32 fd = next_fd++; | ||
| 38 | |||
| 39 | open_files[fd] = device; | ||
| 40 | |||
| 41 | return fd; | ||
| 42 | } | ||
| 43 | |||
| 44 | u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 45 | auto itr = open_files.find(fd); | ||
| 46 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||
| 47 | |||
| 48 | auto device = itr->second; | ||
| 49 | return device->ioctl(command, input, output); | ||
| 50 | } | ||
| 51 | |||
| 52 | ResultCode Module::Close(u32 fd) { | ||
| 53 | auto itr = open_files.find(fd); | ||
| 54 | ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||
| 55 | |||
| 56 | open_files.erase(itr); | ||
| 57 | |||
| 58 | // TODO(flerovium): return correct result code if operation failed. | ||
| 59 | return RESULT_SUCCESS; | ||
| 60 | } | ||
| 61 | |||
| 62 | } // namespace Nvidia | ||
| 20 | } // namespace Service | 63 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 7530d80ad..e44644624 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -11,109 +11,48 @@ | |||
| 11 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service { |
| 14 | namespace NVDRV { | 14 | namespace Nvidia { |
| 15 | 15 | ||
| 16 | class nvdevice { | 16 | namespace Devices { |
| 17 | public: | 17 | class nvdevice; |
| 18 | virtual ~nvdevice() = default; | 18 | } |
| 19 | |||
| 20 | virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; | ||
| 21 | }; | ||
| 22 | 19 | ||
| 23 | class nvmap : public nvdevice { | 20 | class Module final { |
| 24 | public: | 21 | public: |
| 25 | /// Returns the allocated address of an nvmap object given its handle. | 22 | Module(); |
| 26 | VAddr GetObjectAddress(u32 handle) const; | 23 | ~Module() = default; |
| 24 | |||
| 25 | /// Returns a pointer to one of the available devices, identified by its name. | ||
| 26 | template <typename T> | ||
| 27 | std::shared_ptr<T> GetDevice(std::string name) { | ||
| 28 | auto itr = devices.find(name); | ||
| 29 | if (itr == devices.end()) | ||
| 30 | return nullptr; | ||
| 31 | return std::static_pointer_cast<T>(itr->second); | ||
| 32 | } | ||
| 33 | |||
| 34 | /// Opens a device node and returns a file descriptor to it. | ||
| 35 | u32 Open(std::string device_name); | ||
| 36 | /// Sends an ioctl command to the specified file descriptor. | ||
| 37 | u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output); | ||
| 38 | /// Closes a device file descriptor and returns operation success. | ||
| 39 | ResultCode Close(u32 fd); | ||
| 27 | 40 | ||
| 28 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 29 | private: | 41 | private: |
| 30 | // Represents an nvmap object. | 42 | /// Id to use for the next open file descriptor. |
| 31 | struct Object { | 43 | u32 next_fd = 1; |
| 32 | enum class Status { Created, Allocated }; | ||
| 33 | u32 id; | ||
| 34 | u32 size; | ||
| 35 | u32 flags; | ||
| 36 | u32 align; | ||
| 37 | u8 kind; | ||
| 38 | VAddr addr; | ||
| 39 | Status status; | ||
| 40 | }; | ||
| 41 | |||
| 42 | u32 next_handle = 1; | ||
| 43 | u32 next_id = 1; | ||
| 44 | std::unordered_map<u32, std::shared_ptr<Object>> handles; | ||
| 45 | |||
| 46 | enum IoctlCommands { | ||
| 47 | IocCreateCommand = 0xC0080101, | ||
| 48 | IocFromIdCommand = 0xC0080103, | ||
| 49 | IocAllocCommand = 0xC0200104, | ||
| 50 | IocParamCommand = 0xC00C0109, | ||
| 51 | IocGetIdCommand = 0xC008010E | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct IocCreateParams { | ||
| 55 | // Input | ||
| 56 | u32_le size; | ||
| 57 | // Output | ||
| 58 | u32_le handle; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct IocAllocParams { | ||
| 62 | // Input | ||
| 63 | u32_le handle; | ||
| 64 | u32_le heap_mask; | ||
| 65 | u32_le flags; | ||
| 66 | u32_le align; | ||
| 67 | u8 kind; | ||
| 68 | INSERT_PADDING_BYTES(7); | ||
| 69 | u64_le addr; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct IocGetIdParams { | ||
| 73 | // Output | ||
| 74 | u32_le id; | ||
| 75 | // Input | ||
| 76 | u32_le handle; | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct IocFromIdParams { | ||
| 80 | // Input | ||
| 81 | u32_le id; | ||
| 82 | // Output | ||
| 83 | u32_le handle; | ||
| 84 | }; | ||
| 85 | 44 | ||
| 86 | struct IocParamParams { | 45 | /// Mapping of file descriptors to the devices they reference. |
| 87 | // Input | 46 | std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; |
| 88 | u32_le handle; | ||
| 89 | u32_le type; | ||
| 90 | // Output | ||
| 91 | u32_le value; | ||
| 92 | }; | ||
| 93 | 47 | ||
| 94 | u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); | 48 | /// Mapping of device node names to their implementation. |
| 95 | u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); | 49 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; |
| 96 | u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 97 | u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 98 | u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 99 | }; | ||
| 100 | |||
| 101 | class nvdisp_disp0 : public nvdevice { | ||
| 102 | public: | ||
| 103 | nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {} | ||
| 104 | ~nvdisp_disp0() = default; | ||
| 105 | |||
| 106 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 107 | |||
| 108 | /// Performs a screen flip, drawing the buffer pointed to by the handle. | ||
| 109 | void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); | ||
| 110 | |||
| 111 | private: | ||
| 112 | std::shared_ptr<nvmap> nvmap_dev; | ||
| 113 | }; | 50 | }; |
| 114 | 51 | ||
| 115 | /// Registers all NVDRV services with the specified service manager. | 52 | /// Registers all NVDRV services with the specified service manager. |
| 116 | void InstallInterfaces(SM::ServiceManager& service_manager); | 53 | void InstallInterfaces(SM::ServiceManager& service_manager); |
| 117 | 54 | ||
| 118 | } // namespace NVDRV | 55 | extern std::weak_ptr<Module> nvdrv; |
| 56 | |||
| 57 | } // namespace Nvidia | ||
| 119 | } // namespace Service | 58 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.h b/src/core/hle/service/nvdrv/nvdrv_a.h deleted file mode 100644 index 62f10e9f6..000000000 --- a/src/core/hle/service/nvdrv/nvdrv_a.h +++ /dev/null | |||
| @@ -1,51 +0,0 @@ | |||
| 1 | // Copyright 2018 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 | #include <string> | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace NVDRV { | ||
| 14 | |||
| 15 | namespace Devices { | ||
| 16 | class nvdevice; | ||
| 17 | } | ||
| 18 | |||
| 19 | class NVDRV_A final : public ServiceFramework<NVDRV_A> { | ||
| 20 | public: | ||
| 21 | NVDRV_A(); | ||
| 22 | ~NVDRV_A() = default; | ||
| 23 | |||
| 24 | /// Returns a pointer to one of the available devices, identified by its name. | ||
| 25 | template <typename T> | ||
| 26 | std::shared_ptr<T> GetDevice(std::string name) { | ||
| 27 | auto itr = devices.find(name); | ||
| 28 | if (itr == devices.end()) | ||
| 29 | return nullptr; | ||
| 30 | return std::static_pointer_cast<T>(itr->second); | ||
| 31 | } | ||
| 32 | |||
| 33 | private: | ||
| 34 | void Open(Kernel::HLERequestContext& ctx); | ||
| 35 | void Ioctl(Kernel::HLERequestContext& ctx); | ||
| 36 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 37 | |||
| 38 | /// Id to use for the next open file descriptor. | ||
| 39 | u32 next_fd = 1; | ||
| 40 | |||
| 41 | /// Mapping of file descriptors to the devices they reference. | ||
| 42 | std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; | ||
| 43 | |||
| 44 | /// Mapping of device node names to their implementation. | ||
| 45 | std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | ||
| 46 | }; | ||
| 47 | |||
| 48 | extern std::weak_ptr<NVDRV_A> nvdrv_a; | ||
| 49 | |||
| 50 | } // namespace NVDRV | ||
| 51 | } // namespace Service | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 02d434660..fe76b381c 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 15 | #include "core/hle/kernel/server_port.h" | 15 | #include "core/hle/kernel/server_port.h" |
| 16 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | #include "core/hle/service/acc/acc.h" | ||
| 17 | #include "core/hle/service/am/am.h" | 18 | #include "core/hle/service/am/am.h" |
| 18 | #include "core/hle/service/aoc/aoc_u.h" | 19 | #include "core/hle/service/aoc/aoc_u.h" |
| 19 | #include "core/hle/service/apm/apm.h" | 20 | #include "core/hle/service/apm/apm.h" |
| @@ -164,13 +165,14 @@ void Init() { | |||
| 164 | SM::g_service_manager = std::make_shared<SM::ServiceManager>(); | 165 | SM::g_service_manager = std::make_shared<SM::ServiceManager>(); |
| 165 | SM::ServiceManager::InstallInterfaces(SM::g_service_manager); | 166 | SM::ServiceManager::InstallInterfaces(SM::g_service_manager); |
| 166 | 167 | ||
| 168 | Account::InstallInterfaces(*SM::g_service_manager); | ||
| 167 | AM::InstallInterfaces(*SM::g_service_manager); | 169 | AM::InstallInterfaces(*SM::g_service_manager); |
| 168 | AOC::InstallInterfaces(*SM::g_service_manager); | 170 | AOC::InstallInterfaces(*SM::g_service_manager); |
| 169 | APM::InstallInterfaces(*SM::g_service_manager); | 171 | APM::InstallInterfaces(*SM::g_service_manager); |
| 170 | Audio::InstallInterfaces(*SM::g_service_manager); | 172 | Audio::InstallInterfaces(*SM::g_service_manager); |
| 171 | HID::InstallInterfaces(*SM::g_service_manager); | 173 | HID::InstallInterfaces(*SM::g_service_manager); |
| 172 | LM::InstallInterfaces(*SM::g_service_manager); | 174 | LM::InstallInterfaces(*SM::g_service_manager); |
| 173 | NVDRV::InstallInterfaces(*SM::g_service_manager); | 175 | Nvidia::InstallInterfaces(*SM::g_service_manager); |
| 174 | PCTL::InstallInterfaces(*SM::g_service_manager); | 176 | PCTL::InstallInterfaces(*SM::g_service_manager); |
| 175 | Time::InstallInterfaces(*SM::g_service_manager); | 177 | Time::InstallInterfaces(*SM::g_service_manager); |
| 176 | VI::InstallInterfaces(*SM::g_service_manager); | 178 | VI::InstallInterfaces(*SM::g_service_manager); |
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index e3d58aa60..674b59509 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp | |||
| @@ -2,14 +2,140 @@ | |||
| 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 <chrono> | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/hle/ipc_helpers.h" | ||
| 8 | #include "core/hle/kernel/client_port.h" | ||
| 9 | #include "core/hle/kernel/client_session.h" | ||
| 5 | #include "core/hle/service/time/time.h" | 10 | #include "core/hle/service/time/time.h" |
| 6 | #include "core/hle/service/time/time_s.h" | ||
| 7 | 11 | ||
| 8 | namespace Service { | 12 | namespace Service { |
| 9 | namespace Time { | 13 | namespace Time { |
| 10 | 14 | ||
| 15 | class ISystemClock final : public ServiceFramework<ISystemClock> { | ||
| 16 | public: | ||
| 17 | ISystemClock() : ServiceFramework("ISystemClock") { | ||
| 18 | static const FunctionInfo functions[] = { | ||
| 19 | {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, | ||
| 20 | }; | ||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | private: | ||
| 25 | void GetCurrentTime(Kernel::HLERequestContext& ctx) { | ||
| 26 | const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>( | ||
| 27 | std::chrono::system_clock::now().time_since_epoch()) | ||
| 28 | .count()}; | ||
| 29 | IPC::RequestBuilder rb{ctx, 4}; | ||
| 30 | rb.Push(RESULT_SUCCESS); | ||
| 31 | rb.Push<u64>(time_since_epoch); | ||
| 32 | LOG_DEBUG(Service, "called"); | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | class ISteadyClock final : public ServiceFramework<ISteadyClock> { | ||
| 37 | public: | ||
| 38 | ISteadyClock() : ServiceFramework("ISteadyClock") {} | ||
| 39 | }; | ||
| 40 | |||
| 41 | class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { | ||
| 42 | public: | ||
| 43 | ITimeZoneService() : ServiceFramework("ITimeZoneService") { | ||
| 44 | static const FunctionInfo functions[] = { | ||
| 45 | {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, | ||
| 46 | {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, | ||
| 47 | }; | ||
| 48 | RegisterHandlers(functions); | ||
| 49 | } | ||
| 50 | |||
| 51 | private: | ||
| 52 | void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { | ||
| 53 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 54 | LocationName name{}; | ||
| 55 | IPC::RequestBuilder rb{ctx, 11}; | ||
| 56 | rb.Push(RESULT_SUCCESS); | ||
| 57 | rb.PushRaw(name); | ||
| 58 | } | ||
| 59 | |||
| 60 | void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) { | ||
| 61 | IPC::RequestParser rp{ctx}; | ||
| 62 | u64 posixTime = rp.Pop<u64>(); | ||
| 63 | |||
| 64 | LOG_WARNING(Service, "(STUBBED) called, posixTime=0x%016llX", posixTime); | ||
| 65 | |||
| 66 | CalendarTime calendarTime{2018, 1, 1, 0, 0, 0}; | ||
| 67 | CalendarAdditionalInfo additionalInfo{}; | ||
| 68 | IPC::RequestBuilder rb{ctx, 10}; | ||
| 69 | rb.Push(RESULT_SUCCESS); | ||
| 70 | rb.PushRaw(calendarTime); | ||
| 71 | rb.PushRaw(additionalInfo); | ||
| 72 | } | ||
| 73 | }; | ||
| 74 | |||
| 75 | void TIME::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { | ||
| 76 | auto client_port = std::make_shared<ISystemClock>()->CreatePort(); | ||
| 77 | auto session = client_port->Connect(); | ||
| 78 | if (session.Succeeded()) { | ||
| 79 | LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", | ||
| 80 | (*session)->GetObjectId()); | ||
| 81 | IPC::RequestBuilder rb{ctx, 2, 0, 1}; | ||
| 82 | rb.Push(RESULT_SUCCESS); | ||
| 83 | rb.PushMoveObjects(std::move(session).Unwrap()); | ||
| 84 | } else { | ||
| 85 | UNIMPLEMENTED(); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | void TIME::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { | ||
| 90 | auto client_port = std::make_shared<ISystemClock>()->CreatePort(); | ||
| 91 | auto session = client_port->Connect(); | ||
| 92 | if (session.Succeeded()) { | ||
| 93 | LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", | ||
| 94 | (*session)->GetObjectId()); | ||
| 95 | IPC::RequestBuilder rb{ctx, 2, 0, 1}; | ||
| 96 | rb.Push(RESULT_SUCCESS); | ||
| 97 | rb.PushMoveObjects(std::move(session).Unwrap()); | ||
| 98 | } else { | ||
| 99 | UNIMPLEMENTED(); | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | void TIME::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | ||
| 104 | auto client_port = std::make_shared<ISteadyClock>()->CreatePort(); | ||
| 105 | auto session = client_port->Connect(); | ||
| 106 | if (session.Succeeded()) { | ||
| 107 | LOG_DEBUG(Service, "called, initialized ISteadyClock -> session=%u", | ||
| 108 | (*session)->GetObjectId()); | ||
| 109 | IPC::RequestBuilder rb{ctx, 2, 0, 1}; | ||
| 110 | rb.Push(RESULT_SUCCESS); | ||
| 111 | rb.PushMoveObjects(std::move(session).Unwrap()); | ||
| 112 | } else { | ||
| 113 | UNIMPLEMENTED(); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | void TIME::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | ||
| 118 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 119 | rb.Push(RESULT_SUCCESS); | ||
| 120 | rb.PushIpcInterface<ITimeZoneService>(); | ||
| 121 | LOG_DEBUG(Service, "called"); | ||
| 122 | } | ||
| 123 | |||
| 124 | TIME::TIME(const char* name) : ServiceFramework(name) { | ||
| 125 | static const FunctionInfo functions[] = { | ||
| 126 | {0x00000000, &TIME::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | ||
| 127 | {0x00000001, &TIME::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"}, | ||
| 128 | {0x00000002, &TIME::GetStandardSteadyClock, "GetStandardSteadyClock"}, | ||
| 129 | {0x00000003, &TIME::GetTimeZoneService, "GetTimeZoneService"}, | ||
| 130 | }; | ||
| 131 | RegisterHandlers(functions); | ||
| 132 | } | ||
| 133 | |||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 134 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
| 12 | std::make_shared<TimeS>()->InstallAsService(service_manager); | 135 | std::make_shared<TIME>("time:a")->InstallAsService(service_manager); |
| 136 | std::make_shared<TIME>("time:r")->InstallAsService(service_manager); | ||
| 137 | std::make_shared<TIME>("time:s")->InstallAsService(service_manager); | ||
| 138 | std::make_shared<TIME>("time:u")->InstallAsService(service_manager); | ||
| 13 | } | 139 | } |
| 14 | 140 | ||
| 15 | } // namespace Time | 141 | } // namespace Time |
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 7d0803e24..5f332d057 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h | |||
| @@ -9,6 +9,42 @@ | |||
| 9 | namespace Service { | 9 | namespace Service { |
| 10 | namespace Time { | 10 | namespace Time { |
| 11 | 11 | ||
| 12 | // TODO(Rozelette) RE this structure | ||
| 13 | struct LocationName { | ||
| 14 | INSERT_PADDING_BYTES(0x24); | ||
| 15 | }; | ||
| 16 | static_assert(sizeof(LocationName) == 0x24, "LocationName structure has incorrect size"); | ||
| 17 | |||
| 18 | struct CalendarTime { | ||
| 19 | u16_le year; | ||
| 20 | u8 month; // Starts at 1 | ||
| 21 | u8 day; // Starts at 1 | ||
| 22 | u8 hour; | ||
| 23 | u8 minute; | ||
| 24 | u8 second; | ||
| 25 | INSERT_PADDING_BYTES(1); | ||
| 26 | }; | ||
| 27 | static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size"); | ||
| 28 | |||
| 29 | // TODO(Rozelette) RE this structure | ||
| 30 | struct CalendarAdditionalInfo { | ||
| 31 | INSERT_PADDING_BYTES(0x18); | ||
| 32 | }; | ||
| 33 | static_assert(sizeof(CalendarAdditionalInfo) == 0x18, | ||
| 34 | "CalendarAdditionalInfo structure has incorrect size"); | ||
| 35 | |||
| 36 | class TIME final : public ServiceFramework<TIME> { | ||
| 37 | public: | ||
| 38 | explicit TIME(const char* name); | ||
| 39 | ~TIME() = default; | ||
| 40 | |||
| 41 | private: | ||
| 42 | void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); | ||
| 43 | void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx); | ||
| 44 | void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); | ||
| 45 | void GetTimeZoneService(Kernel::HLERequestContext& ctx); | ||
| 46 | }; | ||
| 47 | |||
| 12 | /// Registers all Time services with the specified service manager. | 48 | /// Registers all Time services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 49 | void InstallInterfaces(SM::ServiceManager& service_manager); |
| 14 | 50 | ||
diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp deleted file mode 100644 index 6b0597d8e..000000000 --- a/src/core/hle/service/time/time_s.cpp +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <chrono> | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/hle/ipc_helpers.h" | ||
| 8 | #include "core/hle/kernel/client_port.h" | ||
| 9 | #include "core/hle/kernel/client_session.h" | ||
| 10 | #include "core/hle/service/time/time_s.h" | ||
| 11 | |||
| 12 | namespace Service { | ||
| 13 | namespace Time { | ||
| 14 | |||
| 15 | class ISystemClock final : public ServiceFramework<ISystemClock> { | ||
| 16 | public: | ||
| 17 | ISystemClock() : ServiceFramework("ISystemClock") { | ||
| 18 | static const FunctionInfo functions[] = { | ||
| 19 | {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, | ||
| 20 | }; | ||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | private: | ||
| 25 | void GetCurrentTime(Kernel::HLERequestContext& ctx) { | ||
| 26 | const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>( | ||
| 27 | std::chrono::system_clock::now().time_since_epoch()) | ||
| 28 | .count()}; | ||
| 29 | IPC::RequestBuilder rb{ctx, 4}; | ||
| 30 | rb.Push(RESULT_SUCCESS); | ||
| 31 | rb.Push<u64>(time_since_epoch); | ||
| 32 | LOG_DEBUG(Service, "called"); | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | void TimeS::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { | ||
| 37 | auto client_port = std::make_shared<ISystemClock>()->CreatePort(); | ||
| 38 | auto session = client_port->Connect(); | ||
| 39 | if (session.Succeeded()) { | ||
| 40 | LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", | ||
| 41 | (*session)->GetObjectId()); | ||
| 42 | IPC::RequestBuilder rb{ctx, 2, 0, 1}; | ||
| 43 | rb.Push(RESULT_SUCCESS); | ||
| 44 | rb.PushMoveObjects(std::move(session).Unwrap()); | ||
| 45 | } else { | ||
| 46 | UNIMPLEMENTED(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | TimeS::TimeS() : ServiceFramework("time:s") { | ||
| 51 | static const FunctionInfo functions[] = { | ||
| 52 | {0x00000000, &TimeS::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, | ||
| 53 | }; | ||
| 54 | RegisterHandlers(functions); | ||
| 55 | } | ||
| 56 | |||
| 57 | } // namespace Time | ||
| 58 | } // namespace Service | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 93ebbe75f..cae2c4466 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | #include "core/core_timing.h" | 9 | #include "core/core_timing.h" |
| 10 | #include "core/hle/ipc_helpers.h" | 10 | #include "core/hle/ipc_helpers.h" |
| 11 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 11 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| 12 | #include "core/hle/service/nvdrv/nvdrv_a.h" | 12 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 13 | #include "core/hle/service/vi/vi.h" | 13 | #include "core/hle/service/vi/vi.h" |
| 14 | #include "core/hle/service/vi/vi_m.h" | 14 | #include "core/hle/service/vi/vi_m.h" |
| 15 | #include "video_core/renderer_base.h" | 15 | #include "video_core/renderer_base.h" |
| @@ -361,7 +361,7 @@ public: | |||
| 361 | static const FunctionInfo functions[] = { | 361 | static const FunctionInfo functions[] = { |
| 362 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | 362 | {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, |
| 363 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | 363 | {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, |
| 364 | {2, nullptr, "GetNativeHandle"}, | 364 | {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, |
| 365 | {3, nullptr, "TransactParcelAuto"}, | 365 | {3, nullptr, "TransactParcelAuto"}, |
| 366 | }; | 366 | }; |
| 367 | RegisterHandlers(functions); | 367 | RegisterHandlers(functions); |
| @@ -463,6 +463,21 @@ private: | |||
| 463 | rb.Push(RESULT_SUCCESS); | 463 | rb.Push(RESULT_SUCCESS); |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | void GetNativeHandle(Kernel::HLERequestContext& ctx) { | ||
| 467 | IPC::RequestParser rp{ctx}; | ||
| 468 | u32 id = rp.Pop<u32>(); | ||
| 469 | u32 unknown = rp.Pop<u32>(); | ||
| 470 | |||
| 471 | auto buffer_queue = nv_flinger->GetBufferQueue(id); | ||
| 472 | |||
| 473 | // TODO(Subv): Find out what this actually is. | ||
| 474 | |||
| 475 | LOG_WARNING(Service, "(STUBBED) called id=%u, unknown=%08X", id, unknown); | ||
| 476 | IPC::RequestBuilder rb{ctx, 2, 1}; | ||
| 477 | rb.Push(RESULT_SUCCESS); | ||
| 478 | rb.PushCopyObjects(buffer_queue->GetNativeHandle()); | ||
| 479 | } | ||
| 480 | |||
| 466 | std::shared_ptr<NVFlinger> nv_flinger; | 481 | std::shared_ptr<NVFlinger> nv_flinger; |
| 467 | }; | 482 | }; |
| 468 | 483 | ||
| @@ -565,6 +580,15 @@ void IApplicationDisplayService::GetManagerDisplayService(Kernel::HLERequestCont | |||
| 565 | rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); | 580 | rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); |
| 566 | } | 581 | } |
| 567 | 582 | ||
| 583 | void IApplicationDisplayService::GetIndirectDisplayTransactionService( | ||
| 584 | Kernel::HLERequestContext& ctx) { | ||
| 585 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 586 | |||
| 587 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 588 | rb.Push(RESULT_SUCCESS); | ||
| 589 | rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger); | ||
| 590 | } | ||
| 591 | |||
| 568 | void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | 592 | void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { |
| 569 | LOG_WARNING(Service, "(STUBBED) called"); | 593 | LOG_WARNING(Service, "(STUBBED) called"); |
| 570 | IPC::RequestParser rp{ctx}; | 594 | IPC::RequestParser rp{ctx}; |
| @@ -580,6 +604,15 @@ void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | |||
| 580 | rb.Push<u64>(nv_flinger->OpenDisplay(name)); | 604 | rb.Push<u64>(nv_flinger->OpenDisplay(name)); |
| 581 | } | 605 | } |
| 582 | 606 | ||
| 607 | void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) { | ||
| 608 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 609 | IPC::RequestParser rp{ctx}; | ||
| 610 | u64 display_id = rp.Pop<u64>(); | ||
| 611 | |||
| 612 | IPC::RequestBuilder rb = rp.MakeBuilder(4, 0, 0, 0); | ||
| 613 | rb.Push(RESULT_SUCCESS); | ||
| 614 | } | ||
| 615 | |||
| 583 | void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | 616 | void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { |
| 584 | LOG_WARNING(Service, "(STUBBED) called"); | 617 | LOG_WARNING(Service, "(STUBBED) called"); |
| 585 | IPC::RequestParser rp{ctx}; | 618 | IPC::RequestParser rp{ctx}; |
| @@ -605,6 +638,40 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | |||
| 605 | rb.Push<u64>(data.size()); | 638 | rb.Push<u64>(data.size()); |
| 606 | } | 639 | } |
| 607 | 640 | ||
| 641 | void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { | ||
| 642 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 643 | |||
| 644 | IPC::RequestParser rp{ctx}; | ||
| 645 | u32 flags = rp.Pop<u32>(); | ||
| 646 | u64 display_id = rp.Pop<u64>(); | ||
| 647 | |||
| 648 | auto& buffer = ctx.BufferDescriptorB()[0]; | ||
| 649 | |||
| 650 | // TODO(Subv): What's the difference between a Stray and a Managed layer? | ||
| 651 | |||
| 652 | u64 layer_id = nv_flinger->CreateLayer(display_id); | ||
| 653 | u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); | ||
| 654 | |||
| 655 | NativeWindow native_window{buffer_queue_id}; | ||
| 656 | auto data = native_window.Serialize(); | ||
| 657 | Memory::WriteBlock(buffer.Address(), data.data(), data.size()); | ||
| 658 | |||
| 659 | IPC::RequestBuilder rb = rp.MakeBuilder(6, 0, 0, 0); | ||
| 660 | rb.Push(RESULT_SUCCESS); | ||
| 661 | rb.Push(layer_id); | ||
| 662 | rb.Push<u64>(data.size()); | ||
| 663 | } | ||
| 664 | |||
| 665 | void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) { | ||
| 666 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 667 | |||
| 668 | IPC::RequestParser rp{ctx}; | ||
| 669 | u64 layer_id = rp.Pop<u64>(); | ||
| 670 | |||
| 671 | IPC::RequestBuilder rb = rp.MakeBuilder(2, 0, 0, 0); | ||
| 672 | rb.Push(RESULT_SUCCESS); | ||
| 673 | } | ||
| 674 | |||
| 608 | void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { | 675 | void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { |
| 609 | LOG_WARNING(Service, "(STUBBED) called"); | 676 | LOG_WARNING(Service, "(STUBBED) called"); |
| 610 | IPC::RequestParser rp{ctx}; | 677 | IPC::RequestParser rp{ctx}; |
| @@ -633,11 +700,15 @@ IApplicationDisplayService::IApplicationDisplayService(std::shared_ptr<NVFlinger | |||
| 633 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | 700 | {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, |
| 634 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | 701 | {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, |
| 635 | {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, | 702 | {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, |
| 636 | {103, nullptr, "GetIndirectDisplayTransactionService"}, | 703 | {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, |
| 704 | "GetIndirectDisplayTransactionService"}, | ||
| 637 | {1000, nullptr, "ListDisplays"}, | 705 | {1000, nullptr, "ListDisplays"}, |
| 638 | {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | 706 | {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, |
| 707 | {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||
| 639 | {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | 708 | {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, |
| 640 | {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | 709 | {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, |
| 710 | {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||
| 711 | {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||
| 641 | {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | 712 | {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, |
| 642 | }; | 713 | }; |
| 643 | RegisterHandlers(functions); | 714 | RegisterHandlers(functions); |
| @@ -763,12 +834,12 @@ void NVFlinger::Compose() { | |||
| 763 | auto& igbp_buffer = buffer->igbp_buffer; | 834 | auto& igbp_buffer = buffer->igbp_buffer; |
| 764 | 835 | ||
| 765 | // Now send the buffer to the GPU for drawing. | 836 | // Now send the buffer to the GPU for drawing. |
| 766 | auto nvdrv = NVDRV::nvdrv_a.lock(); | 837 | auto nvdrv = Nvidia::nvdrv.lock(); |
| 767 | ASSERT(nvdrv); | 838 | ASSERT(nvdrv); |
| 768 | 839 | ||
| 769 | // TODO(Subv): Support more than just disp0. The display device selection is probably based | 840 | // TODO(Subv): Support more than just disp0. The display device selection is probably based |
| 770 | // on which display we're drawing (Default, Internal, External, etc) | 841 | // on which display we're drawing (Default, Internal, External, etc) |
| 771 | auto nvdisp = nvdrv->GetDevice<NVDRV::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); | 842 | auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); |
| 772 | ASSERT(nvdisp); | 843 | ASSERT(nvdisp); |
| 773 | 844 | ||
| 774 | nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, | 845 | nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, |
| @@ -778,7 +849,9 @@ void NVFlinger::Compose() { | |||
| 778 | } | 849 | } |
| 779 | } | 850 | } |
| 780 | 851 | ||
| 781 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {} | 852 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { |
| 853 | native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); | ||
| 854 | } | ||
| 782 | 855 | ||
| 783 | void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { | 856 | void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { |
| 784 | Buffer buffer{}; | 857 | Buffer buffer{}; |
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 10e894f8c..81d4f3daa 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -59,11 +59,16 @@ public: | |||
| 59 | return id; | 59 | return id; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | Kernel::SharedPtr<Kernel::Event> GetNativeHandle() const { | ||
| 63 | return native_handle; | ||
| 64 | } | ||
| 65 | |||
| 62 | private: | 66 | private: |
| 63 | u32 id; | 67 | u32 id; |
| 64 | u64 layer_id; | 68 | u64 layer_id; |
| 65 | 69 | ||
| 66 | std::vector<Buffer> queue; | 70 | std::vector<Buffer> queue; |
| 71 | Kernel::SharedPtr<Kernel::Event> native_handle; | ||
| 67 | }; | 72 | }; |
| 68 | 73 | ||
| 69 | struct Layer { | 74 | struct Layer { |
| @@ -138,9 +143,13 @@ private: | |||
| 138 | void GetRelayService(Kernel::HLERequestContext& ctx); | 143 | void GetRelayService(Kernel::HLERequestContext& ctx); |
| 139 | void GetSystemDisplayService(Kernel::HLERequestContext& ctx); | 144 | void GetSystemDisplayService(Kernel::HLERequestContext& ctx); |
| 140 | void GetManagerDisplayService(Kernel::HLERequestContext& ctx); | 145 | void GetManagerDisplayService(Kernel::HLERequestContext& ctx); |
| 146 | void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx); | ||
| 141 | void OpenDisplay(Kernel::HLERequestContext& ctx); | 147 | void OpenDisplay(Kernel::HLERequestContext& ctx); |
| 148 | void CloseDisplay(Kernel::HLERequestContext& ctx); | ||
| 142 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx); | 149 | void SetLayerScalingMode(Kernel::HLERequestContext& ctx); |
| 143 | void OpenLayer(Kernel::HLERequestContext& ctx); | 150 | void OpenLayer(Kernel::HLERequestContext& ctx); |
| 151 | void CreateStrayLayer(Kernel::HLERequestContext& ctx); | ||
| 152 | void DestroyStrayLayer(Kernel::HLERequestContext& ctx); | ||
| 144 | void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx); | 153 | void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx); |
| 145 | 154 | ||
| 146 | std::shared_ptr<NVFlinger> nv_flinger; | 155 | std::shared_ptr<NVFlinger> nv_flinger; |
diff --git a/src/core/loader/linker.cpp b/src/core/loader/linker.cpp index f82c6f4b4..87cc65e91 100644 --- a/src/core/loader/linker.cpp +++ b/src/core/loader/linker.cpp | |||
| @@ -48,9 +48,9 @@ struct Elf64_Sym { | |||
| 48 | }; | 48 | }; |
| 49 | static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size."); | 49 | static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size."); |
| 50 | 50 | ||
| 51 | void Linker::WriteRelocations(std::vector<u8>& program_image, | 51 | void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<Symbol>& symbols, |
| 52 | const std::vector<Symbol>& symbols, u64 relocation_offset, | 52 | u64 relocation_offset, u64 size, bool is_jump_relocation, |
| 53 | u64 size, bool is_jump_relocation, VAddr load_base) { | 53 | VAddr load_base) { |
| 54 | for (u64 i = 0; i < size; i += sizeof(Elf64_Rela)) { | 54 | for (u64 i = 0; i < size; i += sizeof(Elf64_Rela)) { |
| 55 | Elf64_Rela rela; | 55 | Elf64_Rela rela; |
| 56 | std::memcpy(&rela, &program_image[relocation_offset + i], sizeof(Elf64_Rela)); | 56 | std::memcpy(&rela, &program_image[relocation_offset + i], sizeof(Elf64_Rela)); |
| @@ -90,8 +90,7 @@ void Linker::WriteRelocations(std::vector<u8>& program_image, | |||
| 90 | } | 90 | } |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, | 93 | void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, VAddr load_base) { |
| 94 | VAddr load_base) { | ||
| 95 | std::map<u64, u64> dynamic; | 94 | std::map<u64, u64> dynamic; |
| 96 | while (dynamic_section_offset < program_image.size()) { | 95 | while (dynamic_section_offset < program_image.size()) { |
| 97 | Elf64_Dyn dyn; | 96 | Elf64_Dyn dyn; |
| @@ -141,8 +140,7 @@ void Linker::ResolveImports() { | |||
| 141 | const auto& search = exports.find(import.first); | 140 | const auto& search = exports.find(import.first); |
| 142 | if (search != exports.end()) { | 141 | if (search != exports.end()) { |
| 143 | Memory::Write64(import.second.ea, search->second + import.second.addend); | 142 | Memory::Write64(import.second.ea, search->second + import.second.addend); |
| 144 | } | 143 | } else { |
| 145 | else { | ||
| 146 | LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); | 144 | LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); |
| 147 | } | 145 | } |
| 148 | } | 146 | } |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index a5d09512b..66c61b038 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -118,13 +118,6 @@ bool AppLoader_NRO::LoadNro(const std::string& path, VAddr load_base) { | |||
| 118 | } | 118 | } |
| 119 | program_image.resize(PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)); | 119 | program_image.resize(PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)); |
| 120 | 120 | ||
| 121 | // Relocate symbols if there was a proper MOD header - This must happen after the image has been | ||
| 122 | // loaded into memory | ||
| 123 | if (has_mod_header) { | ||
| 124 | Relocate(program_image, nro_header.module_header_offset + mod_header.dynamic_offset, | ||
| 125 | load_base); | ||
| 126 | } | ||
| 127 | |||
| 128 | // Load codeset for current process | 121 | // Load codeset for current process |
| 129 | codeset->name = path; | 122 | codeset->name = path; |
| 130 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | 123 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); |
| @@ -154,8 +147,6 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 154 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 147 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 155 | process->Run(base_addr, 48, Kernel::DEFAULT_STACK_SIZE); | 148 | process->Run(base_addr, 48, Kernel::DEFAULT_STACK_SIZE); |
| 156 | 149 | ||
| 157 | ResolveImports(); | ||
| 158 | |||
| 159 | is_loaded = true; | 150 | is_loaded = true; |
| 160 | return ResultStatus::Success; | 151 | return ResultStatus::Success; |
| 161 | } | 152 | } |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 7e1953701..ef769dd91 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -19,7 +19,10 @@ struct NsoSegmentHeader { | |||
| 19 | u32_le offset; | 19 | u32_le offset; |
| 20 | u32_le location; | 20 | u32_le location; |
| 21 | u32_le size; | 21 | u32_le size; |
| 22 | u32_le alignment; | 22 | union { |
| 23 | u32_le alignment; | ||
| 24 | u32_le bss_size; | ||
| 25 | }; | ||
| 23 | }; | 26 | }; |
| 24 | static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size."); | 27 | static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size."); |
| 25 | 28 | ||
| @@ -85,7 +88,7 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 85 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; | 88 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base, bool relocate) { | 91 | VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base) { |
| 89 | FileUtil::IOFile file(path, "rb"); | 92 | FileUtil::IOFile file(path, "rb"); |
| 90 | if (!file.IsOpen()) { | 93 | if (!file.IsOpen()) { |
| 91 | return {}; | 94 | return {}; |
| @@ -120,23 +123,18 @@ VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base, bool relo | |||
| 120 | 123 | ||
| 121 | // Read MOD header | 124 | // Read MOD header |
| 122 | ModHeader mod_header{}; | 125 | ModHeader mod_header{}; |
| 123 | u32 bss_size{Memory::PAGE_SIZE}; // Default .bss to page size if MOD0 section doesn't exist | 126 | // Default .bss to size in segment header if MOD0 section doesn't exist |
| 127 | u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)}; | ||
| 124 | std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader)); | 128 | std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader)); |
| 125 | const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')}; | 129 | const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')}; |
| 126 | if (has_mod_header) { | 130 | if (has_mod_header) { |
| 127 | // Resize program image to include .bss section and page align each section | 131 | // Resize program image to include .bss section and page align each section |
| 128 | bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); | 132 | bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset); |
| 129 | codeset->data.size += bss_size; | ||
| 130 | } | 133 | } |
| 134 | codeset->data.size += bss_size; | ||
| 131 | const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; | 135 | const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)}; |
| 132 | program_image.resize(image_size); | 136 | program_image.resize(image_size); |
| 133 | 137 | ||
| 134 | // Relocate symbols if there was a proper MOD header - This must happen after the image has been | ||
| 135 | // loaded into memory | ||
| 136 | if (has_mod_header && relocate) { | ||
| 137 | Relocate(program_image, module_offset + mod_header.dynamic_offset, load_base); | ||
| 138 | } | ||
| 139 | |||
| 140 | // Load codeset for current process | 138 | // Load codeset for current process |
| 141 | codeset->name = path; | 139 | codeset->name = path; |
| 142 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | 140 | codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); |
| @@ -157,7 +155,8 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 157 | 155 | ||
| 158 | // Load NSO modules | 156 | // Load NSO modules |
| 159 | VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; | 157 | VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; |
| 160 | for (const auto& module : {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4"}) { | 158 | for (const auto& module : |
| 159 | {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4"}) { | ||
| 161 | const std::string path = filepath.substr(0, filepath.find_last_of("/\\")) + "/" + module; | 160 | const std::string path = filepath.substr(0, filepath.find_last_of("/\\")) + "/" + module; |
| 162 | const VAddr load_addr = next_load_addr; | 161 | const VAddr load_addr = next_load_addr; |
| 163 | next_load_addr = LoadNso(path, load_addr); | 162 | next_load_addr = LoadNso(path, load_addr); |
| @@ -176,8 +175,6 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) { | |||
| 176 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); | 175 | Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); |
| 177 | process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); | 176 | process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); |
| 178 | 177 | ||
| 179 | ResolveImports(); | ||
| 180 | |||
| 181 | is_loaded = true; | 178 | is_loaded = true; |
| 182 | return ResultStatus::Success; | 179 | return ResultStatus::Success; |
| 183 | } | 180 | } |
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 28df00384..a24bcdc24 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -18,8 +18,7 @@ namespace Loader { | |||
| 18 | class AppLoader_NSO final : public AppLoader, Linker { | 18 | class AppLoader_NSO final : public AppLoader, Linker { |
| 19 | public: | 19 | public: |
| 20 | AppLoader_NSO(FileUtil::IOFile&& file, std::string filepath) | 20 | AppLoader_NSO(FileUtil::IOFile&& file, std::string filepath) |
| 21 | : AppLoader(std::move(file)), filepath(std::move(filepath)) { | 21 | : AppLoader(std::move(file)), filepath(std::move(filepath)) {} |
| 22 | } | ||
| 23 | 22 | ||
| 24 | /** | 23 | /** |
| 25 | * Returns the type of the file | 24 | * Returns the type of the file |
| @@ -35,7 +34,7 @@ public: | |||
| 35 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; | 34 | ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; |
| 36 | 35 | ||
| 37 | private: | 36 | private: |
| 38 | VAddr LoadNso(const std::string& path, VAddr load_base, bool relocate = false); | 37 | VAddr LoadNso(const std::string& path, VAddr load_base); |
| 39 | 38 | ||
| 40 | std::string filepath; | 39 | std::string filepath; |
| 41 | }; | 40 | }; |
diff --git a/src/core/memory.h b/src/core/memory.h index 91bd4d889..7e554f394 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -136,7 +136,7 @@ enum : VAddr { | |||
| 136 | 136 | ||
| 137 | /// Application heap (includes stack). | 137 | /// Application heap (includes stack). |
| 138 | HEAP_VADDR = 0x108000000, | 138 | HEAP_VADDR = 0x108000000, |
| 139 | HEAP_SIZE = 0x18000000, | 139 | HEAP_SIZE = 0xF0000000, |
| 140 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, | 140 | HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, |
| 141 | 141 | ||
| 142 | /// Area where shared memory buffers are mapped onto. | 142 | /// Area where shared memory buffers are mapped onto. |
| @@ -177,7 +177,7 @@ enum : VAddr { | |||
| 177 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 177 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 178 | 178 | ||
| 179 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 179 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 180 | TLS_AREA_VADDR = 0x1FF82000, | 180 | TLS_AREA_VADDR = 0x228000000, |
| 181 | TLS_ENTRY_SIZE = 0x200, | 181 | TLS_ENTRY_SIZE = 0x200, |
| 182 | 182 | ||
| 183 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | 183 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 26752699e..ad3b56fcc 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -69,7 +69,7 @@ PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) { | |||
| 69 | double PerfStats::GetLastFrameTimeScale() { | 69 | double PerfStats::GetLastFrameTimeScale() { |
| 70 | std::lock_guard<std::mutex> lock(object_mutex); | 70 | std::lock_guard<std::mutex> lock(object_mutex); |
| 71 | 71 | ||
| 72 | constexpr double FRAME_LENGTH = 1.0 / 60; // GPU::SCREEN_REFRESH_RATE; | 72 | constexpr double FRAME_LENGTH = 1.0 / 60; |
| 73 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; | 73 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; |
| 74 | } | 74 | } |
| 75 | 75 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index dd01e1b1a..db6c355a5 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -61,7 +61,8 @@ private: | |||
| 61 | // Loads framebuffer from emulated memory into the display information structure | 61 | // Loads framebuffer from emulated memory into the display information structure |
| 62 | void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); | 62 | void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); |
| 63 | // Fills active OpenGL texture with the given RGBA color. | 63 | // Fills active OpenGL texture with the given RGBA color. |
| 64 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture); | 64 | void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, |
| 65 | const TextureInfo& texture); | ||
| 65 | 66 | ||
| 66 | EmuWindow* render_window; ///< Handle to render window | 67 | EmuWindow* render_window; ///< Handle to render window |
| 67 | 68 | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index c52d5627a..f5c46f1e9 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -66,11 +66,7 @@ file(GLOB_RECURSE THEMES ${CMAKE_SOURCE_DIR}/dist/qt_themes/*) | |||
| 66 | 66 | ||
| 67 | create_directory_groups(${SRCS} ${HEADERS} ${UIS}) | 67 | create_directory_groups(${SRCS} ${HEADERS} ${UIS}) |
| 68 | 68 | ||
| 69 | if (Qt5_FOUND) | 69 | qt5_wrap_ui(UI_HDRS ${UIS}) |
| 70 | qt5_wrap_ui(UI_HDRS ${UIS}) | ||
| 71 | else() | ||
| 72 | qt4_wrap_ui(UI_HDRS ${UIS}) | ||
| 73 | endif() | ||
| 74 | 70 | ||
| 75 | if (APPLE) | 71 | if (APPLE) |
| 76 | set(MACOSX_ICON "../../dist/yuzu.icns") | 72 | set(MACOSX_ICON "../../dist/yuzu.icns") |
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index 0f1b6cdc6..da3429822 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { | 9 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { |
| 10 | ui->setupUi(this); | 10 | ui->setupUi(this); |
| 11 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( | 11 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( |
| 12 | Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | 12 | Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | AboutDialog::~AboutDialog() {} | 15 | AboutDialog::~AboutDialog() {} |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 843ac6ad7..61d678c9b 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -1,12 +1,8 @@ | |||
| 1 | #include <QApplication> | 1 | #include <QApplication> |
| 2 | #include <QHBoxLayout> | 2 | #include <QHBoxLayout> |
| 3 | #include <QKeyEvent> | 3 | #include <QKeyEvent> |
| 4 | |||
| 5 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 6 | // Required for screen DPI information | ||
| 7 | #include <QScreen> | 4 | #include <QScreen> |
| 8 | #include <QWindow> | 5 | #include <QWindow> |
| 9 | #endif | ||
| 10 | 6 | ||
| 11 | #include "common/microprofile.h" | 7 | #include "common/microprofile.h" |
| 12 | #include "common/scm_rev.h" | 8 | #include "common/scm_rev.h" |
| @@ -120,15 +116,13 @@ GRenderWindow::~GRenderWindow() { | |||
| 120 | 116 | ||
| 121 | void GRenderWindow::moveContext() { | 117 | void GRenderWindow::moveContext() { |
| 122 | DoneCurrent(); | 118 | DoneCurrent(); |
| 123 | // We need to move GL context to the swapping thread in Qt5 | 119 | |
| 124 | #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) | ||
| 125 | // If the thread started running, move the GL Context to the new thread. Otherwise, move it | 120 | // If the thread started running, move the GL Context to the new thread. Otherwise, move it |
| 126 | // back. | 121 | // back. |
| 127 | auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) | 122 | auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) |
| 128 | ? emu_thread | 123 | ? emu_thread |
| 129 | : qApp->thread(); | 124 | : qApp->thread(); |
| 130 | child->context()->moveToThread(thread); | 125 | child->context()->moveToThread(thread); |
| 131 | #endif | ||
| 132 | } | 126 | } |
| 133 | 127 | ||
| 134 | void GRenderWindow::SwapBuffers() { | 128 | void GRenderWindow::SwapBuffers() { |
| @@ -191,12 +185,8 @@ QByteArray GRenderWindow::saveGeometry() { | |||
| 191 | } | 185 | } |
| 192 | 186 | ||
| 193 | qreal GRenderWindow::windowPixelRatio() { | 187 | qreal GRenderWindow::windowPixelRatio() { |
| 194 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 195 | // windowHandle() might not be accessible until the window is displayed to screen. | 188 | // windowHandle() might not be accessible until the window is displayed to screen. |
| 196 | return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; | 189 | return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; |
| 197 | #else | ||
| 198 | return 1.0f; | ||
| 199 | #endif | ||
| 200 | } | 190 | } |
| 201 | 191 | ||
| 202 | void GRenderWindow::closeEvent(QCloseEvent* event) { | 192 | void GRenderWindow::closeEvent(QCloseEvent* event) { |
| @@ -299,9 +289,7 @@ void GRenderWindow::OnEmulationStopping() { | |||
| 299 | void GRenderWindow::showEvent(QShowEvent* event) { | 289 | void GRenderWindow::showEvent(QShowEvent* event) { |
| 300 | QWidget::showEvent(event); | 290 | QWidget::showEvent(event); |
| 301 | 291 | ||
| 302 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
| 303 | // windowHandle() is not initialized until the Window is shown, so we connect it here. | 292 | // windowHandle() is not initialized until the Window is shown, so we connect it here. |
| 304 | connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, | 293 | connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this, |
| 305 | SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); | 294 | SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection); |
| 306 | #endif | ||
| 307 | } | 295 | } |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 923a7c53f..6a40f035c 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -18,10 +18,10 @@ Config::Config() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { | 20 | const std::array<int, Settings::NativeButton::NumButtons> Config::default_buttons = { |
| 21 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, Qt::Key_W, | 21 | Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, |
| 22 | Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, Qt::Key_H, Qt::Key_G, | 22 | Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, |
| 23 | Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, Qt::Key_I, Qt::Key_L, | 23 | Qt::Key_H, Qt::Key_G, Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, |
| 24 | Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, | 24 | Qt::Key_I, Qt::Key_L, Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ | 27 | const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 9eb71c593..a45edd510 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include "ui_configure_debug.h" | 6 | #include "ui_configure_debug.h" |
| 7 | #include "yuzu/configuration/configure_debug.h" | 7 | #include "yuzu/configuration/configure_debug.h" |
| 8 | 8 | ||
| 9 | |||
| 10 | ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { | 9 | ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { |
| 11 | ui->setupUi(this); | 10 | ui->setupUi(this); |
| 12 | this->setConfiguration(); | 11 | this->setConfiguration(); |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 96638ebdb..a10bea2f4 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -13,24 +13,24 @@ | |||
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Form</string> | 14 | <string>Form</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_1"> |
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 18 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 19 | <item> | 19 | <item> |
| 20 | <widget class="QGroupBox" name="groupBox"> | 20 | <widget class="QGroupBox" name="groupBox"> |
| 21 | <property name="title"> | 21 | <property name="title"> |
| 22 | <string>GDB</string> | 22 | <string>GDB</string> |
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 24 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel"> | 26 | <widget class="QLabel" name="label_1"> |
| 27 | <property name="text"> | 27 | <property name="text"> |
| 28 | <string>The GDB Stub only works correctly when the CPU JIT is off.</string> | 28 | <string>The GDB Stub only works correctly when the CPU JIT is off.</string> |
| 29 | </property> | 29 | </property> |
| 30 | </widget> | 30 | </widget> |
| 31 | </item> | 31 | </item> |
| 32 | <item> | 32 | <item> |
| 33 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 33 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 34 | <item> | 34 | <item> |
| 35 | <widget class="QCheckBox" name="toggle_gdbstub"> | 35 | <widget class="QCheckBox" name="toggle_gdbstub"> |
| 36 | <property name="text"> | 36 | <property name="text"> |
| @@ -52,7 +52,7 @@ | |||
| 52 | </spacer> | 52 | </spacer> |
| 53 | </item> | 53 | </item> |
| 54 | <item> | 54 | <item> |
| 55 | <widget class="QLabel" name="label"> | 55 | <widget class="QLabel" name="label_2"> |
| 56 | <property name="text"> | 56 | <property name="text"> |
| 57 | <string>Port:</string> | 57 | <string>Port:</string> |
| 58 | </property> | 58 | </property> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 23e5687d0..358f33005 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include "yuzu/configuration/config.h" | 7 | #include "yuzu/configuration/config.h" |
| 8 | #include "yuzu/configuration/configure_dialog.h" | 8 | #include "yuzu/configuration/configure_dialog.h" |
| 9 | 9 | ||
| 10 | |||
| 11 | ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { | 10 | ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { |
| 12 | ui->setupUi(this); | 11 | ui->setupUi(this); |
| 13 | this->setConfiguration(); | 12 | this->setConfiguration(); |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index cd7520f29..10043e6e8 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -42,6 +42,52 @@ static void SetAnalogButton(const Common::ParamPackage& input_param, | |||
| 42 | analog_param.Set(button_name, input_param.Serialize()); | 42 | analog_param.Set(button_name, input_param.Serialize()); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static QString ButtonToText(const Common::ParamPackage& param) { | ||
| 46 | if (!param.Has("engine")) { | ||
| 47 | return QObject::tr("[not set]"); | ||
| 48 | } else if (param.Get("engine", "") == "keyboard") { | ||
| 49 | return getKeyName(param.Get("code", 0)); | ||
| 50 | } else if (param.Get("engine", "") == "sdl") { | ||
| 51 | QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str()); | ||
| 52 | if (param.Has("hat")) { | ||
| 53 | text += QString(QObject::tr(" Hat %1 %2")) | ||
| 54 | .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); | ||
| 55 | } | ||
| 56 | if (param.Has("axis")) { | ||
| 57 | text += QString(QObject::tr(" Axis %1%2")) | ||
| 58 | .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); | ||
| 59 | } | ||
| 60 | if (param.Has("button")) { | ||
| 61 | text += QString(QObject::tr(" Button %1")).arg(param.Get("button", "").c_str()); | ||
| 62 | } | ||
| 63 | return text; | ||
| 64 | } else { | ||
| 65 | return QObject::tr("[unknown]"); | ||
| 66 | } | ||
| 67 | }; | ||
| 68 | |||
| 69 | static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { | ||
| 70 | if (!param.Has("engine")) { | ||
| 71 | return QObject::tr("[not set]"); | ||
| 72 | } else if (param.Get("engine", "") == "analog_from_button") { | ||
| 73 | return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); | ||
| 74 | } else if (param.Get("engine", "") == "sdl") { | ||
| 75 | if (dir == "modifier") { | ||
| 76 | return QString(QObject::tr("[unused]")); | ||
| 77 | } | ||
| 78 | |||
| 79 | QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str()); | ||
| 80 | if (dir == "left" || dir == "right") { | ||
| 81 | text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_x", "").c_str()); | ||
| 82 | } else if (dir == "up" || dir == "down") { | ||
| 83 | text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_y", "").c_str()); | ||
| 84 | } | ||
| 85 | return text; | ||
| 86 | } else { | ||
| 87 | return QObject::tr("[unknown]"); | ||
| 88 | } | ||
| 89 | }; | ||
| 90 | |||
| 45 | ConfigureInput::ConfigureInput(QWidget* parent) | 91 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 46 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), | 92 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), |
| 47 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { | 93 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { |
| @@ -50,13 +96,13 @@ ConfigureInput::ConfigureInput(QWidget* parent) | |||
| 50 | setFocusPolicy(Qt::ClickFocus); | 96 | setFocusPolicy(Qt::ClickFocus); |
| 51 | 97 | ||
| 52 | button_map = { | 98 | button_map = { |
| 53 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, | 99 | ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, |
| 54 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, | 100 | ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, |
| 55 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, | 101 | ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, |
| 56 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, | 102 | ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, |
| 57 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, | 103 | ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, |
| 58 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, | 104 | ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, |
| 59 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, | 105 | ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, |
| 60 | }; | 106 | }; |
| 61 | 107 | ||
| 62 | analog_map_buttons = {{ | 108 | analog_map_buttons = {{ |
| @@ -166,37 +212,18 @@ void ConfigureInput::restoreDefaults() { | |||
| 166 | } | 212 | } |
| 167 | 213 | ||
| 168 | void ConfigureInput::updateButtonLabels() { | 214 | void ConfigureInput::updateButtonLabels() { |
| 169 | QString non_keyboard(tr("[non-keyboard]")); | ||
| 170 | |||
| 171 | auto KeyToText = [&non_keyboard](const Common::ParamPackage& param) { | ||
| 172 | if (!param.Has("engine")) { | ||
| 173 | return QString("[not set]"); | ||
| 174 | } else if (param.Get("engine", "") != "keyboard") { | ||
| 175 | return non_keyboard; | ||
| 176 | } else { | ||
| 177 | return getKeyName(param.Get("code", 0)); | ||
| 178 | } | ||
| 179 | }; | ||
| 180 | |||
| 181 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { | 215 | for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { |
| 182 | button_map[button]->setText(KeyToText(buttons_param[button])); | 216 | button_map[button]->setText(ButtonToText(buttons_param[button])); |
| 183 | } | 217 | } |
| 184 | 218 | ||
| 185 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { | 219 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { |
| 186 | if (analogs_param[analog_id].Get("engine", "") != "analog_from_button") { | 220 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { |
| 187 | for (QPushButton* button : analog_map_buttons[analog_id]) { | 221 | if (analog_map_buttons[analog_id][sub_button_id]) { |
| 188 | if (button) | 222 | analog_map_buttons[analog_id][sub_button_id]->setText( |
| 189 | button->setText(non_keyboard); | 223 | AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); |
| 190 | } | ||
| 191 | } else { | ||
| 192 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { | ||
| 193 | Common::ParamPackage param( | ||
| 194 | analogs_param[analog_id].Get(analog_sub_buttons[sub_button_id], "")); | ||
| 195 | if (analog_map_buttons[analog_id][sub_button_id]) | ||
| 196 | analog_map_buttons[analog_id][sub_button_id]->setText(KeyToText(param)); | ||
| 197 | } | 224 | } |
| 198 | } | 225 | } |
| 199 | analog_map_stick[analog_id]->setText("Set Analog Stick"); | 226 | analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); |
| 200 | } | 227 | } |
| 201 | } | 228 | } |
| 202 | 229 | ||
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 417afef87..89e783687 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "yuzu/configuration/configure_system.h" | 8 | #include "yuzu/configuration/configure_system.h" |
| 9 | #include "yuzu/ui_settings.h" | 9 | #include "yuzu/ui_settings.h" |
| 10 | 10 | ||
| 11 | |||
| 12 | static const std::array<int, 12> days_in_month = {{ | 11 | static const std::array<int, 12> days_in_month = {{ |
| 13 | 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, | 12 | 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, |
| 14 | }}; | 13 | }}; |
| @@ -73,5 +72,6 @@ void ConfigureSystem::refreshConsoleID() { | |||
| 73 | if (reply == QMessageBox::No) | 72 | if (reply == QMessageBox::No) |
| 74 | return; | 73 | return; |
| 75 | u64 console_id{}; | 74 | u64 console_id{}; |
| 76 | ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper()); | 75 | ui->label_console_id->setText( |
| 76 | tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); | ||
| 77 | } | 77 | } |
diff --git a/src/yuzu/debugger/registers.cpp b/src/yuzu/debugger/registers.cpp index a52725075..06e2d1647 100644 --- a/src/yuzu/debugger/registers.cpp +++ b/src/yuzu/debugger/registers.cpp | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include "yuzu/debugger/registers.h" | 8 | #include "yuzu/debugger/registers.h" |
| 9 | #include "yuzu/util/util.h" | 9 | #include "yuzu/util/util.h" |
| 10 | 10 | ||
| 11 | |||
| 12 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { | 11 | RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { |
| 13 | cpu_regs_ui.setupUi(this); | 12 | cpu_regs_ui.setupUi(this); |
| 14 | 13 | ||
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 532c4ae63..679c89828 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -174,7 +174,7 @@ void GameList::onTextChanged(const QString& newText) { | |||
| 174 | child_file->data(GameListItemPath::ProgramIdRole).toString().toLower(); | 174 | child_file->data(GameListItemPath::ProgramIdRole).toString().toLower(); |
| 175 | 175 | ||
| 176 | // Only items which filename in combination with its title contains all words | 176 | // Only items which filename in combination with its title contains all words |
| 177 | // that are in the searchfiel will be visible in the gamelist | 177 | // that are in the searchfield will be visible in the gamelist |
| 178 | // The search is case insensitive because of toLower() | 178 | // The search is case insensitive because of toLower() |
| 179 | // I decided not to use Qt::CaseInsensitive in containsAllWords to prevent | 179 | // I decided not to use Qt::CaseInsensitive in containsAllWords to prevent |
| 180 | // multiple conversions of edit_filter_text for each game in the gamelist | 180 | // multiple conversions of edit_filter_text for each game in the gamelist |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index e40cd38b3..a758b77aa 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include <QRunnable> | 9 | #include <QRunnable> |
| 10 | #include <QStandardItem> | 10 | #include <QStandardItem> |
| 11 | #include <QString> | 11 | #include <QString> |
| 12 | #include "yuzu/util/util.h" | ||
| 13 | #include "common/string_util.h" | 12 | #include "common/string_util.h" |
| 13 | #include "yuzu/util/util.h" | ||
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * Gets the default icon (for games without valid SMDH) | 16 | * Gets the default icon (for games without valid SMDH) |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 7c711158a..31f2825ee 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -122,8 +122,9 @@ void GMainWindow::InitializeWidgets() { | |||
| 122 | statusBar()->addPermanentWidget(message_label, 1); | 122 | statusBar()->addPermanentWidget(message_label, 1); |
| 123 | 123 | ||
| 124 | emu_speed_label = new QLabel(); | 124 | emu_speed_label = new QLabel(); |
| 125 | emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% " | 125 | emu_speed_label->setToolTip( |
| 126 | "indicate emulation is running faster or slower than a Switch.")); | 126 | tr("Current emulation speed. Values higher or lower than 100% " |
| 127 | "indicate emulation is running faster or slower than a Switch.")); | ||
| 127 | game_fps_label = new QLabel(); | 128 | game_fps_label = new QLabel(); |
| 128 | game_fps_label->setToolTip(tr("How many frames per second the game is currently displaying. " | 129 | game_fps_label->setToolTip(tr("How many frames per second the game is currently displaying. " |
| 129 | "This will vary from game to game and scene to scene.")); | 130 | "This will vary from game to game and scene to scene.")); |
| @@ -185,8 +186,8 @@ void GMainWindow::InitializeRecentFileMenuActions() { | |||
| 185 | void GMainWindow::InitializeHotkeys() { | 186 | void GMainWindow::InitializeHotkeys() { |
| 186 | RegisterHotkey("Main Window", "Load File", QKeySequence::Open); | 187 | RegisterHotkey("Main Window", "Load File", QKeySequence::Open); |
| 187 | RegisterHotkey("Main Window", "Start Emulation"); | 188 | RegisterHotkey("Main Window", "Start Emulation"); |
| 188 | RegisterHotkey( "Main Window", "Fullscreen", QKeySequence::FullScreen ); | 189 | RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen); |
| 189 | RegisterHotkey( "Main Window", "Exit Fullscreen", QKeySequence::Cancel, Qt::ApplicationShortcut ); | 190 | RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence::Cancel, Qt::ApplicationShortcut); |
| 190 | LoadHotkeys(); | 191 | LoadHotkeys(); |
| 191 | 192 | ||
| 192 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, | 193 | connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, |
| @@ -194,9 +195,9 @@ void GMainWindow::InitializeHotkeys() { | |||
| 194 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, | 195 | connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, |
| 195 | SLOT(OnStartGame())); | 196 | SLOT(OnStartGame())); |
| 196 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated, | 197 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated, |
| 197 | ui.action_Fullscreen, &QAction::trigger); | 198 | ui.action_Fullscreen, &QAction::trigger); |
| 198 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously, | 199 | connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously, |
| 199 | ui.action_Fullscreen, &QAction::trigger); | 200 | ui.action_Fullscreen, &QAction::trigger); |
| 200 | connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] { | 201 | connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] { |
| 201 | if (emulation_running) { | 202 | if (emulation_running) { |
| 202 | ui.action_Fullscreen->setChecked(false); | 203 | ui.action_Fullscreen->setChecked(false); |
diff --git a/src/yuzu/util/spinbox.cpp b/src/yuzu/util/spinbox.cpp index ede6fe0a8..92753ec1c 100644 --- a/src/yuzu/util/spinbox.cpp +++ b/src/yuzu/util/spinbox.cpp | |||
| @@ -31,8 +31,8 @@ | |||
| 31 | #include <cstdlib> | 31 | #include <cstdlib> |
| 32 | #include <QLineEdit> | 32 | #include <QLineEdit> |
| 33 | #include <QRegExpValidator> | 33 | #include <QRegExpValidator> |
| 34 | #include "yuzu/util/spinbox.h" | ||
| 35 | #include "common/assert.h" | 34 | #include "common/assert.h" |
| 35 | #include "yuzu/util/spinbox.h" | ||
| 36 | 36 | ||
| 37 | CSpinBox::CSpinBox(QWidget* parent) | 37 | CSpinBox::CSpinBox(QWidget* parent) |
| 38 | : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) { | 38 | : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) { |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 5a2f539b1..156f7a1a4 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -124,8 +124,8 @@ custom_bottom_top = | |||
| 124 | custom_bottom_right = | 124 | custom_bottom_right = |
| 125 | custom_bottom_bottom = | 125 | custom_bottom_bottom = |
| 126 | 126 | ||
| 127 | #Whether to toggle frame limiter on or off. | 127 | # Whether to toggle frame limiter on or off. |
| 128 | # 0: Off , 1 (default): On | 128 | # 0: Off, 1 (default): On |
| 129 | toggle_framelimit = | 129 | toggle_framelimit = |
| 130 | 130 | ||
| 131 | # Swaps the prominent screen with the other screen. | 131 | # Swaps the prominent screen with the other screen. |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 785d96672..8f7c75796 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include "yuzu_cmd/config.h" | 37 | #include "yuzu_cmd/config.h" |
| 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 39 | 39 | ||
| 40 | |||
| 41 | static void PrintHelp(const char* argv0) { | 40 | static void PrintHelp(const char* argv0) { |
| 42 | std::cout << "Usage: " << argv0 | 41 | std::cout << "Usage: " << argv0 |
| 43 | << " [options] <filename>\n" | 42 | << " [options] <filename>\n" |