ncm: update client code to better reflect latest sysupdate

This commit is contained in:
Michael Scire
2022-03-18 20:11:26 -07:00
committed by SciresM
parent ca142889c4
commit 320a946fc7
28 changed files with 1432 additions and 110 deletions

View File

@@ -229,10 +229,10 @@ namespace ams::ncm {
R_TRY(FindDeltaIndex(std::addressof(index), reader, source_version, this->GetKey().version));
/* Get the fragment count. */
auto fragment_count = CountContentExceptForMeta(reader, index);
const auto fragment_count = CountContentExceptForMeta(reader, index);
/* Recalculate. */
*out_size = CalculateSizeImpl<InstallContentMetaHeader, InstallContentInfo>(this->GetExtendedHeaderSize(), fragment_count + 1, 0, this->GetExtendedDataSize(), false);
*out_size = this->CalculateConvertFragmentOnlyInstallContentMetaSize(fragment_count);
return ResultSuccess();
}
@@ -325,4 +325,113 @@ namespace ams::ncm {
}
}
Result MetaConverter::CountContentExceptForMeta(s32 *out, PatchMetaExtendedDataAccessor *accessor, const PatchDeltaHeader &header, s32 delta_index) {
/* Get the count. */
s32 count = 0;
for (auto i = 0; i < static_cast<int>(header.content_count); ++i) {
/* Get the delta content info. */
PackagedContentInfo content_info;
R_TRY(accessor->GetPatchDeltaContentInfo(std::addressof(content_info), delta_index, i));
if (content_info.GetType() != ContentType::Meta) {
++count;
}
}
*out = count;
R_SUCCEED();
}
Result MetaConverter::FindDeltaIndex(s32 *out, PatchMetaExtendedDataAccessor *accessor, u32 source_version, u32 destination_version) {
/* Get the header. */
PatchMetaExtendedDataHeader header;
header.delta_count = 0;
R_TRY(accessor->GetHeader(std::addressof(header)));
/* Iterate over all deltas. */
for (s32 i = 0; i < static_cast<s32>(header.delta_count); i++) {
/* Get the current patch delta header. */
PatchDeltaHeader delta_header;
R_TRY(accessor->GetPatchDeltaHeader(std::addressof(delta_header), i));
/* Check if the current delta matches the versions. */
if ((source_version == 0 || delta_header.delta.source_version == source_version) && delta_header.delta.destination_version == destination_version) {
*out = i;
R_SUCCEED();
}
}
/* We didn't find the delta. */
R_THROW(ncm::ResultDeltaNotFound());
}
Result MetaConverter::GetFragmentOnlyInstallContentMeta(AutoBuffer *out, const InstallContentInfo &meta, const PackagedContentMetaReader &reader, PatchMetaExtendedDataAccessor *accessor, u32 source_version) {
/* Find the appropriate delta index. */
s32 delta_index = 0;
R_TRY(FindDeltaIndex(std::addressof(delta_index), accessor, source_version, reader.GetHeader()->version));
/* Get the delta header. */
PatchDeltaHeader delta_header;
R_TRY(accessor->GetPatchDeltaHeader(std::addressof(delta_header), delta_index));
/* Count content except for meta. */
s32 fragment_count = 0;
R_TRY(CountContentExceptForMeta(std::addressof(fragment_count), accessor, delta_header, delta_index));
/* Determine the required size. */
const size_t meta_size = reader.CalculateConvertFragmentOnlyInstallContentMetaSize(fragment_count);
/* Initialize the out buffer. */
R_TRY(out->Initialize(meta_size));
/* Prepare for conversion. */
const auto *packaged_header = reader.GetHeader();
uintptr_t dst_addr = reinterpret_cast<uintptr_t>(out->Get());
/* Convert the header. */
InstallContentMetaHeader header;
ConvertPackageContentMetaHeaderToInstallContentMetaHeader(std::addressof(header), *packaged_header);
header.install_type = ContentInstallType::FragmentOnly;
/* Set the content count. */
header.content_count = static_cast<u16>(fragment_count) + 1;
/* Copy the header. */
std::memcpy(reinterpret_cast<void *>(dst_addr), std::addressof(header), sizeof(header));
dst_addr += sizeof(header);
/* Copy the extended header. */
std::memcpy(reinterpret_cast<void *>(dst_addr), reader.GetExtendedHeader<void>(), packaged_header->extended_header_size);
dst_addr += packaged_header->extended_header_size;
/* Copy the top level meta. */
std::memcpy(reinterpret_cast<void *>(dst_addr), std::addressof(meta), sizeof(meta));
dst_addr += sizeof(meta);
s32 count = 0;
for (s32 i = 0; i < static_cast<s32>(delta_header.content_count); i++) {
/* Get the delta content info. */
PackagedContentInfo content_info;
R_TRY(accessor->GetPatchDeltaContentInfo(std::addressof(content_info), delta_index, i));
if (content_info.GetType() != ContentType::Meta) {
/* Create the install content info. */
InstallContentInfo install_content_info = InstallContentInfo::Make(content_info, packaged_header->type);
/* Copy the info. */
std::memcpy(reinterpret_cast<void *>(dst_addr), std::addressof(install_content_info), sizeof(InstallContentInfo));
dst_addr += sizeof(InstallContentInfo);
/* Increment the count. */
count++;
}
}
/* Assert that we copied the right number of infos. */
AMS_ASSERT(count == fragment_count);
R_SUCCEED();
}
}