diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/file_sys/registered_cache.cpp | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index a6960170c..04da93d5c 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -9,6 +9,7 @@ #include "common/fs/path_util.h" #include "common/hex_util.h" #include "common/logging/log.h" +#include "common/scope_exit.h" #include "core/crypto/key_manager.h" #include "core/file_sys/card_image.h" #include "core/file_sys/common_funcs.h" @@ -416,9 +417,9 @@ void RegisteredCache::ProcessFiles(const std::vector<NcaID>& ids) { if (file == nullptr) continue; - const auto nca = std::make_shared<NCA>(parser(file, id), nullptr, 0); + const auto nca = std::make_shared<NCA>(parser(file, id)); if (nca->GetStatus() != Loader::ResultStatus::Success || - nca->GetType() != NCAContentType::Meta) { + nca->GetType() != NCAContentType::Meta || nca->GetSubdirectories().empty()) { continue; } @@ -500,7 +501,7 @@ std::unique_ptr<NCA> RegisteredCache::GetEntry(u64 title_id, ContentRecordType t const auto raw = GetEntryRaw(title_id, type); if (raw == nullptr) return nullptr; - return std::make_unique<NCA>(raw, nullptr, 0); + return std::make_unique<NCA>(raw); } template <typename T> @@ -606,9 +607,9 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex const auto result = RemoveExistingEntry(title_id); // Install Metadata File - const auto res = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); - if (res != InstallResult::Success) { - return res; + const auto meta_result = RawInstallNCA(**meta_iter, copy, overwrite_if_exists, meta_id_data); + if (meta_result != InstallResult::Success) { + return meta_result; } // Install all the other NCAs @@ -621,9 +622,19 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex if (nca == nullptr) { return InstallResult::ErrorCopyFailed; } - const auto res2 = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); - if (res2 != InstallResult::Success) { - return res2; + if (nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && + nca->GetTitleId() != title_id) { + // Create fake cnmt for patch to multiprogram application + const auto sub_nca_result = + InstallEntry(*nca, cnmt.GetHeader(), record, overwrite_if_exists, copy); + if (sub_nca_result != InstallResult::Success) { + return sub_nca_result; + } + continue; + } + const auto nca_result = RawInstallNCA(*nca, copy, overwrite_if_exists, record.nca_id); + if (nca_result != InstallResult::Success) { + return nca_result; } } @@ -662,7 +673,34 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type, return RawInstallNCA(nca, copy, overwrite_if_exists, c_rec.nca_id); } +InstallResult RegisteredCache::InstallEntry(const NCA& nca, const CNMTHeader& base_header, + const ContentRecord& base_record, + bool overwrite_if_exists, const VfsCopyFunction& copy) { + const CNMTHeader header{ + .title_id = nca.GetTitleId(), + .title_version = base_header.title_version, + .type = base_header.type, + .reserved = {}, + .table_offset = 0x10, + .number_content_entries = 1, + .number_meta_entries = 0, + .attributes = 0, + .reserved2 = {}, + .is_committed = 0, + .required_download_system_version = 0, + .reserved3 = {}, + }; + const OptionalHeader opt_header{0, 0}; + const CNMT new_cnmt(header, opt_header, {base_record}, {}); + if (!RawInstallYuzuMeta(new_cnmt)) { + return InstallResult::ErrorMetaFailed; + } + return RawInstallNCA(nca, copy, overwrite_if_exists, base_record.nca_id); +} + bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { + bool removed_data = false; + const auto delete_nca = [this](const NcaID& id) { const auto path = GetRelativePathFromNcaID(id, false, true, false); @@ -706,11 +744,20 @@ bool RegisteredCache::RemoveExistingEntry(u64 title_id) const { const auto deleted_html = delete_nca(html_id); const auto deleted_legal = delete_nca(legal_id); - return deleted_meta && (deleted_meta || deleted_program || deleted_data || - deleted_control || deleted_html || deleted_legal); + removed_data |= (deleted_meta || deleted_program || deleted_data || deleted_control || + deleted_html || deleted_legal); } - return false; + // If patch entries for any program exist in yuzu meta, remove them + for (u8 i = 0; i < 0x10; i++) { + const auto meta_dir = dir->CreateDirectoryRelative("yuzu_meta"); + const auto filename = GetCNMTName(TitleType::Update, title_id + i); + if (meta_dir->GetFile(filename)) { + removed_data |= meta_dir->DeleteFile(filename); + } + } + + return removed_data; } InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFunction& copy, @@ -964,7 +1011,7 @@ std::unique_ptr<NCA> ManualContentProvider::GetEntry(u64 title_id, ContentRecord const auto res = GetEntryRaw(title_id, type); if (res == nullptr) return nullptr; - return std::make_unique<NCA>(res, nullptr, 0); + return std::make_unique<NCA>(res); } std::vector<ContentProviderEntry> ManualContentProvider::ListEntriesFilter( |