summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2017-10-06 21:45:28 +0200
committerLéo Lam <leo@innovatetechnologi.es>2017-10-08 18:57:58 +0200
commit02e17594b06151e652a1b51ce1018ce4747feecd (patch)
treeddeb6c96b916e2f827d1b2341c1f31aea4afd67f /Source/Core
parente1c0b8d01124f13d07d0b7bd0e271e88b1178d0d (diff)
WiiUtils: Attempt to fix the NAND more aggressively
Change the repair logic to fix issues more aggressively by deleting bad titles. This is necessary because of a bug in Dolphin's WAD boot code. The UI code was updated to inform the user about titles that will be deleted if they continue a repair, before deleting anything.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/WiiUtils.cpp47
-rw-r--r--Source/Core/Core/WiiUtils.h8
-rw-r--r--Source/Core/DolphinQt2/MenuBar.cpp31
-rw-r--r--Source/Core/DolphinWX/FrameTools.cpp26
4 files changed, 83 insertions, 29 deletions
diff --git a/Source/Core/Core/WiiUtils.cpp b/Source/Core/Core/WiiUtils.cpp
index f721107d76..4235c9ba96 100644
--- a/Source/Core/Core/WiiUtils.cpp
+++ b/Source/Core/Core/WiiUtils.cpp
@@ -686,16 +686,16 @@ UpdateResult DoDiscUpdate(UpdateCallback update_callback, const std::string& ima
return result;
}
-bool CheckNAND(IOS::HLE::Kernel& ios)
+NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios)
{
- bool bad = false;
+ NANDCheckResult result;
const auto es = ios.GetES();
// Check for NANDs that were used with old Dolphin versions.
if (File::Exists(Common::RootUserPath(Common::FROM_CONFIGURED_ROOT) + "/sys/replace"))
{
ERROR_LOG(CORE, "CheckNAND: NAND was used with old versions, so it is likely to be damaged");
- bad = true;
+ result.bad = true;
}
for (const u64 title_id : es->GetInstalledTitles())
@@ -704,12 +704,12 @@ bool CheckNAND(IOS::HLE::Kernel& ios)
if (!File::IsDirectory(Common::GetTitleContentPath(title_id, Common::FROM_CONFIGURED_ROOT)))
{
ERROR_LOG(CORE, "CheckNAND: Missing content directory for title %016" PRIx64, title_id);
- bad = true;
+ result.bad = true;
}
if (!File::IsDirectory(Common::GetTitleDataPath(title_id, Common::FROM_CONFIGURED_ROOT)))
{
ERROR_LOG(CORE, "CheckNAND: Missing data directory for title %016" PRIx64, title_id);
- bad = true;
+ result.bad = true;
}
// Check for incomplete title installs (missing ticket, TMD or contents).
@@ -717,13 +717,26 @@ bool CheckNAND(IOS::HLE::Kernel& ios)
if (!IOS::ES::IsDiscTitle(title_id) && !ticket.IsValid())
{
ERROR_LOG(CORE, "CheckNAND: Missing ticket for title %016" PRIx64, title_id);
- bad = true;
+ result.titles_to_remove.insert(title_id);
+ result.bad = true;
}
+ const std::string content_dir =
+ Common::GetTitleContentPath(title_id, Common::FROM_CONFIGURED_ROOT);
+
const auto tmd = es->FindInstalledTMD(title_id);
if (!tmd.IsValid())
{
- WARN_LOG(CORE, "CheckNAND: Missing TMD for title %016" PRIx64, title_id);
+ if (File::ScanDirectoryTree(content_dir, false).children.empty())
+ {
+ WARN_LOG(CORE, "CheckNAND: Missing TMD for title %016" PRIx64, title_id);
+ }
+ else
+ {
+ ERROR_LOG(CORE, "CheckNAND: Missing TMD for title %016" PRIx64, title_id);
+ result.titles_to_remove.insert(title_id);
+ result.bad = true;
+ }
// Further checks require the TMD to be valid.
continue;
}
@@ -736,11 +749,12 @@ bool CheckNAND(IOS::HLE::Kernel& ios)
(tmd.GetTitleFlags() & IOS::ES::TitleFlags::TITLE_TYPE_WFS_MAYBE) == 0)
{
ERROR_LOG(CORE, "CheckNAND: Missing contents for title %016" PRIx64, title_id);
- bad = true;
+ result.titles_to_remove.insert(title_id);
+ result.bad = true;
}
}
- return !bad;
+ return result;
}
bool RepairNAND(IOS::HLE::Kernel& ios)
@@ -759,15 +773,18 @@ bool RepairNAND(IOS::HLE::Kernel& ios)
File::CreateDir(content_dir);
File::CreateDir(data_dir);
- // If there's nothing in the content/data directories and no ticket,
+ // If there's nothing in the content directory and no ticket,
// this title shouldn't exist at all on the NAND.
- if (File::ScanDirectoryTree(content_dir, false).children.empty() &&
- File::ScanDirectoryTree(data_dir, false).children.empty() &&
- !DiscIO::FindSignedTicket(title_id).IsValid())
+ // WARNING: This will delete associated save data!
+ const auto content_files = File::ScanDirectoryTree(content_dir, false).children;
+ const bool has_no_tmd_but_contents =
+ !es->FindInstalledTMD(title_id).IsValid() && !content_files.empty();
+ if (has_no_tmd_but_contents || !DiscIO::FindSignedTicket(title_id).IsValid())
{
- es->DeleteTitle(title_id);
+ const std::string title_dir = Common::GetTitlePath(title_id, Common::FROM_CONFIGURED_ROOT);
+ File::DeleteDirRecursively(title_dir);
}
}
- return CheckNAND(ios);
+ return !CheckNAND(ios).bad;
}
}
diff --git a/Source/Core/Core/WiiUtils.h b/Source/Core/Core/WiiUtils.h
index 2320b1f154..0047e2c63d 100644
--- a/Source/Core/Core/WiiUtils.h
+++ b/Source/Core/Core/WiiUtils.h
@@ -7,6 +7,7 @@
#include <cstddef>
#include <functional>
#include <string>
+#include <unordered_set>
#include "Common/CommonTypes.h"
@@ -58,6 +59,11 @@ UpdateResult DoOnlineUpdate(UpdateCallback update_callback, const std::string& r
UpdateResult DoDiscUpdate(UpdateCallback update_callback, const std::string& image_path);
// Check the emulated NAND for common issues.
-bool CheckNAND(IOS::HLE::Kernel& ios);
+struct NANDCheckResult
+{
+ bool bad = false;
+ std::unordered_set<u64> titles_to_remove;
+};
+NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios);
bool RepairNAND(IOS::HLE::Kernel& ios);
}
diff --git a/Source/Core/DolphinQt2/MenuBar.cpp b/Source/Core/DolphinQt2/MenuBar.cpp
index b7b7410e6f..401f7f4d7e 100644
--- a/Source/Core/DolphinQt2/MenuBar.cpp
+++ b/Source/Core/DolphinQt2/MenuBar.cpp
@@ -22,6 +22,7 @@
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/State.h"
+#include "Core/TitleDatabase.h"
#include "Core/WiiUtils.h"
#include "DiscIO/NANDImporter.h"
#include "DolphinQt2/AboutDialog.h"
@@ -537,21 +538,37 @@ void MenuBar::ExportWiiSaves()
void MenuBar::CheckNAND()
{
IOS::HLE::Kernel ios;
- if (WiiUtils::CheckNAND(ios))
+ WiiUtils::NANDCheckResult result = WiiUtils::CheckNAND(ios);
+ if (!result.bad)
{
QMessageBox::information(this, tr("NAND Check"), tr("No issues have been detected."));
return;
}
- if (QMessageBox::question(
- this, tr("NAND Check"),
- tr("The emulated NAND is damaged. System titles such as the Wii Menu and "
- "the Wii Shop Channel may not work correctly.\n\n"
- "Do you want to try to repair the NAND?")) != QMessageBox::Yes)
+ QString message = tr("The emulated NAND is damaged. System titles such as the Wii Menu and "
+ "the Wii Shop Channel may not work correctly.\n\n"
+ "Do you want to try to repair the NAND?");
+ if (!result.titles_to_remove.empty())
{
- return;
+ message += tr("\n\nWARNING: Fixing this NAND requires the deletion of titles that have "
+ "incomplete data on the NAND, including all associated save data. "
+ "By continuing, the following title(s) will be removed:\n\n");
+ Core::TitleDatabase title_db;
+ for (const u64 title_id : result.titles_to_remove)
+ {
+ const std::string name = title_db.GetTitleName(title_id);
+ message += !name.empty() ?
+ QStringLiteral("%1 (%2)")
+ .arg(QString::fromStdString(name))
+ .arg(title_id, 16, 16, QLatin1Char('0')) :
+ QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char('0'));
+ message += QStringLiteral("\n");
+ }
}
+ if (QMessageBox::question(this, tr("NAND Check"), message) != QMessageBox::Yes)
+ return;
+
if (WiiUtils::RepairNAND(ios))
{
QMessageBox::information(this, tr("NAND Check"), tr("The NAND has been repaired."));
diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp
index cda03e9c6d..592f338cd2 100644
--- a/Source/Core/DolphinWX/FrameTools.cpp
+++ b/Source/Core/DolphinWX/FrameTools.cpp
@@ -1312,20 +1312,34 @@ void CFrame::OnImportBootMiiBackup(wxCommandEvent& WXUNUSED(event))
void CFrame::OnCheckNAND(wxCommandEvent&)
{
IOS::HLE::Kernel ios;
- if (WiiUtils::CheckNAND(ios))
+ WiiUtils::NANDCheckResult result = WiiUtils::CheckNAND(ios);
+ if (!result.bad)
{
wxMessageBox(_("No issues have been detected."), _("NAND Check"), wxOK | wxICON_INFORMATION);
return;
}
- if (wxMessageBox("The emulated NAND is damaged. System titles such as the Wii Menu and "
- "the Wii Shop Channel may not work correctly.\n\n"
- "Do you want to try to repair the NAND?",
- _("NAND Check"), wxYES_NO) != wxYES)
+ wxString message = _("The emulated NAND is damaged. System titles such as the Wii Menu and "
+ "the Wii Shop Channel may not work correctly.\n\n"
+ "Do you want to try to repair the NAND?");
+ if (!result.titles_to_remove.empty())
{
- return;
+ message += _("\n\nWARNING: Fixing this NAND requires the deletion of titles that have "
+ "incomplete data on the NAND, including all associated save data. "
+ "By continuing, the following title(s) will be removed:\n\n");
+ Core::TitleDatabase title_db;
+ for (const u64 title_id : result.titles_to_remove)
+ {
+ const std::string name = title_db.GetTitleName(title_id);
+ message += !name.empty() ? StringFromFormat("%s (%016" PRIx64 ")", name.c_str(), title_id) :
+ StringFromFormat("%016" PRIx64, title_id);
+ message += "\n";
+ }
}
+ if (wxMessageBox(message, _("NAND Check"), wxYES_NO) != wxYES)
+ return;
+
if (WiiUtils::RepairNAND(ios))
{
wxMessageBox(_("The NAND has been repaired."), _("NAND Check"), wxOK | wxICON_INFORMATION);