diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 498b9c7e71..b6d64c655f 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -55,6 +55,8 @@ public: ReturnCode Close(u32 fd) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; + ReturnCode DeleteTitleContent(u64 title_id) const; + private: enum { diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index 2de0ab7c40..254276994d 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -376,20 +376,29 @@ IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } +ReturnCode ES::DeleteTitleContent(u64 title_id) const +{ + if (!CanDeleteTitle(title_id)) + return ES_EINVAL; + + const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT); + if (!File::IsDirectory(content_dir)) + return FS_ENOENT; + + for (const auto& file : File::ScanDirectoryTree(content_dir, false).children) + { + if (file.virtualName.size() == 12 && file.virtualName.compare(8, 4, ".app") == 0) + File::Delete(file.physicalName); + } + + return IPC_SUCCESS; +} + IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request) { - if (!request.HasNumberOfValidVectors(1, 0)) + if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64)) return GetDefaultReply(ES_EINVAL); - - u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_DELETETITLECONTENT: title: %08x/%08x", (u32)(TitleID >> 32), - (u32)TitleID); - - // Presumably return -1017 when title not installed TODO verify - if (!DiscIO::CNANDContentManager::Access().RemoveTitle(TitleID, Common::FROM_SESSION_ROOT)) - return GetDefaultReply(ES_EINVAL); - - return GetDefaultReply(IPC_SUCCESS); + return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address))); } IPCCommandResult ES::ExportTitleInit(Context& context, const IOCtlVRequest& request) diff --git a/Source/Core/DiscIO/NANDContentLoader.cpp b/Source/Core/DiscIO/NANDContentLoader.cpp index b87e52a246..4e7f6f12ba 100644 --- a/Source/Core/DiscIO/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/NANDContentLoader.cpp @@ -241,40 +241,11 @@ const CNANDContentLoader& CNANDContentManager::GetNANDLoader(u64 title_id, return GetNANDLoader(path); } -bool CNANDContentManager::RemoveTitle(u64 title_id, Common::FromWhichRoot from) -{ - auto& loader = GetNANDLoader(title_id, from); - if (!loader.IsValid()) - return false; - loader.RemoveTitle(); - return GetNANDLoader(title_id, from).IsValid(); -} - void CNANDContentManager::ClearCache() { m_map.clear(); } -void CNANDContentLoader::RemoveTitle() const -{ - const u64 title_id = m_tmd.GetTitleId(); - INFO_LOG(DISCIO, "RemoveTitle %016" PRIx64, title_id); - if (IsValid()) - { - // remove TMD? - for (const auto& content : m_Content) - { - if (!content.m_metadata.IsShared()) - { - std::string path = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_metadata.id); - INFO_LOG(DISCIO, "Delete %s", path.c_str()); - File::Delete(path); - } - } - CNANDContentManager::Access().ClearCache(); // deletes 'this' - } -} - u64 CNANDContentManager::Install_WiiWAD(const std::string& filename) { if (filename.find(".wad") == std::string::npos) diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h index 6e6a5d77e8..3b16b82bda 100644 --- a/Source/Core/DiscIO/NANDContentLoader.h +++ b/Source/Core/DiscIO/NANDContentLoader.h @@ -79,7 +79,6 @@ public: ~CNANDContentLoader(); bool IsValid() const; - void RemoveTitle() const; const SNANDContent* GetContentByID(u32 id) const; const SNANDContent* GetContentByIndex(int index) const; const IOS::ES::TMDReader& GetTMD() const { return m_tmd; } @@ -111,7 +110,6 @@ public: const CNANDContentLoader& GetNANDLoader(const std::string& content_path); const CNANDContentLoader& GetNANDLoader(u64 title_id, Common::FromWhichRoot from); - bool RemoveTitle(u64 title_id, Common::FromWhichRoot from); void ClearCache(); private: diff --git a/Source/Core/DolphinQt2/GameList/GameFile.cpp b/Source/Core/DolphinQt2/GameList/GameFile.cpp index 1088e66e82..2f23107776 100644 --- a/Source/Core/DolphinQt2/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt2/GameList/GameFile.cpp @@ -13,6 +13,8 @@ #include "Common/NandPaths.h" #include "Core/ConfigManager.h" #include "Core/HW/WiiSaveCrypted.h" +#include "Core/IOS/ES/ES.h" +#include "Core/IOS/IOS.h" #include "DiscIO/Blob.h" #include "DiscIO/Enums.h" #include "DiscIO/NANDContentLoader.h" @@ -324,9 +326,8 @@ bool GameFile::Install() bool GameFile::Uninstall() { _assert_(m_platform == DiscIO::Platform::WII_WAD); - - return DiscIO::CNANDContentManager::Access().RemoveTitle(m_title_id, - Common::FROM_CONFIGURED_ROOT); + IOS::HLE::Kernel ios; + return ios.GetES()->DeleteTitleContent(m_title_id) == IOS::HLE::IPC_SUCCESS; } bool GameFile::ExportWiiSave() diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 09a6e625fa..232c5418ab 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -42,6 +42,7 @@ #include "Core/HW/Wiimote.h" #include "Core/Host.h" #include "Core/HotkeyManager.h" +#include "Core/IOS/ES/ES.h" #include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/IOS/USB/Bluetooth/BTEmu.h" @@ -1228,7 +1229,8 @@ void CFrame::OnUninstallWAD(wxCommandEvent&) } u64 title_id = file->GetTitleID(); - if (!DiscIO::CNANDContentManager::Access().RemoveTitle(title_id, Common::FROM_CONFIGURED_ROOT)) + IOS::HLE::Kernel ios; + if (ios.GetES()->DeleteTitleContent(title_id) < 0) { PanicAlertT("Failed to remove this title from the NAND."); return;