registration: Add support for installing NSP files
This commit is contained in:
		| @@ -358,17 +358,21 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter( | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| static std::shared_ptr<NCA> GetNCAFromXCIForID(std::shared_ptr<XCI> 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> nca) { return nca->GetName() == filename; }); | ||||
|     return iter == xci->GetNCAs().end() ? nullptr : *iter; | ||||
| static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> 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<NCA>(file); | ||||
| } | ||||
|  | ||||
| InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> 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> 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) { | ||||
|         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 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); | ||||
|   | ||||
| @@ -89,10 +89,12 @@ public: | ||||
|         boost::optional<ContentRecordType> record_type = boost::none, | ||||
|         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 | ||||
|     // 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> xci, bool overwrite_if_exists = false, | ||||
|                                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 | ||||
|     // 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; | ||||
|     }; | ||||
|  | ||||
|     if (filename.endsWith("xci", Qt::CaseInsensitive)) { | ||||
|         const auto xci = std::make_shared<FileSys::XCI>( | ||||
|             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<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>( | ||||
|                 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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user