registration: Add support for installing NSP files
This commit is contained in:
		| @@ -358,17 +358,21 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter( | |||||||
|     return out; |     return out; | ||||||
| } | } | ||||||
|  |  | ||||||
| static std::shared_ptr<NCA> GetNCAFromXCIForID(std::shared_ptr<XCI> xci, const NcaID& id) { | static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) { | ||||||
|     const auto filename = fmt::format("{}.nca", Common::HexArrayToString(id, false)); |     const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false))); | ||||||
|     const auto iter = |     if (file == nullptr) | ||||||
|         std::find_if(xci->GetNCAs().begin(), xci->GetNCAs().end(), |         return nullptr; | ||||||
|                      [&filename](std::shared_ptr<NCA> nca) { return nca->GetName() == filename; }); |     return std::make_shared<NCA>(file); | ||||||
|     return iter == xci->GetNCAs().end() ? nullptr : *iter; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists, | InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists, | ||||||
|                                             const VfsCopyFunction& copy) { |                                             const VfsCopyFunction& copy) { | ||||||
|     const auto& ncas = xci->GetNCAs(); |     return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> 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> nca) { |     const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) { | ||||||
|         return nca->GetType() == NCAContentType::Meta; |         return nca->GetType() == NCAContentType::Meta; | ||||||
|     }); |     }); | ||||||
| @@ -392,7 +396,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overw | |||||||
|     const auto cnmt_file = section0->GetFiles()[0]; |     const auto cnmt_file = section0->GetFiles()[0]; | ||||||
|     const CNMT cnmt(cnmt_file); |     const CNMT cnmt(cnmt_file); | ||||||
|     for (const auto& record : cnmt.GetContentRecords()) { |     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) |         if (nca == nullptr) | ||||||
|             return InstallResult::ErrorCopyFailed; |             return InstallResult::ErrorCopyFailed; | ||||||
|         const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id); |         const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id); | ||||||
|   | |||||||
| @@ -89,10 +89,12 @@ public: | |||||||
|         boost::optional<ContentRecordType> record_type = boost::none, |         boost::optional<ContentRecordType> record_type = boost::none, | ||||||
|         boost::optional<u64> title_id = boost::none) const; |         boost::optional<u64> title_id = boost::none) const; | ||||||
|  |  | ||||||
|     // Raw copies all the ncas from the xci to the csache. Does some quick checks to make sure there |     // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure | ||||||
|     // is a meta NCA and all of them are accessible. |     // there is a meta NCA and all of them are accessible. | ||||||
|     InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false, |     InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false, | ||||||
|                                const VfsCopyFunction& copy = &VfsRawCopy); |                                const VfsCopyFunction& copy = &VfsRawCopy); | ||||||
|  |     InstallResult InstallEntry(std::shared_ptr<NSP> 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 |     // 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 |     // poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a | ||||||
|   | |||||||
| @@ -806,22 +806,34 @@ void GMainWindow::OnMenuInstallToNAND() { | |||||||
|                QMessageBox::Yes; |                QMessageBox::Yes; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     if (filename.endsWith("xci", Qt::CaseInsensitive)) { |     if (filename.endsWith("xci", Qt::CaseInsensitive) || | ||||||
|  |         filename.endsWith("nsp", Qt::CaseInsensitive)) { | ||||||
|  |  | ||||||
|  |         std::shared_ptr<FileSys::NSP> nsp; | ||||||
|  |         if (filename.endsWith("nsp", Qt::CaseInsensitive)) { | ||||||
|  |             nsp = std::make_shared<FileSys::NSP>( | ||||||
|  |                 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||||||
|  |             if (!nsp->IsExtractedType()) | ||||||
|  |                 failed(); | ||||||
|  |         } else { | ||||||
|             const auto xci = std::make_shared<FileSys::XCI>( |             const auto xci = std::make_shared<FileSys::XCI>( | ||||||
|                 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); |                 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||||||
|         if (xci->GetStatus() != Loader::ResultStatus::Success) { |             nsp = xci->GetSecurePartitionNSP(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||||||
|             failed(); |             failed(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         const auto res = |         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) { |         if (res == FileSys::InstallResult::Success) { | ||||||
|             success(); |             success(); | ||||||
|         } else { |         } else { | ||||||
|             if (res == FileSys::InstallResult::ErrorAlreadyExists) { |             if (res == FileSys::InstallResult::ErrorAlreadyExists) { | ||||||
|                 if (overwrite()) { |                 if (overwrite()) { | ||||||
|                     const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry( |                     const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry( | ||||||
|                         xci, true, qt_raw_copy); |                         nsp, true, qt_raw_copy); | ||||||
|                     if (res2 == FileSys::InstallResult::Success) { |                     if (res2 == FileSys::InstallResult::Success) { | ||||||
|                         success(); |                         success(); | ||||||
|                     } else { |                     } else { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user