From f7eaea424d07e971d0279257d20d408b64ef05b6 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 11:50:04 -0400 Subject: [PATCH] registration: Add support for installing NSP files --- src/core/file_sys/registered_cache.cpp | 20 ++++++++++++-------- src/core/file_sys/registered_cache.h | 6 ++++-- src/yuzu/main.cpp | 24 ++++++++++++++++++------ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index d9decc104d..94268d1278 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -358,17 +358,21 @@ std::vector RegisteredCache::ListEntriesFilter( return out; } -static std::shared_ptr GetNCAFromXCIForID(std::shared_ptr xci, const NcaID& id) { - const auto filename = fmt::format("{}.nca", Common::HexArrayToString(id, false)); - const auto iter = - std::find_if(xci->GetNCAs().begin(), xci->GetNCAs().end(), - [&filename](std::shared_ptr nca) { return nca->GetName() == filename; }); - return iter == xci->GetNCAs().end() ? nullptr : *iter; +static std::shared_ptr GetNCAFromNSPForID(std::shared_ptr nsp, const NcaID& id) { + const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false))); + if (file == nullptr) + return nullptr; + return std::make_shared(file); } InstallResult RegisteredCache::InstallEntry(std::shared_ptr xci, bool overwrite_if_exists, const VfsCopyFunction& copy) { - const auto& ncas = xci->GetNCAs(); + return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy); +} + +InstallResult RegisteredCache::InstallEntry(std::shared_ptr nsp, bool overwrite_if_exists, + const VfsCopyFunction& copy) { + const auto& ncas = nsp->GetNCAsCollapsed(); const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr nca) { return nca->GetType() == NCAContentType::Meta; }); @@ -392,7 +396,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr xci, bool overw const auto cnmt_file = section0->GetFiles()[0]; const CNMT cnmt(cnmt_file); for (const auto& record : cnmt.GetContentRecords()) { - const auto nca = GetNCAFromXCIForID(xci, record.nca_id); + const auto nca = GetNCAFromNSPForID(nsp, record.nca_id); if (nca == nullptr) return InstallResult::ErrorCopyFailed; const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id); diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index fe2cdc3d99..50e26f8fb2 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -89,10 +89,12 @@ public: boost::optional record_type = boost::none, boost::optional title_id = boost::none) const; - // Raw copies all the ncas from the xci to the csache. Does some quick checks to make sure there - // is a meta NCA and all of them are accessible. + // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure + // there is a meta NCA and all of them are accessible. InstallResult InstallEntry(std::shared_ptr xci, bool overwrite_if_exists = false, const VfsCopyFunction& copy = &VfsRawCopy); + InstallResult InstallEntry(std::shared_ptr nsp, bool overwrite_if_exists = false, + const VfsCopyFunction& copy = &VfsRawCopy); // Due to the fact that we must use Meta-type NCAs to determine the existance of files, this // poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 262e33487e..c4eda4babf 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -806,22 +806,34 @@ void GMainWindow::OnMenuInstallToNAND() { QMessageBox::Yes; }; - if (filename.endsWith("xci", Qt::CaseInsensitive)) { - const auto xci = std::make_shared( - vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); - if (xci->GetStatus() != Loader::ResultStatus::Success) { + if (filename.endsWith("xci", Qt::CaseInsensitive) || + filename.endsWith("nsp", Qt::CaseInsensitive)) { + + std::shared_ptr nsp; + if (filename.endsWith("nsp", Qt::CaseInsensitive)) { + nsp = std::make_shared( + vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); + if (!nsp->IsExtractedType()) + failed(); + } else { + const auto xci = std::make_shared( + vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); + nsp = xci->GetSecurePartitionNSP(); + } + + if (nsp->GetStatus() != Loader::ResultStatus::Success) { failed(); return; } const auto res = - Service::FileSystem::GetUserNANDContents()->InstallEntry(xci, false, qt_raw_copy); + Service::FileSystem::GetUserNANDContents()->InstallEntry(nsp, false, qt_raw_copy); if (res == FileSys::InstallResult::Success) { success(); } else { if (res == FileSys::InstallResult::ErrorAlreadyExists) { if (overwrite()) { const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry( - xci, true, qt_raw_copy); + nsp, true, qt_raw_copy); if (res2 == FileSys::InstallResult::Success) { success(); } else {