From 26163a3254337427b17d04d1569b738ab38e644f Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sat, 27 Jun 2026 18:54:17 -0700 Subject: [PATCH 1/5] mapping pak stuff --- src/assets/ui.cpp | 41 ++++++++++++++++++------ src/public/rui_package.h | 68 ++++++++++++++++++++++++++++++++++++++-- src/public/ui.h | 12 ++++++- 3 files changed, 109 insertions(+), 12 deletions(-) diff --git a/src/assets/ui.cpp b/src/assets/ui.cpp index 8810490..8eac445 100644 --- a/src/assets/ui.cpp +++ b/src/assets/ui.cpp @@ -5,11 +5,11 @@ void UI_loadFromPackage(CPakFileBuilder* const pak, const PakGuid_t assetGuid, const char* const assetPath) { - if ((pak->GetHeader().flags & PAK_HEADER_FLAGS_HAS_MODULE) == 0) - { - Error("UI: Failed to add UI asset because pak '%s' did not specify \"hasDynamicLibrary\": true\nAll pakfiles containing RUI assets must also include this flag\n", pak->GetPath().c_str()); - return; - } + //if ((pak->GetHeader().flags & PAK_HEADER_FLAGS_HAS_MODULE) == 0) + //{ + // Error("UI: Failed to add UI asset because pak '%s' did not specify \"hasDynamicLibrary\": true\nAll pakfiles containing RUI assets must also include this flag\n", pak->GetPath().c_str()); + // return; + //} UNUSED(assetGuid); const fs::path inputFilePath = pak->GetAssetPath() / fs::path(assetPath).replace_extension("ruip"); @@ -33,9 +33,28 @@ void UI_loadFromPackage(CPakFileBuilder* const pak, const PakGuid_t assetGuid, c } pak->AddPointer(hdrChunk,offsetof(RuiHeader_v30_s,dataStructInitData),defaultValuesChunk,0); - PakPageLump_s transformDataChunk = pak->CreatePageLump(rui.transformData.size(),SF_CPU|SF_CLIENT,8); - memcpy(transformDataChunk.data,rui.transformData.data(),rui.transformData.size()); - pak->AddPointer(hdrChunk,offsetof(RuiHeader_v30_s,transformData),transformDataChunk,0); + if (!rui.keyframingMappings.empty()) + { + PakPageLump_s keyframingChunk = pak->CreatePageLump(rui.RuntimeKeyframingSize(), SF_CPU | SF_CLIENT, 8); + const size_t keyframingValuesOffset = rui.keyframingMappings.size() * sizeof(RuiMapping_v30_s); + + if (!rui.keyframingValues.empty()) + memcpy(&keyframingChunk.data[keyframingValuesOffset], rui.keyframingValues.data(), rui.keyframingValues.size()); + + for (size_t i = 0; i < rui.keyframingMappings.size(); ++i) + { + const RuiPackageMapping_v1_t& packageMapping = rui.keyframingMappings[i]; + RuiMapping_v30_s* const mapping = reinterpret_cast(&keyframingChunk.data[i * sizeof(RuiMapping_v30_s)]); + + mapping->dataCount = packageMapping.dataCount; + mapping->nestedMappingCount = packageMapping.nestedMappingCount; + mapping->cublicSpline = packageMapping.cublicSpline != 0; + + pak->AddPointer(keyframingChunk, (i * sizeof(RuiMapping_v30_s)) + offsetof(RuiMapping_v30_s, data), keyframingChunk, keyframingValuesOffset + rui.keyframingValueOffsets[i]); + } + + pak->AddPointer(hdrChunk, offsetof(RuiHeader_v30_s, keyframings), keyframingChunk, 0); + } PakPageLump_s argClustersChunk = pak->CreatePageLump(rui.argCluster.size()*sizeof(ArgCluster_s),SF_CPU|SF_CLIENT,8); memcpy(argClustersChunk.data,rui.argCluster.data(),rui.argCluster.size()*sizeof(ArgCluster_s)); @@ -55,6 +74,10 @@ void UI_loadFromPackage(CPakFileBuilder* const pak, const PakGuid_t assetGuid, c memcpy(renderJobChunk.data,rui.renderJobs.data(),rui.renderJobs.size()); pak->AddPointer(hdrChunk,offsetof(RuiHeader_v30_s,renderJobData),renderJobChunk,0); + PakPageLump_s transformDataChunk = pak->CreatePageLump(rui.transformData.size(),SF_CPU|SF_CLIENT,8); + memcpy(transformDataChunk.data,rui.transformData.data(),rui.transformData.size()); + pak->AddPointer(hdrChunk,offsetof(RuiHeader_v30_s,transformData),transformDataChunk,0); + asset.InitAsset(hdrChunk.GetPointer(),sizeof(RuiHeader_v30_s), PagePtr_t::NullPtr(),R2_UI_VERSION,AssetType::UI); asset.SetHeaderPointer(hdrChunk.data); @@ -68,4 +91,4 @@ void Assets::AddRuiAsset_v30(CPakFileBuilder* const pak, const PakGuid_t assetGu { UNUSED(mapEntry); UI_loadFromPackage(pak,assetGuid,assetPath); -} \ No newline at end of file +} diff --git a/src/public/rui_package.h b/src/public/rui_package.h index fe9e04c..7ffd366 100644 --- a/src/public/rui_package.h +++ b/src/public/rui_package.h @@ -45,6 +45,15 @@ struct RuiPackageHeader_v1_t { }; #pragma pack(pop) +#pragma pack(push, 1) +struct RuiPackageMapping_v1_t { + uint32_t dataCount; + uint16_t nestedMappingCount; + uint16_t cublicSpline; +}; +#pragma pack(pop) +static_assert(sizeof(RuiPackageMapping_v1_t) == 8); + struct RuiPackage { @@ -95,6 +104,11 @@ struct RuiPackage { argCluster.resize(hdr.argClusterCount); fread(argCluster.data(),sizeof(ArgCluster_s),hdr.argClusterCount,f); + fseek(f, (long)hdr.keyframingOffset, 0); + std::vector keyframingData; + keyframingData.resize(hdr.keyframingSize); + fread(keyframingData.data(), 1, hdr.keyframingSize, f); + ParseKeyframingData(keyframingData); fclose(f); } else { @@ -103,7 +117,7 @@ struct RuiPackage { } RuiHeader_v30_s CreateRuiHeader_v30() { - RuiHeader_v30_s ruiHdr; + RuiHeader_v30_s ruiHdr{}; ruiHdr.elementWidth = hdr.elementWidth; ruiHdr.elementHeight = hdr.elementHeight; @@ -122,6 +136,53 @@ struct RuiPackage { return ruiHdr; } + void ParseKeyframingData(const std::vector& keyframingData) { + const size_t mappingDataSize = static_cast(hdr.keyframingCount) * sizeof(RuiPackageMapping_v1_t); + + if (hdr.keyframingSize < mappingDataSize) + Error("RUI package keyframing data is too small for %u mappings (%u bytes, expected at least %zu).\n", + hdr.keyframingCount, hdr.keyframingSize, mappingDataSize); + + keyframingMappings.resize(hdr.keyframingCount); + + if (!keyframingMappings.empty()) + memcpy(keyframingMappings.data(), keyframingData.data(), mappingDataSize); + + const size_t valuesSize = static_cast(hdr.keyframingSize) - mappingDataSize; + keyframingValues.resize(valuesSize); + keyframingValueOffsets.clear(); + + if (valuesSize > 0) + memcpy(keyframingValues.data(), &keyframingData[mappingDataSize], valuesSize); + + size_t valueOffset = 0; + + for (const RuiPackageMapping_v1_t& mapping : keyframingMappings) + { + keyframingValueOffsets.push_back(valueOffset); + + const size_t nestedValueCount = static_cast(mapping.dataCount) * mapping.nestedMappingCount; + const size_t valueFloatCount = static_cast(mapping.dataCount) + nestedValueCount + (mapping.cublicSpline ? nestedValueCount : 0); + const size_t valueSize = valueFloatCount * sizeof(float); + + if (valueOffset + valueSize > valuesSize) + { + const size_t remainingSize = valueOffset < valuesSize ? valuesSize - valueOffset : 0; + Error("RUI package mapping data needs %zu bytes, but only %zu bytes of keyframing value data remain.\n", + valueSize, remainingSize); + } + + valueOffset += valueSize; + } + + if (valueOffset != valuesSize) + Error("RUI package keyframing data has %zu unexpected trailing bytes.\n", valuesSize - valueOffset); + } + + size_t RuntimeKeyframingSize() const { + return (keyframingMappings.size() * sizeof(RuiMapping_v30_s)) + keyframingValues.size(); + } + RuiPackageHeader_v1_t hdr{}; std::vector name; @@ -133,4 +194,7 @@ struct RuiPackage { std::vector arguments; std::vector argCluster; std::vector styleDescriptors; -}; \ No newline at end of file + std::vector keyframingMappings; + std::vector keyframingValueOffsets; + std::vector keyframingValues; +}; diff --git a/src/public/ui.h b/src/public/ui.h index 1f8bece..da90c12 100644 --- a/src/public/ui.h +++ b/src/public/ui.h @@ -72,6 +72,16 @@ struct StyleDescriptor_v30_s { uint16_t val_32; }; +struct RuiMapping_v30_s +{ + uint32_t dataCount; + uint16_t nestedMappingCount; + bool cublicSpline; + uint8_t pad; + float* data; +}; +static_assert(sizeof(RuiMapping_v30_s) == 16); + struct RuiHeader_v30_s { const char* name; @@ -94,6 +104,6 @@ struct RuiHeader_v30_s uint16_t argClusterCount; StyleDescriptor_v30_s* styleDescriptors; uint8_t* renderJobData; - void* keyframings; // maps values to others through linar/qubicSpline regression + RuiMapping_v30_s* keyframings; // maps values to others through linear/cubic spline regression }; From 5142d748399e9183a8bce7cce4b3148f3321c9bb Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sat, 27 Jun 2026 21:53:52 -0700 Subject: [PATCH 2/5] small changes --- src/public/rui_package.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/public/rui_package.h b/src/public/rui_package.h index 7ffd366..44c6741 100644 --- a/src/public/rui_package.h +++ b/src/public/rui_package.h @@ -165,18 +165,10 @@ struct RuiPackage { const size_t valueFloatCount = static_cast(mapping.dataCount) + nestedValueCount + (mapping.cublicSpline ? nestedValueCount : 0); const size_t valueSize = valueFloatCount * sizeof(float); - if (valueOffset + valueSize > valuesSize) - { - const size_t remainingSize = valueOffset < valuesSize ? valuesSize - valueOffset : 0; - Error("RUI package mapping data needs %zu bytes, but only %zu bytes of keyframing value data remain.\n", - valueSize, remainingSize); - } + valueOffset += valueSize; } - - if (valueOffset != valuesSize) - Error("RUI package keyframing data has %zu unexpected trailing bytes.\n", valuesSize - valueOffset); } size_t RuntimeKeyframingSize() const { From b8550fe417a6afa67855cf1786a945e17ac4d079 Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sat, 27 Jun 2026 21:56:03 -0700 Subject: [PATCH 3/5] add this back --- src/assets/ui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/assets/ui.cpp b/src/assets/ui.cpp index 8eac445..e2066af 100644 --- a/src/assets/ui.cpp +++ b/src/assets/ui.cpp @@ -5,11 +5,11 @@ void UI_loadFromPackage(CPakFileBuilder* const pak, const PakGuid_t assetGuid, const char* const assetPath) { - //if ((pak->GetHeader().flags & PAK_HEADER_FLAGS_HAS_MODULE) == 0) - //{ - // Error("UI: Failed to add UI asset because pak '%s' did not specify \"hasDynamicLibrary\": true\nAll pakfiles containing RUI assets must also include this flag\n", pak->GetPath().c_str()); - // return; - //} + if ((pak->GetHeader().flags & PAK_HEADER_FLAGS_HAS_MODULE) == 0) + { + Error("UI: Failed to add UI asset because pak '%s' did not specify \"hasDynamicLibrary\": true\nAll pakfiles containing RUI assets must also include this flag\n", pak->GetPath().c_str()); + return; + } UNUSED(assetGuid); const fs::path inputFilePath = pak->GetAssetPath() / fs::path(assetPath).replace_extension("ruip"); From 0c7e90e02577992de9119fad9ac5756b9d8fe3fd Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sat, 27 Jun 2026 21:56:22 -0700 Subject: [PATCH 4/5] fix flag --- src/logic/pakfile.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/logic/pakfile.cpp b/src/logic/pakfile.cpp index b15f105..537cbce 100644 --- a/src/logic/pakfile.cpp +++ b/src/logic/pakfile.cpp @@ -774,6 +774,13 @@ void CPakFileBuilder::BuildFromMap(const js::Document& doc) Log("*** building pak file \"%s\".\n", m_pakFilePath.c_str()); + // If this is set and we have "example.rpak", the runtime will load the + // library `example.dll` during the load of `example.rpak`, from the same + // directory the pak is being loaded from. The loading of the library + // happens before the individual assets are being loaded and parsed. + if (JSON_GetValueOrDefault(doc, "hasDynamicLibrary", false)) + m_Header.flags |= PAK_HEADER_FLAGS_HAS_MODULE; + // Skip the header data at first so we can come back and fill it in when we have all of the info out.Pad(GetVersion() >= 8 ? PAK_HEADER_SIZE_V8 : PAK_HEADER_SIZE_V6); @@ -847,12 +854,6 @@ void CPakFileBuilder::BuildFromMap(const js::Document& doc) // set header descriptors this->SetFileTime(Utils::GetSystemFileTime()); - // If this is set and we have "example.rpak", the runtime will load the - // library `example.dll` during the load of `example.rpak`, from the same - // directory the pak is being loaded from. The loading of the library - // happens before the individual assets are being loaded and parsed. - if (JSON_GetValueOrDefault(doc, "hasDynamicLibrary", false)) - m_Header.flags |= PAK_HEADER_FLAGS_HAS_MODULE; // Go back to the start of the file since now we can write the header successfully out.SeekPut(0); From f54380cba15f562e93d6d1b1e4cbbd9db8b414bf Mon Sep 17 00:00:00 2001 From: Allusive <154700875+AllusiveWheat@users.noreply.github.com> Date: Sun, 28 Jun 2026 14:48:21 -0700 Subject: [PATCH 5/5] no need for pragma pack --- src/public/rui_package.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/public/rui_package.h b/src/public/rui_package.h index 44c6741..3d3885c 100644 --- a/src/public/rui_package.h +++ b/src/public/rui_package.h @@ -45,13 +45,12 @@ struct RuiPackageHeader_v1_t { }; #pragma pack(pop) -#pragma pack(push, 1) struct RuiPackageMapping_v1_t { uint32_t dataCount; uint16_t nestedMappingCount; uint16_t cublicSpline; }; -#pragma pack(pop) + static_assert(sizeof(RuiPackageMapping_v1_t) == 8);