summaryrefslogtreecommitdiffstats
path: root/src/yuzu/game_list_worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu/game_list_worker.cpp')
-rw-r--r--src/yuzu/game_list_worker.cpp125
1 files changed, 57 insertions, 68 deletions
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index b37710f59..8687e7c5a 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -12,12 +12,15 @@
#include "common/common_paths.h"
#include "common/file_util.h"
+#include "core/core.h"
+#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
+#include "core/file_sys/submission_package.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
#include "yuzu/compatibility_list.h"
@@ -119,20 +122,25 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
}
} // Anonymous namespace
-GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan,
- const CompatibilityList& compatibility_list)
- : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan),
+GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs,
+ FileSys::ManualContentProvider* provider, QString dir_path,
+ bool deep_scan, const CompatibilityList& compatibility_list)
+ : vfs(std::move(vfs)), provider(provider), dir_path(std::move(dir_path)), deep_scan(deep_scan),
compatibility_list(compatibility_list) {}
GameListWorker::~GameListWorker() = default;
-void GameListWorker::AddInstalledTitlesToGameList() {
- const auto cache = Service::FileSystem::GetUnionContents();
- const auto installed_games = cache.ListEntriesFilter(FileSys::TitleType::Application,
- FileSys::ContentRecordType::Program);
+void GameListWorker::AddTitlesToGameList() {
+ const auto& cache = dynamic_cast<FileSys::ContentProviderUnion&>(
+ Core::System::GetInstance().GetContentProvider());
+ const auto installed_games = cache.ListEntriesFilterOrigin(
+ std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
- for (const auto& game : installed_games) {
- const auto file = cache.GetEntryUnparsed(game);
+ for (const auto& [slot, game] : installed_games) {
+ if (slot == FileSys::ContentProviderUnionSlot::FrontendManual)
+ continue;
+
+ const auto file = cache.GetEntryUnparsed(game.title_id, game.type);
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file);
if (!loader)
continue;
@@ -150,45 +158,13 @@ void GameListWorker::AddInstalledTitlesToGameList() {
emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id,
compatibility_list, patch));
}
-
- const auto control_data = cache.ListEntriesFilter(FileSys::TitleType::Application,
- FileSys::ContentRecordType::Control);
-
- for (const auto& entry : control_data) {
- auto nca = cache.GetEntry(entry);
- if (nca != nullptr) {
- nca_control_map.insert_or_assign(entry.title_id, std::move(nca));
- }
- }
}
-void GameListWorker::FillControlMap(const std::string& dir_path) {
- const auto nca_control_callback = [this](u64* num_entries_out, const std::string& directory,
- const std::string& virtual_name) -> bool {
- if (stop_processing) {
- // Breaks the callback loop
- return false;
- }
-
- const std::string physical_name = directory + DIR_SEP + virtual_name;
- const QFileInfo file_info(QString::fromStdString(physical_name));
- if (!file_info.isDir() && file_info.suffix() == QStringLiteral("nca")) {
- auto nca =
- std::make_unique<FileSys::NCA>(vfs->OpenFile(physical_name, FileSys::Mode::Read));
- if (nca->GetType() == FileSys::NCAContentType::Control) {
- const u64 title_id = nca->GetTitleId();
- nca_control_map.insert_or_assign(title_id, std::move(nca));
- }
- }
- return true;
- };
-
- FileUtil::ForeachDirectoryEntry(nullptr, dir_path, nca_control_callback);
-}
-
-void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) {
- const auto callback = [this, recursion](u64* num_entries_out, const std::string& directory,
- const std::string& virtual_name) -> bool {
+void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path,
+ unsigned int recursion) {
+ const auto callback = [this, target, recursion](u64* num_entries_out,
+ const std::string& directory,
+ const std::string& virtual_name) -> bool {
if (stop_processing) {
// Breaks the callback loop.
return false;
@@ -198,7 +174,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
const bool is_dir = FileUtil::IsDirectory(physical_name);
if (!is_dir &&
(HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
- auto loader = Loader::GetLoader(vfs->OpenFile(physical_name, FileSys::Mode::Read));
+ const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read);
+ auto loader = Loader::GetLoader(file);
if (!loader) {
return true;
}
@@ -209,31 +186,42 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
return true;
}
- std::vector<u8> icon;
- const auto res1 = loader->ReadIcon(icon);
-
u64 program_id = 0;
const auto res2 = loader->ReadProgramId(program_id);
- std::string name = " ";
- const auto res3 = loader->ReadTitle(name);
+ if (target == ScanTarget::FillManualContentProvider) {
+ if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
+ provider->AddEntry(FileSys::TitleType::Application,
+ FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
+ program_id, file);
+ } else if (res2 == Loader::ResultStatus::Success &&
+ (file_type == Loader::FileType::XCI ||
+ file_type == Loader::FileType::NSP)) {
+ const auto nsp = file_type == Loader::FileType::NSP
+ ? std::make_shared<FileSys::NSP>(file)
+ : FileSys::XCI{file}.GetSecurePartitionNSP();
+ for (const auto& title : nsp->GetNCAs()) {
+ for (const auto& entry : title.second) {
+ provider->AddEntry(entry.first.first, entry.first.second, title.first,
+ entry.second->GetBaseFile());
+ }
+ }
+ }
+ } else {
+ std::vector<u8> icon;
+ const auto res1 = loader->ReadIcon(icon);
- const FileSys::PatchManager patch{program_id};
+ std::string name = " ";
+ const auto res3 = loader->ReadTitle(name);
- if (res1 != Loader::ResultStatus::Success && res3 != Loader::ResultStatus::Success &&
- res2 == Loader::ResultStatus::Success) {
- // Use from metadata pool.
- if (nca_control_map.find(program_id) != nca_control_map.end()) {
- const auto& nca = nca_control_map[program_id];
- GetMetadataFromControlNCA(patch, *nca, icon, name);
- }
- }
+ const FileSys::PatchManager patch{program_id};
- emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id,
- compatibility_list, patch));
+ emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id,
+ compatibility_list, patch));
+ }
} else if (is_dir && recursion > 0) {
watch_list.append(QString::fromStdString(physical_name));
- AddFstEntriesToGameList(physical_name, recursion - 1);
+ ScanFileSystem(target, physical_name, recursion - 1);
}
return true;
@@ -245,10 +233,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign
void GameListWorker::run() {
stop_processing = false;
watch_list.append(dir_path);
- FillControlMap(dir_path.toStdString());
- AddInstalledTitlesToGameList();
- AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0);
- nca_control_map.clear();
+ provider->ClearAllEntries();
+ ScanFileSystem(ScanTarget::FillManualContentProvider, dir_path.toStdString(),
+ deep_scan ? 256 : 0);
+ AddTitlesToGameList();
+ ScanFileSystem(ScanTarget::PopulateGameList, dir_path.toStdString(), deep_scan ? 256 : 0);
emit Finished(watch_list);
}