From 788eb98352abfb024ff83e5c8085f99248537602 Mon Sep 17 00:00:00 2001 From: AyeZeeBB Date: Sat, 24 Oct 2026 22:47:02 -0500 Subject: [PATCH] Mods: a chunk no list describes gets an owner hash and meta in the merged bundle, instead of an empty record the game reads through null merge_chunk_metadata gave such a chunk a record with no fields. The game's reader (0x41af080) takes a record without "h64" as a "g" record and, with no "g" either, reads its guid through null (Skate.exe+0x15b2c34: computerK-Fingerboard adds its grip texture to a game deck bundle whose list has no record for it). The record is now an owner hash no resource has, with an empty meta, which the game passes over. --- .../Vfs/Test/chunk_metadata_merge_tests.cpp | 11 ++++++++++ Engine/Vfs/mod_merge_combine.cpp | 20 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Engine/Vfs/Test/chunk_metadata_merge_tests.cpp b/Engine/Vfs/Test/chunk_metadata_merge_tests.cpp index 9bed834a..4c6b5836 100644 --- a/Engine/Vfs/Test/chunk_metadata_merge_tests.cpp +++ b/Engine/Vfs/Test/chunk_metadata_merge_tests.cpp @@ -170,6 +170,17 @@ int main() { check(read_list(merge_chunk_metadata(lists, unknown, gameList, shipped)) == std::vector{mesh, Record{}, textureA, other, textureB, mesh, Record{}}, "a chunk no list describes gets a record that says nothing, and the others stay in step"); + // The game reads a record without "h64" as a "g" record, and one with neither through null. + { + const auto written = merge_chunk_metadata(lists, unknown, gameList, shipped); + const std::span bytes(reinterpret_cast(written.data()), written.size()); + const auto root = db::read(bytes, "chunk metadata", nullptr); + check(std::ranges::all_of(root.children, [](const db::Node& row) { + const auto* owner = row.field("h64"); + return owner && owner->payload().size() == 8 && row.field("meta"); + }), + "every record has the owner hash and meta the game reads"); + } // A bundle the game has no list for (it has no chunks there, or does not ship the bundle): every // chunk is a mod's, with the record of the copy it came in. Maps each add their loading screen diff --git a/Engine/Vfs/mod_merge_combine.cpp b/Engine/Vfs/mod_merge_combine.cpp index a9a5dcbf..bbd915a2 100644 --- a/Engine/Vfs/mod_merge_combine.cpp +++ b/Engine/Vfs/mod_merge_combine.cpp @@ -336,15 +336,33 @@ std::vector merge_chunk_metadata(std::span