From 4f54b8076cd8a82807307b277a0cd343a83aa5c4 Mon Sep 17 00:00:00 2001 From: JPikachu Date: Tue, 25 Mar 2025 20:56:47 +0000 Subject: [PATCH] Rewrote mm:u to follow switchbrew.org documentation and update them Credit: Antique - [Sudachi Dev] (https://sudachi.emuplace.app/) --- src/core/hle/service/mm/mm_u.cpp | 151 ++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 21 deletions(-) diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index 6f43b19684..8fa2341ffb 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp @@ -7,8 +7,43 @@ #include "core/hle/service/server_manager.h" #include "core/hle/service/sm/sm.h" +#include + namespace Service::MM { +enum class Module : u32 { + CPU = 0, + GPU = 1, + EMC = 2, + SYS_BUS = 3, + M_SELECT = 4, + NVDEC = 5, + NVENC = 6, + NVJPG = 7, + TEST = 8 +}; + +class Session { +public: + Session(Module module_, u32 request_id_, bool is_auto_clear_event_) { + this->module = module_; + this->request_id = request_id_; + this->is_auto_clear_event = is_auto_clear_event_; + this->min = 0; + this->max = -1; + }; + +public: + Module module; + u32 request_id, min; + s32 max; + bool is_auto_clear_event; + void SetAndWait(u32 min_, s32 max_) { + this->min = min_; + this->max = max_; + } +}; + class MM_U final : public ServiceFramework { public: explicit MM_U(Core::System& system_) : ServiceFramework{system_, "mm:u"} { @@ -30,26 +65,53 @@ public: private: void InitializeOld(HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); + LOG_DEBUG(Service_MM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + const auto module = rp.PopEnum(); + rp.Pop(); + const auto event_clear_mode = rp.Pop(); + const bool is_auto_clear_event = event_clear_mode == 1; + + sessions.push_back({module, request_id++, is_auto_clear_event}); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void FinalizeOld(HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); + LOG_DEBUG(Service_MM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + const auto module = rp.PopEnum(); + + for (auto it = sessions.begin(); it != sessions.end(); ++it) { + if (it->module == module) { + sessions.erase(it); + break; + } + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void SetAndWaitOld(HLERequestContext& ctx) { + LOG_DEBUG(Service_MM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; - min = rp.Pop(); - max = rp.Pop(); - LOG_DEBUG(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); + const auto module = rp.PopEnum(); + const auto min = rp.Pop(); + const auto max = rp.Pop(); - current = min; + for (auto& session : sessions) { + if (session.module == module) { + session.SetAndWait(min, max); + break; + } + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -57,35 +119,72 @@ private: void GetOld(HLERequestContext& ctx) { LOG_DEBUG(Service_MM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto module = rp.PopEnum(); + + for (const auto& session : sessions) { + if (session.module == module) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + rb.Push(session.min); + return; + } + } + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(current); + rb.Push(0); } void Initialize(HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); + LOG_DEBUG(Service_MM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + const auto module = rp.PopEnum(); + rp.Pop(); + const auto event_clear_mode = rp.Pop(); + + const bool is_auto_clear_event = event_clear_mode == 1; + + sessions.push_back({module, request_id++, is_auto_clear_event}); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(id); // Any non zero value + rb.Push(request_id - 1); } void Finalize(HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); + LOG_DEBUG(Service_MM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto id = rp.Pop(); + + for (auto it = sessions.begin(); it != sessions.end(); ++it) { + if (it->request_id == id) { + sessions.erase(it); + break; + } + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } void SetAndWait(HLERequestContext& ctx) { + LOG_DEBUG(Service_MM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; - u32 input_id = rp.Pop(); - min = rp.Pop(); - max = rp.Pop(); - LOG_DEBUG(Service_MM, "(STUBBED) called, input_id=0x{:X}, min=0x{:X}, max=0x{:X}", input_id, - min, max); + const auto id = rp.Pop(); + const auto min = rp.Pop(); + const auto max = rp.Pop(); - current = min; + for (auto& session : sessions) { + if (session.request_id == id) { + session.SetAndWait(min, max); + break; + } + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -93,15 +192,25 @@ private: void Get(HLERequestContext& ctx) { LOG_DEBUG(Service_MM, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto id = rp.Pop(); + + for (const auto& session : sessions) { + if (session.request_id == id) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(session.min); + return; + } + } + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(current); + rb.Push(0); } - u32 min{0}; - u32 max{0}; - u32 current{0}; - u32 id{1}; + std::vector sessions; + u32 request_id{1}; }; void LoopProcess(Core::System& system) {