main: Prevent installing base titles into NAND

Many users have been installing their base titles into NAND instead of adding them into the games list. This prevents users from installing any base titles and warns the user about the action.
This commit is contained in:
Morph 2021-05-16 00:24:06 -04:00
parent 9edfd88a8a
commit a170aa16b6
4 changed files with 28 additions and 3 deletions

View file

@ -12,6 +12,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/crypto/key_manager.h" #include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h" #include "core/file_sys/card_image.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/content_archive.h" #include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h" #include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h" #include "core/file_sys/registered_cache.h"
@ -592,6 +593,12 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex
const CNMT cnmt(cnmt_file); const CNMT cnmt(cnmt_file);
const auto title_id = cnmt.GetTitleID(); const auto title_id = cnmt.GetTitleID();
const auto version = cnmt.GetTitleVersion();
if (title_id == GetBaseTitleID(title_id) && version == 0) {
return InstallResult::ErrorBaseInstall;
}
const auto result = RemoveExistingEntry(title_id); const auto result = RemoveExistingEntry(title_id);
// Install Metadata File // Install Metadata File

View file

@ -38,6 +38,7 @@ enum class InstallResult {
ErrorAlreadyExists, ErrorAlreadyExists,
ErrorCopyFailed, ErrorCopyFailed,
ErrorMetaFailed, ErrorMetaFailed,
ErrorBaseInstall,
}; };
struct ContentProviderEntry { struct ContentProviderEntry {

View file

@ -2101,6 +2101,7 @@ void GMainWindow::OnMenuInstallToNAND() {
QStringList new_files{}; // Newly installed files that do not yet exist in the NAND QStringList new_files{}; // Newly installed files that do not yet exist in the NAND
QStringList overwritten_files{}; // Files that overwrote those existing in the NAND QStringList overwritten_files{}; // Files that overwrote those existing in the NAND
QStringList failed_files{}; // Files that failed to install due to errors QStringList failed_files{}; // Files that failed to install due to errors
bool detected_base_install{}; // Whether a base game was attempted to be installed
ui.action_Install_File_NAND->setEnabled(false); ui.action_Install_File_NAND->setEnabled(false);
@ -2126,6 +2127,7 @@ void GMainWindow::OnMenuInstallToNAND() {
while (!future.isFinished()) { while (!future.isFinished()) {
QCoreApplication::processEvents(); QCoreApplication::processEvents();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
} }
result = future.result(); result = future.result();
@ -2146,6 +2148,10 @@ void GMainWindow::OnMenuInstallToNAND() {
case InstallResult::Failure: case InstallResult::Failure:
failed_files.append(QFileInfo(file).fileName()); failed_files.append(QFileInfo(file).fileName());
break; break;
case InstallResult::BaseInstallAttempted:
failed_files.append(QFileInfo(file).fileName());
detected_base_install = true;
break;
} }
--remaining; --remaining;
@ -2153,6 +2159,13 @@ void GMainWindow::OnMenuInstallToNAND() {
install_progress->close(); install_progress->close();
if (detected_base_install) {
QMessageBox::warning(
this, tr("Install Results"),
tr("To avoid possible conflicts, we discourage users from installing base games to the "
"NAND.\nPlease, only use this feature to install updates and DLC."));
}
const QString install_results = const QString install_results =
(new_files.isEmpty() ? QString{} (new_files.isEmpty() ? QString{}
: tr("%n file(s) were newly installed\n", "", new_files.size())) + : tr("%n file(s) were newly installed\n", "", new_files.size())) +
@ -2214,11 +2227,14 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) {
const auto res = const auto res =
Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry(
*nsp, true, qt_raw_copy); *nsp, true, qt_raw_copy);
if (res == FileSys::InstallResult::Success) { switch (res) {
case FileSys::InstallResult::Success:
return InstallResult::Success; return InstallResult::Success;
} else if (res == FileSys::InstallResult::OverwriteExisting) { case FileSys::InstallResult::OverwriteExisting:
return InstallResult::Overwrite; return InstallResult::Overwrite;
} else { case FileSys::InstallResult::ErrorBaseInstall:
return InstallResult::BaseInstallAttempted;
default:
return InstallResult::Failure; return InstallResult::Failure;
} }
} }

View file

@ -76,6 +76,7 @@ enum class InstallResult {
Success, Success,
Overwrite, Overwrite,
Failure, Failure,
BaseInstallAttempted,
}; };
enum class ReinitializeKeyBehavior { enum class ReinitializeKeyBehavior {