Browse Source

test changes and stability

fs_external_dlcupdates
Maufeat 1 week ago
parent
commit
eda4b95cfc
  1. 22
      src/core/file_sys/external_content_index.cpp
  2. 85
      src/core/file_sys/patch_manager.cpp

22
src/core/file_sys/external_content_index.cpp

@ -158,12 +158,10 @@ void ExternalContentIndexer::ParseContainerNSP(VirtualFile file, bool is_update)
continue;
const auto& cnmt = *cnmt_opt;
const auto base_id = BaseTitleId(title_id);
if (is_update && cnmt.GetType() == TitleType::Update) {
ParsedUpdate candidate{};
// Register updates under their Update TID so PatchManager can find/apply them
candidate.title_id = FileSys::GetUpdateTitleID(base_id);
candidate.title_id = cnmt.GetTitleID();
candidate.version = cnmt.GetTitleVersion();
for (const auto& rec : cnmt.GetContentRecords()) {
const auto it = nca_map.find({cnmt.GetType(), rec.type});
@ -171,7 +169,7 @@ void ExternalContentIndexer::ParseContainerNSP(VirtualFile file, bool is_update)
candidate.ncas[rec.type] = it->second->GetBaseFile();
}
}
auto& vec = m_updates_by_title[base_id];
auto& vec = m_updates_by_title[candidate.title_id];
vec.emplace_back(std::move(candidate));
} else if (cnmt.GetType() == TitleType::AOC) {
const auto dlc_title_id = cnmt.GetTitleID();
@ -201,12 +199,10 @@ void ExternalContentIndexer::ParseLooseCnmtNca(VirtualFile meta_nca_file, const
return;
const auto& cnmt = *cnmt_opt;
const auto base_id = BaseTitleId(cnmt.GetTitleID());
if (is_update && cnmt.GetType() == TitleType::Update) {
ParsedUpdate candidate{};
// Register updates under their Update TID so PatchManager can find/apply them
candidate.title_id = FileSys::GetUpdateTitleID(base_id);
candidate.title_id = cnmt.GetTitleID();
candidate.version = cnmt.GetTitleVersion();
for (const auto& rec : cnmt.GetContentRecords()) {
@ -218,7 +214,7 @@ void ExternalContentIndexer::ParseLooseCnmtNca(VirtualFile meta_nca_file, const
}
}
auto& vec = m_updates_by_title[base_id];
auto& vec = m_updates_by_title[candidate.title_id];
vec.emplace_back(std::move(candidate));
} else if (cnmt.GetType() == TitleType::AOC) {
const auto dlc_title_id = cnmt.GetTitleID();
@ -259,11 +255,11 @@ bool ExternalContentIndexer::IsMeta(const NCA& nca) {
}
void ExternalContentIndexer::Commit() {
// Updates: register all discovered versions per base title under unique variant TIDs,
// Updates: register all discovered versions per update title under unique variant TIDs,
// and additionally register the highest version under the canonical update TID for default
// usage.
size_t update_variants_count = 0;
for (auto& [base_title, vec] : m_updates_by_title) {
for (auto& [update_tid, vec] : m_updates_by_title) {
if (vec.empty())
continue;
// sort ascending by version, dedupe identical versions (for NAND overlap, for example)
@ -281,14 +277,14 @@ void ExternalContentIndexer::Commit() {
for (const auto& [rtype, file] : latest.ncas) {
if (!file)
continue;
const auto canonical_tid = FileSys::GetUpdateTitleID(base_title);
const auto canonical_tid = update_tid;
m_provider.AddEntry(TitleType::Update, rtype, canonical_tid, file);
}
// variants under update_tid + i (i starts at1 to avoid colliding with canonical)
// variants under update_tid | (i << 48)
for (size_t i = 0; i < vec.size(); ++i) {
const auto& upd = vec[i];
const u64 variant_tid = FileSys::GetUpdateTitleID(base_title) + static_cast<u64>(i + 1);
const u64 variant_tid = update_tid | (static_cast<u64>(i + 1) << 48);
for (const auto& [rtype, file] : upd.ncas) {
if (!file)
continue;

85
src/core/file_sys/patch_manager.cpp

@ -150,7 +150,7 @@ std::vector<u64> EnumerateUpdateVariants(const ContentProvider& provider, u64 ba
std::vector<u64> tids;
const auto entries = provider.ListEntriesFilter(TitleType::Update, type);
for (const auto& e : entries) {
if (GetBaseTitleID(e.title_id) == base_title_id) {
if ((e.title_id & 0xFF00FFFFFFFFFFFFULL) == GetUpdateTitleID(base_title_id)) {
tids.push_back(e.title_id);
}
}
@ -245,7 +245,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
// Game Updates
std::optional<u64> selected_update_tid;
if (!update_disabled) {
if (!update_disabled && (title_id & 0x00FF000000000800ULL) == 0) {
selected_update_tid = ChooseUpdateVariant(content_provider, title_id,
ContentRecordType::Program, fs_controller);
if (!selected_update_tid.has_value()) {
@ -557,54 +557,73 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs
auto romfs = base_romfs;
// Game Updates
std::optional<u64> selected_update_tid = ChooseUpdateVariant(content_provider, title_id, type, fs_controller);
if (!selected_update_tid.has_value()) {
selected_update_tid = GetUpdateTitleID(title_id);
std::optional<u64> selected_update_tid;
const bool is_update = (title_id & 0x00FF000000000800ULL) != 0;
if (!is_update) {
selected_update_tid = ChooseUpdateVariant(content_provider, title_id, type, fs_controller);
if (!selected_update_tid.has_value()) {
selected_update_tid = GetUpdateTitleID(title_id);
}
}
const auto update_raw = content_provider.GetEntryRaw(*selected_update_tid, type);
const auto update_raw = selected_update_tid.has_value()
? content_provider.GetEntryRaw(*selected_update_tid, type)
: nullptr;
const auto& disabled = Settings::values.disabled_addons[title_id];
const auto update_disabled =
std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
if (!update_disabled && update_raw != nullptr && base_nca != nullptr) {
const auto new_nca = std::make_shared<NCA>(update_raw, base_nca);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
const auto version = content_provider.GetEntryVersion(*selected_update_tid).value_or(0);
LOG_DEBUG(Loader, " RomFS: Update ({}) applied successfully", FormatTitleVersion(version));
romfs = new_nca->GetRomFS();
bool applied_update = false;
if (!update_disabled && base_nca != nullptr && selected_update_tid.has_value()) {
if (update_raw != nullptr) {
const auto new_nca = std::make_shared<NCA>(update_raw, base_nca);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
const auto version =
content_provider.GetEntryVersion(*selected_update_tid).value_or(0);
LOG_DEBUG(Loader, " RomFS: Update ({}) applied successfully",
FormatTitleVersion(version));
romfs = new_nca->GetRomFS();
applied_update = true;
}
} else if (!update_disabled && base_nca != nullptr) {
ContentRecordType alt_type = type;
if (type == ContentRecordType::Program) {
alt_type = ContentRecordType::Data;
} else if (type == ContentRecordType::Data) {
alt_type = ContentRecordType::Program;
}
if (alt_type != type) {
const auto alt_update_raw =
content_provider.GetEntryRaw(*selected_update_tid, alt_type);
if (alt_update_raw != nullptr) {
const auto new_nca = std::make_shared<NCA>(alt_update_raw, base_nca);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
LOG_DEBUG(Loader, " RomFS: Update (fallback {}) applied successfully",
alt_type == ContentRecordType::Data ? "DATA" : "PROGRAM");
romfs = new_nca->GetRomFS();
if (!applied_update) {
ContentRecordType alt_type = type;
if (type == ContentRecordType::Program) {
alt_type = ContentRecordType::Data;
} else if (type == ContentRecordType::Data) {
alt_type = ContentRecordType::Program;
}
if (alt_type != type) {
const auto alt_update_raw =
content_provider.GetEntryRaw(*selected_update_tid, alt_type);
if (alt_update_raw != nullptr) {
const auto new_nca = std::make_shared<NCA>(alt_update_raw, base_nca);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
LOG_DEBUG(Loader, " RomFS: Update (fallback {}) applied successfully",
alt_type == ContentRecordType::Data ? "DATA" : "PROGRAM");
romfs = new_nca->GetRomFS();
applied_update = true;
} else {
LOG_WARNING(Loader, " RomFS: Update (fallback) NCA is not valid");
}
}
}
}
} else if (!update_disabled && packed_update_raw != nullptr && base_nca != nullptr) {
}
if (!applied_update && !update_disabled && packed_update_raw != nullptr && base_nca != nullptr) {
const auto new_nca = std::make_shared<NCA>(packed_update_raw, base_nca);
if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
new_nca->GetRomFS() != nullptr) {
LOG_INFO(Loader, " RomFS: Update (PACKED) applied successfully");
romfs = new_nca->GetRomFS();
applied_update = true;
}
}
@ -617,7 +636,7 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs
}
std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
if (title_id == 0) {
if (title_id == 0 || (title_id & 0x00FF000000000800ULL) != 0) {
return {};
}
@ -788,7 +807,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
dlc_match.reserve(dlc_entries.size());
std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
[this](const ContentProviderEntry& entry) {
return GetBaseTitleID(entry.title_id) == title_id &&
return GetBaseTitleID(entry.title_id) == GetBaseTitleID(title_id) &&
content_provider.GetEntry(entry)->GetStatus() ==
Loader::ResultStatus::Success;
});

Loading…
Cancel
Save