From 0bb7990c4919b466658c8d75927ae92a76e86877 Mon Sep 17 00:00:00 2001
From: Narr the Reg <juangerman-13@hotmail.com>
Date: Sun, 1 Oct 2023 13:00:30 -0600
Subject: [PATCH] service: Stub multiple functions to increase stability of
 album applet

---
 src/core/hle/service/am/am.cpp                | 84 ++++++++++++++++++-
 src/core/hle/service/am/am.h                  | 19 +++++
 src/core/hle/service/am/applet_ae.cpp         | 20 ++++-
 .../hle/service/am/applets/applet_error.cpp   |  5 ++
 src/core/hle/service/nifm/nifm.cpp            | 12 ++-
 src/core/hle/service/nifm/nifm.h              |  1 +
 src/core/hle/service/pctl/pctl_module.cpp     |  9 +-
 7 files changed, 144 insertions(+), 6 deletions(-)

diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index a92243fc7f..3bb080883e 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -764,6 +764,66 @@ void AppletMessageQueue::OperationModeChanged() {
     on_operation_mode_changed->Signal();
 }
 
+ILockAccessor::ILockAccessor(Core::System& system_)
+    : ServiceFramework{system_, "ILockAccessor"}, service_context{system_, "ILockAccessor"} {
+    // clang-format off
+        static const FunctionInfo functions[] = {
+            {1, &ILockAccessor::TryLock, "TryLock"},
+            {2, &ILockAccessor::Unlock, "Unlock"},
+            {3, &ILockAccessor::GetEvent, "GetEvent"},
+            {4,&ILockAccessor::IsLocked, "IsLocked"},
+        };
+    // clang-format on
+
+    RegisterHandlers(functions);
+
+    lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
+}
+
+ILockAccessor::~ILockAccessor() = default;
+
+void ILockAccessor::TryLock(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto return_handle = rp.Pop<bool>();
+
+    LOG_WARNING(Service_AM, "(STUBBED) called, return_handle={}", return_handle);
+
+    // TODO: When return_handle is true this function should return the lock handle
+
+    is_locked = true;
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_locked);
+}
+
+void ILockAccessor::Unlock(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    is_locked = false;
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+}
+
+void ILockAccessor::GetEvent(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    lock_event->Signal();
+
+    IPC::ResponseBuilder rb{ctx, 2, 1};
+    rb.Push(ResultSuccess);
+    rb.PushCopyObjects(lock_event->GetReadableEvent());
+}
+
+void ILockAccessor::IsLocked(HLERequestContext& ctx) {
+    LOG_INFO(Service_AM, "called");
+
+    IPC::ResponseBuilder rb{ctx, 2};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_locked);
+}
+
 ICommonStateGetter::ICommonStateGetter(Core::System& system_,
                                        std::shared_ptr<AppletMessageQueue> msg_queue_)
     : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
@@ -787,7 +847,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
         {14, nullptr, "GetWakeupCount"},
         {20, nullptr, "PushToGeneralChannel"},
         {30, nullptr, "GetHomeButtonReaderLockAccessor"},
