| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | // Copyright 2017 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2+
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-07 00:40:15 +02:00
										 |  |  | #include "DolphinQt/WiiUpdate.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <cinttypes>
 | 
					
						
							|  |  |  | #include <future>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QCloseEvent>
 | 
					
						
							|  |  |  | #include <QMessageBox>
 | 
					
						
							|  |  |  | #include <QObject>
 | 
					
						
							|  |  |  | #include <QProgressDialog>
 | 
					
						
							|  |  |  | #include <QPushButton>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Common/FileUtil.h"
 | 
					
						
							|  |  |  | #include "Common/Flag.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-28 03:48:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | #include "Core/Core.h"
 | 
					
						
							|  |  |  | #include "Core/WiiUtils.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-28 03:48:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | #include "DiscIO/NANDImporter.h"
 | 
					
						
							| 
									
										
										
										
											2018-05-28 03:48:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-07 00:40:15 +02:00
										 |  |  | #include "DolphinQt/QtUtils/QueueOnObject.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace WiiUpdate | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  | static void ShowResult(QWidget* parent, WiiUtils::UpdateResult result) | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  |   switch (result) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::Succeeded: | 
					
						
							|  |  |  |     QMessageBox::information(parent, QObject::tr("Update completed"), | 
					
						
							|  |  |  |                              QObject::tr("The emulated Wii console has been updated.")); | 
					
						
							|  |  |  |     DiscIO::NANDImporter().ExtractCertificates(File::GetUserPath(D_WIIROOT_IDX)); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::AlreadyUpToDate: | 
					
						
							|  |  |  |     QMessageBox::information(parent, QObject::tr("Update completed"), | 
					
						
							|  |  |  |                              QObject::tr("The emulated Wii console is already up-to-date.")); | 
					
						
							|  |  |  |     DiscIO::NANDImporter().ExtractCertificates(File::GetUserPath(D_WIIROOT_IDX)); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::ServerFailed: | 
					
						
							|  |  |  |     QMessageBox::critical(parent, QObject::tr("Update failed"), | 
					
						
							|  |  |  |                           QObject::tr("Could not download update information from Nintendo. " | 
					
						
							|  |  |  |                                       "Please check your Internet connection and try again.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::DownloadFailed: | 
					
						
							|  |  |  |     QMessageBox::critical(parent, QObject::tr("Update failed"), | 
					
						
							|  |  |  |                           QObject::tr("Could not download update files from Nintendo. " | 
					
						
							|  |  |  |                                       "Please check your Internet connection and try again.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::ImportFailed: | 
					
						
							|  |  |  |     QMessageBox::critical(parent, QObject::tr("Update failed"), | 
					
						
							|  |  |  |                           QObject::tr("Could not install an update to the Wii system memory. " | 
					
						
							|  |  |  |                                       "Please refer to logs for more information.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::Cancelled: | 
					
						
							|  |  |  |     QMessageBox::warning( | 
					
						
							|  |  |  |         parent, QObject::tr("Update cancelled"), | 
					
						
							|  |  |  |         QObject::tr("The update has been cancelled. It is strongly recommended to " | 
					
						
							|  |  |  |                     "finish it in order to avoid inconsistent system software versions.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::RegionMismatch: | 
					
						
							|  |  |  |     QMessageBox::critical(parent, QObject::tr("Update failed"), | 
					
						
							|  |  |  |                           QObject::tr("The game's region does not match your console's. " | 
					
						
							|  |  |  |                                       "To avoid issues with the system menu, it is not possible " | 
					
						
							|  |  |  |                                       "to update the emulated console using this disc.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::MissingUpdatePartition: | 
					
						
							|  |  |  |   case WiiUtils::UpdateResult::DiscReadFailed: | 
					
						
							|  |  |  |     QMessageBox::critical(parent, QObject::tr("Update failed"), | 
					
						
							|  |  |  |                           QObject::tr("The game disc does not contain any usable " | 
					
						
							|  |  |  |                                       "update information.")); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  | template <typename Callable, typename... Args> | 
					
						
							|  |  |  | static WiiUtils::UpdateResult ShowProgress(QWidget* parent, Callable function, Args&&... args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |   // Do not allow the user to close the dialog. Instead, wait until the update is finished
 | 
					
						
							|  |  |  |   // or cancelled.
 | 
					
						
							|  |  |  |   class UpdateProgressDialog final : public QProgressDialog | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     using QProgressDialog::QProgressDialog; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   protected: | 
					
						
							|  |  |  |     void reject() override {} | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   UpdateProgressDialog dialog{parent}; | 
					
						
							|  |  |  |   dialog.setLabelText(QObject::tr("Preparing to update...\nThis can take a while.")); | 
					
						
							|  |  |  |   dialog.setWindowTitle(QObject::tr("Updating")); | 
					
						
							| 
									
										
										
										
											2017-06-29 18:52:53 -06:00
										 |  |  |   dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |   // QProgressDialog doesn't set its minimum size correctly.
 | 
					
						
							|  |  |  |   dialog.setMinimumSize(360, 150); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // QProgressDialog doesn't allow us to disable the cancel button when it's pressed,
 | 
					
						
							|  |  |  |   // so we have to pass it our own push button. Note: the dialog takes ownership of it.
 | 
					
						
							|  |  |  |   auto* cancel_button = new QPushButton(QObject::tr("&Cancel"), parent); | 
					
						
							|  |  |  |   dialog.setCancelButton(cancel_button); | 
					
						
							|  |  |  |   Common::Flag was_cancelled; | 
					
						
							| 
									
										
										
										
											2017-07-04 19:16:13 +02:00
										 |  |  |   QObject::disconnect(&dialog, &QProgressDialog::canceled, nullptr, nullptr); | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |   QObject::connect(&dialog, &QProgressDialog::canceled, [&] { | 
					
						
							|  |  |  |     dialog.setLabelText(QObject::tr("Finishing the update...\nThis can take a while.")); | 
					
						
							|  |  |  |     cancel_button->setEnabled(false); | 
					
						
							|  |  |  |     was_cancelled.Set(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   std::future<WiiUtils::UpdateResult> result = std::async(std::launch::async, [&] { | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  |     const WiiUtils::UpdateResult res = function( | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |         [&](size_t processed, size_t total, u64 title_id) { | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  |           QueueOnObject(&dialog, [&dialog, &was_cancelled, processed, total, title_id] { | 
					
						
							| 
									
										
										
										
											2017-07-01 13:16:18 -07:00
										 |  |  |             if (was_cancelled.IsSet()) | 
					
						
							|  |  |  |               return; | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-01 13:16:18 -07:00
										 |  |  |             dialog.setRange(0, static_cast<int>(total)); | 
					
						
							|  |  |  |             dialog.setValue(static_cast<int>(processed)); | 
					
						
							|  |  |  |             dialog.setLabelText(QObject::tr("Updating title %1...\nThis can take a while.") | 
					
						
							|  |  |  |                                     .arg(title_id, 16, 16, QLatin1Char('0'))); | 
					
						
							|  |  |  |           }); | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |           return !was_cancelled.IsSet(); | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  |         std::forward<Args>(args)...); | 
					
						
							| 
									
										
										
										
											2017-07-04 19:16:13 +02:00
										 |  |  |     QueueOnObject(&dialog, [&dialog] { dialog.done(0); }); | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  |     return res; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dialog.exec(); | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  |   return result.get(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-04 17:38:25 +02:00
										 |  |  | void PerformOnlineUpdate(const std::string& region, QWidget* parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const int confirm = QMessageBox::question( | 
					
						
							|  |  |  |       parent, QObject::tr("Confirm"), | 
					
						
							|  |  |  |       QObject::tr("Connect to the Internet and perform an online system update?")); | 
					
						
							|  |  |  |   if (confirm != QMessageBox::Yes) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const WiiUtils::UpdateResult result = ShowProgress(parent, WiiUtils::DoOnlineUpdate, region); | 
					
						
							|  |  |  |   ShowResult(parent, result); | 
					
						
							| 
									
										
										
										
											2017-06-14 11:58:11 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-07-04 18:45:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void PerformDiscUpdate(const std::string& file_path, QWidget* parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const WiiUtils::UpdateResult result = ShowProgress(parent, WiiUtils::DoDiscUpdate, file_path); | 
					
						
							|  |  |  |   ShowResult(parent, result); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-07-30 15:56:12 -04:00
										 |  |  | }  // namespace WiiUpdate
 |