From d9d0fc63ec965b60d99895f31cd751a3a51466c4 Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Sat, 25 Mar 2023 14:36:14 -0700
Subject: [PATCH] applet: Fix HLE applet pre-start lifecycle. (#6362)

---
 src/core/hle/applets/applet.cpp       | 16 ++++++++++++----
 src/core/hle/applets/applet.h         | 14 +++++++++++---
 src/core/hle/applets/erreula.cpp      |  1 -
 src/core/hle/applets/mii_selector.cpp |  1 -
 src/core/hle/applets/mint.cpp         |  1 -
 src/core/hle/applets/swkbd.cpp        |  1 -
 6 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index 8be1a0e7e..b10795b76 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -80,6 +80,9 @@ ResultCode Applet::Create(Service::APT::AppletId id, Service::APT::AppletId pare
         manager->FinishPreloadingLibraryApplet(id);
     }
 
+    // Schedule the update event
+    Core::System::GetInstance().CoreTiming().ScheduleEvent(
+        usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id));
     return RESULT_SUCCESS;
 }
 
@@ -96,7 +99,9 @@ static void AppletUpdateEvent(u64 applet_id, s64 cycles_late) {
     const auto applet = Applet::Get(id);
     ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id={:08X}", id);
 
-    applet->Update();
+    if (applet->IsActive()) {
+        applet->Update();
+    }
 
     // If the applet is still running after the last update, reschedule the event
     if (applet->IsRunning()) {
@@ -112,14 +117,16 @@ bool Applet::IsRunning() const {
     return is_running;
 }
 
+bool Applet::IsActive() const {
+    return is_active;
+}
+
 ResultCode Applet::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
     switch (parameter.signal) {
     case Service::APT::SignalType::Wakeup: {
         ResultCode result = Start(parameter);
         if (!result.IsError()) {
-            // Schedule the update event
-            Core::System::GetInstance().CoreTiming().ScheduleEvent(
-                usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id));
+            is_active = true;
         }
         return result;
     }
@@ -146,6 +153,7 @@ void Applet::CloseApplet(std::shared_ptr<Kernel::Object> object, const std::vect
         LOG_ERROR(Service_APT, "called after destructing applet manager");
     }
 
+    is_active = false;
     is_running = false;
 }
 
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
index 36f895be8..8160aeeb2 100644
--- a/src/core/hle/applets/applet.h
+++ b/src/core/hle/applets/applet.h
@@ -40,10 +40,15 @@ public:
     ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter);
 
     /**
-     * Whether the applet is currently executing instead of the host application or not.
+     * Whether the applet is currently running.
      */
     [[nodiscard]] bool IsRunning() const;
 
+    /**
+     * Whether the applet is currently active instead of the host application or not.
+     */
+    [[nodiscard]] bool IsActive() const;
+
     /**
      * Handles an update tick for the Applet, lets it update the screen, send commands, etc.
      */
@@ -79,8 +84,11 @@ protected:
     bool preload;                                 ///< Whether the Applet is being preloaded.
     std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet
 
-    /// Whether this applet is currently running instead of the host application or not.
-    bool is_running = false;
+    /// Whether this applet is running.
+    bool is_running = true;
+
+    /// Whether this applet is currently active instead of the host application or not.
+    bool is_active = false;
 
     void SendParameter(const Service::APT::MessageParameter& parameter);
     void CloseApplet(std::shared_ptr<Kernel::Object> object, const std::vector<u8>& buffer);
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
index 69d6071d6..3ee74689d 100644
--- a/src/core/hle/applets/erreula.cpp
+++ b/src/core/hle/applets/erreula.cpp
@@ -44,7 +44,6 @@ ResultCode ErrEula::ReceiveParameterImpl(const Service::APT::MessageParameter& p
 }
 
 ResultCode ErrEula::Start(const Service::APT::MessageParameter& parameter) {
-    is_running = true;
     startup_param = parameter.buffer;
 
     // TODO(Subv): Set the expected fields in the response buffer before resending it to the
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index ca4a0878b..be672ed88 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -65,7 +65,6 @@ ResultCode MiiSelector::Start(const Service::APT::MessageParameter& parameter) {
     MiiSelectorConfig frontend_config = ToFrontendConfig(config);
     frontend_applet->Setup(frontend_config);
 
-    is_running = true;
     return RESULT_SUCCESS;
 }
 
diff --git a/src/core/hle/applets/mint.cpp b/src/core/hle/applets/mint.cpp
index 0f62e4917..24975bd86 100644
--- a/src/core/hle/applets/mint.cpp
+++ b/src/core/hle/applets/mint.cpp
@@ -44,7 +44,6 @@ ResultCode Mint::ReceiveParameterImpl(const Service::APT::MessageParameter& para
 }
 
 ResultCode Mint::Start(const Service::APT::MessageParameter& parameter) {
-    is_running = true;
     startup_param = parameter.buffer;
 
     // TODO(Subv): Set the expected fields in the response buffer before resending it to the
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index f864eee80..6a1d5706a 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -106,7 +106,6 @@ ResultCode SoftwareKeyboard::Start(Service::APT::MessageParameter const& paramet
 
     frontend_applet->Execute(ToFrontendConfig(config));
 
-    is_running = true;
     return RESULT_SUCCESS;
 }