diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 1ece557313..2c145bd09d 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -176,7 +176,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { for (const VirtualFile& file : partitions[static_cast(part)]->GetFiles()) { if (file->GetExtension() != "nca") continue; - auto nca = std::make_shared(file); + auto nca = std::make_shared(file, nullptr, 0, keys); // TODO(DarkLordZach): Add proper Rev1+ Support if (nca->IsUpdate()) continue; diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 8f62571cfb..25f5914b6d 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -9,6 +9,7 @@ #include #include "common/common_types.h" #include "common/swap.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/vfs.h" namespace Loader { @@ -107,5 +108,7 @@ private: std::shared_ptr secure_partition; std::shared_ptr program; std::vector> ncas; + + Core::Crypto::KeyManager keys; }; } // namespace FileSys diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index b46fe893cf..19b6f86003 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp @@ -101,8 +101,9 @@ static bool IsValidNCA(const NCAHeader& header) { return header.magic == Common::MakeMagic('N', 'C', 'A', '3'); } -NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset) - : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)) { +NCA::NCA(VirtualFile file_, VirtualFile bktr_base_romfs_, u64 bktr_base_ivfc_offset, + Core::Crypto::KeyManager keys_) + : file(std::move(file_)), bktr_base_romfs(std::move(bktr_base_romfs_)), keys(std::move(keys_)) { if (file == nullptr) { status = Loader::ResultStatus::ErrorNullFile; return; diff --git a/src/core/file_sys/content_archive.h b/src/core/file_sys/content_archive.h index 4bba556071..99294cbb45 100644 --- a/src/core/file_sys/content_archive.h +++ b/src/core/file_sys/content_archive.h @@ -79,7 +79,8 @@ inline bool IsDirectoryExeFS(const std::shared_ptr& pfs) { class NCA : public ReadOnlyVfsDirectory { public: explicit NCA(VirtualFile file, VirtualFile bktr_base_romfs = nullptr, - u64 bktr_base_ivfc_offset = 0); + u64 bktr_base_ivfc_offset = 0, + Core::Crypto::KeyManager keys = Core::Crypto::KeyManager()); ~NCA() override; Loader::ResultStatus GetStatus() const; diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 96302a241b..a3f8f2f737 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -106,9 +106,12 @@ static ContentRecordType GetCRTypeFromNCAType(NCAContentType type) { VirtualFile RegisteredCache::OpenFileOrDirectoryConcat(const VirtualDir& dir, std::string_view path) const { - if (dir->GetFileRelative(path) != nullptr) - return dir->GetFileRelative(path); - if (dir->GetDirectoryRelative(path) != nullptr) { + const auto file = dir->GetFileRelative(path); + if (file != nullptr) + return file; + + const auto nca_dir = dir->GetDirectoryRelative(path); + if (nca_dir != nullptr) { const auto nca_dir = dir->GetDirectoryRelative(path); VirtualFile file = nullptr; @@ -225,7 +228,7 @@ void RegisteredCache::ProcessFiles(const std::vector& ids) { if (file == nullptr) continue; - const auto nca = std::make_shared(parser(file, id)); + const auto nca = std::make_shared(parser(file, id), nullptr, 0, keys); if (nca->GetStatus() != Loader::ResultStatus::Success || nca->GetType() != NCAContentType::Meta) { continue; @@ -315,7 +318,7 @@ std::unique_ptr RegisteredCache::GetEntry(u64 title_id, ContentRecordType t const auto raw = GetEntryRaw(title_id, type); if (raw == nullptr) return nullptr; - return std::make_unique(raw); + return std::make_unique(raw, nullptr, 0, keys); } std::unique_ptr RegisteredCache::GetEntry(RegisteredCacheEntry entry) const { diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index 6cfb160175..6b89db8de3 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -12,6 +12,7 @@ #include #include #include "common/common_types.h" +#include "core/crypto/key_manager.h" #include "core/file_sys/vfs.h" namespace FileSys { @@ -133,6 +134,8 @@ private: VirtualDir dir; RegisteredCacheParsingFunction parser; + Core::Crypto::KeyManager keys; + // maps tid -> NcaID of meta boost::container::flat_map meta_id; // maps tid -> meta diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 2aaba4179c..e1a4210dbf 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp @@ -252,7 +252,7 @@ void NSP::ReadNCAs(const std::vector& files) { continue; } - auto next_nca = std::make_shared(next_file); + auto next_nca = std::make_shared(next_file, nullptr, 0, keys); if (next_nca->GetType() == NCAContentType::Program) program_status[cnmt.GetTitleID()] = next_nca->GetStatus(); if (next_nca->GetStatus() == Loader::ResultStatus::Success || diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 338080b7ea..9a28ed5bbe 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -70,6 +70,8 @@ private: std::map>> ncas; std::vector ticket_files; + Core::Crypto::KeyManager keys; + VirtualFile romfs; VirtualDir exefs; }; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 554474cf6d..5d62940168 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -329,9 +329,16 @@ ResultVal OpenSDMC() { return sdmc_factory->Open(); } -std::unique_ptr GetUnionContents() { - return std::make_unique(std::vector{ - GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); +std::shared_ptr registered_cache_union; + +std::shared_ptr GetUnionContents() { + if (registered_cache_union == nullptr) { + registered_cache_union = + std::make_shared(std::vector{ + GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); + } + + return registered_cache_union; } FileSys::RegisteredCache* GetSystemNANDContents() { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index e38f028699..ff9182e848 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -48,7 +48,7 @@ ResultVal OpenSaveData(FileSys::SaveDataSpaceId space, ResultVal OpenSaveDataSpace(FileSys::SaveDataSpaceId space); ResultVal OpenSDMC(); -std::unique_ptr GetUnionContents(); +std::shared_ptr GetUnionContents(); FileSys::RegisteredCache* GetSystemNANDContents(); FileSys::RegisteredCache* GetUserNANDContents(); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 60606bb339..be69fb831a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -171,6 +171,7 @@ void Config::ReadValues() { qt_config->beginGroup("UIGameList"); UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool(); + UISettings::values.show_add_ons = qt_config->value("show_add_ons", true).toBool(); UISettings::values.icon_size = qt_config->value("icon_size", 64).toUInt(); UISettings::values.row_1_text_id = qt_config->value("row_1_text_id", 3).toUInt(); UISettings::values.row_2_text_id = qt_config->value("row_2_text_id", 2).toUInt(); @@ -312,6 +313,7 @@ void Config::SaveValues() { qt_config->beginGroup("UIGameList"); qt_config->setValue("show_unknown", UISettings::values.show_unknown); + qt_config->setValue("show_add_ons", UISettings::values.show_add_ons); qt_config->setValue("icon_size", UISettings::values.icon_size); qt_config->setValue("row_1_text_id", UISettings::values.row_1_text_id); qt_config->setValue("row_2_text_id", UISettings::values.row_2_text_id); diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp index 8743ce982d..639d5df0ff 100644 --- a/src/yuzu/configuration/configure_gamelist.cpp +++ b/src/yuzu/configuration/configure_gamelist.cpp @@ -42,6 +42,7 @@ ConfigureGameList::~ConfigureGameList() = default; void ConfigureGameList::applyConfiguration() { UISettings::values.show_unknown = ui->show_unknown->isChecked(); + UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); UISettings::values.row_2_text_id = ui->row_2_text_combobox->currentData().toUInt(); @@ -50,6 +51,7 @@ void ConfigureGameList::applyConfiguration() { void ConfigureGameList::setConfiguration() { ui->show_unknown->setChecked(UISettings::values.show_unknown); + ui->show_add_ons->setChecked(UISettings::values.show_add_ons); ui->icon_size_combobox->setCurrentIndex( ui->icon_size_combobox->findData(UISettings::values.icon_size)); ui->row_1_text_combobox->setCurrentIndex( diff --git a/src/yuzu/configuration/configure_gamelist.ui b/src/yuzu/configuration/configure_gamelist.ui index 7471fdb600..7a69377e7d 100644 --- a/src/yuzu/configuration/configure_gamelist.ui +++ b/src/yuzu/configuration/configure_gamelist.ui @@ -1,126 +1,133 @@ ConfigureGameList - - - - 0 - 0 - 300 - 377 - - - - Form - - - - + + + + 0 + 0 + 300 + 377 + + + + Form + + + + + + + + General + + + + - - - General - - - - - - - - Show files with type 'Unknown' - - - - - - - + + + Show files with type 'Unknown' + + - - - Icon Size + + + Show Add-Ons Column + + + + + + + + + + + + Icon Size + + + + + + + + + + Icon Size: - - - - - - - - - Icon Size: - - - - - - - - - - - - + + + + + + + + + + + + + + + + Row Text + + + + + + + + + + Row 1 Text: + + + + + + + - - - Row Text + + + + + Row 2 Text: - - - - - - - - - Row 1 Text: - - - - - - - - - - - - - - Row 2 Text: - - - - - - - - - - - - + + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + - + + + diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index a5a4aa432b..11a8c390b1 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -215,12 +215,18 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent) tree_view->setUniformRowHeights(true); tree_view->setContextMenuPolicy(Qt::CustomContextMenu); - item_model->insertColumns(0, COLUMN_COUNT); + item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1); item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); - item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); - item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); - item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); + + if (UISettings::values.show_add_ons) { + item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); + item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); + item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); + } else { + item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type")); + item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size")); + } connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); @@ -394,6 +400,25 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { } tree_view->setEnabled(false); + + // Update the columns in case UISettings has changed + item_model->removeColumns(0, item_model->columnCount()); + item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1); + item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); + item_model->setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility")); + + if (UISettings::values.show_add_ons) { + item_model->setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons")); + item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type")); + item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size")); + } else { + item_model->setHeaderData(COLUMN_FILE_TYPE - 1, Qt::Horizontal, tr("File type")); + item_model->setHeaderData(COLUMN_SIZE - 1, Qt::Horizontal, tr("Size")); + item_model->removeColumns(COLUMN_COUNT - 1, 1); + } + + LoadInterfaceLayout(); + // Delete any rows that might already exist if we're repopulating item_model->removeRows(0, item_model->rowCount()); diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 3d865a12df..362902e460 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -123,17 +123,22 @@ void GameListWorker::AddInstalledTitlesToGameList() { if (it != compatibility_list.end()) compatibility = it->second.first; - emit EntryReady({ + QList list{ new GameListItemPath( FormatGameName(file->GetFullPath()), icon, QString::fromStdString(name), QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), program_id), new GameListItemCompat(compatibility), - new GameListItem(FormatPatchNameVersions(patch, *loader)), new GameListItem( QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(file->GetSize()), - }); + }; + + if (UISettings::values.show_add_ons) { + list.insert(2, new GameListItem(FormatPatchNameVersions(patch, *loader))); + } + + emit EntryReady(list); } const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application, @@ -216,18 +221,23 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign if (it != compatibility_list.end()) compatibility = it->second.first; - emit EntryReady({ + QList list{ new GameListItemPath( FormatGameName(physical_name), icon, QString::fromStdString(name), QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType())), program_id), new GameListItemCompat(compatibility), - new GameListItem( - FormatPatchNameVersions(patch, *loader, loader->IsRomFSUpdatable())), new GameListItem( QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), - }); + }; + + if (UISettings::values.show_add_ons) { + list.insert(2, new GameListItem(FormatPatchNameVersions( + patch, *loader, loader->IsRomFSUpdatable()))); + } + + emit EntryReady(std::move(list)); } else if (is_dir && recursion > 0) { watch_list.append(QString::fromStdString(physical_name)); AddFstEntriesToGameList(physical_name, recursion - 1); diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h index 2e617d52ad..32a0d813c4 100644 --- a/src/yuzu/ui_settings.h +++ b/src/yuzu/ui_settings.h @@ -59,6 +59,7 @@ struct Values { // Game List bool show_unknown; + bool show_add_ons; uint32_t icon_size; uint8_t row_1_text_id; uint8_t row_2_text_id;