From c46f54b09172bd43c40004a7276cf2cae720822b Mon Sep 17 00:00:00 2001
From: german77 <juangerman-13@hotmail.com>
Date: Thu, 21 Sep 2023 21:38:58 -0600
Subject: [PATCH] service: am: Implement stuff needed for Mii Edit

---
 src/core/hle/service/am/am.cpp        | 184 +++++++++++++++++++++++++-
 src/core/hle/service/am/am.h          |  28 ++++
 src/core/hle/service/am/applet_ae.cpp |  52 +++++---
 3 files changed, 240 insertions(+), 24 deletions(-)

diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 8ffdd19e7..7c705651a 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -19,6 +19,7 @@
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
 #include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/am/applets/applet_mii_edit_types.h"
 #include "core/hle/service/am/applets/applet_profile_select.h"
 #include "core/hle/service/am/applets/applet_web_browser.h"
 #include "core/hle/service/am/applets/applets.h"
@@ -724,7 +725,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
         {110, nullptr, "OpenMyGpuErrorHandler"},
         {120, nullptr, "GetAppletLaunchedHistory"},
         {200, nullptr, "GetOperationModeSystemInfo"},
-        {300, nullptr, "GetSettingsPlatformRegion"},
+        {300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
         {400, nullptr, "ActivateMigrationService"},
         {401, nullptr, "DeactivateMigrationService"},
         {500, nullptr, "DisableSleepTillShutdown"},
@@ -736,6 +737,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
     // clang-format on
 
     RegisterHandlers(functions);
+
+    // Configure applets to be in foreground state
+    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
+    msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
 }
 
 ICommonStateGetter::~ICommonStateGetter() = default;
@@ -867,6 +872,14 @@ void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext&
     rb.Push(ResultSuccess);
 }
 
+void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushEnum(SysPlatformRegion::Global);
+}
+
 void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
     HLERequestContext& ctx) {
     LOG_WARNING(Service_AM, "(STUBBED) called");
@@ -1324,18 +1337,19 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
 
 ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
     : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
+    // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "PopInData"},
+        {0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
         {1, nullptr, "PushOutData"},
         {2, nullptr, "PopInteractiveInData"},
         {3, nullptr, "PushInteractiveOutData"},
         {5, nullptr, "GetPopInDataEvent"},
         {6, nullptr, "GetPopInteractiveInDataEvent"},
         {10, nullptr, "ExitProcessAndReturn"},
-        {11, nullptr, "GetLibraryAppletInfo"},
+        {11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
         {12, nullptr, "GetMainAppletIdentityInfo"},
         {13, nullptr, "CanUseApplicationCore"},
-        {14, nullptr, "GetCallerAppletIdentityInfo"},
+        {14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
         {15, nullptr, "GetMainAppletApplicationControlProperty"},
         {16, nullptr, "GetMainAppletStorageId"},
         {17, nullptr, "GetCallerAppletIdentityInfoStack"},
@@ -1361,10 +1375,126 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
         {140, nullptr, "SetApplicationMemoryReservation"},
         {150, nullptr, "ShouldSetGpuTimeSliceManually"},
     };
+    // clang-format on
     RegisterHandlers(functions);
+
+    PushInShowMiiEditData();
 }
 
 ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
+void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    if (queue_data.empty()) {
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultNoDataInChannel);
+        return;
+    }
+
+    auto data = queue_data.front();
+    queue_data.pop_front();
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<IStorage>(system, std::move(data));
+}
+
+void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
+    struct LibraryAppletInfo {
+        Applets::AppletId applet_id;
+        Applets::LibraryAppletMode library_applet_mode;
+    };
+
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    const LibraryAppletInfo applet_info{
+        .applet_id = Applets::AppletId::MiiEdit,
+        .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 4};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(applet_info);
+}
+
+void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
+    struct AppletIdentityInfo {
+        Applets::AppletId applet_id;
+        INSERT_PADDING_BYTES(0x4);
+        u64 application_id;
+    };
+
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    const AppletIdentityInfo applet_info{
+        .applet_id = Applets::AppletId::QLaunch,
+        .application_id = 0x0100000000001000ull,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 6};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(applet_info);
+}
+
+void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
+    struct MiiEditV3 {
+        Applets::MiiEditAppletInputCommon common;
+        Applets::MiiEditAppletInputV3 input;
+    };
+    static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
+
+    MiiEditV3 mii_arguments{
+        .common =
+            {
+                .version = Applets::MiiEditAppletVersion::Version3,
+                .applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
+            },
+        .input{},
+    };
+
+    std::vector<u8> argument_data(sizeof(mii_arguments));
+    std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
+
+    queue_data.emplace_back(std::move(argument_data));
+}
+
+IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
+    : ServiceFramework{system_, "IAppletCommonFunctions"} {
+    // clang-format off
+    static const FunctionInfo functions[] = {
+        {0, nullptr, "SetTerminateResult"},
+        {10, nullptr, "ReadThemeStorage"},
+        {11, nullptr, "WriteThemeStorage"},
+        {20, nullptr, "PushToAppletBoundChannel"},
+        {21, nullptr, "TryPopFromAppletBoundChannel"},
+        {40, nullptr, "GetDisplayLogicalResolution"},
+        {42, nullptr, "SetDisplayMagnification"},
+        {50, nullptr, "SetHomeButtonDoubleClickEnabled"},
+        {51, nullptr, "GetHomeButtonDoubleClickEnabled"},
+        {52, nullptr, "IsHomeButtonShortPressedBlocked"},
+        {60, nullptr, "IsVrModeCurtainRequired"},
+        {61, nullptr, "IsSleepRequiredByHighTemperature"},
+        {62, nullptr, "IsSleepRequiredByLowBattery"},
+        {70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
+        {80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
+        {81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
+        {90, nullptr, "OpenNamedChannelAsParent"},
+        {91, nullptr, "OpenNamedChannelAsChild"},
+        {100, nullptr, "SetApplicationCoreUsageMode"},
+    };
+    // clang-format on
+
+    RegisterHandlers(functions);
+}
+
+IAppletCommonFunctions::~IAppletCommonFunctions() = default;
+
+void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
 
 IApplicationFunctions::IApplicationFunctions(Core::System& system_)
     : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
@@ -2049,8 +2179,8 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
     : ServiceFramework{system_, "IProcessWindingController"} {
     // clang-format off
     static const FunctionInfo functions[] = {
-        {0, nullptr, "GetLaunchReason"},
-        {11, nullptr, "OpenCallingLibraryApplet"},
+        {0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
+        {11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
         {21, nullptr, "PushContext"},
         {22, nullptr, "PopContext"},
         {23, nullptr, "CancelWindingReservation"},
@@ -2064,4 +2194,46 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
 }
 
 IProcessWindingController::~IProcessWindingController() = default;
+
+void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    struct AppletProcessLaunchReason {
+        u8 flag;
+        INSERT_PADDING_BYTES(3);
+    };
+    static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
+                  "AppletProcessLaunchReason is an invalid size");
+
+    AppletProcessLaunchReason reason{
+        .flag = 0,
+    };
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.PushRaw(reason);
+}
+
+void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
+    const auto applet_id = Applets::AppletId::MiiEdit;
+    const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
+
+    LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
+                applet_mode);
+
+    const auto& applet_manager{system.GetAppletManager()};
+    const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
+
+    if (applet == nullptr) {
+        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(ResultUnknown);
+        return;
+    }
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
+}
 } // namespace Service::AM
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index f86841c60..3d5eae44e 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -212,6 +212,11 @@ private:
         CaptureButtonLongPressing,
     };
 