-        {31, nullptr, "GetReaderLockAccessorEx"},
+        {31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
         {32, nullptr, "GetWriterLockAccessorEx"},
         {40, nullptr, "GetCradleFwVersion"},
         {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
@@ -805,7 +865,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
         {65, nullptr, "GetApplicationIdByContentActionName"},
         {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
         {67, nullptr, "CancelCpuBoostMode"},
-        {68, nullptr, "GetBuiltInDisplayType"},
+        {68, &ICommonStateGetter::GetBuiltInDisplayType, "GetBuiltInDisplayType"},
         {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
         {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
         {91, nullptr, "GetCurrentPerformanceConfiguration"},
@@ -886,6 +946,18 @@ void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
     rb.Push(ResultSuccess);
 }
 
+void ICommonStateGetter::GetReaderLockAccessorEx(HLERequestContext& ctx) {
+    IPC::RequestParser rp{ctx};
+    const auto unknown = rp.Pop<u32>();
+
+    LOG_INFO(Service_AM, "called, unknown={}", unknown);
+
+    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+    rb.Push(ResultSuccess);
+    rb.PushIpcInterface<ILockAccessor>(system);
+}
+
 void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
     LOG_WARNING(Service_AM, "called");
 
@@ -970,6 +1042,14 @@ void ICommonStateGetter::SetCpuBoostMode(HLERequestContext& ctx) {
     apm_sys->SetCpuBoostMode(ctx);
 }
 
+void ICommonStateGetter::GetBuiltInDisplayType(HLERequestContext& ctx) {
+    LOG_WARNING(Service_AM, "(STUBBED) called");
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push(0);
+}
+
 void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx) {
     IPC::RequestParser rp{ctx};
     const auto system_button{rp.PopEnum<SystemButtonType>()};
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 62994a13f8..4a045cfd43 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -195,6 +195,23 @@ private:
     ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
 };
 
+class ILockAccessor final : public ServiceFramework<ILockAccessor> {
+public:
+    explicit ILockAccessor(Core::System& system_);
+    ~ILockAccessor() override;
+
+private:
+    void TryLock(HLERequestContext& ctx);
+    void Unlock(HLERequestContext& ctx);
+    void GetEvent(HLERequestContext& ctx);
+    void IsLocked(HLERequestContext& ctx);
+
+    bool is_locked{};
+
+    Kernel::KEvent* lock_event;
+    KernelHelpers::ServiceContext service_context;
+};
+
 class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
 public:
     explicit ICommonStateGetter(Core::System& system_,
@@ -237,6 +254,7 @@ private:
     void GetCurrentFocusState(HLERequestContext& ctx);
     void RequestToAcquireSleepLock(HLERequestContext& ctx);
     void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
+    void GetReaderLockAccessorEx(HLERequestContext& ctx);
     void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
     void GetOperationMode(HLERequestContext& ctx);
     void GetPerformanceMode(HLERequestContext& ctx);
@@ -248,6 +266,7 @@ private:
     void EndVrModeEx(HLERequestContext& ctx);
     void GetDefaultDisplayResolution(HLERequestContext& ctx);
     void SetCpuBoostMode(HLERequestContext& ctx);
+    void GetBuiltInDisplayType(HLERequestContext& ctx);
     void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
     void GetSettingsPlatformRegion(HLERequestContext& ctx);
     void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index eb12312cca..e30e6478a9 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -28,8 +28,8 @@ public:
             {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
             {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
             {21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
-            {22, nullptr, "GetHomeMenuFunctions"},
-            {23, nullptr, "GetGlobalStateController"},
+            {22, &ILibraryAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
+            {23, &ILibraryAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
             {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
         };
         // clang-format on
@@ -110,6 +110,22 @@ private:
         rb.PushIpcInterface<IAppletCommonFunctions>(system);
     }
 
+    void GetHomeMenuFunctions(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IHomeMenuFunctions>(system);
+    }
+
+    void GetGlobalStateController(HLERequestContext& ctx) {
+        LOG_DEBUG(Service_AM, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(ResultSuccess);
+        rb.PushIpcInterface<IGlobalStateController>(system);
+    }
+
     void GetDebugFunctions(HLERequestContext& ctx) {
         LOG_DEBUG(Service_AM, "called");
 
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index b46ea840cf..5d17c353f6 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -138,6 +138,10 @@ void Error::Initialize() {
         CopyArgumentData(data, args->application_error);
         error_code = Result(args->application_error.error_code);
         break;
+    case ErrorAppletMode::ShowErrorPctl:
+        CopyArgumentData(data, args->error_record);
+        error_code = Decode64BitError(args->error_record.error_code_64);
+        break;
     case ErrorAppletMode::ShowErrorRecord:
         CopyArgumentData(data, args->error_record);
         error_code = Decode64BitError(args->error_record.error_code_64);
@@ -191,6 +195,7 @@ void Error::Execute() {
         frontend.ShowCustomErrorText(error_code, main_text_string, detail_text_string, callback);
         break;
     }
+    case ErrorAppletMode::ShowErrorPctl:
     case ErrorAppletMode::ShowErrorRecord:
         reporter.SaveErrorReport(title_id, error_code,
                                  fmt::format("{:016X}", args->error_record.posix_time));
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 21b06d10ba..22dc55a6dc 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -545,6 +545,16 @@ void IGeneralService::IsAnyInternetRequestAccepted(HLERequestContext& ctx) {
     }
 }
 
+void IGeneralService::IsAnyForegroundRequestAccepted(HLERequestContext& ctx) {
+    const bool is_accepted{};
+
+    LOG_WARNING(Service_NIFM, "(STUBBED) called, is_accepted={}", is_accepted);
+
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(ResultSuccess);
+    rb.Push<u8>(is_accepted);
+}
+
 IGeneralService::IGeneralService(Core::System& system_)
     : ServiceFramework{system_, "IGeneralService"}, network{system_.GetRoomNetwork()} {
     // clang-format off
@@ -569,7 +579,7 @@ IGeneralService::IGeneralService(Core::System& system_)
         {19, nullptr, "SetEthernetCommunicationEnabled"},
         {20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
         {21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},
-        {22, nullptr, "IsAnyForegroundRequestAccepted"},
+        {22, &IGeneralService::IsAnyForegroundRequestAccepted, "IsAnyForegroundRequestAccepted"},
         {23, nullptr, "PutToSleep"},
         {24, nullptr, "WakeUp"},
         {25, nullptr, "GetSsidListVersion"},
diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h
index ae99c46955..b74b664381 100644
--- a/src/core/hle/service/nifm/nifm.h
+++ b/src/core/hle/service/nifm/nifm.h
@@ -35,6 +35,7 @@ private:
     void GetInternetConnectionStatus(HLERequestContext& ctx);
     void IsEthernetCommunicationEnabled(HLERequestContext& ctx);
     void IsAnyInternetRequestAccepted(HLERequestContext& ctx);
+    void IsAnyForegroundRequestAccepted(HLERequestContext& ctx);
 
     Network::RoomNetwork& network;
 };
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 5db1703d1a..938330dd00 100644
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -33,7 +33,7 @@ public:
             {1001, &IParentalControlService::CheckFreeCommunicationPermission, "CheckFreeCommunicationPermission"},
             {1002, nullptr, "ConfirmLaunchApplicationPermission"},
             {1003, nullptr, "ConfirmResumeApplicationPermission"},
-            {1004, nullptr, "ConfirmSnsPostPermission"},
+            {1004, &IParentalControlService::ConfirmSnsPostPermission, "ConfirmSnsPostPermission"},
             {1005, nullptr, "ConfirmSystemSettingsPermission"},
             {1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"},
             {1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
@@ -236,6 +236,13 @@ private:
         states.free_communication = true;
     }
 
+    void ConfirmSnsPostPermission(HLERequestContext& ctx) {
+        LOG_WARNING(Service_PCTL, "(STUBBED) called");
+
+        IPC::ResponseBuilder rb{ctx, 2};
+        rb.Push(Error::ResultNoFreeCommunication);
+    }
+
     void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) {
         const bool is_temporary_unlocked = false;