From 00546740e48f01a88184408052762793c82b264e Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Wed, 14 Jan 2026 22:14:43 +0000 Subject: [PATCH] fix: filling union members that are not supposed to be written * This causes some pointers to be partially overwritten when filling in the wrong order as well --- src/Common/Game/IW3/IW3_Assets.h | 2 +- src/Common/Game/IW4/IW4_Assets.h | 2 +- src/Common/Game/IW5/IW5_Assets.h | 2 +- .../Game/IW3/XAssets/MaterialTechniqueSet.txt | 5 ++ .../Game/IW4/XAssets/MaterialTechniqueSet.txt | 7 +- .../Game/IW5/XAssets/MaterialTechniqueSet.txt | 7 +- .../Game/T5/XAssets/MaterialTechniqueSet.txt | 7 +- .../Game/T6/XAssets/MaterialTechniqueSet.txt | 7 +- .../Computations/MemberComputations.cpp | 8 +-- .../Domain/Computations/MemberComputations.h | 4 +- .../Computations/StructureComputations.cpp | 4 +- .../Computations/StructureComputations.h | 2 +- .../Generating/Templates/ZoneLoadTemplate.cpp | 12 ++-- .../Generating/Templates/ZoneMarkTemplate.cpp | 4 +- .../Templates/ZoneWriteTemplate.cpp | 68 +++++++------------ 15 files changed, 72 insertions(+), 69 deletions(-) diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index 596ed16c..e9bcb463 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -2594,8 +2594,8 @@ namespace IW3 union entryInternalData { - int op; Operand operand; + int op; }; enum expressionEntryType : int diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index c06c59f7..1e3437e1 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -2044,8 +2044,8 @@ namespace IW4 union entryInternalData { - int op; Operand operand; + int op; }; enum expressionEntryType : int diff --git a/src/Common/Game/IW5/IW5_Assets.h b/src/Common/Game/IW5/IW5_Assets.h index befefc05..4613e8b0 100644 --- a/src/Common/Game/IW5/IW5_Assets.h +++ b/src/Common/Game/IW5/IW5_Assets.h @@ -2608,8 +2608,8 @@ namespace IW5 union entryInternalData { - int op; Operand operand; + int op; }; struct expressionEntry diff --git a/src/ZoneCode/Game/IW3/XAssets/MaterialTechniqueSet.txt b/src/ZoneCode/Game/IW3/XAssets/MaterialTechniqueSet.txt index 406c7870..50fda5da 100644 --- a/src/ZoneCode/Game/IW3/XAssets/MaterialTechniqueSet.txt +++ b/src/ZoneCode/Game/IW3/XAssets/MaterialTechniqueSet.txt @@ -27,6 +27,11 @@ use MaterialShaderArgument; set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST || type == MTL_ARG_LITERAL_PIXEL_CONST; set reusable u::literalConst; +set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST +|| type == MTL_ARG_CODE_PIXEL_CONST; +set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER; +set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST +|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER; // MaterialPixelShader set string MaterialPixelShader::name; diff --git a/src/ZoneCode/Game/IW4/XAssets/MaterialTechniqueSet.txt b/src/ZoneCode/Game/IW4/XAssets/MaterialTechniqueSet.txt index 4769818a..9daf9333 100644 --- a/src/ZoneCode/Game/IW4/XAssets/MaterialTechniqueSet.txt +++ b/src/ZoneCode/Game/IW4/XAssets/MaterialTechniqueSet.txt @@ -23,4 +23,9 @@ set count args perPrimArgCount + perObjArgCount + stableArgCount; use MaterialShaderArgument; set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST || type == MTL_ARG_LITERAL_PIXEL_CONST; -set reusable u::literalConst; \ No newline at end of file +set reusable u::literalConst; +set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST +|| type == MTL_ARG_CODE_PIXEL_CONST; +set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER; +set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST +|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER; \ No newline at end of file diff --git a/src/ZoneCode/Game/IW5/XAssets/MaterialTechniqueSet.txt b/src/ZoneCode/Game/IW5/XAssets/MaterialTechniqueSet.txt index 4769818a..9daf9333 100644 --- a/src/ZoneCode/Game/IW5/XAssets/MaterialTechniqueSet.txt +++ b/src/ZoneCode/Game/IW5/XAssets/MaterialTechniqueSet.txt @@ -23,4 +23,9 @@ set count args perPrimArgCount + perObjArgCount + stableArgCount; use MaterialShaderArgument; set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST || type == MTL_ARG_LITERAL_PIXEL_CONST; -set reusable u::literalConst; \ No newline at end of file +set reusable u::literalConst; +set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST +|| type == MTL_ARG_CODE_PIXEL_CONST; +set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER; +set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST +|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER; \ No newline at end of file diff --git a/src/ZoneCode/Game/T5/XAssets/MaterialTechniqueSet.txt b/src/ZoneCode/Game/T5/XAssets/MaterialTechniqueSet.txt index e539d863..b1f51957 100644 --- a/src/ZoneCode/Game/T5/XAssets/MaterialTechniqueSet.txt +++ b/src/ZoneCode/Game/T5/XAssets/MaterialTechniqueSet.txt @@ -46,4 +46,9 @@ set count GfxPixelShaderLoadDef::program programSize; use MaterialShaderArgument; set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST || type == MTL_ARG_LITERAL_PIXEL_CONST; -set reusable u::literalConst; \ No newline at end of file +set reusable u::literalConst; +set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST +|| type == MTL_ARG_CODE_PIXEL_CONST; +set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER; +set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST +|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER; \ No newline at end of file diff --git a/src/ZoneCode/Game/T6/XAssets/MaterialTechniqueSet.txt b/src/ZoneCode/Game/T6/XAssets/MaterialTechniqueSet.txt index 92a9f878..06ee267d 100644 --- a/src/ZoneCode/Game/T6/XAssets/MaterialTechniqueSet.txt +++ b/src/ZoneCode/Game/T6/XAssets/MaterialTechniqueSet.txt @@ -51,4 +51,9 @@ set count GfxPixelShaderLoadDef::program programSize; use MaterialShaderArgument; set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST || type == MTL_ARG_LITERAL_PIXEL_CONST; -set reusable u::literalConst; \ No newline at end of file +set reusable u::literalConst; +set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST +|| type == MTL_ARG_CODE_PIXEL_CONST; +set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER; +set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST +|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER; \ No newline at end of file diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp index 7cfddc4d..9bbafa40 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.cpp @@ -189,15 +189,15 @@ bool MemberComputations::IsInRuntimeBlock() const return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::RUNTIME; } -bool MemberComputations::IsFirstUsedMember() const +bool MemberComputations::IsFirstUsedMember(const bool includeLeafs) const { - const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); + const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(includeLeafs); return !parentUsedMembers.empty() && parentUsedMembers[0] == m_info; } -bool MemberComputations::IsLastUsedMember() const +bool MemberComputations::IsLastUsedMember(const bool includeLeafs) const { - const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); + const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(includeLeafs); return !parentUsedMembers.empty() && parentUsedMembers[parentUsedMembers.size() - 1] == m_info; } diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h index 2ab179f6..5468ab82 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberComputations.h @@ -25,8 +25,8 @@ public: [[nodiscard]] bool IsNotInDefaultNormalBlock() const; [[nodiscard]] bool IsInTempBlock() const; [[nodiscard]] bool IsInRuntimeBlock() const; - [[nodiscard]] bool IsFirstUsedMember() const; - [[nodiscard]] bool IsLastUsedMember() const; + [[nodiscard]] bool IsFirstUsedMember(bool includeLeafs) const; + [[nodiscard]] bool IsLastUsedMember(bool includeLeafs) const; [[nodiscard]] bool HasDynamicArraySize() const; [[nodiscard]] bool IsDynamicMember() const; [[nodiscard]] bool IsAfterPartialLoad() const; diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp index 5e434f75..92cd8193 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.cpp @@ -38,7 +38,7 @@ bool StructureComputations::HasNonDynamicMember() const return false; } -std::vector StructureComputations::GetUsedMembers() const +std::vector StructureComputations::GetUsedMembers(const bool includeLeafs) const { std::vector members; @@ -54,7 +54,7 @@ std::vector StructureComputations::GetUsedMembers() const { for (const auto& member : m_info->m_ordered_members) { - if (!member->m_is_leaf && !MemberComputations(member.get()).ShouldIgnore()) + if ((includeLeafs || !member->m_is_leaf) && !MemberComputations(member.get()).ShouldIgnore()) members.push_back(member.get()); } } diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h index 2792bdb4..2dfbb2c8 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/StructureComputations.h @@ -10,7 +10,7 @@ public: [[nodiscard]] bool IsAsset() const; [[nodiscard]] MemberInformation* GetDynamicMember() const; [[nodiscard]] bool HasNonDynamicMember() const; - [[nodiscard]] std::vector GetUsedMembers() const; + [[nodiscard]] std::vector GetUsedMembers(bool includeLeafs) const; [[nodiscard]] bool IsInTempBlock() const; private: diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index 5ef45bc6..7d04375a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -596,7 +596,7 @@ namespace { const MemberComputations computations(&member); - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(false)) { if (member.m_condition) { @@ -614,7 +614,7 @@ namespace PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(false)) { if (member.m_condition) { @@ -810,7 +810,7 @@ namespace if (computations.ShouldIgnore()) continue; - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(false)) { LINE("") if (member->m_condition) @@ -829,7 +829,7 @@ namespace PrintDynamicOversize_DynamicMember(info, *member); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(false)) { if (member->m_condition) { @@ -1788,7 +1788,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(false)) { LINE("") if (member->m_condition) @@ -1807,7 +1807,7 @@ namespace LoadMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(false)) { if (member->m_condition) { diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp index 3dcc8873..050c993a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp @@ -670,7 +670,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(false)) { LINE("") if (member->m_condition) @@ -689,7 +689,7 @@ namespace MarkMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(false)) { if (member->m_condition) { diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp index 8969ecc1..f80b4a5a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp @@ -1010,7 +1010,7 @@ namespace { const MemberComputations computations(member); - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(false)) { LINE("") if (member->m_condition) @@ -1029,7 +1029,7 @@ namespace WriteMember_Reference(info, member, DeclarationModifierComputations(member)); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(false)) { if (member->m_condition) { @@ -1326,12 +1326,20 @@ namespace } } + static bool ShouldFillMember(const DeclarationModifierComputations& modifier) + { + return !modifier.HasPointerModifier(); + } + // nestedBaseOffset: Base offset in case member is part of a nested anonymous sub-struct void PrintFillStruct_Member(const StructureInformation& structInfo, const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, const size_t nestedBaseOffset) { + if (!ShouldFillMember(modifier)) + return; + if (modifier.IsDynamicArray()) { } @@ -1360,7 +1368,7 @@ namespace { const MemberComputations computations(&member); - if (computations.IsFirstUsedMember()) + if (computations.IsFirstUsedMember(true)) { if (member.m_condition) { @@ -1378,7 +1386,7 @@ namespace PrintFillStruct_Member(structInfo, member, modifier, 0u); } } - else if (computations.IsLastUsedMember()) + else if (computations.IsLastUsedMember(true)) { if (member.m_condition) { @@ -1423,49 +1431,10 @@ namespace } } - static bool ShouldFillMember(const DeclarationModifierComputations& modifier) - { - return !modifier.HasPointerModifier(); - } - void PrintFillStruct_Struct(const StructureInformation& info) { const auto* dynamicMember = StructureComputations(&info).GetDynamicMember(); - - if (dynamicMember) - { - if (info.m_definition->GetType() == DataDefinitionType::UNION) - { - for (const auto& member : info.m_ordered_members) - { - const MemberComputations computations(member.get()); - if (computations.ShouldIgnore()) - continue; - - DeclarationModifierComputations modifier(member.get()); - if (!ShouldFillMember(modifier)) - continue; - - PrintFillStruct_Member_Condition_Union(info, *member, modifier); - } - } - else - { - for (const auto& member : info.m_ordered_members) - { - const MemberComputations computations(member.get()); - if (computations.ShouldIgnore() || member.get() == dynamicMember) - continue; - - DeclarationModifierComputations modifier(member.get()); - if (!ShouldFillMember(modifier)) - continue; - - PrintFillStruct_Member(info, *member, modifier, 0u); - } - } - } - else + if (info.m_definition->GetType() == DataDefinitionType::UNION) { for (const auto& member : info.m_ordered_members) { @@ -1474,9 +1443,18 @@ namespace continue; DeclarationModifierComputations modifier(member.get()); - if (!ShouldFillMember(modifier)) + PrintFillStruct_Member_Condition_Union(info, *member, modifier); + } + } + else + { + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore() || member.get() == dynamicMember) continue; + DeclarationModifierComputations modifier(member.get()); PrintFillStruct_Member(info, *member, modifier, 0u); } }