From 6abd4d2f2b7bdd90dfe6e4ad02fd8d8bc7fd3b57 Mon Sep 17 00:00:00 2001
From: JPikachu <JPikachu@EDEN-emu.git>
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 <vector>
+
 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<MM_U> {
 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<Module>();
+        rp.Pop<u32>();
+        const auto event_clear_mode = rp.Pop<u32>();
 
+        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<Module>();
+
+        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<u32>();
-        max = rp.Pop<u32>();
-        LOG_DEBUG(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
+        const auto module = rp.PopEnum<Module>();
+        const auto min = rp.Pop<u32>();
+        const auto max = rp.Pop<s32>();
 
-        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<Module>();
+
+        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<u32>(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<Module>();
+        rp.Pop<u32>();
+        const auto event_clear_mode = rp.Pop<u32>();
+
+        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<u32>(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<u32>();
+
+        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<u32>();
-        min = rp.Pop<u32>();
-        max = rp.Pop<u32>();
-        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<u32>();
+        const auto min = rp.Pop<u32>();
+        const auto max = rp.Pop<s32>();
 
-        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<u32>();
+
+        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<u32>(0);
     }
 
-    u32 min{0};
-    u32 max{0};
-    u32 current{0};
-    u32 id{1};
+    std::vector<Session> sessions;
+    u32 request_id{1};
 };
 
 void LoopProcess(Core::System& system) {