diff options
| author | 2018-08-25 11:50:04 -0400 | |
|---|---|---|
| committer | 2018-09-04 14:28:41 -0400 | |
| commit | f7eaea424d07e971d0279257d20d408b64ef05b6 (patch) | |
| tree | 4ddf73c89c0b2a88cecb7b508c9ef5d680b506c7 /src | |
| parent | loader: Add AppLoader for NSP files (diff) | |
| download | yuzu-f7eaea424d07e971d0279257d20d408b64ef05b6.tar.gz yuzu-f7eaea424d07e971d0279257d20d408b64ef05b6.tar.xz yuzu-f7eaea424d07e971d0279257d20d408b64ef05b6.zip | |
registration: Add support for installing NSP files
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/registered_cache.cpp | 20 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.h | 6 | ||||
| -rw-r--r-- | 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 d9decc104..94268d127 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -358,17 +358,21 @@ std::vector<RegisteredCacheEntry> RegisteredCache::ListEntriesFilter( | |||
| 358 | return out; | 358 | return out; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static std::shared_ptr<NCA> GetNCAFromXCIForID(std::shared_ptr<XCI> xci, const NcaID& id) { | 361 | static std::shared_ptr<NCA> GetNCAFromNSPForID(std::shared_ptr<NSP> nsp, const NcaID& id) { |
| 362 | const auto filename = fmt::format("{}.nca", Common::HexArrayToString(id, false)); | 362 | const auto file = nsp->GetFile(fmt::format("{}.nca", Common::HexArrayToString(id, false))); |
| 363 | const auto iter = | 363 | if (file == nullptr) |
| 364 | std::find_if(xci->GetNCAs().begin(), xci->GetNCAs().end(), | 364 | return nullptr; |
| 365 | [&filename](std::shared_ptr<NCA> nca) { return nca->GetName() == filename; }); | 365 | return std::make_shared<NCA>(file); |
| 366 | return iter == xci->GetNCAs().end() ? nullptr : *iter; | ||
| 367 | } | 366 | } |
| 368 | 367 | ||
| 369 | InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists, | 368 | InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists, |
| 370 | const VfsCopyFunction& copy) { | 369 | const VfsCopyFunction& copy) { |
| 371 | const auto& ncas = xci->GetNCAs(); | 370 | return InstallEntry(xci->GetSecurePartitionNSP(), overwrite_if_exists, copy); |
| 371 | } | ||
| 372 | |||
| 373 | InstallResult RegisteredCache::InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists, | ||
| 374 | const VfsCopyFunction& copy) { | ||
| 375 | const auto& ncas = nsp->GetNCAsCollapsed(); | ||
| 372 | const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) { | 376 | const auto& meta_iter = std::find_if(ncas.begin(), ncas.end(), [](std::shared_ptr<NCA> nca) { |
| 373 | return nca->GetType() == NCAContentType::Meta; | 377 | return nca->GetType() == NCAContentType::Meta; |
| 374 | }); | 378 | }); |
| @@ -392,7 +396,7 @@ InstallResult RegisteredCache::InstallEntry(std::shared_ptr<XCI> xci, bool overw | |||
| 392 | const auto cnmt_file = section0->GetFiles()[0]; | 396 | const auto cnmt_file = section0->GetFiles()[0]; |
| 393 | const CNMT cnmt(cnmt_file); | 397 | const CNMT cnmt(cnmt_file); |
| 394 | for (const auto& record : cnmt.GetContentRecords()) { | 398 | for (const auto& record : cnmt.GetContentRecords()) { |
| 395 | const auto nca = GetNCAFromXCIForID(xci, record.nca_id); | 399 | const auto nca = GetNCAFromNSPForID(nsp, record.nca_id); |
| 396 | if (nca == nullptr) | 400 | if (nca == nullptr) |
| 397 | return InstallResult::ErrorCopyFailed; | 401 | return InstallResult::ErrorCopyFailed; |
| 398 | const auto res2 = RawInstallNCA(nca, copy, overwrite_if_exists, record.nca_id); | 402 | 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 fe2cdc3d9..50e26f8fb 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h | |||
| @@ -89,10 +89,12 @@ public: | |||
| 89 | boost::optional<ContentRecordType> record_type = boost::none, | 89 | boost::optional<ContentRecordType> record_type = boost::none, |
| 90 | boost::optional<u64> title_id = boost::none) const; | 90 | boost::optional<u64> title_id = boost::none) const; |
| 91 | 91 | ||
| 92 | // Raw copies all the ncas from the xci to the csache. Does some quick checks to make sure there | 92 | // Raw copies all the ncas from the xci/nsp to the csache. Does some quick checks to make sure |
| 93 | // is a meta NCA and all of them are accessible. | 93 | // there is a meta NCA and all of them are accessible. |
| 94 | InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false, | 94 | InstallResult InstallEntry(std::shared_ptr<XCI> xci, bool overwrite_if_exists = false, |
| 95 | const VfsCopyFunction& copy = &VfsRawCopy); | 95 | const VfsCopyFunction& copy = &VfsRawCopy); |
| 96 | InstallResult InstallEntry(std::shared_ptr<NSP> nsp, bool overwrite_if_exists = false, | ||
| 97 | const VfsCopyFunction& copy = &VfsRawCopy); | ||
| 96 | 98 | ||
| 97 | // Due to the fact that we must use Meta-type NCAs to determine the existance of files, this | 99 | // Due to the fact that we must use Meta-type NCAs to determine the existance of files, this |
| 98 | // poses quite a challenge. Instead of creating a new meta NCA for this file, yuzu will create a | 100 | // 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 262e33487..c4eda4bab 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -806,22 +806,34 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 806 | QMessageBox::Yes; | 806 | QMessageBox::Yes; |
| 807 | }; | 807 | }; |
| 808 | 808 | ||
| 809 | if (filename.endsWith("xci", Qt::CaseInsensitive)) { | 809 | if (filename.endsWith("xci", Qt::CaseInsensitive) || |
| 810 | const auto xci = std::make_shared<FileSys::XCI>( | 810 | filename.endsWith("nsp", Qt::CaseInsensitive)) { |
| 811 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | 811 | |
| 812 | if (xci->GetStatus() != Loader::ResultStatus::Success) { | 812 | std::shared_ptr<FileSys::NSP> nsp; |
| 813 | if (filename.endsWith("nsp", Qt::CaseInsensitive)) { | ||
| 814 | nsp = std::make_shared<FileSys::NSP>( | ||
| 815 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 816 | if (!nsp->IsExtractedType()) | ||
| 817 | failed(); | ||
| 818 | } else { | ||
| 819 | const auto xci = std::make_shared<FileSys::XCI>( | ||
| 820 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 821 | nsp = xci->GetSecurePartitionNSP(); | ||
| 822 | } | ||
| 823 | |||
| 824 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 813 | failed(); | 825 | failed(); |
| 814 | return; | 826 | return; |
| 815 | } | 827 | } |
| 816 | const auto res = | 828 | const auto res = |
| 817 | Service::FileSystem::GetUserNANDContents()->InstallEntry(xci, false, qt_raw_copy); | 829 | Service::FileSystem::GetUserNANDContents()->InstallEntry(nsp, false, qt_raw_copy); |
| 818 | if (res == FileSys::InstallResult::Success) { | 830 | if (res == FileSys::InstallResult::Success) { |
| 819 | success(); | 831 | success(); |
| 820 | } else { | 832 | } else { |
| 821 | if (res == FileSys::InstallResult::ErrorAlreadyExists) { | 833 | if (res == FileSys::InstallResult::ErrorAlreadyExists) { |
| 822 | if (overwrite()) { | 834 | if (overwrite()) { |
| 823 | const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry( | 835 | const auto res2 = Service::FileSystem::GetUserNANDContents()->InstallEntry( |
| 824 | xci, true, qt_raw_copy); | 836 | nsp, true, qt_raw_copy); |
| 825 | if (res2 == FileSys::InstallResult::Success) { | 837 | if (res2 == FileSys::InstallResult::Success) { |
| 826 | success(); | 838 | success(); |
| 827 | } else { | 839 | } else { |