diff --git a/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.cpp b/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.cpp new file mode 100644 index 00000000..24a79bce --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.cpp @@ -0,0 +1,21 @@ +#include "BaseRenderingContext.h" + +BaseRenderingContext::BaseRenderingContext(std::string game, const Architecture gameArchitecture, std::vector fastFileBlocks) + : m_game(std::move(game)), + m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE), + m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)), + m_blocks(std::move(fastFileBlocks)), + m_default_normal_block(nullptr), + m_default_temp_block(nullptr) +{ + for (const auto* block : m_blocks) + { + if (block->m_is_default) + { + if (block->m_type == FastFileBlockType::NORMAL && m_default_normal_block == nullptr) + m_default_normal_block = block; + else if (block->m_type == FastFileBlockType::TEMP && m_default_temp_block == nullptr) + m_default_temp_block = block; + } + } +} diff --git a/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.h b/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.h new file mode 100644 index 00000000..4d5949f3 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Generating/BaseRenderingContext.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Persistence/IDataRepository.h" + +#include +#include + +class BaseRenderingContext +{ +public: + std::string m_game; + bool m_architecture_mismatch; + unsigned m_pointer_size; + std::vector m_blocks; + + const FastFileBlock* m_default_normal_block; + const FastFileBlock* m_default_temp_block; + +protected: + BaseRenderingContext(std::string game, Architecture gameArchitecture, std::vector fastFileBlocks); +}; diff --git a/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.cpp b/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.cpp index 1eed2adf..0152888a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.cpp @@ -21,14 +21,9 @@ RenderingUsedType::RenderingUsedType(const DataDefinition* type, StructureInform OncePerAssetRenderingContext::OncePerAssetRenderingContext(std::string game, const Architecture gameArchitecture, std::vector fastFileBlocks) - : m_game(std::move(game)), - m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE), - m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)), - m_blocks(std::move(fastFileBlocks)), + : BaseRenderingContext(std::move(game), gameArchitecture, std::move(fastFileBlocks)), m_asset(nullptr), - m_has_actions(false), - m_default_normal_block(nullptr), - m_default_temp_block(nullptr) + m_has_actions(false) { for (const auto* block : m_blocks) { diff --git a/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.h b/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.h index 62bb914a..2ffbb9bf 100644 --- a/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.h +++ b/src/ZoneCodeGeneratorLib/Generating/OncePerAssetRenderingContext.h @@ -1,5 +1,6 @@ #pragma once +#include "BaseRenderingContext.h" #include "Domain/Computations/MemberComputations.h" #include "Domain/Information/StructureInformation.h" #include "Persistence/IDataRepository.h" @@ -24,16 +25,11 @@ public: bool m_pointer_array_reference_is_reusable; }; -class OncePerAssetRenderingContext +class OncePerAssetRenderingContext : public BaseRenderingContext { public: static std::unique_ptr BuildContext(const IDataRepository* repository, StructureInformation* asset); - std::string m_game; - bool m_architecture_mismatch; - unsigned m_pointer_size; - std::vector m_blocks; - StructureInformation* m_asset; std::vector m_used_types; @@ -41,9 +37,6 @@ public: std::vector m_referenced_assets; bool m_has_actions; - const FastFileBlock* m_default_normal_block; - const FastFileBlock* m_default_temp_block; - private: OncePerAssetRenderingContext(std::string game, Architecture gameArchitecture, std::vector fastFileBlocks); diff --git a/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.cpp b/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.cpp index bbc2c17b..3985e4a5 100644 --- a/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.cpp @@ -8,13 +8,8 @@ OncePerTemplateRenderingContext::OncePerTemplateRenderingContext(std::string gam const Architecture gameArchitecture, std::vector fastFileBlocks, std::vector assets) - : m_game(std::move(game)), - m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE), - m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)), - m_blocks(std::move(fastFileBlocks)), - m_assets(std::move(assets)), - m_default_normal_block(nullptr), - m_default_temp_block(nullptr) + : BaseRenderingContext(std::move(game), gameArchitecture, std::move(fastFileBlocks)), + m_assets(std::move(assets)) { for (const auto* block : m_blocks) { diff --git a/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.h b/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.h index 8f619916..3b1adc04 100644 --- a/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.h +++ b/src/ZoneCodeGeneratorLib/Generating/OncePerTemplateRenderingContext.h @@ -1,24 +1,18 @@ #pragma once +#include "BaseRenderingContext.h" #include "Persistence/IDataRepository.h" #include #include -class OncePerTemplateRenderingContext +class OncePerTemplateRenderingContext : public BaseRenderingContext { public: static std::unique_ptr BuildContext(const IDataRepository* repository); - std::string m_game; - bool m_architecture_mismatch; - unsigned m_pointer_size; - std::vector m_blocks; std::vector m_assets; - const FastFileBlock* m_default_normal_block; - const FastFileBlock* m_default_temp_block; - private: OncePerTemplateRenderingContext(std::string game, Architecture gameArchitecture, diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/AssetStructTestsTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/AssetStructTestsTemplate.cpp index 4cfa9078..1b851e06 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/AssetStructTestsTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/AssetStructTestsTemplate.cpp @@ -15,7 +15,7 @@ namespace { public: PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp index 89b535cb..b9a3778b 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp @@ -5,9 +5,10 @@ #include -BaseTemplate::BaseTemplate(std::ostream& stream) +BaseTemplate::BaseTemplate(std::ostream& stream, const BaseRenderingContext& context) : m_out(stream), - m_intendation(0u) + m_intendation(0u), + m_env(context) { } @@ -61,13 +62,6 @@ void BaseTemplate::MakeTypeVarNameInternal(const DataDefinition* def, std::ostri MakeSafeTypeNameInternal(def, str); } -void BaseTemplate::MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str) -{ - str << "var"; - MakeSafeTypeNameInternal(def, str); - str << "Written"; -} - void BaseTemplate::MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str) { str << "var"; @@ -75,13 +69,6 @@ void BaseTemplate::MakeTypePtrVarNameInternal(const DataDefinition* def, std::os str << "Ptr"; } -void BaseTemplate::MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str) -{ - str << "var"; - MakeSafeTypeNameInternal(def, str); - str << "PtrWritten"; -} - void BaseTemplate::MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str) { for (const auto index : modifierComputations.GetArrayIndices()) @@ -97,13 +84,6 @@ std::string BaseTemplate::MakeTypeVarName(const DataDefinition* def) return str.str(); } -std::string BaseTemplate::MakeTypeWrittenVarName(const DataDefinition* def) -{ - std::ostringstream str; - MakeTypeWrittenVarNameInternal(def, str); - return str.str(); -} - std::string BaseTemplate::MakeTypePtrVarName(const DataDefinition* def) { std::ostringstream str; @@ -111,13 +91,6 @@ std::string BaseTemplate::MakeTypePtrVarName(const DataDefinition* def) return str.str(); } -std::string BaseTemplate::MakeTypeWrittenPtrVarName(const DataDefinition* def) -{ - std::ostringstream str; - MakeTypeWrittenPtrVarNameInternal(def, str); - return str.str(); -} - std::string BaseTemplate::MakeSafeTypeName(const DataDefinition* def) { std::ostringstream str; @@ -135,17 +108,6 @@ std::string BaseTemplate::MakeMemberAccess(const StructureInformation* info, con return str.str(); } -std::string - BaseTemplate::MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) -{ - std::ostringstream str; - MakeTypeWrittenVarNameInternal(info->m_definition, str); - str << "->" << member->m_member->m_name; - MakeArrayIndicesInternal(modifier, str); - - return str.str(); -} - std::string BaseTemplate::MakeTypeDecl(const TypeDeclaration* decl) { std::ostringstream str; @@ -299,3 +261,43 @@ std::string BaseTemplate::MakeEvaluation(const IEvaluation* evaluation) MakeEvaluationInternal(evaluation, str); return str.str(); } + +size_t BaseTemplate::SizeForDeclModifierLevel(const MemberInformation& memberInfo, const size_t level) const +{ + const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers; + if (declModifiers.empty()) + return memberInfo.m_member->m_type_declaration->GetSize(); + + if (level == 0) + return memberInfo.m_member->m_type_declaration->GetSize(); + + size_t currentSize = memberInfo.m_member->m_type_declaration->m_type->GetSize(); + const auto end = declModifiers.rbegin() + (declModifiers.size() - level); + for (auto i = declModifiers.rbegin(); i != end; ++i) + { + if ((*i)->GetType() == DeclarationModifierType::POINTER) + currentSize = m_env.m_pointer_size; + else + currentSize *= dynamic_cast(i->get())->m_size; + } + + return currentSize; +} + +size_t BaseTemplate::OffsetForMemberModifier(const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) const +{ + size_t curOffset = memberInfo.m_member->m_offset; + + auto curLevel = 0u; + for (const auto index : modifier.GetArrayIndices()) + { + if (index > 0) + curOffset += index * SizeForDeclModifierLevel(memberInfo, curLevel + 1); + + curLevel++; + } + + return curOffset + nestedBaseOffset; +} diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h index fb01b398..e20e5e54 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h @@ -5,6 +5,7 @@ #include "Domain/Evaluation/OperandDynamic.h" #include "Domain/Evaluation/OperandStatic.h" #include "Domain/Evaluation/Operation.h" +#include "Generating/BaseRenderingContext.h" #include #include @@ -14,7 +15,7 @@ class BaseTemplate protected: static constexpr auto INTENDATION = " "; - explicit BaseTemplate(std::ostream& stream); + explicit BaseTemplate(std::ostream& stream, const BaseRenderingContext& context); void DoIntendation() const; @@ -23,13 +24,9 @@ protected: static std::string Upper(std::string str); static std::string Lower(std::string str); static std::string MakeTypeVarName(const DataDefinition* def); - static std::string MakeTypeWrittenVarName(const DataDefinition* def); static std::string MakeTypePtrVarName(const DataDefinition* def); - static std::string MakeTypeWrittenPtrVarName(const DataDefinition* def); static std::string MakeSafeTypeName(const DataDefinition* def); static std::string MakeMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier); - static std::string - MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier); static std::string MakeTypeDecl(const TypeDeclaration* decl); static std::string MakeFollowingReferences(const std::vector& modifiers); static std::string MakeArrayIndices(const DeclarationModifierComputations& modifierComputations); @@ -37,20 +34,25 @@ protected: static std::string MakeArrayCount(const ArrayDeclarationModifier* arrayModifier); static std::string MakeEvaluation(const IEvaluation* evaluation); + static void MakeSafeTypeNameInternal(const DataDefinition* def, std::ostringstream& str); + static void MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str); + + [[nodiscard]] size_t SizeForDeclModifierLevel(const MemberInformation& memberInfo, size_t level) const; + [[nodiscard]] size_t + OffsetForMemberModifier(const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, size_t nestedBaseOffset) const; + std::ostream& m_out; unsigned m_intendation; private: - static void MakeSafeTypeNameInternal(const DataDefinition* def, std::ostringstream& str); static void MakeTypeVarNameInternal(const DataDefinition* def, std::ostringstream& str); - static void MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str); static void MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str); - static void MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str); - static void MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str); static void MakeOperandStatic(const OperandStatic* op, std::ostringstream& str); static void MakeOperandDynamic(const OperandDynamic* op, std::ostringstream& str); static void MakeOperation(const Operation* operation, std::ostringstream& str); static void MakeEvaluationInternal(const IEvaluation* evaluation, std::ostringstream& str); + + const BaseRenderingContext& m_env; }; #define LINE(x) \ diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index 128d0770..6c213543 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -18,7 +18,7 @@ namespace { public: PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } @@ -44,7 +44,7 @@ namespace { public: PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } @@ -267,7 +267,7 @@ namespace return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def)); } - bool ShouldGenerateFillMethod(const RenderingUsedType& type) + static bool ShouldGenerateFillMethod(const RenderingUsedType& type) { const auto isNotForeignAsset = type.m_is_context_asset || !type.m_info || !StructureComputations(type.m_info).IsAsset(); const auto hasMismatchingStructure = @@ -372,47 +372,6 @@ namespace LINE("}") } - [[nodiscard]] size_t SizeForDeclModifierLevel(const MemberInformation& memberInfo, const size_t level) const - { - const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers; - if (declModifiers.empty()) - return memberInfo.m_member->m_type_declaration->GetSize(); - - if (level == 0) - return memberInfo.m_member->m_type_declaration->GetSize(); - - size_t currentSize = memberInfo.m_member->m_type_declaration->m_type->GetSize(); - const auto end = declModifiers.rbegin() + (declModifiers.size() - level); - for (auto i = declModifiers.rbegin(); i != end; ++i) - { - if ((*i)->GetType() == DeclarationModifierType::POINTER) - currentSize = m_env.m_pointer_size; - else - currentSize *= dynamic_cast(i->get())->m_size; - } - - return currentSize; - } - - [[nodiscard]] size_t - OffsetForMemberModifier(const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, const size_t nestedBaseOffset) const - { - size_t curOffset = memberInfo.m_member->m_offset; - - const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers; - auto curDeclModifier = declModifiers.begin(); - auto curLevel = 0u; - for (const auto index : modifier.GetArrayIndices()) - { - if (index > 0) - curOffset += index * SizeForDeclModifierLevel(memberInfo, curLevel + 1); - - curLevel++; - } - - return curOffset + nestedBaseOffset; - } - void PrintFillStruct_Member_DynamicArray(const StructureInformation& structInfo, const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp index df1177cb..3dcc8873 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneMarkTemplate.cpp @@ -18,7 +18,7 @@ namespace { public: PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } @@ -44,7 +44,7 @@ namespace { public: PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp index 6952c402..c4d96493 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneWriteTemplate.cpp @@ -18,7 +18,7 @@ namespace { public: PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } @@ -44,7 +44,7 @@ namespace { public: PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) - : BaseTemplate(stream), + : BaseTemplate(stream, context), m_env(context) { } @@ -106,8 +106,8 @@ namespace LINE("") LINE(VariableDecl(m_env.m_asset->m_definition)) - LINE(WrittenVariableDecl(m_env.m_asset->m_definition)) LINE(PointerVariableDecl(m_env.m_asset->m_definition)) + LINE(WrittenVariableDecl(m_env.m_asset->m_definition)) LINE(WrittenPointerVariableDecl(m_env.m_asset->m_definition)) LINE("") @@ -115,18 +115,25 @@ namespace for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) - { LINE(VariableDecl(type->m_type)) - LINE(WrittenVariableDecl(type->m_type)) - } } for (const auto* type : m_env.m_used_types) { if (type->m_pointer_array_reference_exists && !type->m_is_context_asset) - { LINE(PointerVariableDecl(type->m_type)) + } + + LINE("") + + for (const auto* type : m_env.m_used_types) + { + if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) + LINE(WrittenVariableDecl(type->m_type)) + } + for (const auto* type : m_env.m_used_types) + { + if (type->m_pointer_array_reference_exists && !type->m_is_context_asset) LINE(WrittenPointerVariableDecl(type->m_type)) - } } m_intendation--; @@ -213,7 +220,7 @@ namespace static std::string WrittenVariableDecl(const DataDefinition* def) { - return std::format("{0}* var{1}Written;", def->GetFullName(), MakeSafeTypeName(def)); + return std::format("ZoneOutputOffset var{0}Written;", MakeSafeTypeName(def)); } static std::string PointerVariableDecl(const DataDefinition* def) @@ -223,7 +230,7 @@ namespace static std::string WrittenPointerVariableDecl(const DataDefinition* def) { - return std::format("{0}** var{1}PtrWritten;", def->GetFullName(), MakeSafeTypeName(def)); + return std::format("ZoneOutputOffset var{0}PtrWritten;", MakeSafeTypeName(def)); } void PrintHeaderPtrArrayWriteMethodDeclaration(const DataDefinition* def) const @@ -248,7 +255,7 @@ namespace void PrintHeaderMainWriteMethodDeclaration(const StructureInformation* info) const { - LINEF("void Write({0}** pAsset);", info->m_definition->GetFullName()) + LINEF("void Write({0}* pAsset, ZoneOutputOffset pointerWrittenOffset);", info->m_definition->GetFullName()) } void PrintHeaderConstructor() const @@ -261,19 +268,60 @@ namespace LINEF("var{0} = nullptr;", def->m_name) } - void PrintWrittenVariableInitialization(const DataDefinition* def) const - { - LINEF("var{0}Written = nullptr;", def->m_name) - } - void PrintPointerVariableInitialization(const DataDefinition* def) const { LINEF("var{0}Ptr = nullptr;", def->m_name) } - void PrintWrittenPointerVariableInitialization(const DataDefinition* def) const + static void MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str) { - LINEF("var{0}PtrWritten = nullptr;", def->m_name) + str << "var"; + MakeSafeTypeNameInternal(def, str); + str << "PtrWritten"; + } + + static void MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str) + { + str << "var"; + MakeSafeTypeNameInternal(def, str); + str << "Written"; + } + + static std::string MakeTypeWrittenVarName(const DataDefinition* def) + { + std::ostringstream str; + MakeTypeWrittenVarNameInternal(def, str); + return str.str(); + } + + static std::string MakeTypeWrittenPtrVarName(const DataDefinition* def) + { + std::ostringstream str; + MakeTypeWrittenPtrVarNameInternal(def, str); + return str.str(); + } + + std::string + MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const + { + std::ostringstream str; + MakeTypeWrittenVarNameInternal(info->m_definition, str); + str << ".WithInnerOffset("; + + if (m_env.m_architecture_mismatch) + { + str << OffsetForMemberModifier(*member, modifier, 0); + } + else + { + str << "offsetof(" << info->m_definition->GetFullName() << ", " << member->m_member->m_name; + MakeArrayIndicesInternal(modifier, str); + str << ')'; + } + + str << ')'; + + return str.str(); } void PrintConstructorMethod() @@ -290,26 +338,18 @@ namespace m_intendation++; PrintVariableInitialization(m_env.m_asset->m_definition); - PrintWrittenVariableInitialization(m_env.m_asset->m_definition); PrintPointerVariableInitialization(m_env.m_asset->m_definition); - PrintWrittenPointerVariableInitialization(m_env.m_asset->m_definition); LINE("") for (const auto* type : m_env.m_used_types) { if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset()) - { PrintVariableInitialization(type->m_type); - PrintWrittenVariableInitialization(type->m_type); - } } for (const auto* type : m_env.m_used_types) { if (type->m_info && type->m_pointer_array_reference_exists && !type->m_is_context_asset) - { PrintPointerVariableInitialization(type->m_type); - PrintWrittenPointerVariableInitialization(type->m_type); - } } m_intendation--; @@ -334,7 +374,7 @@ namespace } else if (writeType == MemberWriteType::EMBEDDED) { - LINEF("{0} = UseScriptString({1});", MakeWrittenMemberAccess(info, member, modifier), MakeMemberAccess(info, member, modifier)) + LINEF("UseScriptString({0}, {1});", MakeMemberAccess(info, member, modifier), MakeWrittenMemberAccess(info, member, modifier)) } else { @@ -351,7 +391,7 @@ namespace if (writeType == MemberWriteType::SINGLE_POINTER) { LINEF("{0} writer({1}, m_zone, *m_stream);", WriterClassName(member->m_type), MakeMemberAccess(info, member, modifier)) - LINEF("writer.Write(&{0});", MakeWrittenMemberAccess(info, member, modifier)) + LINEF("writer.Write({0}, {1});", MakeMemberAccess(info, member, modifier), MakeWrittenMemberAccess(info, member, modifier)) } else if (writeType == MemberWriteType::POINTER_ARRAY) { @@ -373,18 +413,20 @@ namespace { if (member->m_member->m_type_declaration->m_is_const) { - LINEF("varXStringWritten = &{0};", MakeWrittenMemberAccess(info, member, modifier)) + LINEF("varXString = &{0};", MakeMemberAccess(info, member, modifier)) } else { - LINEF("varXStringWritten = const_cast(&{0});", MakeWrittenMemberAccess(info, member, modifier)) + LINEF("varXString = const_cast(&{0});", MakeMemberAccess(info, member, modifier)) } + LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINE("WriteXString(false);") } else if (writeType == MemberWriteType::POINTER_ARRAY) { if (modifier.IsArray()) { + LINEF("varXString = {0};", MakeMemberAccess(info, member, modifier)) LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("WriteXStringArray(false, {0});", modifier.GetArraySize()) } @@ -507,7 +549,7 @@ namespace else { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - LINEF("{0} = &{1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) + LINEF("{0} = {1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) LINEF("Write_{0}(false);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } } @@ -730,6 +772,14 @@ namespace return member->m_is_reusable; } + std::string MakeReusableInnerOffset(const DataDefinition* dataDefinition, const Variable* member) const + { + if (m_env.m_architecture_mismatch) + return std::to_string(member->m_offset); + + return std::format("offsetof({0}, {1})", dataDefinition->GetFullName(), member->m_name); + } + void WriteMember_Reuse(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier, @@ -741,7 +791,10 @@ namespace return; } - LINEF("if (m_stream->ReusableShouldWrite(&{0}))", MakeWrittenMemberAccess(info, member, modifier)) + LINEF("if (m_stream->ReusableShouldWrite({0}, {1}.WithInnerOffset({2})))", + MakeMemberAccess(info, member, modifier), + MakeTypeWrittenVarName(info->m_definition), + MakeReusableInnerOffset(info->m_definition, member->m_member)) LINE("{") m_intendation++; @@ -1001,17 +1054,17 @@ namespace } else { - LINEF("{0} = m_stream->WritePartial<{1}>({2}, offsetof({1}, {3}));", + LINEF("{0} = m_stream->WritePartial({1}, offsetof({2}, {3}));", MakeTypeWrittenVarName(info->m_definition), - info->m_definition->GetFullName(), MakeTypeVarName(info->m_definition), + info->m_definition->GetFullName(), dynamicMember->m_member->m_name) } m_intendation--; LINE("") - LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(info->m_definition)) + LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenVarName(info->m_definition)) } else { @@ -1063,7 +1116,7 @@ namespace m_intendation--; LINE("") - LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(info->m_definition)) + LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenPtrVarName(info->m_definition)) LINE("") if (inTemp) @@ -1071,7 +1124,7 @@ namespace LINEF("m_stream->PushBlock({0});", m_env.m_default_temp_block->m_name) LINE("") } - LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(info->m_definition)) + LINEF("if (m_stream->ReusableShouldWrite(*{0}, {1}))", MakeTypePtrVarName(info->m_definition), MakeTypeWrittenPtrVarName(info->m_definition)) LINE("{") m_intendation++; @@ -1089,7 +1142,7 @@ namespace } LINE("") - LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(info->m_definition)) + LINEF("m_stream->MarkFollowing({0});", MakeTypeWrittenPtrVarName(info->m_definition)) m_intendation--; LINE("}") @@ -1106,7 +1159,9 @@ namespace void PrintMainWriteMethod() { - LINEF("void {0}::Write({1}** pAsset)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) + LINEF("void {0}::Write({1}* pAsset, const ZoneOutputOffset pointerWrittenOffset)", + WriterClassName(m_env.m_asset), + m_env.m_asset->m_definition->GetFullName()) LINE("{") m_intendation++; @@ -1116,9 +1171,8 @@ namespace LINE("") LINEF("auto* zoneAsset = static_cast<{0}*>(m_asset->m_ptr);", m_env.m_asset->m_definition->GetFullName()) LINEF("{0} = &zoneAsset;", MakeTypePtrVarName(m_env.m_asset->m_definition)) - LINEF("{0} = &zoneAsset;", MakeTypeWrittenPtrVarName(m_env.m_asset->m_definition)) + LINEF("{0} = pointerWrittenOffset;", MakeTypeWrittenPtrVarName(m_env.m_asset->m_definition)) LINEF("WritePtr_{0}(false);", MakeSafeTypeName(m_env.m_asset->m_definition)) - LINE("*pAsset = zoneAsset;") m_intendation--; LINE("}") @@ -1142,7 +1196,7 @@ namespace { LINEF("m_stream->Write<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def)) } - LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(def)) + LINEF("m_stream->MarkFollowing({0});", MakeTypeWrittenPtrVarName(def)) } void PrintWritePtrArrayMethod_PointerCheck(const DataDefinition* def, const StructureInformation* info, const bool reusable) @@ -1154,13 +1208,13 @@ namespace if (info && StructureComputations(info).IsAsset()) { LINEF("{0} writer(*{1}, m_zone, *m_stream);", WriterClassName(info), MakeTypePtrVarName(def)) - LINEF("writer.Write({0});", MakeTypeWrittenPtrVarName(def)) + LINEF("writer.Write(*{0}, {1});", MakeTypePtrVarName(def), MakeTypeWrittenPtrVarName(def)) } else { if (reusable) { - LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(def)) + LINEF("if (m_stream->ReusableShouldWrite(*{0}, {1}))", MakeTypePtrVarName(def), MakeTypeWrittenPtrVarName(def)) LINE("{") m_intendation++; @@ -1194,11 +1248,11 @@ namespace m_intendation--; LINE("") - LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(def)) + LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenPtrVarName(def)) LINE("") LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) - LINEF("{0}** varWritten = {1};", def->GetFullName(), MakeTypeWrittenPtrVarName(def)) + LINEF("ZoneOutputOffset varWritten = {1};", def->GetFullName(), MakeTypeWrittenPtrVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; @@ -1208,7 +1262,7 @@ namespace PrintWritePtrArrayMethod_PointerCheck(def, info, reusable); LINE("") LINE("var++;") - LINE("varWritten++;") + LINE("varWritten.Inc(m_stream->GetPointerByteCount());") m_intendation--; LINE("}") @@ -1230,11 +1284,11 @@ namespace m_intendation--; LINE("") - LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(def)) + LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenVarName(def)) LINE("") LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) - LINEF("{0}* varWritten = {1};", def->GetFullName(), MakeTypeWrittenVarName(def)) + LINEF("ZoneOutputOffset varWritten = {1};", def->GetFullName(), MakeTypeWrittenVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; @@ -1243,7 +1297,7 @@ namespace LINEF("{0} = varWritten;", MakeTypeWrittenVarName(info->m_definition)) LINEF("Write_{0}(false);", info->m_definition->m_name) LINE("var++;") - LINE("varWritten++;") + LINE("varWritten.Inc(m_stream->GetPointerByteCount());") m_intendation--; LINE("}") diff --git a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp index 7acc1f11..34d9fbd6 100644 --- a/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ContentWriterIW3.cpp @@ -79,11 +79,14 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart) { +#ifdef ARCH_x86 + static_assert(offsetof(XAsset, header.data) == 4u); +#endif #define WRITE_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ - writer.Write(&varXAsset->header.headerEntry); \ + writer.Write(varXAsset->header.headerEntry, varXAssetWritten.WithInnerOffset(4)); \ break; \ } #define SKIP_ASSET(type_index, typeName, headerEntry) \ diff --git a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp index b6f12ad2..1017573d 100644 --- a/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp @@ -79,11 +79,14 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart) { +#ifdef ARCH_x86 + static_assert(offsetof(XAsset, header.data) == 4u); +#endif #define WRITE_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ - writer.Write(&varXAsset->header.headerEntry); \ + writer.Write(varXAsset->header.headerEntry, varXAssetWritten.WithInnerOffset(4)); \ break; \ } #define SKIP_ASSET(type_index, typeName, headerEntry) \ diff --git a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp index 554ad4c0..fef99578 100644 --- a/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ContentWriterIW5.cpp @@ -79,11 +79,14 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart) { +#ifdef ARCH_x86 + static_assert(offsetof(XAsset, header.data) == 4u); +#endif #define WRITE_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ - writer.Write(&varXAsset->header.headerEntry); \ + writer.Write(varXAsset->header.headerEntry, varXAssetWritten.WithInnerOffset(4)); \ break; \ } #define SKIP_ASSET(type_index, typeName, headerEntry) \ diff --git a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp index ae2c40ce..9814fe6d 100644 --- a/src/ZoneWriting/Game/T5/ContentWriterT5.cpp +++ b/src/ZoneWriting/Game/T5/ContentWriterT5.cpp @@ -79,11 +79,14 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart) { +#ifdef ARCH_x86 + static_assert(offsetof(XAsset, header.data) == 4u); +#endif #define WRITE_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ - writer.Write(&varXAsset->header.headerEntry); \ + writer.Write(varXAsset->header.headerEntry, varXAssetWritten.WithInnerOffset(4)); \ break; \ } #define SKIP_ASSET(type_index, typeName, headerEntry) \ diff --git a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp index c9544b45..3f40d075 100644 --- a/src/ZoneWriting/Game/T6/ContentWriterT6.cpp +++ b/src/ZoneWriting/Game/T6/ContentWriterT6.cpp @@ -82,11 +82,14 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart) { +#ifdef ARCH_x86 + static_assert(offsetof(XAsset, header.data) == 4u); +#endif #define WRITE_ASSET(type_index, typeName, headerEntry) \ case type_index: \ { \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ - writer.Write(&varXAsset->header.headerEntry); \ + writer.Write(varXAsset->header.headerEntry, varXAssetWritten.WithInnerOffset(4)); \ break; \ } diff --git a/src/ZoneWriting/Writing/AssetWriter.cpp b/src/ZoneWriting/Writing/AssetWriter.cpp index ecd8d70c..80a1e99f 100644 --- a/src/ZoneWriting/Writing/AssetWriter.cpp +++ b/src/ZoneWriting/Writing/AssetWriter.cpp @@ -18,16 +18,16 @@ const char* AssetWriter::NonReferenceAssetName(const char* assetName) return assetName; } -scr_string_t AssetWriter::UseScriptString(const scr_string_t scrString) const +void AssetWriter::UseScriptString(const scr_string_t scrString, const ZoneOutputOffset written) const { assert(scrString < m_asset->m_zone->m_script_strings.Count()); if (m_asset->m_zone == &m_zone) - return scrString; + return; // The asset comes from a different zone, we need to translate it const auto strValue = m_asset->m_zone->m_script_strings.CValue(scrString); - return m_zone.m_script_strings.GetScriptString(strValue); + *static_cast(written.Offset()) = m_zone.m_script_strings.GetScriptString(strValue); } void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t count) @@ -42,7 +42,7 @@ void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t for (size_t index = 0; index < count; index++) { - *static_cast(varScriptStringWritten.Offset()) = UseScriptString(*varScriptString); + UseScriptString(*varScriptString, varScriptStringWritten); varScriptString++; varScriptStringWritten.Inc(sizeof(scr_string_t)); diff --git a/src/ZoneWriting/Writing/AssetWriter.h b/src/ZoneWriting/Writing/AssetWriter.h index 10220241..863a6a6c 100644 --- a/src/ZoneWriting/Writing/AssetWriter.h +++ b/src/ZoneWriting/Writing/AssetWriter.h @@ -11,7 +11,7 @@ protected: AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, ZoneOutputStream& stream); [[nodiscard]] static const char* NonReferenceAssetName(const char* assetName); - [[nodiscard]] scr_string_t UseScriptString(scr_string_t scrString) const; + void UseScriptString(scr_string_t scrString, ZoneOutputOffset written) const; void WriteScriptStringArray(bool atStreamStart, size_t count); XAssetInfoGeneric* m_asset; diff --git a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp index d8a209be..42952a21 100644 --- a/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp +++ b/src/ZoneWriting/Zone/Stream/ZoneOutputStream.cpp @@ -220,9 +220,10 @@ namespace { assert((reinterpret_cast(ptr) - reinterpret_cast(entry.m_start_ptr)) % entrySize == 0); const auto finalZonePointer = entry.m_start_zone_ptr + (reinterpret_cast(ptr) - reinterpret_cast(entry.m_start_ptr)); + auto* writtenPtrOffset = outputOffset.Offset(); for (auto i = 0u; i < m_pointer_byte_count; i++) - static_cast(ptr)[i] = reinterpret_cast(&finalZonePointer)[i]; + static_cast(writtenPtrOffset)[i] = reinterpret_cast(&finalZonePointer)[i]; return false; }