+    enum class SysPlatformRegion : s32 {
+        Global = 1,
+        Terra = 2,
+    };
+
     void GetEventHandle(HLERequestContext& ctx);
     void ReceiveMessage(HLERequestContext& ctx);
     void GetCurrentFocusState(HLERequestContext& ctx);
@@ -227,6 +232,7 @@ private:
     void GetDefaultDisplayResolution(HLERequestContext& ctx);
     void SetCpuBoostMode(HLERequestContext& ctx);
     void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
+    void GetSettingsPlatformRegion(HLERequestContext& ctx);
     void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
 
     std::shared_ptr<AppletMessageQueue> msg_queue;
@@ -294,6 +300,24 @@ class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletS
 public:
     explicit ILibraryAppletSelfAccessor(Core::System& system_);
     ~ILibraryAppletSelfAccessor() override;
+
+private:
+    void PopInData(HLERequestContext& ctx);
+    void GetLibraryAppletInfo(HLERequestContext& ctx);
+    void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
+
+    void PushInShowMiiEditData();
+
+    std::deque<std::vector<u8>> queue_data;
+};
+
+class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
+public:
+    explicit IAppletCommonFunctions(Core::System& system_);
+    ~IAppletCommonFunctions() override;
+
+private:
+    void SetCpuBoostRequestPriority(HLERequestContext& ctx);
 };
 
 class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
@@ -378,6 +402,10 @@ class IProcessWindingController final : public ServiceFramework<IProcessWindingC
 public:
     explicit IProcessWindingController(Core::System& system_);
     ~IProcessWindingController() override;
+
+private:
+    void GetLaunchReason(HLERequestContext& ctx);
+    void OpenCallingLibraryApplet(HLERequestContext& ctx);
 };
 
 void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index ee9d99a54..eb12312cc 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -27,7 +27,7 @@ public:
             {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
             {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
             {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
-            {21, nullptr, "GetAppletCommonFunctions"},
+            {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
             {22, nullptr, "GetHomeMenuFunctions"},
             {23, nullptr, "GetGlobalStateController"},
             {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
@@ -86,14 +86,6 @@ private:
         rb.PushIpcInterface<IProcessWindingController>(system);
     }
 
-    void GetDebugFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
-    }
-
     void GetLibraryAppletCreator(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
@@ -110,6 +102,22 @@ private:
         rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
     }
 
+    void GetAppletCommonFunctions(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IAppletCommonFunctions>(system);
+    }
+
+    void GetDebugFunctions(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IDebugFunctions>(system);
+    }
+
     Nvnflinger::Nvnflinger& nvnflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
 };
@@ -133,7 +141,7 @@ public:
             {20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
             {21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
             {22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
-            {23, nullptr, "GetAppletCommonFunctions"},
+            {23,  &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
             {1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
         };
         // clang-format on
@@ -182,14 +190,6 @@ private:
         rb.PushIpcInterface<IDisplayController>(system);
     }
 
-    void GetDebugFunctions(HLERequestContext& ctx) {
-        LOG_DEBUG(Service_AM, "called");
-
-        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-        rb.Push(ResultSuccess);
-        rb.PushIpcInterface<IDebugFunctions>(system);
-    }
-
     void GetLibraryAppletCreator(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
@@ -222,6 +222,22 @@ private:
         rb.PushIpcInterface<IApplicationCreator>(system);
     }
 
+    void GetAppletCommonFunctions(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IAppletCommonFunctions>(system);
+    }
+
+    void GetDebugFunctions(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IDebugFunctions>(system);
+    }
+
     Nvnflinger::Nvnflinger& nvnflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
 };