From c49379442ddbeb609826197f10045013e5305823 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Thu, 20 Oct 2022 23:14:57 +0200 Subject: [PATCH 1/5] Fix auto updating ncch files --- src/common/file_util.cpp | 4 ++++ src/common/file_util.h | 2 ++ src/core/core.cpp | 5 +++++ src/core/core.h | 7 +++++++ src/core/hle/service/am/am.cpp | 7 ++++++- 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 436d94406..9ec740b36 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -738,6 +738,10 @@ 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 cdd55b665..24198d80b 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -182,6 +182,8 @@ 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 ec29ab002..3e364ae43 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -324,6 +324,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st status = ResultStatus::Success; m_emu_window = &emu_window; m_filepath = filepath; + self_delete_pending = false; // Reset counters and set time origin to current frame [[maybe_unused]] const PerfStats::Results result = GetAndResetPerfStats(); @@ -556,6 +557,10 @@ void System::Shutdown(bool is_deserializing) { memory.reset(); + if (self_delete_pending) + FileUtil::Delete(m_filepath); + self_delete_pending = false; + LOG_DEBUG(Core, "Shutdown OK"); } diff --git a/src/core/core.h b/src/core/core.h index 47edb49f3..4ec54018d 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -305,6 +305,12 @@ public: void LoadState(u32 slot); + /// Self delete ncch + void SetSelfDelete(const std::string& file) { + if (m_filepath == file) + self_delete_pending = true; + } + private: /** * Initialize the emulated system. @@ -374,6 +380,7 @@ private: Frontend::EmuWindow* m_emu_window; std::string m_filepath; u64 title_id; + bool self_delete_pending; std::mutex signal_mutex; Signal current_signal; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 5c2639eff..28a13044a 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -318,7 +318,12 @@ bool CIAFile::Close() const { if (abort) break; - FileUtil::Delete(GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index)); + // 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. + std::string toDelete = GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); + if (!FileUtil::Delete(toDelete) && FileUtil::GetCurrentRomPath() == toDelete) + Core::System::GetInstance().SetSelfDelete(toDelete); } FileUtil::Delete(old_tmd_path); From d396944487d27f85800f4a3a3f8c1645e8120ab5 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Fri, 21 Oct 2022 01:12:29 +0200 Subject: [PATCH 2/5] 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); From fd7ada2a9c7cff006a2b0e01c57488114f0ec4ef Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Sun, 23 Oct 2022 22:55:50 +0200 Subject: [PATCH 3/5] Fix chainloading for all apps --- src/core/core.cpp | 18 +++---------- src/core/core.h | 4 ++- src/core/hle/service/apt/applet_manager.cpp | 30 ++++++++++++++++----- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 7c4f557b8..accf52e4f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -576,23 +576,11 @@ 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; - } - } + if (!m_chainloadpath.empty()) { + m_filepath = m_chainloadpath; + m_chainloadpath.clear(); } // Reload the system with the same setting diff --git a/src/core/core.h b/src/core/core.h index b8e80f9f9..146470e26 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -125,7 +125,8 @@ public: bool SendSignal(Signal signal, u32 param = 0); /// Request reset of the system - void RequestReset() { + void RequestReset(const std::string& chainload = "") { + m_chainloadpath = chainload; SendSignal(Signal::Reset); } @@ -382,6 +383,7 @@ private: /// Saved variables for reset Frontend::EmuWindow* m_emu_window; std::string m_filepath; + std::string m_chainloadpath; u64 title_id; bool self_delete_pending; diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index b90f6248e..99b7726e3 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -5,6 +5,7 @@ #include "common/common_paths.h" #include "core/core.h" #include "core/hle/applets/applet.h" +#include "core/hle/service/am/am.h" #include "core/hle/service/apt/applet_manager.h" #include "core/hle/service/apt/errors.h" #include "core/hle/service/apt/ns.h" @@ -527,17 +528,31 @@ ResultCode AppletManager::DoApplicationJump(DeliverArg arg) { // prompts it to call GetProgramIdOnApplicationJump and // PrepareToStartApplication/StartApplication on the title to launch. - if (app_jump_parameters.next_title_id == app_jump_parameters.current_title_id) { - // Perform a soft-reset if we're trying to relaunch the same title. - // TODO(Subv): Note that this reboots the entire emulated system, a better way would be to - // simply re-launch the title without closing all services, but this would only work for - // installed titles since we have no way of getting the file path of an arbitrary game dump - // based only on the title id. - system.RequestReset(); + // Perform a soft-reset if we're trying to relaunch the same title. + // TODO(Subv): Note that this reboots the entire emulated system, a better way would be to + // simply re-launch the title without closing all services, but this would only work for + // installed titles since we have no way of getting the file path of an arbitrary game dump + // based only on the title id. + + std::string new_path = Service::AM::GetTitleContentPath(app_jump_parameters.next_media_type, + app_jump_parameters.next_title_id); + if (new_path.empty() || !FileUtil::Exists(new_path)) { + LOG_CRITICAL( + Service_APT, + "Failed to find title during application jump: {} Resetting current title instead.", + new_path); + new_path.clear(); return RESULT_SUCCESS; } + system.RequestReset(new_path); + return RESULT_SUCCESS; + // Launch the title directly. + // The emulator does not suport terminating old processes, would require a lot of cleanup + // This code is left commented for when this is implemented, for now we cannot use NS + // as the old process resources would interfere with the new ones + /* auto process = NS::LaunchTitle(app_jump_parameters.next_media_type, app_jump_parameters.next_title_id); if (!process) { @@ -545,6 +560,7 @@ ResultCode AppletManager::DoApplicationJump(DeliverArg arg) { system.RequestShutdown(); } return RESULT_SUCCESS; + */ } void AppletManager::EnsureHomeMenuLoaded() { From e14b9f7a252142edc4ea9f054cb801358afb883e Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Thu, 27 Oct 2022 01:09:18 +0200 Subject: [PATCH 4/5] Fix clang-format and unused include --- src/core/core.cpp | 1 - src/core/hle/service/am/am.cpp | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index accf52e4f..55c65d125 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -31,7 +31,6 @@ #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" diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index dddd2aacf..48de08702 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -321,10 +321,11 @@ bool CIAFile::Close() const { // 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); + std::string to_delete = + GetTitleContentPath(media_type, old_tmd.GetTitleID(), old_index); if (!(Core::System::GetInstance().IsPoweredOn() && - Core::System::GetInstance().SetSelfDelete(toDelete))) - FileUtil::Delete(toDelete); + Core::System::GetInstance().SetSelfDelete(to_delete))) + FileUtil::Delete(to_delete); } FileUtil::Delete(old_tmd_path); From d04d71e4c9ec143a72cd68f45f8e7e5141a0fbb4 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Wed, 9 Nov 2022 16:25:52 +0100 Subject: [PATCH 5/5] Remove misplaced return statement --- src/core/hle/service/apt/applet_manager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index 99b7726e3..ab5e828bd 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -542,7 +542,6 @@ ResultCode AppletManager::DoApplicationJump(DeliverArg arg) { "Failed to find title during application jump: {} Resetting current title instead.", new_path); new_path.clear(); - return RESULT_SUCCESS; } system.RequestReset(new_path);