registration: Add support for installing NSP files
This commit is contained in:
parent
d7518cf6e0
commit
f7eaea424d
|
@ -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