diff --git a/src/Common/Game/IW3/IW3_Assets.h b/src/Common/Game/IW3/IW3_Assets.h index 510aead7..2958e8bc 100644 --- a/src/Common/Game/IW3/IW3_Assets.h +++ b/src/Common/Game/IW3/IW3_Assets.h @@ -132,11 +132,52 @@ namespace IW3 }; typedef char cbrushedge_t; - typedef float vec2_t[2]; - typedef float vec3_t[3]; - typedef float vec4_t[4]; typedef tdef_align32(128) unsigned int raw_uint128; + union vec2_t + { + float v[2]; + + struct + { + float x; + float y; + }; + }; + + union vec3_t + { + struct + { + float x; + float y; + float z; + }; + + float v[3]; + }; + + union vec4_t + { + float v[4]; + + struct + { + float x; + float y; + float z; + float w; + }; + + struct + { + float r; + float g; + float b; + float a; + }; + }; + struct XModelPiece { XModel* model; diff --git a/src/Common/Game/IW4/IW4_Assets.h b/src/Common/Game/IW4/IW4_Assets.h index 03493a12..d0a9b181 100644 --- a/src/Common/Game/IW4/IW4_Assets.h +++ b/src/Common/Game/IW4/IW4_Assets.h @@ -161,9 +161,50 @@ namespace IW4 typedef tdef_align32(128) unsigned int raw_uint128; typedef unsigned char cbrushedge_t; typedef unsigned short r_index_t; - typedef float vec2_t[2]; - typedef float vec3_t[3]; - typedef float vec4_t[4]; + + union vec2_t + { + float v[2]; + + struct + { + float x; + float y; + }; + }; + + union vec3_t + { + struct + { + float x; + float y; + float z; + }; + + float v[3]; + }; + + union vec4_t + { + float v[4]; + + struct + { + float x; + float y; + float z; + float w; + }; + + struct + { + float r; + float g; + float b; + float a; + }; + }; struct PhysPreset { diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index b607c7cc..b4b1cf7c 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -5650,7 +5650,10 @@ namespace T6 uint16_t _2[1]; }; - typedef tdef_align32(4) int16_t XQuat2[2]; + struct type_align32(4) XQuat2 + { + int16_t value[2]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames2 { @@ -5676,7 +5679,10 @@ namespace T6 uint16_t _2[1]; }; - typedef tdef_align32(4) int16_t XQuat[4]; + struct type_align32(4) XQuat + { + int16_t value[4]; + }; struct type_align32(4) XAnimDeltaPartQuatDataFrames { diff --git a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp index 5434043a..e44ef3c2 100644 --- a/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp +++ b/src/ObjLoading/Game/IW4/Weapon/InfoStringLoaderWeaponIW4.cpp @@ -382,8 +382,8 @@ namespace for (auto i = 0u; i < originalGraphKnotCount; i++) { const auto& commonKnot = graph.knots[i]; - originalGraphKnots[i][0] = static_cast(commonKnot.x); - originalGraphKnots[i][1] = static_cast(commonKnot.y); + originalGraphKnots[i].x = static_cast(commonKnot.x); + originalGraphKnots[i].y = static_cast(commonKnot.y); } graphKnots = originalGraphKnots; diff --git a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp index e95f3ef5..0d388e3c 100644 --- a/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperWeapon.cpp @@ -231,8 +231,8 @@ namespace IW4 for (auto i = 0u; i < originalKnotCount; i++) { auto& knot = graph.knots[i]; - knot.x = originalKnots[i][0]; - knot.y = originalKnots[i][1]; + knot.x = originalKnots[i].x; + knot.y = originalKnots[i].y; } return graph; diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp index aec0c366..f30e49ca 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.cpp @@ -2,6 +2,7 @@ #include "Domain/Definition/ArrayDeclarationModifier.h" #include "Domain/Definition/PointerDeclarationModifier.h" +#include "Domain/Definition/TypedefDefinition.h" #include "MemberComputations.h" #include @@ -71,7 +72,7 @@ std::vector DeclarationModifierComputations::GetFollowingD return following; } -std::vector DeclarationModifierComputations::GetArrayIndices() const +const std::vector& DeclarationModifierComputations::GetArrayIndices() const { return m_modifier_indices; } @@ -241,6 +242,15 @@ const IEvaluation* DeclarationModifierComputations::GetDynamicArraySizeEvaluatio return dynamic_cast(declarationModifier)->m_dynamic_size_evaluation.get(); } +bool DeclarationModifierComputations::HasPointerModifier() const +{ + return std::ranges::any_of(m_information->m_member->m_type_declaration->m_declaration_modifiers, + [](const std::unique_ptr& modifier) + { + return modifier->GetType() == DeclarationModifierType::POINTER; + }); +} + unsigned DeclarationModifierComputations::GetAlignment() const { const auto following = GetFollowingDeclarationModifiers(); diff --git a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h index f01bd2e1..256bff1e 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h +++ b/src/ZoneCodeGeneratorLib/Domain/Computations/MemberDeclarationModifierComputations.h @@ -13,7 +13,7 @@ public: [[nodiscard]] DeclarationModifier* GetDeclarationModifier() const; [[nodiscard]] DeclarationModifier* GetNextDeclarationModifier() const; [[nodiscard]] std::vector GetFollowingDeclarationModifiers() const; - [[nodiscard]] std::vector GetArrayIndices() const; + [[nodiscard]] const std::vector& GetArrayIndices() const; [[nodiscard]] bool IsArray() const; [[nodiscard]] int GetArraySize() const; [[nodiscard]] bool HasDynamicArrayCount() const; @@ -26,6 +26,7 @@ public: [[nodiscard]] const IEvaluation* GetPointerArrayCountEvaluation() const; [[nodiscard]] bool IsDynamicArray() const; [[nodiscard]] const IEvaluation* GetDynamicArraySizeEvaluation() const; + [[nodiscard]] bool HasPointerModifier() const; [[nodiscard]] unsigned GetAlignment() const; private: diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h b/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h index 86ea7049..073ae611 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/DeclarationModifier.h @@ -1,8 +1,8 @@ #pragma once -#include "Utils/ClassUtils.h" +#include -enum class DeclarationModifierType +enum class DeclarationModifierType : std::uint8_t { POINTER, ARRAY diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp index 7b5cafe2..a7aeb157 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp @@ -5,13 +5,13 @@ #include TypeDeclaration::TypeDeclaration(const DataDefinition* type) - : m_flags(0), - m_size(0), - m_alignment(0), - m_is_const(false), + : m_is_const(false), m_has_custom_bit_size(false), m_type(type), - m_custom_bit_size(0) + m_custom_bit_size(0), + m_flags(0), + m_size(0), + m_alignment(0) { assert(m_type != nullptr); } diff --git a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp new file mode 100644 index 00000000..cc30f874 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.cpp @@ -0,0 +1,19 @@ +#include "Architecture.h" + +#include + +unsigned GetPointerSizeForArchitecture(const Architecture architecture) +{ + switch (architecture) + { + case Architecture::X86: + return sizeof(uint32_t); + + case Architecture::X64: + return sizeof(uint64_t); + + default: + assert(false); + return sizeof(uint32_t); + } +} diff --git a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h index 80d06532..ec02e787 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h +++ b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h @@ -1,6 +1,8 @@ #pragma once -enum class Architecture +#include + +enum class Architecture : std::uint8_t { UNKNOWN, X86, @@ -14,3 +16,5 @@ static constexpr Architecture OWN_ARCHITECTURE = Architecture::X64 #endif ; + +extern unsigned GetPointerSizeForArchitecture(Architecture architecture); diff --git a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp index 2ce6a650..189c53c9 100644 --- a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.cpp @@ -21,6 +21,7 @@ RenderingUsedType::RenderingUsedType(const DataDefinition* type, StructureInform RenderingContext::RenderingContext(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_asset(nullptr), m_has_actions(false), diff --git a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h index 0527cbe7..d6587718 100644 --- a/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h +++ b/src/ZoneCodeGeneratorLib/Generating/RenderingContext.h @@ -31,6 +31,7 @@ public: std::string m_game; bool m_architecture_mismatch; + unsigned m_pointer_size; std::vector m_blocks; StructureInformation* m_asset; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp index 6513a060..1a8ce438 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.cpp @@ -136,18 +136,6 @@ std::string return str.str(); } -std::string BaseTemplate::MakeMemberAccess(const std::string& variableName, - StructureInformation* info, - const MemberInformation* member, - const DeclarationModifierComputations& modifier) -{ - std::ostringstream str; - str << variableName << "->" << member->m_member->m_name; - MakeArrayIndicesInternal(modifier, str); - - return str.str(); -} - std::string BaseTemplate::MakeTypeDecl(const TypeDeclaration* decl) { std::ostringstream str; diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h index 5818957d..e9b8622a 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/Internal/BaseTemplate.h @@ -29,10 +29,6 @@ protected: 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 MakeMemberAccess(const std::string& variableName, - 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); diff --git a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp index f4ac70e2..573a32bc 100644 --- a/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp +++ b/src/ZoneCodeGeneratorLib/Generating/Templates/ZoneLoadTemplate.cpp @@ -6,6 +6,7 @@ #include "Utils/StringUtils.h" #include +#include #include namespace @@ -61,7 +62,8 @@ namespace // Method Declarations for (const auto* type : m_env.m_used_types) { - if (type->m_info && type->m_type == type->m_info->m_definition && !type->m_info->m_has_matching_cross_platform_structure) + if (type->m_info && type->m_type == type->m_info->m_definition && !type->m_info->m_has_matching_cross_platform_structure + && (type->m_is_context_asset || !StructureComputations(type->m_info).IsAsset())) { PrintFillStructMethodDeclaration(type->m_info); } @@ -104,7 +106,8 @@ namespace // Variable Declarations: type varType; 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()) + if (type->m_info && !type->m_info->m_definition->m_anonymous + && (!type->m_info->m_is_leaf || !type->m_info->m_has_matching_cross_platform_structure) && !StructureComputations(type->m_info).IsAsset()) { LINE(VariableDecl(type->m_type)) } @@ -148,6 +151,7 @@ namespace LINE("") LINE("#include ") LINE("#include ") + LINE("#include ") LINE("") LINEF("using namespace {0};", m_env.m_game) @@ -158,7 +162,8 @@ namespace for (const auto* type : m_env.m_used_types) { - if (type->m_info && type->m_type == type->m_info->m_definition && !type->m_info->m_has_matching_cross_platform_structure) + if (type->m_info && type->m_type == type->m_info->m_definition && !type->m_info->m_has_matching_cross_platform_structure + && (type->m_is_context_asset || !StructureComputations(type->m_info).IsAsset())) { LINE("") PrintFillStructMethod(type->m_info); @@ -317,6 +322,251 @@ 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, + const size_t nestedBaseOffset) + { + + LINEF("const auto dynamicArraySize = {0};", MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) + LINE("if (dynamicArraySize > 0)") + LINE("{") + m_intendation++; + + const auto callFillForMember = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure; + + if (callFillForMember) + { + LINEF("{0} = &{1}[0];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + else + { + LINEF("fillAccessor.Fill({0}[0], {1});", MakeMemberAccess(&structInfo, &memberInfo, modifier), memberInfo.m_member->m_offset) + } + + LINEF("const auto dynamicFill = m_stream.LoadWithFill({0} * static_cast(dynamicArraySize - 1));", + memberInfo.m_member->m_type_declaration->GetSize()) + + LINEF("for (auto i = 1u; i < dynamicArraySize; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + LINE("{") + m_intendation++; + if (callFillForMember) + { + LINEF("{0} = &{1}[i];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(dynamicFill.AtOffset((i - 1u) * {1}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + memberInfo.m_member->m_type_declaration->GetSize()) + } + else + { + LINEF("dynamicFill.Fill({0}[i], (i - 1u) * {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + memberInfo.m_member->m_type_declaration->GetSize()) + } + m_intendation--; + LINE("}") + + m_intendation--; + LINE("}") + } + + void PrintFillStruct_Member_PointerArray(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + if (modifier.IsArray()) + { + LINEF("for (auto i = 0u; i < std::extent_v; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + m_intendation++; + LINEF("fillAccessor.FillPtr({0}[i], {1} + {2} * i);", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + m_env.m_pointer_size) + m_intendation--; + } + else + { + LINEF("fillAccessor.FillPtr({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + + void PrintFillStruct_Member_EmbeddedArray(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + if (memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure) + { + LINEF("for (auto i = 0u; i < std::extent_v; i++)", structInfo.m_definition->m_name, memberInfo.m_member->m_name) + LINE("{") + m_intendation++; + LINEF("{0} = &{1}[i];", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1} + i * {2}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset), + memberInfo.m_member->m_type_declaration->m_type->GetSize()) + m_intendation--; + LINE("}") + } + else + { + LINEF("fillAccessor.FillArray({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + + void PrintFillStruct_Member_Embedded(const StructureInformation& structInfo, + const MemberInformation& memberInfo, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + const auto hasAnonymousType = memberInfo.m_type && memberInfo.m_type->m_definition->m_anonymous; + + if (!hasAnonymousType) + { + if (memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure) + { + LINEF("{0} = &{1};", MakeTypeVarName(memberInfo.m_member->m_type_declaration->m_type), MakeMemberAccess(&structInfo, &memberInfo, modifier)) + LINEF("FillStruct_{0}(fillAccessor.AtOffset({1}));", + MakeSafeTypeName(memberInfo.m_member->m_type_declaration->m_type), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + else + { + LINEF("fillAccessor.Fill({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + } + else if (memberInfo.m_member->m_name.empty()) + { + const auto anonymousMemberOffset = memberInfo.m_member->m_offset + nestedBaseOffset; + for (const auto& anonymousMember : memberInfo.m_type->m_ordered_members) + { + PrintFillStruct_Member(structInfo, *anonymousMember, DeclarationModifierComputations(anonymousMember.get()), anonymousMemberOffset); + } + } + else + { + LINEF("#error Unsupported anonymous struct with name: {0}", memberInfo.m_member->m_name); + } + } + + void PrintFillStruct_Member_ReferenceArray(const StructureInformation& info, + const MemberInformation& member, + const DeclarationModifierComputations& modifier, + const size_t nestedBaseOffset) + { + for (const auto& entry : modifier.GetArrayEntries()) + { + PrintFillStruct_Member(info, member, entry, nestedBaseOffset); + } + } + + // 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 (modifier.IsDynamicArray()) + { + PrintFillStruct_Member_DynamicArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsSinglePointer() || modifier.IsArrayPointer()) + { + LINEF("fillAccessor.FillPtr({0}, {1});", + MakeMemberAccess(&structInfo, &memberInfo, modifier), + OffsetForMemberModifier(memberInfo, modifier, nestedBaseOffset)) + } + else if (modifier.IsPointerArray()) + { + PrintFillStruct_Member_PointerArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsArray() && modifier.GetNextDeclarationModifier() == nullptr) + { + PrintFillStruct_Member_EmbeddedArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.GetDeclarationModifier() == nullptr) + { + PrintFillStruct_Member_Embedded(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else if (modifier.IsArray()) + { + PrintFillStruct_Member_ReferenceArray(structInfo, memberInfo, modifier, nestedBaseOffset); + } + else + { + assert(false); + LINEF("#error PrintFillStruct_Member failed @ {0}", memberInfo.m_member->m_name) + } + } + + void PrintFillStruct_Struct(const StructureInformation& info) + { + const auto* dynamicMember = StructureComputations(&info).GetDynamicMember(); + for (const auto& member : info.m_ordered_members) + { + const MemberComputations computations(member.get()); + if (computations.ShouldIgnore() || member.get() == dynamicMember) + continue; + + PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u); + } + + // Always fill dynamic members last + if (dynamicMember) + PrintFillStruct_Member(info, *dynamicMember, DeclarationModifierComputations(dynamicMember), 0u); + } + void PrintFillStructMethod(const StructureInformation* info) { LINEF("void {0}::FillStruct_{1}(const ZoneStreamFillReadAccessor& fillAccessor)", @@ -326,14 +576,7 @@ namespace LINE("{") m_intendation++; - for (const auto& member : info->m_ordered_members) - { - const MemberComputations computations(member.get()); - if (computations.ShouldIgnore()) - continue; - - LINEF("// FillStruct_{0}();", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) - } + PrintFillStruct_Struct(*info); m_intendation--; LINE("}") @@ -341,7 +584,11 @@ namespace void PrintLoadPtrArrayMethod_Loading(const DataDefinition* def, const StructureInformation* info) const { - LINEF("*{0} = m_stream.Alloc<{1}>({2});", MakeTypePtrVarName(def), def->GetFullName(), def->GetAlignment()) + LINEF("*{0} = m_stream.{1}<{2}>({3});", + MakeTypePtrVarName(def), + m_env.m_architecture_mismatch ? "AllocOutOfBlock" : "Alloc", + def->GetFullName(), + def->GetAlignment()) if (info && !info->m_is_leaf) { @@ -369,7 +616,8 @@ namespace { if (reusable) { - LINEF("if (*{0} == PTR_FOLLOWING)", MakeTypePtrVarName(def)) + LINEF("const auto zonePtrType = GetZonePointerType(*{0});", MakeTypePtrVarName(def)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING)", MakeTypePtrVarName(def)) LINE("{") m_intendation++; @@ -406,9 +654,25 @@ namespace LINE("") LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream.Load<{0}*>({1}, count);", def->GetFullName(), MakeTypePtrVarName(def)) - m_intendation--; + + if (m_env.m_architecture_mismatch) + { + LINE("{") + m_intendation++; + LINEF("const auto ptrArrayFill = m_stream.LoadWithFill({0} * count);", m_env.m_pointer_size) + LINE("for (size_t index = 0; index < count; index++)") + m_intendation++; + LINEF("ptrArrayFill.FillPtr({0}[index], {1} * index);", MakeTypePtrVarName(def), m_env.m_pointer_size) + m_intendation--; + m_intendation--; + LINE("}") + } + else + { + m_intendation++; + LINEF("m_stream.Load<{0}*>({1}, count);", def->GetFullName(), MakeTypePtrVarName(def)) + m_intendation--; + } LINE("") LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) @@ -436,17 +700,45 @@ namespace LINEF("assert({0} != nullptr);", MakeTypeVarName(def)) LINE("") LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream.Load<{0}>({1}, count);", def->GetFullName(), MakeTypeVarName(def)) - m_intendation--; + + if (info->m_has_matching_cross_platform_structure) + { + m_intendation++; + LINEF("m_stream.Load<{0}>({1}, count);", info->m_definition->GetFullName(), MakeTypeVarName(def)) + m_intendation--; + } + else + { + LINE("{") + m_intendation++; + + LINEF("const auto arrayFill = m_stream.LoadWithFill({0} * count);", def->GetSize()) + LINEF("auto* arrayStart = {0};", MakeTypeVarName(def)) + LINEF("auto* var = {0};", MakeTypeVarName(def)) + LINE("for (size_t index = 0; index < count; index++)") + LINE("{") + m_intendation++; + + LINEF("{0} = var;", MakeTypeVarName(def)) + LINEF("FillStruct_{0}(arrayFill.AtOffset(0 + {1} * index));", info->m_definition->m_name, def->GetSize()) + LINE("var++;") + + m_intendation--; + LINE("}") + + LINEF("{0} = arrayStart;", MakeTypeVarName(def)) + + m_intendation--; + LINE("}") + } LINE("") - LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) + LINEF("auto* var = {0};", MakeTypeVarName(def)) LINE("for (size_t index = 0; index < count; index++)") LINE("{") m_intendation++; - LINEF("{0} = var;", MakeTypeVarName(info->m_definition)) + LINEF("{0} = var;", MakeTypeVarName(def)) LINEF("Load_{0}(false);", info->m_definition->m_name) LINE("var++;") @@ -575,7 +867,7 @@ namespace { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - if (computations.IsAfterPartialLoad()) + if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("LoadArray_{0}(true, {1});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), arraySizeStr) } @@ -596,7 +888,7 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } - else if (computations.IsAfterPartialLoad()) + else if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("m_stream.Load<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), @@ -611,11 +903,12 @@ namespace if (member->m_type && !member->m_type->m_is_leaf) { LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - LINEF("LoadArray_{0}(true, {1});", + LINEF("LoadArray_{0}({1}, {2});", MakeSafeTypeName(member->m_member->m_type_declaration->m_type), + m_env.m_architecture_mismatch ? "false" : "true", MakeEvaluation(modifier.GetDynamicArraySizeEvaluation())) } - else + else if (info->m_has_matching_cross_platform_structure) { LINEF("m_stream.Load<{0}{1}>({2}, {3});", MakeTypeDecl(member->m_member->m_type_declaration.get()), @@ -632,7 +925,7 @@ namespace { LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) - if (computations.IsAfterPartialLoad()) + if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("Load_{0}(true);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) } @@ -653,7 +946,7 @@ namespace LINE(MakeCustomActionCall(member->m_post_load_action.get())) } } - else if (computations.IsAfterPartialLoad()) + else if (computations.IsAfterPartialLoad() && !m_env.m_architecture_mismatch) { LINEF("m_stream.Load<{0}{1}>(&{2});", MakeTypeDecl(member->m_member->m_type_declaration.get()), @@ -775,39 +1068,58 @@ namespace return; } - const MemberComputations computations(member); - if (computations.IsInTempBlock()) - { - LINEF("{0}* ptr = {1};", member->m_member->m_type_declaration->m_type->GetFullName(), MakeMemberAccess(info, member, modifier)) - } - const auto typeDecl = MakeTypeDecl(member->m_member->m_type_declaration.get()); const auto followingReferences = MakeFollowingReferences(modifier.GetFollowingDeclarationModifiers()); + const auto allocOutOfBlock = + (member->m_type && !member->m_type->m_has_matching_cross_platform_structure) || loadType == MemberLoadType::POINTER_ARRAY; + + LINE_STARTF("{0} = m_stream.", MakeMemberAccess(info, member, modifier)) + if (allocOutOfBlock) + LINE_MIDDLE("AllocOutOfBlock") + else + LINE_MIDDLE("Alloc") + + LINE_MIDDLEF("<{0}{1}>(", typeDecl, followingReferences) + // This used to use `alignof()` to calculate alignment but due to inconsistencies between compilers and bugs discovered in MSVC // (Alignment specified via `__declspec(align())` showing as correct via intellisense but is incorrect when compiled for types that have a larger // alignment than the specified value) this was changed to make ZoneCodeGenerator calculate what is supposed to be used as alignment when // allocating. This is more reliable when being used with different compilers and the value used can be seen in the source code directly if (member->m_alloc_alignment) { - LINEF("{0} = m_stream.Alloc<{1}{2}>({3});", - MakeMemberAccess(info, member, modifier), - typeDecl, - followingReferences, - MakeEvaluation(member->m_alloc_alignment.get())) + LINE_MIDDLE(MakeEvaluation(member->m_alloc_alignment.get())) } else { - LINEF("{0} = m_stream.Alloc<{1}{2}>({3});", MakeMemberAccess(info, member, modifier), typeDecl, followingReferences, modifier.GetAlignment()) + LINE_MIDDLEF("{0}", modifier.GetAlignment()) } + if (allocOutOfBlock && modifier.IsArrayPointer()) + LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) + else if (allocOutOfBlock && modifier.IsPointerArray()) + LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetPointerArrayCountEvaluation())) + + LINE_END(");") + + const MemberComputations computations(member); if (computations.IsInTempBlock()) { LINE("") - LINEF("{0}** toInsert = nullptr;", member->m_member->m_type_declaration->m_type->GetFullName()) - LINE("if (ptr == PTR_INSERT)") + + if (m_env.m_architecture_mismatch) + LINE("uintptr_t toInsertLookupEntry = 0;") + else + LINEF("{0}** toInsert = nullptr;", member->m_member->m_type_declaration->m_type->GetFullName()) + + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("toInsert = m_stream.InsertPointerNative<{0}>();", member->m_member->m_type_declaration->m_type->GetFullName()) + + if (m_env.m_architecture_mismatch) + LINE("toInsertLookupEntry = m_stream.InsertPointerAliasLookup();") + else + LINEF("toInsert = m_stream.InsertPointerNative<{0}>();", member->m_member->m_type_declaration->m_type->GetFullName()) + m_intendation--; LINE("") } @@ -817,9 +1129,15 @@ namespace if (computations.IsInTempBlock()) { LINE("") - LINE("if (toInsert != nullptr)") + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; - LINEF("*toInsert = {0}->{1};", MakeTypeVarName(info->m_definition), member->m_member->m_name) + + if (m_env.m_architecture_mismatch) + LINEF( + "m_stream.SetInsertedPointerAliasLookup(toInsertLookupEntry, {0}->{1});", MakeTypeVarName(info->m_definition), member->m_member->m_name) + else + LINEF("*toInsert = {0}->{1};", MakeTypeVarName(info->m_definition), member->m_member->m_name) + m_intendation--; } } @@ -850,10 +1168,12 @@ namespace return; } + LINEF("const auto zonePtrType = GetZonePointerType({0});", MakeMemberAccess(info, member, modifier)) + const MemberComputations computations(member); if (computations.IsInTempBlock()) { - LINEF("if ({0} == PTR_FOLLOWING || {0} == PTR_INSERT)", MakeMemberAccess(info, member, modifier)) + LINE("if (zonePtrType == ZonePointerType::FOLLOWING || zonePtrType == ZonePointerType::INSERT)") LINE("{") m_intendation++; @@ -872,7 +1192,7 @@ namespace } else { - LINEF("if ({0} == PTR_FOLLOWING)", MakeMemberAccess(info, member, modifier)) + LINE("if (zonePtrType == ZonePointerType::FOLLOWING)") LINE("{") m_intendation++; @@ -1123,10 +1443,9 @@ namespace LINE("") LINE("if (atStreamStart)") + m_intendation++; if (info->m_has_matching_cross_platform_structure) { - m_intendation++; - if (dynamicMember == nullptr) { LINEF("m_stream.Load<{0}>({1}); // Size: {2}", @@ -1141,20 +1460,12 @@ namespace MakeTypeVarName(info->m_definition), dynamicMember->m_member->m_name) } - - m_intendation--; } else { - LINE("{") - m_intendation++; - - LINEF("{0} = m_memory.Alloc<{1}>();", MakeTypeVarName(info->m_definition), info->m_definition->m_name) LINEF("FillStruct_{0}(m_stream.LoadWithFill({1}));", MakeSafeTypeName(info->m_definition), info->m_definition->GetSize()) - - m_intendation--; - LINE("}") } + m_intendation--; } else { @@ -1197,10 +1508,17 @@ namespace LINEF("assert({0} != nullptr);", MakeTypePtrVarName(info->m_definition)) LINE("") - LINE("if (atStreamStart)") - m_intendation++; - LINEF("m_stream.Load<{0}*>({1});", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) - m_intendation--; + if (!m_env.m_architecture_mismatch) + { + LINE("if (atStreamStart)") + m_intendation++; + LINEF("m_stream.Load<{0}*>({1});", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) + m_intendation--; + } + else + { + LINE("assert(!atStreamStart);"); + } LINE("") if (inTemp) @@ -1213,23 +1531,21 @@ namespace LINE("{") m_intendation++; + LINEF("const auto zonePtrType = GetZonePointerType(*{0});", MakeTypePtrVarName(info->m_definition)) if (inTemp) { - LINEF("if (*{0} == PTR_FOLLOWING || *{0} == PTR_INSERT)", MakeTypePtrVarName(info->m_definition)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING || zonePtrType == ZonePointerType::INSERT)", MakeTypePtrVarName(info->m_definition)) } else { - LINEF("if (*{0} == PTR_FOLLOWING)", MakeTypePtrVarName(info->m_definition)) + LINEF("if (zonePtrType == ZonePointerType::FOLLOWING)", MakeTypePtrVarName(info->m_definition)) } LINE("{") m_intendation++; - if (inTemp) - { - LINEF("{0}* ptr = *{1};", info->m_definition->GetFullName(), MakeTypePtrVarName(info->m_definition)) - } - LINEF("*{0} = m_stream.Alloc<{1}>({2});", + LINEF("*{0} = m_stream.{1}<{2}>({3});", MakeTypePtrVarName(info->m_definition), + m_env.m_architecture_mismatch ? "AllocOutOfBlock" : "Alloc", info->m_definition->GetFullName(), info->m_definition->GetAlignment()) @@ -1237,7 +1553,7 @@ namespace { LINE("") LINEF("{0}** toInsert = nullptr;", info->m_definition->GetFullName()) - LINE("if (ptr == PTR_INSERT)") + LINE("if (zonePtrType == ZonePointerType::INSERT)") m_intendation++; LINEF("toInsert = m_stream.InsertPointerNative<{0}>();", info->m_definition->GetFullName()) m_intendation--; @@ -1293,7 +1609,14 @@ namespace if (inTemp) { - LINEF("*{0} = m_stream.ConvertOffsetToAliasNative(*{0});", MakeTypePtrVarName(info->m_definition)) + if (info->m_has_matching_cross_platform_structure) + { + LINEF("*{0} = m_stream.ConvertOffsetToAliasNative(*{0});", MakeTypePtrVarName(info->m_definition)) + } + else + { + LINEF("*{0} = m_stream.ConvertOffsetToPointerRedirect(*{0});", MakeTypePtrVarName(info->m_definition)) + } } else { @@ -1328,7 +1651,7 @@ namespace LINE("assert(pAsset != nullptr);") LINE("") LINEF("{0} marker(m_zone);", MarkerClassName(m_env.m_asset)) - LINE("marker.Mark(*pAsset);") + LINE("// marker.Mark(*pAsset); // TODO") LINE("") LINEF("auto* reallocatedAsset = m_zone.Memory().Alloc<{0}>();", info->m_definition->GetFullName()) LINEF("std::memcpy(reallocatedAsset, *pAsset, sizeof({0}));", info->m_definition->GetFullName()) diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp index a79b262d..e6b9fdc3 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp @@ -12,22 +12,6 @@ namespace bool CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition); bool CalculateFields(IDataRepository* repository, TypeDeclaration* declaration); - unsigned GetPointerSizeForArchitecture(const Architecture architecture) - { - switch (architecture) - { - case Architecture::X86: - return sizeof(uint32_t); - - case Architecture::X64: - return sizeof(uint64_t); - - default: - assert(false); - return sizeof(uint32_t); - } - } - bool CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration) { auto hasPointerModifier = false; diff --git a/src/ZoneCommon/Zone/XBlock.cpp b/src/ZoneCommon/Zone/XBlock.cpp index f5825865..239ab536 100644 --- a/src/ZoneCommon/Zone/XBlock.cpp +++ b/src/ZoneCommon/Zone/XBlock.cpp @@ -1,34 +1,23 @@ #include "XBlock.h" -#include - -XBlock::XBlock(const std::string& name, const int index, const Type type) +XBlock::XBlock(std::string name, const unsigned index, const XBlockType type) + : m_name(std::move(name)), + m_index(index), + m_type(type), + m_buffer_size(0u) { - m_name = name; - m_index = index; - m_type = type; - m_buffer = nullptr; - m_buffer_size = 0; -} - -XBlock::~XBlock() -{ - delete[] m_buffer; - m_buffer = nullptr; } void XBlock::Alloc(const size_t blockSize) { - delete[] m_buffer; - if (blockSize > 0) { - m_buffer = new uint8_t[blockSize]; + m_buffer = std::make_unique(blockSize); m_buffer_size = blockSize; } else { - m_buffer = nullptr; + m_buffer.reset(); m_buffer_size = 0; } } diff --git a/src/ZoneCommon/Zone/XBlock.h b/src/ZoneCommon/Zone/XBlock.h index 8128864a..a1cb17c4 100644 --- a/src/ZoneCommon/Zone/XBlock.h +++ b/src/ZoneCommon/Zone/XBlock.h @@ -1,27 +1,29 @@ #pragma once + +#include #include +#include #include +enum class XBlockType : std::uint8_t +{ + BLOCK_TYPE_TEMP, + BLOCK_TYPE_RUNTIME, + BLOCK_TYPE_DELAY, + BLOCK_TYPE_NORMAL +}; + class XBlock { public: - enum class Type - { - BLOCK_TYPE_TEMP, - BLOCK_TYPE_RUNTIME, - BLOCK_TYPE_DELAY, - BLOCK_TYPE_NORMAL - }; + XBlock(std::string name, unsigned index, XBlockType type); + + void Alloc(size_t blockSize); std::string m_name; unsigned m_index; - Type m_type; + XBlockType m_type; - uint8_t* m_buffer; + std::unique_ptr m_buffer; size_t m_buffer_size; - - XBlock(const std::string& name, int index, Type type); - ~XBlock(); - - void Alloc(size_t blockSize); }; diff --git a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp index 8ad2b90a..02f9c444 100644 --- a/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp +++ b/src/ZoneLoading/Game/IW3/ContentLoaderIW3.cpp @@ -48,7 +48,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; @@ -146,7 +146,7 @@ void ContentLoader::Load() if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; diff --git a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp index 557b976d..553fe88c 100644 --- a/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp +++ b/src/ZoneLoading/Game/IW3/ZoneLoaderFactoryIW3.cpp @@ -44,15 +44,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -92,7 +92,8 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& }, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, - ZoneConstants::INSERT_BLOCK)); + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp index 62782ed7..9182b0c8 100644 --- a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp @@ -71,9 +71,9 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); - varScriptStringList->strings = m_stream.Alloc(4); + varScriptStringList->strings = m_stream.AllocOutOfBlock(4, varScriptStringList->count); varXString = varScriptStringList->strings; LoadXStringArray(true, varScriptStringList->count); @@ -156,7 +156,16 @@ void ContentLoader::LoadXAssetArray(const bool atStreamStart, const size_t count assert(varXAsset != nullptr); if (atStreamStart) - m_stream.Load(varXAsset, count); + { + const auto fill = m_stream.LoadWithFill(8u * count); + + for (size_t index = 0; index < count; index++) + { + fill.Fill(varXAsset[index].type, 8u * index); + fill.FillPtr(varXAsset[index].header.data, 8u * index + 4u); + fill.InsertPointerRedirect(m_stream.AllocRedirectEntry(varXAsset[index].header.data), 8u * index + 4u); + } + } for (size_t index = 0; index < count; index++) { @@ -179,9 +188,9 @@ void ContentLoader::Load() if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); - assetList.assets = m_stream.Alloc(alignof(XAsset)); + assetList.assets = m_stream.AllocOutOfBlock(4, assetList.assetCount); varXAsset = assetList.assets; LoadXAssetArray(true, assetList.assetCount); } diff --git a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp index 7e13c582..514e290b 100644 --- a/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ZoneLoaderFactoryIW4.cpp @@ -80,14 +80,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(IW4::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -208,13 +208,14 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& // Start of the zone content zoneLoader->AddLoadingStep(step::CreateStepLoadZoneContent( - [&zonePtr](ZoneInputStream& stream) + [zonePtr](ZoneInputStream& stream) { return std::make_unique(*zonePtr, stream); }, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, - ZoneConstants::INSERT_BLOCK)); + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp index b8430c67..c524d3b1 100644 --- a/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ContentLoaderIW5.cpp @@ -63,7 +63,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; @@ -175,7 +175,7 @@ void ContentLoader::Load() if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; diff --git a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp index eeb68206..162fc445 100644 --- a/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp +++ b/src/ZoneLoading/Game/IW5/ZoneLoaderFactoryIW5.cpp @@ -63,15 +63,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -191,7 +191,8 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& }, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, - ZoneConstants::INSERT_BLOCK)); + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp b/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp index b26734bb..9536f02a 100644 --- a/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp +++ b/src/ZoneLoading/Game/T5/ContentLoaderT5.cpp @@ -55,7 +55,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; @@ -159,7 +159,7 @@ void ContentLoader::Load() if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; diff --git a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp index 555d955f..23331452 100644 --- a/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp +++ b/src/ZoneLoading/Game/T5/ZoneLoaderFactoryT5.cpp @@ -46,13 +46,13 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -92,7 +92,8 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& }, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, - ZoneConstants::INSERT_BLOCK)); + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); return zoneLoader; } diff --git a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp index 12c62d4f..b551cd91 100644 --- a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp +++ b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp @@ -71,7 +71,7 @@ void ContentLoader::LoadScriptStringList(const bool atStreamStart) if (varScriptStringList->strings != nullptr) { - assert(varScriptStringList->strings == PTR_FOLLOWING); + assert(GetZonePointerType(varScriptStringList->strings) == ZonePointerType::FOLLOWING); varScriptStringList->strings = m_stream.Alloc(alignof(const char*)); varXString = varScriptStringList->strings; @@ -188,7 +188,7 @@ void ContentLoader::Load() if (assetList.depends != nullptr) { - assert(assetList.depends == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.depends) == ZonePointerType::FOLLOWING); assetList.depends = m_stream.Alloc(alignof(const char*)); varXString = assetList.depends; @@ -197,7 +197,7 @@ void ContentLoader::Load() if (assetList.assets != nullptr) { - assert(assetList.assets == PTR_FOLLOWING); + assert(GetZonePointerType(assetList.assets) == ZonePointerType::FOLLOWING); assetList.assets = m_stream.Alloc(alignof(XAsset)); varXAsset = assetList.assets; diff --git a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp index 4df11d30..cdc06d5d 100644 --- a/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp +++ b/src/ZoneLoading/Game/T6/ZoneLoaderFactoryT6.cpp @@ -93,14 +93,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlockType::BLOCK_TYPE_RUNTIME)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlockType::BLOCK_TYPE_DELAY)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlockType::BLOCK_TYPE_DELAY)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + zoneLoader.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } @@ -210,7 +210,8 @@ std::unique_ptr ZoneLoaderFactory::CreateLoaderForHeader(ZoneHeader& }, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, - ZoneConstants::INSERT_BLOCK)); + ZoneConstants::INSERT_BLOCK, + zonePtr->Memory())); if (isSecure) { diff --git a/src/ZoneLoading/Loading/ContentLoaderBase.cpp b/src/ZoneLoading/Loading/ContentLoaderBase.cpp index 45fa3b1a..d424cbff 100644 --- a/src/ZoneLoading/Loading/ContentLoaderBase.cpp +++ b/src/ZoneLoading/Loading/ContentLoaderBase.cpp @@ -1,15 +1,22 @@ #include "ContentLoaderBase.h" #include - -const void* ContentLoaderBase::PTR_FOLLOWING = reinterpret_cast(-1); -const void* ContentLoaderBase::PTR_INSERT = reinterpret_cast(-2); +#include +#include ContentLoaderBase::ContentLoaderBase(Zone& zone, ZoneInputStream& stream) : varXString(nullptr), m_zone(zone), m_memory(zone.Memory()), - m_stream(stream) + m_stream(stream), + + // -1 + m_zone_ptr_following( + reinterpret_cast(std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount()))), + + // -2 + m_zone_ptr_insert( + reinterpret_cast((std::numeric_limits::max() >> ((sizeof(std::uintptr_t) * 8u) - stream.GetPointerBitCount())) - 1u)) { } @@ -22,9 +29,9 @@ void ContentLoaderBase::LoadXString(const bool atStreamStart) const if (*varXString != nullptr) { - if (*varXString == PTR_FOLLOWING) + if (GetZonePointerType(*varXString) == ZonePointerType::FOLLOWING) { - *varXString = m_stream.Alloc(alignof(const char)); + *varXString = m_stream.Alloc(1); m_stream.LoadNullTerminated(const_cast(*varXString)); } else @@ -39,7 +46,12 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t assert(varXString != nullptr); if (atStreamStart) - m_stream.Load(varXString, count); + { + const auto fill = m_stream.LoadWithFill(4u * count); + + for (size_t index = 0; index < count; index++) + fill.FillPtr(varXString[index], 4u * index); + } for (size_t index = 0; index < count; index++) { @@ -47,3 +59,13 @@ void ContentLoaderBase::LoadXStringArray(const bool atStreamStart, const size_t varXString++; } } + +ZonePointerType ContentLoaderBase::GetZonePointerType(const void* zonePtr) const +{ + if (zonePtr == m_zone_ptr_following) + return ZonePointerType::FOLLOWING; + if (zonePtr == m_zone_ptr_insert) + return ZonePointerType::INSERT; + + return ZonePointerType::OFFSET; +} diff --git a/src/ZoneLoading/Loading/ContentLoaderBase.h b/src/ZoneLoading/Loading/ContentLoaderBase.h index 5edddb5e..8093476d 100644 --- a/src/ZoneLoading/Loading/ContentLoaderBase.h +++ b/src/ZoneLoading/Loading/ContentLoaderBase.h @@ -3,12 +3,17 @@ #include "Zone/Stream/ZoneInputStream.h" #include "Zone/Zone.h" +#include + +enum class ZonePointerType : std::uint8_t +{ + FOLLOWING, + INSERT, + OFFSET +}; + class ContentLoaderBase { -protected: - static const void* PTR_FOLLOWING; - static const void* PTR_INSERT; - public: virtual ~ContentLoaderBase() = default; ContentLoaderBase(const ContentLoaderBase& other) = default; @@ -22,9 +27,20 @@ protected: void LoadXString(bool atStreamStart) const; void LoadXStringArray(bool atStreamStart, size_t count); + [[nodiscard]] ZonePointerType GetZonePointerType(const void* zonePtr) const; + + template [[nodiscard]] ZonePointerType GetZonePointerType(T* zonePtr) const + { + return GetZonePointerType(reinterpret_cast(zonePtr)); + } + const char** varXString; Zone& m_zone; MemoryManager& m_memory; ZoneInputStream& m_stream; + +private: + const void* m_zone_ptr_following; + const void* m_zone_ptr_insert; }; diff --git a/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.cpp b/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.cpp new file mode 100644 index 00000000..e9bb12ef --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.cpp @@ -0,0 +1,19 @@ +#include "InvalidAliasLookupException.h" + +#include + +InvalidAliasLookupException::InvalidAliasLookupException(const size_t lookupIndex, const size_t lookupCount) + : m_lookup_index(lookupIndex), + m_lookup_count(lookupCount) +{ +} + +std::string InvalidAliasLookupException::DetailedMessage() +{ + return std::format("Tried to resolve zone alias lookup {} when there are only {} entries in the lookup", m_lookup_index, m_lookup_count); +} + +char const* InvalidAliasLookupException::what() const noexcept +{ + return "Tried to resolve invalid zone alias lookup"; +} diff --git a/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.h b/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.h new file mode 100644 index 00000000..b89fa27a --- /dev/null +++ b/src/ZoneLoading/Loading/Exception/InvalidAliasLookupException.h @@ -0,0 +1,16 @@ +#pragma once +#include "LoadingException.h" +#include "Zone/XBlock.h" + +class InvalidAliasLookupException final : public LoadingException +{ +public: + InvalidAliasLookupException(size_t lookupIndex, size_t lookupCount); + + std::string DetailedMessage() override; + [[nodiscard]] char const* what() const noexcept override; + +private: + size_t m_lookup_index; + size_t m_lookup_count; +}; diff --git a/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp b/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp index c4b9d59e..7e75ceca 100644 --- a/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp +++ b/src/ZoneLoading/Loading/Steps/StepAllocXBlocks.cpp @@ -4,7 +4,7 @@ namespace { - constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000; + constexpr uint64_t MAX_XBLOCK_SIZE = 0x3C000000; // ~1GB class StepAllocXBlocks final : public ILoadingStep { diff --git a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp index 651b36f6..80cb3591 100644 --- a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp +++ b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.cpp @@ -10,17 +10,20 @@ namespace StepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, const unsigned pointerBitCount, const unsigned offsetBlockBitCount, - const block_t insertBlock) + const block_t insertBlock, + MemoryManager& memory) : m_entry_point_factory(std::move(entryPointFactory)), m_pointer_bit_count(pointerBitCount), m_offset_block_bit_count(offsetBlockBitCount), - m_insert_block(insertBlock) + m_insert_block(insertBlock), + m_memory(memory) { } void PerformStep(ZoneLoader& zoneLoader, ILoadingStream& stream) override { - const auto inputStream = ZoneInputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, zoneLoader.m_blocks, m_insert_block, stream); + const auto inputStream = + ZoneInputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, zoneLoader.m_blocks, m_insert_block, stream, m_memory); const auto entryPoint = m_entry_point_factory(*inputStream); assert(entryPoint); @@ -33,6 +36,7 @@ namespace unsigned m_pointer_bit_count; unsigned m_offset_block_bit_count; block_t m_insert_block; + MemoryManager& m_memory; }; } // namespace @@ -41,8 +45,9 @@ namespace step std::unique_ptr CreateStepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, const unsigned pointerBitCount, const unsigned offsetBlockBitCount, - const block_t insertBlock) + const block_t insertBlock, + MemoryManager& memory) { - return std::make_unique(std::move(entryPointFactory), pointerBitCount, offsetBlockBitCount, insertBlock); + return std::make_unique(std::move(entryPointFactory), pointerBitCount, offsetBlockBitCount, insertBlock, memory); } } // namespace step diff --git a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h index 536ef1a4..621fa2a2 100644 --- a/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h +++ b/src/ZoneLoading/Loading/Steps/StepLoadZoneContent.h @@ -12,5 +12,6 @@ namespace step std::unique_ptr CreateStepLoadZoneContent(std::function(ZoneInputStream&)> entryPointFactory, unsigned pointerBitCount, unsigned offsetBlockBitCount, - block_t insertBlock); + block_t insertBlock, + MemoryManager& memory); } diff --git a/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp b/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp index 572e8494..5d9abc07 100644 --- a/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp +++ b/src/ZoneLoading/Zone/Stream/ZoneInputStream.cpp @@ -1,6 +1,7 @@ #include "ZoneInputStream.h" #include "Loading/Exception/BlockOverflowException.h" +#include "Loading/Exception/InvalidAliasLookupException.h" #include "Loading/Exception/InvalidOffsetBlockException.h" #include "Loading/Exception/InvalidOffsetBlockOffsetException.h" #include "Loading/Exception/OutOfBlockBoundsException.h" @@ -10,17 +11,33 @@ #include #include -ZoneStreamFillReadAccessor::ZoneStreamFillReadAccessor(const void* buffer, const size_t bufferSize, const unsigned pointerByteCount) - : m_buffer(buffer), +ZoneStreamFillReadAccessor::ZoneStreamFillReadAccessor(const void* dataBuffer, void* blockBuffer, const size_t bufferSize, const unsigned pointerByteCount) + : m_data_buffer(dataBuffer), + m_block_buffer(blockBuffer), m_buffer_size(bufferSize), m_pointer_byte_count(pointerByteCount) { + // Otherwise we cannot insert alias + assert(m_pointer_byte_count <= sizeof(uintptr_t)); } ZoneStreamFillReadAccessor ZoneStreamFillReadAccessor::AtOffset(const size_t offset) const { assert(offset < m_buffer_size); - return ZoneStreamFillReadAccessor(static_cast(m_buffer) + offset, m_buffer_size - offset, m_pointer_byte_count); + return ZoneStreamFillReadAccessor( + static_cast(m_data_buffer) + offset, static_cast(m_block_buffer) + offset, m_buffer_size - offset, m_pointer_byte_count); +} + +void ZoneStreamFillReadAccessor::InsertPointerRedirect(const uintptr_t aliasValue, const size_t offset) const +{ + // Memory should be zero by default + if (aliasValue == 0) + return; + + assert(offset < m_buffer_size); + assert(m_block_buffer); + + std::memcpy(static_cast(m_block_buffer) + offset, &aliasValue, m_pointer_byte_count); } namespace @@ -28,12 +45,19 @@ namespace class XBlockInputStream final : public ZoneInputStream { public: - XBlockInputStream( - const unsigned pointerBitCount, const unsigned blockBitCount, std::vector& blocks, const block_t insertBlock, ILoadingStream& stream) + XBlockInputStream(const unsigned pointerBitCount, + const unsigned blockBitCount, + std::vector& blocks, + const block_t insertBlock, + ILoadingStream& stream, + MemoryManager& memory) : m_blocks(blocks), m_stream(stream), + m_memory(memory), m_pointer_byte_count(pointerBitCount / 8u), - m_block_bit_count(blockBitCount) + m_block_mask((std::numeric_limits::max() >> (sizeof(uintptr_t) * 8 - blockBitCount)) << (pointerBitCount - blockBitCount)), + m_block_shift(pointerBitCount - blockBitCount), + m_offset_mask(std::numeric_limits::max() >> (sizeof(uintptr_t) * 8 - (pointerBitCount - blockBitCount))) { assert(pointerBitCount % 8u == 0u); assert(insertBlock < static_cast(blocks.size())); @@ -45,6 +69,11 @@ namespace m_insert_block = blocks[insertBlock]; } + [[nodiscard]] unsigned GetPointerBitCount() const override + { + return m_pointer_byte_count * 8u; + } + void PushBlock(const block_t block) override { assert(block < static_cast(m_blocks.size())); @@ -54,7 +83,7 @@ namespace m_block_stack.push(newBlock); - if (newBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) m_temp_offsets.push(m_block_offsets[newBlock->m_index]); } @@ -70,7 +99,7 @@ namespace m_block_stack.pop(); // If the temp block is not used anymore right now, reset it to the buffer start since as the name suggests, the data inside is temporary. - if (poppedBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { m_block_offsets[poppedBlock->m_index] = m_temp_offsets.top(); m_temp_offsets.pop(); @@ -96,6 +125,23 @@ namespace return &block->m_buffer[m_block_offsets[block->m_index]]; } + void* AllocOutOfBlock(const unsigned align, const size_t size) override + { + assert(!m_block_stack.empty()); + + if (m_block_stack.empty()) + return nullptr; + + auto* block = m_block_stack.top(); + + Align(align); + + if (m_block_offsets[block->m_index] > block->m_buffer_size) + throw BlockOverflowException(block); + + return m_memory.AllocRaw(size); + } + void LoadDataRaw(void* dst, const size_t size) override { m_stream.Load(dst, size); @@ -108,10 +154,10 @@ namespace { auto* block = m_block_stack.top(); - if (block->m_buffer > dst || block->m_buffer + block->m_buffer_size < dst) + if (block->m_buffer.get() > dst || block->m_buffer.get() + block->m_buffer_size < dst) throw OutOfBlockBoundsException(block); - if (static_cast(dst) + size > block->m_buffer + block->m_buffer_size) + if (static_cast(dst) + size > block->m_buffer.get() + block->m_buffer_size) throw BlockOverflowException(block); // Theoretically ptr should always be at the current block offset. @@ -119,16 +165,16 @@ namespace switch (block->m_type) { - case XBlock::Type::BLOCK_TYPE_TEMP: - case XBlock::Type::BLOCK_TYPE_NORMAL: + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: m_stream.Load(dst, size); break; - case XBlock::Type::BLOCK_TYPE_RUNTIME: + case XBlockType::BLOCK_TYPE_RUNTIME: std::memset(dst, 0, size); break; - case XBlock::Type::BLOCK_TYPE_DELAY: + case XBlockType::BLOCK_TYPE_DELAY: assert(false); break; } @@ -150,14 +196,14 @@ namespace auto* block = m_block_stack.top(); - if (block->m_buffer > dst || block->m_buffer + block->m_buffer_size < dst) + if (block->m_buffer.get() > dst || block->m_buffer.get() + block->m_buffer_size < dst) throw OutOfBlockBoundsException(block); // Theoretically ptr should always be at the current block offset. assert(dst == &block->m_buffer[m_block_offsets[block->m_index]]); uint8_t byte; - auto offset = static_cast(static_cast(dst) - block->m_buffer); + auto offset = static_cast(static_cast(dst) - block->m_buffer.get()); do { if (offset >= block->m_buffer_size) @@ -179,33 +225,34 @@ namespace if (!m_block_stack.empty()) { const auto* block = m_block_stack.top(); + auto* blockBufferForFill = &block->m_buffer[m_block_offsets[block->m_index]]; + switch (block->m_type) { - case XBlock::Type::BLOCK_TYPE_TEMP: - case XBlock::Type::BLOCK_TYPE_NORMAL: + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: m_stream.Load(dst, size); break; - case XBlock::Type::BLOCK_TYPE_RUNTIME: + case XBlockType::BLOCK_TYPE_RUNTIME: std::memset(dst, 0, size); break; - case XBlock::Type::BLOCK_TYPE_DELAY: + case XBlockType::BLOCK_TYPE_DELAY: assert(false); break; } IncBlockPos(size); - } - else - { - m_stream.Load(dst, size); + + return ZoneStreamFillReadAccessor(dst, blockBufferForFill, size, m_pointer_byte_count); } - return ZoneStreamFillReadAccessor(dst, size, m_pointer_byte_count); + m_stream.Load(dst, size); + return ZoneStreamFillReadAccessor(dst, nullptr, size, m_pointer_byte_count); } - void* InsertPointer() override + void* InsertPointerNative() override { m_block_stack.push(m_insert_block); @@ -224,14 +271,46 @@ namespace return ptr; } + uintptr_t InsertPointerAliasLookup() override + { + m_block_stack.push(m_insert_block); + + // Alignment of pointer should always be its size + Align(m_pointer_byte_count); + + if (m_block_offsets[m_insert_block->m_index] + m_pointer_byte_count > m_insert_block->m_buffer_size) + throw BlockOverflowException(m_insert_block); + + auto* ptr = static_cast(&m_insert_block->m_buffer[m_block_offsets[m_insert_block->m_index]]); + + IncBlockPos(m_pointer_byte_count); + + m_block_stack.pop(); + + const auto newLookupIndex = static_cast(m_alias_lookup.size()) + 1; + m_alias_lookup.emplace_back(nullptr); + + std::memcpy(ptr, &newLookupIndex, m_pointer_byte_count); + + return newLookupIndex; + } + + void SetInsertedPointerAliasLookup(const uintptr_t lookupEntry, void* value) override + { + assert(lookupEntry > 0); + assert(lookupEntry <= m_alias_lookup.size()); + + m_alias_lookup[lookupEntry - 1] = value; + } + void* ConvertOffsetToPointerNative(const void* offset) override { // -1 because otherwise Block 0 Offset 0 would be just 0 which is already used to signalize a nullptr. // So all offsets are moved by 1. const auto offsetInt = reinterpret_cast(offset) - 1u; - const auto blockNum = static_cast(offsetInt >> (sizeof(offsetInt) * 8u - m_block_bit_count)); - const auto blockOffset = static_cast(offsetInt & (UINTPTR_MAX >> m_block_bit_count)); + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) throw InvalidOffsetBlockException(blockNum); @@ -249,8 +328,8 @@ namespace // For details see ConvertOffsetToPointer const auto offsetInt = reinterpret_cast(offset) - 1u; - const auto blockNum = static_cast(offsetInt >> (sizeof(offsetInt) * 8u - m_block_bit_count)); - const auto blockOffset = static_cast(offsetInt & (UINTPTR_MAX >> m_block_bit_count)); + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) throw InvalidOffsetBlockException(blockNum); @@ -263,6 +342,73 @@ namespace return *reinterpret_cast(&block->m_buffer[blockOffset]); } + uintptr_t AllocRedirectEntry(void** alias) override + { + // nullptr is always lookup alias 0 + if (*alias == nullptr) + return 0; + + const auto newIndex = m_pointer_redirect_lookup.size(); + + m_pointer_redirect_lookup.emplace_back(alias); + + return static_cast(newIndex + 1); + } + + void* ConvertOffsetToPointerRedirect(const void* offset) override + { + // For details see ConvertOffsetToPointer + const auto offsetInt = reinterpret_cast(offset) - 1u; + + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); + + if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) + throw InvalidOffsetBlockException(blockNum); + + auto* block = m_blocks[blockNum]; + + if (block->m_buffer_size <= blockOffset + sizeof(void*)) + throw InvalidOffsetBlockOffsetException(block, blockOffset); + + uintptr_t lookupEntry = 0u; + std::memcpy(&lookupEntry, &block->m_buffer[blockOffset], m_pointer_byte_count); + + if (lookupEntry == 0) + return nullptr; + if (lookupEntry > m_pointer_redirect_lookup.size()) + throw InvalidAliasLookupException(lookupEntry - 1, m_pointer_redirect_lookup.size()); + + return *m_pointer_redirect_lookup[lookupEntry - 1]; + } + + void* ConvertOffsetToAliasLookup(const void* offset) override + { + // For details see ConvertOffsetToPointer + const auto offsetInt = reinterpret_cast(offset) - 1u; + + const auto blockNum = static_cast((offsetInt & m_block_mask) >> m_block_shift); + const auto blockOffset = static_cast(offsetInt & m_offset_mask); + + if (blockNum < 0 || blockNum >= static_cast(m_blocks.size())) + throw InvalidOffsetBlockException(blockNum); + + auto* block = m_blocks[blockNum]; + + if (block->m_buffer_size <= blockOffset + sizeof(void*)) + throw InvalidOffsetBlockOffsetException(block, blockOffset); + + uintptr_t lookupEntry = 0u; + std::memcpy(&lookupEntry, &block->m_buffer[blockOffset], m_pointer_byte_count); + + if (lookupEntry == 0) + return nullptr; + if (lookupEntry > m_alias_lookup.size()) + throw InvalidAliasLookupException(lookupEntry - 1, m_alias_lookup.size()); + + return m_alias_lookup[lookupEntry - 1]; + } + private: void IncBlockPos(const size_t size) { @@ -293,16 +439,26 @@ namespace std::stack m_temp_offsets; ILoadingStream& m_stream; + MemoryManager& m_memory; + unsigned m_pointer_byte_count; - unsigned m_block_bit_count; + uintptr_t m_block_mask; + unsigned m_block_shift; + uintptr_t m_offset_mask; XBlock* m_insert_block; std::vector m_fill_buffer; + std::vector m_pointer_redirect_lookup; + std::vector m_alias_lookup; }; } // namespace -std::unique_ptr ZoneInputStream::Create( - const unsigned pointerBitCount, const unsigned blockBitCount, std::vector& blocks, const block_t insertBlock, ILoadingStream& stream) +std::unique_ptr ZoneInputStream::Create(const unsigned pointerBitCount, + const unsigned blockBitCount, + std::vector& blocks, + const block_t insertBlock, + ILoadingStream& stream, + MemoryManager& memory) { - return std::make_unique(pointerBitCount, blockBitCount, blocks, insertBlock, stream); + return std::make_unique(pointerBitCount, blockBitCount, blocks, insertBlock, stream, memory); } diff --git a/src/ZoneLoading/Zone/Stream/ZoneInputStream.h b/src/ZoneLoading/Zone/Stream/ZoneInputStream.h index 8c7d0f26..e56d631e 100644 --- a/src/ZoneLoading/Zone/Stream/ZoneInputStream.h +++ b/src/ZoneLoading/Zone/Stream/ZoneInputStream.h @@ -1,17 +1,19 @@ #pragma once #include "Loading/ILoadingStream.h" +#include "Utils/MemoryManager.h" #include "Zone/Stream/IZoneStream.h" #include "Zone/XBlock.h" #include +#include #include #include class ZoneStreamFillReadAccessor { public: - ZoneStreamFillReadAccessor(const void* buffer, size_t bufferSize, unsigned pointerByteCount); + ZoneStreamFillReadAccessor(const void* dataBuffer, void* blockBuffer, size_t bufferSize, unsigned pointerByteCount); [[nodiscard]] ZoneStreamFillReadAccessor AtOffset(size_t offset) const; @@ -19,14 +21,14 @@ public: { assert(offset + sizeof(T) <= m_buffer_size); - value = *reinterpret_cast(static_cast(m_buffer) + offset); + value = *reinterpret_cast(static_cast(m_data_buffer) + offset); } - template void FillArray(T* value, const size_t offset, const size_t arraySize) const + template void FillArray(T (&value)[S], const size_t offset) const { - assert(offset + sizeof(T) * arraySize <= m_buffer_size); + assert(offset + sizeof(T) * S <= m_buffer_size); - std::memcpy(value, static_cast(m_buffer) + offset, sizeof(T) * arraySize); + std::memcpy(value, static_cast(m_data_buffer) + offset, sizeof(T) * S); } template void FillPtr(T*& value, const size_t offset) const @@ -35,11 +37,14 @@ public: assert(m_pointer_byte_count <= sizeof(uintptr_t)); value = nullptr; - std::memcpy(&value, static_cast(m_buffer) + offset, m_pointer_byte_count); + std::memcpy(&value, static_cast(m_data_buffer) + offset, m_pointer_byte_count); } + void InsertPointerRedirect(uintptr_t aliasValue, size_t offset) const; + private: - const void* m_buffer; + const void* m_data_buffer; + void* m_block_buffer; size_t m_buffer_size; unsigned m_pointer_byte_count; }; @@ -47,6 +52,11 @@ private: class ZoneInputStream : public IZoneStream { public: + /** + * \brief Returns the configured bits that make up a pointer. + */ + [[nodiscard]] virtual unsigned GetPointerBitCount() const = 0; + /** * \brief Retrieves the new read position in the current block by aligning the position with the specified value and then returning the current read * position in the block. @@ -64,6 +74,16 @@ public: return static_cast(Alloc(align)); } + virtual void* AllocOutOfBlock(unsigned align, size_t size) = 0; + + /** + * \copydoc ZoneInputStream#AllocOutOfBlock(unsigned) + */ + template T* AllocOutOfBlock(const unsigned align, const size_t arraySize = 1u) + { + return static_cast(AllocOutOfBlock(align, sizeof(T) * arraySize)); + } + /** * \brief Loads data from the underlying stream without considering the current block or advancing the block position. * The data is read directly to the specified location instead of block memory. @@ -99,13 +119,17 @@ public: LoadDataInBlock(const_cast(reinterpret_cast(dst)), size); } - virtual void* InsertPointer() = 0; + virtual void* InsertPointerNative() = 0; template T** InsertPointerNative() { - return static_cast(InsertPointer()); + return static_cast(InsertPointerNative()); } + virtual uintptr_t InsertPointerAliasLookup() = 0; + + virtual void SetInsertedPointerAliasLookup(uintptr_t lookupEntry, void* value) = 0; + virtual void* ConvertOffsetToPointerNative(const void* offset) = 0; template T* ConvertOffsetToPointerNative(T* offset) @@ -120,6 +144,27 @@ public: return static_cast(ConvertOffsetToAliasNative(static_cast(offset))); } - static std::unique_ptr - Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, ILoadingStream& stream); + virtual uintptr_t AllocRedirectEntry(void** alias) = 0; + + template uintptr_t AllocRedirectEntry(T*& offset) + { + return AllocRedirectEntry(reinterpret_cast(&offset)); + } + + virtual void* ConvertOffsetToPointerRedirect(const void* offset) = 0; + + template T* ConvertOffsetToPointerRedirect(T* offset) + { + return static_cast(ConvertOffsetToPointerRedirect(static_cast(offset))); + } + + virtual void* ConvertOffsetToAliasLookup(const void* offset) = 0; + + template T* ConvertOffsetToAliasLookup(T* offset) + { + return static_cast(ConvertOffsetToAliasLookup(static_cast(offset))); + } + + static std::unique_ptr Create( + unsigned pointerBitCount, unsigned blockBitCount, std::vector& blocks, block_t insertBlock, ILoadingStream& stream, MemoryManager& memory); }; diff --git a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp index 9fb99f06..2621980c 100644 --- a/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp +++ b/src/ZoneWriting/Game/IW3/ZoneWriterFactoryIW3.cpp @@ -22,15 +22,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(IW3::XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp index ede84059..0bb35364 100644 --- a/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp +++ b/src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp @@ -24,14 +24,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp index 4ed62b7d..00338ed7 100644 --- a/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp +++ b/src/ZoneWriting/Game/IW5/ZoneWriterFactoryIW5.cpp @@ -24,15 +24,15 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_CALLBACK, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_VERTEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_INDEX, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(XFILE_BLOCK_SCRIPT, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp index c96c6599..cd5ca5bf 100644 --- a/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp +++ b/src/ZoneWriting/Game/T5/ZoneWriterFactoryT5.cpp @@ -22,13 +22,13 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL_RUNTIME, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_LARGE, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T5::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp index ffa5edf6..3d0d1d70 100644 --- a/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp +++ b/src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp @@ -29,14 +29,14 @@ namespace { #define XBLOCK_DEF(name, type) std::make_unique(STR(name), name, type) - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL)); - writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlockType::BLOCK_TYPE_TEMP)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlockType::BLOCK_TYPE_RUNTIME)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlockType::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlockType::BLOCK_TYPE_DELAY)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlockType::BLOCK_TYPE_NORMAL)); + writer.AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlockType::BLOCK_TYPE_NORMAL)); #undef XBLOCK_DEF } diff --git a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp index a1f3760d..6eff9d3f 100644 --- a/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp +++ b/src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp @@ -30,7 +30,7 @@ void InMemoryZoneOutputStream::PushBlock(const block_t block) m_block_stack.push(newBlock); - if (newBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { if (m_temp_sizes.empty()) m_temp_sizes.push(0); @@ -50,7 +50,7 @@ block_t InMemoryZoneOutputStream::PopBlock() m_block_stack.pop(); // If temp block is popped, see if its size is bigger than the current maximum temp size - if (poppedBlock->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (poppedBlock->m_type == XBlockType::BLOCK_TYPE_TEMP) { const auto tempSize = m_temp_sizes.top(); m_temp_sizes.pop(); @@ -70,7 +70,7 @@ void InMemoryZoneOutputStream::Align(const int align) { auto* block = m_block_stack.top(); - if (block->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) m_temp_sizes.top() = (m_temp_sizes.top() + align - 1) / align * align; else block->m_buffer_size = (block->m_buffer_size + align - 1) / align * align; @@ -96,16 +96,16 @@ void* InMemoryZoneOutputStream::WriteDataInBlock(const void* src, const size_t s void* result = nullptr; switch (block->m_type) { - case XBlock::Type::BLOCK_TYPE_TEMP: - case XBlock::Type::BLOCK_TYPE_NORMAL: + case XBlockType::BLOCK_TYPE_TEMP: + case XBlockType::BLOCK_TYPE_NORMAL: result = m_zone_data->GetBufferOfSize(size); memcpy(result, src, size); break; - case XBlock::Type::BLOCK_TYPE_RUNTIME: + case XBlockType::BLOCK_TYPE_RUNTIME: break; - case XBlock::Type::BLOCK_TYPE_DELAY: + case XBlockType::BLOCK_TYPE_DELAY: assert(false); break; } @@ -122,7 +122,7 @@ void InMemoryZoneOutputStream::IncBlockPos(const size_t size) return; auto* block = m_block_stack.top(); - if (block->m_type == XBlock::Type::BLOCK_TYPE_TEMP) + if (block->m_type == XBlockType::BLOCK_TYPE_TEMP) { m_temp_sizes.top() += size; } @@ -141,7 +141,7 @@ void InMemoryZoneOutputStream::WriteNullTerminated(const void* src) uintptr_t InMemoryZoneOutputStream::GetCurrentZonePointer() { assert(!m_block_stack.empty()); - assert(m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_NORMAL); + assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL); uintptr_t ptr = 0; ptr |= static_cast(m_block_stack.top()->m_index) << (sizeof(uintptr_t) * 8 - m_block_bit_count); @@ -168,7 +168,7 @@ void InMemoryZoneOutputStream::MarkFollowing(void** pPtr) { assert(!m_block_stack.empty()); assert(pPtr != nullptr); - *pPtr = m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; + *pPtr = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP ? PTR_INSERT : PTR_FOLLOWING; } bool InMemoryZoneOutputStream::ReusableShouldWrite(void** pPtr, const size_t entrySize, const std::type_index type) @@ -202,7 +202,7 @@ void InMemoryZoneOutputStream::ReusableAddOffset(void* ptr, size_t size, size_t { assert(!m_block_stack.empty()); - const auto inTemp = m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_TEMP; + const auto inTemp = m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP; auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer(); const auto foundEntriesForType = m_reusable_entries.find(type); if (foundEntriesForType == m_reusable_entries.end())