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,