From 3124f3c4d8ac67937693e90056a8f7410dedbb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 25 Apr 2017 23:29:48 +0200 Subject: [PATCH] WX: Add the ability to uninstall WADs from the game list Simple quality-of-life addition that allows "uninstalling" WADs (removing the corresponding installed title) from the NAND. The option is only enabled when the WAD can be uninstalled The motivation for this is actually to encourage proper usage of the WAD launch feature (installing it to the NAND first), so we can drop the "direct WAD title launch" hack. --- Source/Core/DolphinWX/Frame.cpp | 1 + Source/Core/DolphinWX/Frame.h | 1 + Source/Core/DolphinWX/FrameTools.cpp | 27 +++++++++++++++++++++ Source/Core/DolphinWX/GameListCtrl.cpp | 33 +++++++++++++++++++++++--- Source/Core/DolphinWX/Globals.h | 1 + 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 184e9e681e..3c47217525 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -244,6 +244,7 @@ EVT_MENU_RANGE(IDM_FLOAT_LOG_WINDOW, IDM_FLOAT_CODE_WINDOW, CFrame::OnFloatWindo // Game list context menu EVT_MENU(IDM_LIST_INSTALL_WAD, CFrame::OnInstallWAD) +EVT_MENU(IDM_LIST_UNINSTALL_WAD, CFrame::OnUninstallWAD) // Other EVT_ACTIVATE(CFrame::OnActive) diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 236b0ac8be..e404d7858f 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -316,6 +316,7 @@ private: void OnShowCheatsWindow(wxCommandEvent& event); void OnLoadWiiMenu(wxCommandEvent& event); void OnInstallWAD(wxCommandEvent& event); + void OnUninstallWAD(wxCommandEvent& event); void OnImportBootMiiBackup(wxCommandEvent& event); void OnExtractCertificates(wxCommandEvent& event); void OnFifoPlayer(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 996c7770a6..9dd9c7a9a2 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -53,6 +53,8 @@ #include "DiscIO/NANDContentLoader.h" #include "DiscIO/NANDImporter.h" +#include "DiscIO/VolumeCreator.h" +#include "DiscIO/VolumeWad.h" #include "DolphinWX/AboutDolphin.h" #include "DolphinWX/Cheats/CheatsWindow.h" @@ -1228,6 +1230,31 @@ void CFrame::OnInstallWAD(wxCommandEvent& event) } } +void CFrame::OnUninstallWAD(wxCommandEvent&) +{ + const GameListItem* file = m_GameListCtrl->GetSelectedISO(); + if (!file) + return; + + if (!AskYesNoT("Uninstalling the WAD will remove the currently installed version " + "of this title from the NAND without deleting its save data. Continue?")) + { + return; + } + + const auto volume = DiscIO::CreateVolumeFromFilename(file->GetFileName()); + u64 title_id; + volume->GetTitleID(&title_id); + if (!DiscIO::CNANDContentManager::Access().RemoveTitle(title_id, Common::FROM_CONFIGURED_ROOT)) + { + PanicAlertT("Failed to remove this title from the NAND."); + return; + } + + if (title_id == TITLEID_SYSMENU) + UpdateLoadWiiMenuItem(); +} + void CFrame::OnImportBootMiiBackup(wxCommandEvent& WXUNUSED(event)) { if (!AskYesNoT("Merging a new NAND over your currently selected NAND will overwrite any channels " diff --git a/Source/Core/DolphinWX/GameListCtrl.cpp b/Source/Core/DolphinWX/GameListCtrl.cpp index a1bbb00928..738ca91196 100644 --- a/Source/Core/DolphinWX/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/GameListCtrl.cpp @@ -956,6 +956,27 @@ void CGameListCtrl::OnLeftClick(wxMouseEvent& event) event.Skip(); } +static bool IsWADInstalled(const std::string& wad_path) +{ + const auto volume = DiscIO::CreateVolumeFromFilename(wad_path); + u64 title_id; + if (!volume || !volume->GetTitleID(&title_id)) + return false; + + const std::string content_dir = + Common::GetTitleContentPath(title_id, Common::FromWhichRoot::FROM_CONFIGURED_ROOT); + + if (!File::IsDirectory(content_dir)) + return false; + + // Since this isn't IOS and we only need a simple way to figure out if a title is installed, + // we make the (reasonable) assumption that having more than just the TMD in the content + // directory means that the title is installed. + const auto entries = File::ScanDirectoryTree(content_dir, false); + return std::any_of(entries.children.begin(), entries.children.end(), + [](const auto& file) { return file.virtualName != "title.tmd"; }); +} + void CGameListCtrl::OnRightClick(wxMouseEvent& event) { // Focus the clicked item. @@ -1024,9 +1045,15 @@ void CGameListCtrl::OnRightClick(wxMouseEvent& event) if (platform == DiscIO::Platform::WII_WAD) { auto* const install_wad_item = - popupMenu.Append(IDM_LIST_INSTALL_WAD, _("Install to Wii Menu")); - // This should not be allowed while emulation is running, just like the Install WAD option. - install_wad_item->Enable(!Core::IsRunning() || !SConfig::GetInstance().bWii); + popupMenu.Append(IDM_LIST_INSTALL_WAD, _("Install to the NAND")); + auto* const uninstall_wad_item = + popupMenu.Append(IDM_LIST_UNINSTALL_WAD, _("Uninstall from the NAND")); + // These should not be allowed while emulation is running for safety reasons. + for (auto* menu_item : {install_wad_item, uninstall_wad_item}) + menu_item->Enable(!Core::IsRunning() || !SConfig::GetInstance().bWii); + + if (!IsWADInstalled(selected_iso->GetFileName())) + uninstall_wad_item->Enable(false); } popupMenu.Append(IDM_START_NETPLAY, _("Host with Netplay")); diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 9dfc6bc0e4..64ef00a951 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -101,6 +101,7 @@ enum IDM_LOAD_WII_MENU, IDM_MENU_INSTALL_WAD, IDM_LIST_INSTALL_WAD, + IDM_LIST_UNINSTALL_WAD, IDM_IMPORT_NAND, IDM_EXTRACT_CERTIFICATES, IDM_FIFOPLAYER,