registration: Add support for installing NSP files

This commit is contained in:
Zach Hilman 2018-08-25 11:50:04 -04:00
parent d7518cf6e0
commit f7eaea424d
3 changed files with 34 additions and 16 deletions

View File

@ -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);

View File

@ -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

View File

@ -806,22 +806,34 @@ void GMainWindow::OnMenuInstallToNAND() {
QMessageBox::Yes; QMessageBox::Yes;
}; };
if (filename.endsWith("xci", Qt::CaseInsensitive)) { if (filename.endsWith("xci", Qt::CaseInsensitive) ||
const auto xci = std::make_shared<FileSys::XCI>( filename.endsWith("nsp", Qt::CaseInsensitive)) {
vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
if (xci->GetStatus() != Loader::ResultStatus::Success) { 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(); 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 {