registration: Add support for installing NSP files
This commit is contained in:
parent
d7518cf6e0
commit
f7eaea424d
3 changed files with 34 additions and 16 deletions
|
@ -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)) {
|
||||
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));
|
||||
if (xci->GetStatus() != Loader::ResultStatus::Success) {
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue