diff options
Diffstat (limited to 'src/yuzu')
-rw-r--r-- | src/yuzu/applets/qt_amiibo_settings.cpp | 3 | ||||
-rw-r--r-- | src/yuzu/game_list.cpp | 6 | ||||
-rw-r--r-- | src/yuzu/game_list.h | 3 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 118 | ||||
-rw-r--r-- | src/yuzu/main.h | 12 | ||||
-rw-r--r-- | src/yuzu/main.ui | 6 |
6 files changed, 138 insertions, 10 deletions
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp index 4988fcc83..b457a736a 100644 --- a/src/yuzu/applets/qt_amiibo_settings.cpp +++ b/src/yuzu/applets/qt_amiibo_settings.cpp @@ -160,7 +160,8 @@ void QtAmiiboSettingsDialog::LoadAmiiboData() { } const auto amiibo_name = std::string(register_info.amiibo_name.data()); - const auto owner_name = Common::UTF16ToUTF8(register_info.mii_char_info.name.data()); + const auto owner_name = + Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data()); const auto creation_date = QDate(register_info.creation_date.year, register_info.creation_date.month, register_info.creation_date.day); diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 6842ced3e..f254c1e1c 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -589,10 +589,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); }); connect(start_game, &QAction::triggered, [this, path]() { - emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal); + emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Normal, + AmLaunchType::UserInitiated); }); connect(start_game_global, &QAction::triggered, [this, path]() { - emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global); + emit BootGame(QString::fromStdString(path), 0, 0, StartGameType::Global, + AmLaunchType::UserInitiated); }); connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index 8aea646b2..1fcbbf0ba 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -28,6 +28,7 @@ class GameListWorker; class GameListSearchField; class GameListDir; class GMainWindow; +enum class AmLaunchType; enum class StartGameType; namespace FileSys { @@ -103,7 +104,7 @@ public: signals: void BootGame(const QString& game_path, u64 program_id, std::size_t program_index, - StartGameType type); + StartGameType type, AmLaunchType launch_type); void GameChosen(const QString& game_path, const u64 title_id = 0); void ShouldCancelWorker(); void OpenFolderRequested(u64 program_id, GameListOpenTarget target, diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9cea60c32..97d216638 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -8,6 +8,7 @@ #include <iostream> #include <memory> #include <thread> +#include "core/loader/nca.h" #ifdef __APPLE__ #include <unistd.h> // for chdir #endif @@ -1554,6 +1555,7 @@ void GMainWindow::ConnectMenuEvents() { // Help connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder); + connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents); connect_menu(ui->action_About, &GMainWindow::OnAbout); } @@ -1705,7 +1707,8 @@ void GMainWindow::AllowOSSleep() { #endif } -bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index) { +bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t program_index, + AmLaunchType launch_type) { // Shutdown previous session if the emu thread is still active... if (emu_thread != nullptr) { ShutdownGame(); @@ -1717,6 +1720,10 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p system->SetFilesystem(vfs); + if (launch_type == AmLaunchType::UserInitiated) { + system->GetUserChannel().clear(); + } + system->SetAppletFrontendSet({ std::make_unique<QtAmiiboSettings>(*this), // Amiibo Settings (UISettings::values.controller_applet_disabled.GetValue() == true) @@ -1856,7 +1863,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) { } void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, - StartGameType type) { + StartGameType type, AmLaunchType launch_type) { LOG_INFO(Frontend, "yuzu starting..."); StoreRecentFile(filename); // Put the filename on top of the list @@ -1900,7 +1907,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t } } - if (!LoadROM(filename, program_id, program_index)) { + if (!LoadROM(filename, program_id, program_index, launch_type)) { return; } @@ -3369,7 +3376,8 @@ void GMainWindow::OnLoadComplete() { void GMainWindow::OnExecuteProgram(std::size_t program_index) { ShutdownGame(); - BootGame(last_filename_booted, 0, program_index); + BootGame(last_filename_booted, 0, program_index, StartGameType::Normal, + AmLaunchType::ApplicationInitiated); } void GMainWindow::OnExit() { @@ -4000,6 +4008,108 @@ void GMainWindow::OnOpenYuzuFolder() { QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::YuzuDir)))); } +void GMainWindow::OnVerifyInstalledContents() { + // Declare sizes. + size_t total_size = 0; + size_t processed_size = 0; + + // Initialize a progress dialog. + QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(100); + progress.setAutoClose(false); + progress.setAutoReset(false); + + // Declare a list of file names which failed to verify. + std::vector<std::string> failed; + + // Declare progress callback. + auto QtProgressCallback = [&](size_t nca_processed, size_t nca_total) { + if (progress.wasCanceled()) { + return false; + } + progress.setValue(static_cast<int>(((processed_size + nca_processed) * 100) / total_size)); + return true; + }; + + // Get content registries. + auto bis_contents = system->GetFileSystemController().GetSystemNANDContents(); + auto user_contents = system->GetFileSystemController().GetUserNANDContents(); + + std::vector<FileSys::RegisteredCache*> content_providers; + if (bis_contents) { + content_providers.push_back(bis_contents); + } + if (user_contents) { + content_providers.push_back(user_contents); + } + + // Get associated NCA files. + std::vector<FileSys::VirtualFile> nca_files; + + // Get all installed IDs. + for (auto nca_provider : content_providers) { + const auto entries = nca_provider->ListEntriesFilter(); + + for (const auto& entry : entries) { + auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type); + if (!nca_file) { + continue; + } + + total_size += nca_file->GetSize(); + nca_files.push_back(std::move(nca_file)); + } + } + + // Using the NCA loader, determine if all NCAs are valid. + for (auto& nca_file : nca_files) { + Loader::AppLoader_NCA nca_loader(nca_file); + + auto status = nca_loader.VerifyIntegrity(QtProgressCallback); + if (progress.wasCanceled()) { + break; + } + if (status != Loader::ResultStatus::Success) { + FileSys::NCA nca(nca_file); + const auto title_id = nca.GetTitleId(); + std::string title_name = "unknown"; + + const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id), + FileSys::ContentRecordType::Control); + if (control && control->GetStatus() == Loader::ResultStatus::Success) { + const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), + *provider}; + const auto [nacp, logo] = pm.ParseControlNCA(*control); + if (nacp) { + title_name = nacp->GetApplicationName(); + } + } + + if (title_id > 0) { + failed.push_back( + fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name)); + } else { + failed.push_back(fmt::format("{} (unknown)", nca_file->GetName())); + } + } + + processed_size += nca_file->GetSize(); + } + + progress.close(); + + if (failed.size() > 0) { + auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(failed, "\n"))); + QMessageBox::critical( + this, tr("Integrity verification failed!"), + tr("Verification failed for the following files:\n\n%1").arg(failed_names)); + } else { + QMessageBox::information(this, tr("Integrity verification succeeded!"), + tr("The operation completed successfully.")); + } +} + void GMainWindow::OnAbout() { AboutDialog aboutDialog(this); aboutDialog.exec(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 1e4f6e477..cf191f698 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -58,6 +58,11 @@ enum class StartGameType { Global, // Only uses global configuration }; +enum class AmLaunchType { + UserInitiated, + ApplicationInitiated, +}; + namespace Core { enum class SystemResultStatus : u32; class System; @@ -239,9 +244,11 @@ private: void PreventOSSleep(); void AllowOSSleep(); - bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index); + bool LoadROM(const QString& filename, u64 program_id, std::size_t program_index, + AmLaunchType launch_type); void BootGame(const QString& filename, u64 program_id = 0, std::size_t program_index = 0, - StartGameType with_config = StartGameType::Normal); + StartGameType with_config = StartGameType::Normal, + AmLaunchType launch_type = AmLaunchType::UserInitiated); void ShutdownGame(); void ShowTelemetryCallout(); @@ -343,6 +350,7 @@ private slots: void OnConfigurePerGame(); void OnLoadAmiibo(); void OnOpenYuzuFolder(); + void OnVerifyInstalledContents(); void OnAbout(); void OnToggleFilterBar(); void OnToggleStatusBar(); diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 013ba0ceb..e54d7d75d 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -148,6 +148,7 @@ <addaction name="action_Configure_Tas"/> </widget> <addaction name="action_Rederive"/> + <addaction name="action_Verify_installed_contents"/> <addaction name="separator"/> <addaction name="action_Capture_Screenshot"/> <addaction name="menuTAS"/> @@ -214,6 +215,11 @@ <string>&Reinitialize keys...</string> </property> </action> + <action name="action_Verify_installed_contents"> + <property name="text"> + <string>Verify installed contents</string> + </property> + </action> <action name="action_About"> <property name="text"> <string>&About yuzu</string> |