From d396944487d27f85800f4a3a3f8c1645e8120ab5 Mon Sep 17 00:00:00 2001
From: PabloMK7 <hackyglitch2@gmail.com>
Date: Fri, 21 Oct 2022 01:12:29 +0200
Subject: [PATCH] Fix self updating ncch app jump

---
 src/common/file_util.cpp       |  4 ----
 src/common/file_util.h         |  2 --
 src/core/core.cpp              | 18 ++++++++++++++++++
 src/core/core.h                |  7 +++++--
 src/core/hle/service/am/am.cpp | 11 ++++++-----
 5 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 9ec740b36..436d94406 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -738,10 +738,6 @@ void SetCurrentRomPath(const std::string& path) {
     g_currentRomPath = path;
 }
 
-const std::string& GetCurrentRomPath() {
-    return g_currentRomPath;
-}
-
 bool StringReplace(std::string& haystack, const std::string& a, const std::string& b, bool swap) {
     const auto& needle = swap ? b : a;
     const auto& replacement = swap ? a : b;
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 24198d80b..cdd55b665 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -182,8 +182,6 @@ void SetUserPath(const std::string& path = "");
 
 void SetCurrentRomPath(const std::string& path);
 
-const std::string& GetCurrentRomPath();
-
 // Returns a pointer to a string with a Citra data dir in the user's home
 // directory. To be used in "multi-user" mode (that is, installed).
 [[nodiscard]] const std::string& GetUserPath(UserPath path);
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 3e364ae43..7c4f557b8 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -31,6 +31,7 @@
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
 #include "core/hle/kernel/thread.h"
+#include "core/hle/service/am/am.h"
 #include "core/hle/service/apt/applet_manager.h"
 #include "core/hle/service/apt/apt.h"
 #include "core/hle/service/fs/archive.h"
@@ -575,8 +576,25 @@ void System::Reset() {
         deliver_arg = apt->GetAppletManager()->ReceiveDeliverArg();
     }
 
+    bool was_self_delete_pending = self_delete_pending;
+
     Shutdown();
 
+    // Self updating apps may launch themselves after the update, if that's the case
+    // find the new path to launch.
+    if (was_self_delete_pending) {
+        // TODO: We can get the title id, but not the MediaType, so we
+        // check both NAND and SDMC mediatypes.
+        m_filepath = Service::AM::GetTitleContentPath(Service::FS::MediaType::NAND, title_id);
+        if (m_filepath.empty() || !FileUtil::Exists(m_filepath)) {
+            m_filepath = Service::AM::GetTitleContentPath(Service::FS::MediaType::SDMC, title_id);
+            if (m_filepath.empty() || !FileUtil::Exists(m_filepath)) {
+                LOG_CRITICAL(Core, "Failed to get application path for system reset");
+                return;
+            }
+        }
+    }
+
     // Reload the system with the same setting
     [[maybe_unused]] const System::ResultStatus result = Load(*m_emu_window, m_filepath);
 
diff --git a/src/core/core.h b/src/core/core.h
index 4ec54018d..b8e80f9f9 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -306,9 +306,12 @@ public:
     void LoadState(u32 slot);
 
     /// Self delete ncch
-    void SetSelfDelete(const std::string& file) {
-        if (m_filepath == file)
+    bool SetSelfDelete(const std::string& file) {
+        if (m_filepath == file) {
             self_delete_pending = true;
+            return true;
+        }
+        return false;
     }
 
 private:
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 28a13044a..dddd2aacf 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -318,12 +318,13 @@ bool CIAFile::Close() const {
             if (abort)
                 break;
 
-            // Try deleting the file, if it fails it's because it's the currently running file
-            // and we are on windows. In that case, let system know to delete the currently
-            // running file once it shuts down.
+            // If the file to delete is the current launched rom, signal the system to delete
+            // the current rom instead of deleting it now, once all the handles to the file
+            // are closed.
             std::string toDelete = GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index);
-            if (!FileUtil::Delete(toDelete) && FileUtil::GetCurrentRomPath() == toDelete)
-                Core::System::GetInstance().SetSelfDelete(toDelete);
+            if (!(Core::System::GetInstance().IsPoweredOn() &&
+                  Core::System::GetInstance().SetSelfDelete(toDelete)))
+                FileUtil::Delete(toDelete);
         }
 
         FileUtil::Delete(old_tmd_path);