diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 2723ca6431..e5004f4eb2 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -12,9 +12,11 @@ #include #include #include +#include + +#include #include "Common/Common.h" -#include "Common/Compat/optional" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" @@ -34,6 +36,8 @@ #include "Core/NetPlayServer.h" #include "Core/State.h" +#include "DiscIO/NANDImporter.h" + #include "DolphinQt2/AboutDialog.h" #include "DolphinQt2/Config/ControllersWindow.h" #include "DolphinQt2/Config/Graphics/GraphicsWindow.h" @@ -45,6 +49,7 @@ #include "DolphinQt2/MainWindow.h" #include "DolphinQt2/NetPlay/NetPlayDialog.h" #include "DolphinQt2/NetPlay/NetPlaySetupDialog.h" +#include "DolphinQt2/QtUtils/QueueOnObject.h" #include "DolphinQt2/QtUtils/WindowActivationEventFilter.h" #include "DolphinQt2/Resources.h" #include "DolphinQt2/Settings.h" @@ -201,6 +206,7 @@ void MainWindow::ConnectMenuBar() // Tools connect(m_menu_bar, &MenuBar::BootGameCubeIPL, this, &MainWindow::OnBootGameCubeIPL); + connect(m_menu_bar, &MenuBar::ImportNANDBackup, this, &MainWindow::OnImportNANDBackup); connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate); connect(m_menu_bar, &MenuBar::BootWiiSystemMenu, this, &MainWindow::BootWiiSystemMenu); connect(m_menu_bar, &MenuBar::StartNetPlay, this, &MainWindow::ShowNetPlaySetupDialog); @@ -832,3 +838,47 @@ void MainWindow::OnBootGameCubeIPL(DiscIO::Region region) { StartGame(std::make_unique(BootParameters::IPL{region})); } + +void MainWindow::OnImportNANDBackup() +{ + auto response = QMessageBox::question( + this, tr("Question"), + tr("Merging a new NAND over your currently selected NAND will overwrite any channels " + "and savegames that already exist. This process is not reversible, so it is " + "recommended that you keep backups of both NANDs. Are you sure you want to " + "continue?")); + + if (response == QMessageBox::No) + return; + + QString file = QFileDialog::getOpenFileName(this, tr("Select the save file"), QDir::currentPath(), + tr("BootMii NAND backup file (*.bin);;" + "All Files (*)")); + + if (file.isEmpty()) + return; + + QProgressDialog* dialog = new QProgressDialog(this); + dialog->setMinimum(0); + dialog->setMaximum(0); + dialog->setLabelText(tr("Importing NAND backup")); + dialog->setCancelButton(nullptr); + + auto beginning = QDateTime::currentDateTime().toSecsSinceEpoch(); + + auto result = std::async(std::launch::async, [&] { + DiscIO::NANDImporter().ImportNANDBin(file.toStdString(), [&dialog, beginning] { + QueueOnObject(dialog, [&dialog, beginning] { + dialog->setLabelText(tr("Importing NAND backup\n Time elapsed: %1s") + .arg(QDateTime::currentDateTime().toSecsSinceEpoch() - beginning)); + }); + }); + QueueOnObject(dialog, [dialog] { dialog->close(); }); + }); + + dialog->exec(); + + result.wait(); + + m_menu_bar->UpdateToolsMenu(Core::IsRunning()); +} diff --git a/Source/Core/DolphinQt2/MainWindow.h b/Source/Core/DolphinQt2/MainWindow.h index 1d55b39289..96efeef45b 100644 --- a/Source/Core/DolphinQt2/MainWindow.h +++ b/Source/Core/DolphinQt2/MainWindow.h @@ -104,6 +104,7 @@ private: void NetPlayQuit(); void OnBootGameCubeIPL(DiscIO::Region region); + void OnImportNANDBackup(); void OnStopComplete(); void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* event) override; diff --git a/Source/Core/DolphinQt2/MenuBar.cpp b/Source/Core/DolphinQt2/MenuBar.cpp index c235125317..99e9544302 100644 --- a/Source/Core/DolphinQt2/MenuBar.cpp +++ b/Source/Core/DolphinQt2/MenuBar.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "DolphinQt2/MenuBar.h" + #include #include #include @@ -17,9 +19,9 @@ #include "Core/IOS/ES/ES.h" #include "Core/IOS/IOS.h" #include "Core/State.h" +#include "DiscIO/NANDImporter.h" #include "DolphinQt2/AboutDialog.h" #include "DolphinQt2/GameList/GameFile.h" -#include "DolphinQt2/MenuBar.h" #include "DolphinQt2/Settings.h" MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent) @@ -112,6 +114,9 @@ void MenuBar::AddToolsMenu() // Label will be set by a NANDRefresh later m_boot_sysmenu = tools_menu->addAction(QStringLiteral(""), [this] { emit BootWiiSystemMenu(); }); + m_import_backup = tools_menu->addAction(tr("Import BootMii NAND Backup..."), + [this] { emit ImportNANDBackup(); }); + m_boot_sysmenu->setEnabled(false); connect(&Settings::Instance(), &Settings::NANDRefresh, [this] { UpdateToolsMenu(false); }); @@ -393,6 +398,7 @@ void MenuBar::UpdateToolsMenu(bool emulation_started) File::Exists(SConfig::GetInstance().GetBootROMPath(USA_DIR))); m_pal_ipl->setEnabled(!emulation_started && File::Exists(SConfig::GetInstance().GetBootROMPath(EUR_DIR))); + m_import_backup->setEnabled(!emulation_started); if (!emulation_started) { @@ -451,3 +457,4 @@ void MenuBar::ExportWiiSaves() { CWiiSaveCrypted::ExportAllSaves(); } + diff --git a/Source/Core/DolphinQt2/MenuBar.h b/Source/Core/DolphinQt2/MenuBar.h index 28bb00a7e1..2a34f47e50 100644 --- a/Source/Core/DolphinQt2/MenuBar.h +++ b/Source/Core/DolphinQt2/MenuBar.h @@ -9,6 +9,11 @@ #include #include +namespace DiscIO +{ +enum class Region; +}; + class MenuBar final : public QMenuBar { Q_OBJECT @@ -22,11 +27,6 @@ public: void UpdateStateSlotMenu(); void UpdateToolsMenu(bool emulation_started); - // Tools - void InstallWAD(); - void ImportWiiSave(); - void ExportWiiSaves(); - signals: // File void Open(); @@ -52,6 +52,7 @@ signals: void StateSaveOldest(); void SetStateSlot(int slot); void BootWiiSystemMenu(); + void ImportNANDBackup(); void PerformOnlineUpdate(const std::string& region); @@ -92,6 +93,10 @@ private: void AddToolsMenu(); void AddHelpMenu(); + void InstallWAD(); + void ImportWiiSave(); + void ExportWiiSaves(); + // File QAction* m_open_action; QAction* m_exit_action; @@ -103,6 +108,7 @@ private: QAction* m_ntscj_ipl; QAction* m_ntscu_ipl; QAction* m_pal_ipl; + QAction* m_import_backup; // Emulation QAction* m_play_action;