2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-19 15:01:49 +00:00

Merge pull request #648 from Laupetin/feature/x64-zone-writing

feat: x64 zone writing
This commit is contained in:
Jan
2026-01-18 23:25:19 +01:00
committed by GitHub
75 changed files with 1825 additions and 1171 deletions

View File

@@ -2594,8 +2594,8 @@ namespace IW3
union entryInternalData union entryInternalData
{ {
int op;
Operand operand; Operand operand;
int op;
}; };
enum expressionEntryType : int enum expressionEntryType : int

View File

@@ -2044,8 +2044,8 @@ namespace IW4
union entryInternalData union entryInternalData
{ {
int op;
Operand operand; Operand operand;
int op;
}; };
enum expressionEntryType : int enum expressionEntryType : int

View File

@@ -2608,8 +2608,8 @@ namespace IW5
union entryInternalData union entryInternalData
{ {
int op;
Operand operand; Operand operand;
int op;
}; };
struct expressionEntry struct expressionEntry

View File

@@ -198,16 +198,22 @@ ZoneCode.Assets = {
} }
function ZoneCode:outputForAssets(assetList) function ZoneCode:outputForAssets(assetList)
buildoutputs {
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/AssetLoader%{file.basename}.h",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/AssetMarker%{file.basename}.h",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/AssetWriter%{file.basename}.h",
}
for i = 1, #assetList do for i = 1, #assetList do
local assetNameLower = string.lower(assetList[i]) local assetNameLower = string.lower(assetList[i])
buildoutputs { buildoutputs {
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_load_db.cpp", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_load_db.cpp",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_load_db.h", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_load_db.h",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_mark_db.cpp", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_mark_db.cpp",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_mark_db.h", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_mark_db.h",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_write_db.cpp", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_write_db.cpp",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_write_db.h", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_write_db.h",
"%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_struct_test.cpp", "%{wks.location}/src/ZoneCode/Game/%{file.basename}/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_%{string.lower(file.basename)}_struct_test.cpp",
} }
end end
end end
@@ -216,9 +222,11 @@ function ZoneCode:allTestFiles()
result = {} result = {}
for game, assets in pairs(self.Assets) do for game, assets in pairs(self.Assets) do
local gameLower = string.lower(game)
for i, assetName in ipairs(assets) do for i, assetName in ipairs(assets) do
local assetNameLower = string.lower(assetName) local assetNameLower = string.lower(assetName)
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_struct_test.cpp") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_struct_test.cpp")
end end
end end
@@ -229,12 +237,13 @@ function ZoneCode:allMarkFiles()
result = {} result = {}
for game, assets in pairs(self.Assets) do for game, assets in pairs(self.Assets) do
local gameLower = string.lower(game)
-- PerAsset -- PerAsset
for i, assetName in ipairs(assets) do for i, assetName in ipairs(assets) do
local assetNameLower = string.lower(assetName) local assetNameLower = string.lower(assetName)
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_mark_db.cpp") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_mark_db.cpp")
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_mark_db.h") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_mark_db.h")
end end
-- PerTemplate -- PerTemplate
@@ -248,11 +257,17 @@ function ZoneCode:allLoadFiles()
result = {} result = {}
for game, assets in pairs(self.Assets) do for game, assets in pairs(self.Assets) do
local gameLower = string.lower(game)
-- PerAsset
for i, assetName in ipairs(assets) do for i, assetName in ipairs(assets) do
local assetNameLower = string.lower(assetName) local assetNameLower = string.lower(assetName)
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_load_db.cpp") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_load_db.cpp")
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_load_db.h") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_load_db.h")
end end
-- PerTemplate
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/AssetLoader" .. game .. ".h")
end end
return result return result
@@ -262,11 +277,17 @@ function ZoneCode:allWriteFiles()
result = {} result = {}
for game, assets in pairs(self.Assets) do for game, assets in pairs(self.Assets) do
local gameLower = string.lower(game)
-- PerAsset
for i, assetName in ipairs(assets) do for i, assetName in ipairs(assets) do
local assetNameLower = string.lower(assetName) local assetNameLower = string.lower(assetName)
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_write_db.cpp") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_write_db.cpp")
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_write_db.h") table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/XAssets/" .. assetNameLower .. "/" .. assetNameLower .. "_" .. gameLower .. "_write_db.h")
end end
-- PerTemplate
table.insert(result, "%{wks.location}/src/ZoneCode/Game/" .. game .. "/AssetWriter" .. game .. ".h")
end end
return result return result

View File

@@ -27,6 +27,11 @@ use MaterialShaderArgument;
set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST
|| type == MTL_ARG_LITERAL_PIXEL_CONST; || type == MTL_ARG_LITERAL_PIXEL_CONST;
set reusable u::literalConst; set reusable u::literalConst;
set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST
|| type == MTL_ARG_CODE_PIXEL_CONST;
set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER;
set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST
|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER;
// MaterialPixelShader // MaterialPixelShader
set string MaterialPixelShader::name; set string MaterialPixelShader::name;

View File

@@ -24,3 +24,8 @@ use MaterialShaderArgument;
set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST
|| type == MTL_ARG_LITERAL_PIXEL_CONST; || type == MTL_ARG_LITERAL_PIXEL_CONST;
set reusable u::literalConst; set reusable u::literalConst;
set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST
|| type == MTL_ARG_CODE_PIXEL_CONST;
set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER;
set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST
|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER;

View File

@@ -24,3 +24,8 @@ use MaterialShaderArgument;
set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST
|| type == MTL_ARG_LITERAL_PIXEL_CONST; || type == MTL_ARG_LITERAL_PIXEL_CONST;
set reusable u::literalConst; set reusable u::literalConst;
set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST
|| type == MTL_ARG_CODE_PIXEL_CONST;
set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER;
set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST
|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER;

View File

@@ -47,3 +47,8 @@ use MaterialShaderArgument;
set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST
|| type == MTL_ARG_LITERAL_PIXEL_CONST; || type == MTL_ARG_LITERAL_PIXEL_CONST;
set reusable u::literalConst; set reusable u::literalConst;
set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST
|| type == MTL_ARG_CODE_PIXEL_CONST;
set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER;
set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST
|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER;

View File

@@ -52,3 +52,8 @@ use MaterialShaderArgument;
set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST set condition u::literalConst type == MTL_ARG_LITERAL_VERTEX_CONST
|| type == MTL_ARG_LITERAL_PIXEL_CONST; || type == MTL_ARG_LITERAL_PIXEL_CONST;
set reusable u::literalConst; set reusable u::literalConst;
set condition u::codeConst type == MTL_ARG_CODE_VERTEX_CONST
|| type == MTL_ARG_CODE_PIXEL_CONST;
set condition u::codeSampler type == MTL_ARG_CODE_PIXEL_SAMPLER;
set condition u::nameHash type == MTL_ARG_MATERIAL_VERTEX_CONST
|| type == MTL_ARG_MATERIAL_PIXEL_CONST || type == MTL_ARG_MATERIAL_PIXEL_SAMPLER;

View File

@@ -189,15 +189,15 @@ bool MemberComputations::IsInRuntimeBlock() const
return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::RUNTIME; return m_info->m_fast_file_block != nullptr && m_info->m_fast_file_block->m_type == FastFileBlockType::RUNTIME;
} }
bool MemberComputations::IsFirstUsedMember() const bool MemberComputations::IsFirstUsedMember(const bool includeLeafs) const
{ {
const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(includeLeafs);
return !parentUsedMembers.empty() && parentUsedMembers[0] == m_info; return !parentUsedMembers.empty() && parentUsedMembers[0] == m_info;
} }
bool MemberComputations::IsLastUsedMember() const bool MemberComputations::IsLastUsedMember(const bool includeLeafs) const
{ {
const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(); const auto parentUsedMembers = StructureComputations(m_info->m_parent).GetUsedMembers(includeLeafs);
return !parentUsedMembers.empty() && parentUsedMembers[parentUsedMembers.size() - 1] == m_info; return !parentUsedMembers.empty() && parentUsedMembers[parentUsedMembers.size() - 1] == m_info;
} }

View File

@@ -25,8 +25,8 @@ public:
[[nodiscard]] bool IsNotInDefaultNormalBlock() const; [[nodiscard]] bool IsNotInDefaultNormalBlock() const;
[[nodiscard]] bool IsInTempBlock() const; [[nodiscard]] bool IsInTempBlock() const;
[[nodiscard]] bool IsInRuntimeBlock() const; [[nodiscard]] bool IsInRuntimeBlock() const;
[[nodiscard]] bool IsFirstUsedMember() const; [[nodiscard]] bool IsFirstUsedMember(bool includeLeafs) const;
[[nodiscard]] bool IsLastUsedMember() const; [[nodiscard]] bool IsLastUsedMember(bool includeLeafs) const;
[[nodiscard]] bool HasDynamicArraySize() const; [[nodiscard]] bool HasDynamicArraySize() const;
[[nodiscard]] bool IsDynamicMember() const; [[nodiscard]] bool IsDynamicMember() const;
[[nodiscard]] bool IsAfterPartialLoad() const; [[nodiscard]] bool IsAfterPartialLoad() const;

View File

@@ -38,7 +38,7 @@ bool StructureComputations::HasNonDynamicMember() const
return false; return false;
} }
std::vector<MemberInformation*> StructureComputations::GetUsedMembers() const std::vector<MemberInformation*> StructureComputations::GetUsedMembers(const bool includeLeafs) const
{ {
std::vector<MemberInformation*> members; std::vector<MemberInformation*> members;
@@ -54,7 +54,7 @@ std::vector<MemberInformation*> StructureComputations::GetUsedMembers() const
{ {
for (const auto& member : m_info->m_ordered_members) for (const auto& member : m_info->m_ordered_members)
{ {
if (!member->m_is_leaf && !MemberComputations(member.get()).ShouldIgnore()) if ((includeLeafs || !member->m_is_leaf) && !MemberComputations(member.get()).ShouldIgnore())
members.push_back(member.get()); members.push_back(member.get());
} }
} }

View File

@@ -10,7 +10,7 @@ public:
[[nodiscard]] bool IsAsset() const; [[nodiscard]] bool IsAsset() const;
[[nodiscard]] MemberInformation* GetDynamicMember() const; [[nodiscard]] MemberInformation* GetDynamicMember() const;
[[nodiscard]] bool HasNonDynamicMember() const; [[nodiscard]] bool HasNonDynamicMember() const;
[[nodiscard]] std::vector<MemberInformation*> GetUsedMembers() const; [[nodiscard]] std::vector<MemberInformation*> GetUsedMembers(bool includeLeafs) const;
[[nodiscard]] bool IsInTempBlock() const; [[nodiscard]] bool IsInTempBlock() const;
private: private:

View File

@@ -0,0 +1,21 @@
#include "BaseRenderingContext.h"
BaseRenderingContext::BaseRenderingContext(std::string game, const Architecture gameArchitecture, std::vector<const FastFileBlock*> fastFileBlocks)
: m_game(std::move(game)),
m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE),
m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)),
m_blocks(std::move(fastFileBlocks)),
m_default_normal_block(nullptr),
m_default_temp_block(nullptr)
{
for (const auto* block : m_blocks)
{
if (block->m_is_default)
{
if (block->m_type == FastFileBlockType::NORMAL && m_default_normal_block == nullptr)
m_default_normal_block = block;
else if (block->m_type == FastFileBlockType::TEMP && m_default_temp_block == nullptr)
m_default_temp_block = block;
}
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Persistence/IDataRepository.h"
#include <string>
#include <vector>
class BaseRenderingContext
{
public:
std::string m_game;
bool m_architecture_mismatch;
unsigned m_pointer_size;
std::vector<const FastFileBlock*> m_blocks;
const FastFileBlock* m_default_normal_block;
const FastFileBlock* m_default_temp_block;
protected:
BaseRenderingContext(std::string game, Architecture gameArchitecture, std::vector<const FastFileBlock*> fastFileBlocks);
};

View File

@@ -21,14 +21,9 @@ RenderingUsedType::RenderingUsedType(const DataDefinition* type, StructureInform
OncePerAssetRenderingContext::OncePerAssetRenderingContext(std::string game, OncePerAssetRenderingContext::OncePerAssetRenderingContext(std::string game,
const Architecture gameArchitecture, const Architecture gameArchitecture,
std::vector<const FastFileBlock*> fastFileBlocks) std::vector<const FastFileBlock*> fastFileBlocks)
: m_game(std::move(game)), : BaseRenderingContext(std::move(game), gameArchitecture, std::move(fastFileBlocks)),
m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE),
m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)),
m_blocks(std::move(fastFileBlocks)),
m_asset(nullptr), m_asset(nullptr),
m_has_actions(false), m_has_actions(false)
m_default_normal_block(nullptr),
m_default_temp_block(nullptr)
{ {
for (const auto* block : m_blocks) for (const auto* block : m_blocks)
{ {

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "BaseRenderingContext.h"
#include "Domain/Computations/MemberComputations.h" #include "Domain/Computations/MemberComputations.h"
#include "Domain/Information/StructureInformation.h" #include "Domain/Information/StructureInformation.h"
#include "Persistence/IDataRepository.h" #include "Persistence/IDataRepository.h"
@@ -24,16 +25,11 @@ public:
bool m_pointer_array_reference_is_reusable; bool m_pointer_array_reference_is_reusable;
}; };
class OncePerAssetRenderingContext class OncePerAssetRenderingContext : public BaseRenderingContext
{ {
public: public:
static std::unique_ptr<OncePerAssetRenderingContext> BuildContext(const IDataRepository* repository, StructureInformation* asset); static std::unique_ptr<OncePerAssetRenderingContext> BuildContext(const IDataRepository* repository, StructureInformation* asset);
std::string m_game;
bool m_architecture_mismatch;
unsigned m_pointer_size;
std::vector<const FastFileBlock*> m_blocks;
StructureInformation* m_asset; StructureInformation* m_asset;
std::vector<RenderingUsedType*> m_used_types; std::vector<RenderingUsedType*> m_used_types;
@@ -41,9 +37,6 @@ public:
std::vector<RenderingUsedType*> m_referenced_assets; std::vector<RenderingUsedType*> m_referenced_assets;
bool m_has_actions; bool m_has_actions;
const FastFileBlock* m_default_normal_block;
const FastFileBlock* m_default_temp_block;
private: private:
OncePerAssetRenderingContext(std::string game, Architecture gameArchitecture, std::vector<const FastFileBlock*> fastFileBlocks); OncePerAssetRenderingContext(std::string game, Architecture gameArchitecture, std::vector<const FastFileBlock*> fastFileBlocks);

View File

@@ -8,13 +8,8 @@ OncePerTemplateRenderingContext::OncePerTemplateRenderingContext(std::string gam
const Architecture gameArchitecture, const Architecture gameArchitecture,
std::vector<const FastFileBlock*> fastFileBlocks, std::vector<const FastFileBlock*> fastFileBlocks,
std::vector<StructureInformation*> assets) std::vector<StructureInformation*> assets)
: m_game(std::move(game)), : BaseRenderingContext(std::move(game), gameArchitecture, std::move(fastFileBlocks)),
m_architecture_mismatch(gameArchitecture != OWN_ARCHITECTURE), m_assets(std::move(assets))
m_pointer_size(GetPointerSizeForArchitecture(gameArchitecture)),
m_blocks(std::move(fastFileBlocks)),
m_assets(std::move(assets)),
m_default_normal_block(nullptr),
m_default_temp_block(nullptr)
{ {
for (const auto* block : m_blocks) for (const auto* block : m_blocks)
{ {

View File

@@ -1,24 +1,18 @@
#pragma once #pragma once
#include "BaseRenderingContext.h"
#include "Persistence/IDataRepository.h" #include "Persistence/IDataRepository.h"
#include <string> #include <string>
#include <vector> #include <vector>
class OncePerTemplateRenderingContext class OncePerTemplateRenderingContext : public BaseRenderingContext
{ {
public: public:
static std::unique_ptr<OncePerTemplateRenderingContext> BuildContext(const IDataRepository* repository); static std::unique_ptr<OncePerTemplateRenderingContext> BuildContext(const IDataRepository* repository);
std::string m_game;
bool m_architecture_mismatch;
unsigned m_pointer_size;
std::vector<const FastFileBlock*> m_blocks;
std::vector<StructureInformation*> m_assets; std::vector<StructureInformation*> m_assets;
const FastFileBlock* m_default_normal_block;
const FastFileBlock* m_default_temp_block;
private: private:
OncePerTemplateRenderingContext(std::string game, OncePerTemplateRenderingContext(std::string game,
Architecture gameArchitecture, Architecture gameArchitecture,

View File

@@ -15,7 +15,7 @@ namespace
{ {
public: public:
PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context)
: BaseTemplate(stream), : BaseTemplate(stream, context),
m_env(context) m_env(context)
{ {
} }
@@ -87,7 +87,10 @@ std::vector<CodeTemplateFile> AssetStructTestsTemplate::GetFilesToRenderOncePerA
auto assetName = context.m_asset->m_definition->m_name; auto assetName = context.m_asset->m_definition->m_name;
utils::MakeStringLowerCase(assetName); utils::MakeStringLowerCase(assetName);
files.emplace_back(std::format("XAssets/{0}/{0}_struct_test.cpp", assetName), TAG_SOURCE); auto gameName = context.m_game;
utils::MakeStringLowerCase(gameName);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_struct_test.cpp", assetName, gameName), TAG_SOURCE);
return files; return files;
} }

View File

@@ -1,13 +1,15 @@
#include "BaseTemplate.h" #include "BaseTemplate.h"
#include "Domain/Computations/MemberComputations.h" #include "Domain/Computations/MemberComputations.h"
#include "Domain/Computations/StructureComputations.h"
#include "Domain/Definition/ArrayDeclarationModifier.h" #include "Domain/Definition/ArrayDeclarationModifier.h"
#include <sstream> #include <sstream>
BaseTemplate::BaseTemplate(std::ostream& stream) BaseTemplate::BaseTemplate(std::ostream& stream, const BaseRenderingContext& context)
: m_out(stream), : m_out(stream),
m_intendation(0u) m_intendation(0u),
m_env(context)
{ {
} }
@@ -61,13 +63,6 @@ void BaseTemplate::MakeTypeVarNameInternal(const DataDefinition* def, std::ostri
MakeSafeTypeNameInternal(def, str); MakeSafeTypeNameInternal(def, str);
} }
void BaseTemplate::MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str)
{
str << "var";
MakeSafeTypeNameInternal(def, str);
str << "Written";
}
void BaseTemplate::MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str) void BaseTemplate::MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str)
{ {
str << "var"; str << "var";
@@ -75,13 +70,6 @@ void BaseTemplate::MakeTypePtrVarNameInternal(const DataDefinition* def, std::os
str << "Ptr"; str << "Ptr";
} }
void BaseTemplate::MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str)
{
str << "var";
MakeSafeTypeNameInternal(def, str);
str << "PtrWritten";
}
void BaseTemplate::MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str) void BaseTemplate::MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str)
{ {
for (const auto index : modifierComputations.GetArrayIndices()) for (const auto index : modifierComputations.GetArrayIndices())
@@ -97,13 +85,6 @@ std::string BaseTemplate::MakeTypeVarName(const DataDefinition* def)
return str.str(); return str.str();
} }
std::string BaseTemplate::MakeTypeWrittenVarName(const DataDefinition* def)
{
std::ostringstream str;
MakeTypeWrittenVarNameInternal(def, str);
return str.str();
}
std::string BaseTemplate::MakeTypePtrVarName(const DataDefinition* def) std::string BaseTemplate::MakeTypePtrVarName(const DataDefinition* def)
{ {
std::ostringstream str; std::ostringstream str;
@@ -111,13 +92,6 @@ std::string BaseTemplate::MakeTypePtrVarName(const DataDefinition* def)
return str.str(); return str.str();
} }
std::string BaseTemplate::MakeTypeWrittenPtrVarName(const DataDefinition* def)
{
std::ostringstream str;
MakeTypeWrittenPtrVarNameInternal(def, str);
return str.str();
}
std::string BaseTemplate::MakeSafeTypeName(const DataDefinition* def) std::string BaseTemplate::MakeSafeTypeName(const DataDefinition* def)
{ {
std::ostringstream str; std::ostringstream str;
@@ -135,17 +109,6 @@ std::string BaseTemplate::MakeMemberAccess(const StructureInformation* info, con
return str.str(); return str.str();
} }
std::string
BaseTemplate::MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier)
{
std::ostringstream str;
MakeTypeWrittenVarNameInternal(info->m_definition, str);
str << "->" << member->m_member->m_name;
MakeArrayIndicesInternal(modifier, str);
return str.str();
}
std::string BaseTemplate::MakeTypeDecl(const TypeDeclaration* decl) std::string BaseTemplate::MakeTypeDecl(const TypeDeclaration* decl)
{ {
std::ostringstream str; std::ostringstream str;
@@ -299,3 +262,52 @@ std::string BaseTemplate::MakeEvaluation(const IEvaluation* evaluation)
MakeEvaluationInternal(evaluation, str); MakeEvaluationInternal(evaluation, str);
return str.str(); return str.str();
} }
bool BaseTemplate::ShouldGenerateFillMethod(const RenderingUsedType& type)
{
const auto isNotForeignAsset = type.m_is_context_asset || !type.m_info || !StructureComputations(type.m_info).IsAsset();
const auto hasMismatchingStructure = type.m_info && type.m_type == type.m_info->m_definition && !type.m_info->m_has_matching_cross_platform_structure;
const auto isEmbeddedDynamic = type.m_info && type.m_info->m_embedded_reference_exists && StructureComputations(type.m_info).GetDynamicMember();
return isNotForeignAsset && (hasMismatchingStructure || isEmbeddedDynamic);
}
size_t BaseTemplate::SizeForDeclModifierLevel(const MemberInformation& memberInfo, const size_t level) const
{
const auto& declModifiers = memberInfo.m_member->m_type_declaration->m_declaration_modifiers;
if (declModifiers.empty())
return memberInfo.m_member->m_type_declaration->GetSize();
if (level == 0)
return memberInfo.m_member->m_type_declaration->GetSize();
size_t currentSize = memberInfo.m_member->m_type_declaration->m_type->GetSize();
const auto end = declModifiers.rbegin() + (declModifiers.size() - level);
for (auto i = declModifiers.rbegin(); i != end; ++i)
{
if ((*i)->GetType() == DeclarationModifierType::POINTER)
currentSize = m_env.m_pointer_size;
else
currentSize *= dynamic_cast<ArrayDeclarationModifier*>(i->get())->m_size;
}
return currentSize;
}
size_t BaseTemplate::OffsetForMemberModifier(const MemberInformation& memberInfo,
const DeclarationModifierComputations& modifier,
const size_t nestedBaseOffset) const
{
size_t curOffset = memberInfo.m_member->m_offset;
auto curLevel = 0u;
for (const auto index : modifier.GetArrayIndices())
{
if (index > 0)
curOffset += index * SizeForDeclModifierLevel(memberInfo, curLevel + 1);
curLevel++;
}
return curOffset + nestedBaseOffset;
}

View File

@@ -5,6 +5,8 @@
#include "Domain/Evaluation/OperandDynamic.h" #include "Domain/Evaluation/OperandDynamic.h"
#include "Domain/Evaluation/OperandStatic.h" #include "Domain/Evaluation/OperandStatic.h"
#include "Domain/Evaluation/Operation.h" #include "Domain/Evaluation/Operation.h"
#include "Generating/BaseRenderingContext.h"
#include "Generating/OncePerAssetRenderingContext.h"
#include <format> #include <format>
#include <ostream> #include <ostream>
@@ -14,7 +16,7 @@ class BaseTemplate
protected: protected:
static constexpr auto INTENDATION = " "; static constexpr auto INTENDATION = " ";
explicit BaseTemplate(std::ostream& stream); explicit BaseTemplate(std::ostream& stream, const BaseRenderingContext& context);
void DoIntendation() const; void DoIntendation() const;
@@ -23,13 +25,9 @@ protected:
static std::string Upper(std::string str); static std::string Upper(std::string str);
static std::string Lower(std::string str); static std::string Lower(std::string str);
static std::string MakeTypeVarName(const DataDefinition* def); static std::string MakeTypeVarName(const DataDefinition* def);
static std::string MakeTypeWrittenVarName(const DataDefinition* def);
static std::string MakeTypePtrVarName(const DataDefinition* def); static std::string MakeTypePtrVarName(const DataDefinition* def);
static std::string MakeTypeWrittenPtrVarName(const DataDefinition* def);
static std::string MakeSafeTypeName(const DataDefinition* def); static std::string MakeSafeTypeName(const DataDefinition* def);
static std::string MakeMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier); static std::string MakeMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier);
static std::string
MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier);
static std::string MakeTypeDecl(const TypeDeclaration* decl); static std::string MakeTypeDecl(const TypeDeclaration* decl);
static std::string MakeFollowingReferences(const std::vector<DeclarationModifier*>& modifiers); static std::string MakeFollowingReferences(const std::vector<DeclarationModifier*>& modifiers);
static std::string MakeArrayIndices(const DeclarationModifierComputations& modifierComputations); static std::string MakeArrayIndices(const DeclarationModifierComputations& modifierComputations);
@@ -37,20 +35,27 @@ protected:
static std::string MakeArrayCount(const ArrayDeclarationModifier* arrayModifier); static std::string MakeArrayCount(const ArrayDeclarationModifier* arrayModifier);
static std::string MakeEvaluation(const IEvaluation* evaluation); static std::string MakeEvaluation(const IEvaluation* evaluation);
static bool ShouldGenerateFillMethod(const RenderingUsedType& type);
static void MakeSafeTypeNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str);
[[nodiscard]] size_t SizeForDeclModifierLevel(const MemberInformation& memberInfo, size_t level) const;
[[nodiscard]] size_t
OffsetForMemberModifier(const MemberInformation& memberInfo, const DeclarationModifierComputations& modifier, size_t nestedBaseOffset) const;
std::ostream& m_out; std::ostream& m_out;
unsigned m_intendation; unsigned m_intendation;
private: private:
static void MakeSafeTypeNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeTypeVarNameInternal(const DataDefinition* def, std::ostringstream& str); static void MakeTypeVarNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str); static void MakeTypePtrVarNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str);
static void MakeArrayIndicesInternal(const DeclarationModifierComputations& modifierComputations, std::ostringstream& str);
static void MakeOperandStatic(const OperandStatic* op, std::ostringstream& str); static void MakeOperandStatic(const OperandStatic* op, std::ostringstream& str);
static void MakeOperandDynamic(const OperandDynamic* op, std::ostringstream& str); static void MakeOperandDynamic(const OperandDynamic* op, std::ostringstream& str);
static void MakeOperation(const Operation* operation, std::ostringstream& str); static void MakeOperation(const Operation* operation, std::ostringstream& str);
static void MakeEvaluationInternal(const IEvaluation* evaluation, std::ostringstream& str); static void MakeEvaluationInternal(const IEvaluation* evaluation, std::ostringstream& str);
const BaseRenderingContext& m_env;
}; };
#define LINE(x) \ #define LINE(x) \

View File

@@ -12,12 +12,39 @@ namespace
{ {
constexpr int TAG_HEADER = 1; constexpr int TAG_HEADER = 1;
constexpr int TAG_SOURCE = 2; constexpr int TAG_SOURCE = 2;
constexpr int TAG_ALL_LOADERS = 3;
class PerTemplate final : BaseTemplate
{
public:
PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context)
: BaseTemplate(stream, context),
m_env(context)
{
}
void AllLoaders() const
{
AddGeneratedHint();
LINE("#pragma once")
LINE("")
for (const auto* asset : m_env.m_assets)
{
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_load_db.h\"", m_env.m_game, Lower(asset->m_definition->m_name), Lower(m_env.m_game))
}
}
private:
const OncePerTemplateRenderingContext& m_env;
};
class PerAsset final : BaseTemplate class PerAsset final : BaseTemplate
{ {
public: public:
PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context)
: BaseTemplate(stream), : BaseTemplate(stream, context),
m_env(context) m_env(context)
{ {
} }
@@ -135,7 +162,7 @@ namespace
{ {
AddGeneratedHint(); AddGeneratedHint();
LINEF("#include \"{0}_load_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINEF("#include \"{0}_{1}_load_db.h\"", Lower(m_env.m_asset->m_definition->m_name), Lower(m_env.m_game))
LINE("") LINE("")
LINEF("#include \"Game/{0}/AssetMarker{0}.h\"", m_env.m_game) LINEF("#include \"Game/{0}/AssetMarker{0}.h\"", m_env.m_game)
LINE("") LINE("")
@@ -147,7 +174,7 @@ namespace
LINE("// Referenced Assets:") LINE("// Referenced Assets:")
for (const auto* type : m_env.m_referenced_assets) for (const auto* type : m_env.m_referenced_assets)
{ {
LINEF("#include \"../{0}/{0}_load_db.h\"", Lower(type->m_type->m_name)) LINEF("#include \"../{0}/{0}_{1}_load_db.h\"", Lower(type->m_type->m_name), Lower(m_env.m_game))
} }
} }
@@ -240,16 +267,6 @@ namespace
return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def)); return std::format("{0}** var{1}Ptr;", def->GetFullName(), MakeSafeTypeName(def));
} }
bool ShouldGenerateFillMethod(const RenderingUsedType& type)
{
const auto isNotForeignAsset = type.m_is_context_asset || !type.m_info || !StructureComputations(type.m_info).IsAsset();
const auto hasMismatchingStructure =
type.m_info && type.m_type == type.m_info->m_definition && !type.m_info->m_has_matching_cross_platform_structure;
const auto isEmbeddedDynamic = type.m_info && type.m_info->m_embedded_reference_exists && StructureComputations(type.m_info).GetDynamicMember();
return isNotForeignAsset && (hasMismatchingStructure || isEmbeddedDynamic);
}
void PrintFillStructMethodDeclaration(const StructureInformation* info) const void PrintFillStructMethodDeclaration(const StructureInformation* info) const
{ {
LINEF("void FillStruct_{0}(const ZoneStreamFillReadAccessor& fillAccessor);", MakeSafeTypeName(info->m_definition)) LINEF("void FillStruct_{0}(const ZoneStreamFillReadAccessor& fillAccessor);", MakeSafeTypeName(info->m_definition))
@@ -328,7 +345,8 @@ namespace
for (const auto* type : m_env.m_used_types) 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())
{ {
PrintVariableInitialization(type->m_type); PrintVariableInitialization(type->m_type);
} }
@@ -345,47 +363,6 @@ namespace
LINE("}") 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<ArrayDeclarationModifier*>(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, void PrintFillStruct_Member_DynamicArray(const StructureInformation& structInfo,
const MemberInformation& memberInfo, const MemberInformation& memberInfo,
const DeclarationModifierComputations& modifier, const DeclarationModifierComputations& modifier,
@@ -619,7 +596,7 @@ namespace
{ {
const MemberComputations computations(&member); const MemberComputations computations(&member);
if (computations.IsFirstUsedMember()) if (computations.IsFirstUsedMember(true))
{ {
if (member.m_condition) if (member.m_condition)
{ {
@@ -637,7 +614,7 @@ namespace
PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u); PrintFillStruct_Member(structInfo, member, DeclarationModifierComputations(&member), 0u);
} }
} }
else if (computations.IsLastUsedMember()) else if (computations.IsLastUsedMember(true))
{ {
if (member.m_condition) if (member.m_condition)
{ {
@@ -691,9 +668,6 @@ namespace
} }
const auto* dynamicMember = StructureComputations(&info).GetDynamicMember(); const auto* dynamicMember = StructureComputations(&info).GetDynamicMember();
if (dynamicMember)
{
if (info.m_definition->GetType() == DataDefinitionType::UNION) if (info.m_definition->GetType() == DataDefinitionType::UNION)
{ {
for (const auto& member : info.m_ordered_members) for (const auto& member : info.m_ordered_members)
@@ -716,21 +690,10 @@ namespace
PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u); PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u);
} }
if (dynamicMember)
PrintFillStruct_Member_Condition_Struct(info, *dynamicMember); PrintFillStruct_Member_Condition_Struct(info, *dynamicMember);
} }
} }
else
{
for (const auto& member : info.m_ordered_members)
{
const MemberComputations computations(member.get());
if (computations.ShouldIgnore())
continue;
PrintFillStruct_Member(info, *member, DeclarationModifierComputations(member.get()), 0u);
}
}
}
void PrintFillStructMethod(const StructureInformation* info) void PrintFillStructMethod(const StructureInformation* info)
{ {
@@ -833,7 +796,7 @@ namespace
if (computations.ShouldIgnore()) if (computations.ShouldIgnore())
continue; continue;
if (computations.IsFirstUsedMember()) if (computations.IsFirstUsedMember(false))
{ {
LINE("") LINE("")
if (member->m_condition) if (member->m_condition)
@@ -852,7 +815,7 @@ namespace
PrintDynamicOversize_DynamicMember(info, *member); PrintDynamicOversize_DynamicMember(info, *member);
} }
} }
else if (computations.IsLastUsedMember()) else if (computations.IsLastUsedMember(false))
{ {
if (member->m_condition) if (member->m_condition)
{ {
@@ -1811,7 +1774,7 @@ namespace
{ {
const MemberComputations computations(member); const MemberComputations computations(member);
if (computations.IsFirstUsedMember()) if (computations.IsFirstUsedMember(false))
{ {
LINE("") LINE("")
if (member->m_condition) if (member->m_condition)
@@ -1830,7 +1793,7 @@ namespace
LoadMember_Reference(info, member, DeclarationModifierComputations(member)); LoadMember_Reference(info, member, DeclarationModifierComputations(member));
} }
} }
else if (computations.IsLastUsedMember()) else if (computations.IsLastUsedMember(false))
{ {
if (member->m_condition) if (member->m_condition)
{ {
@@ -2192,6 +2155,23 @@ namespace
}; };
} // namespace } // namespace
std::vector<CodeTemplateFile> ZoneLoadTemplate::GetFilesToRenderOncePerTemplate(const OncePerTemplateRenderingContext& context)
{
std::vector<CodeTemplateFile> files;
files.emplace_back(std::format("AssetLoader{0}.h", context.m_game), TAG_ALL_LOADERS);
return files;
}
void ZoneLoadTemplate::RenderOncePerTemplateFile(std::ostream& stream, const CodeTemplateFileTag fileTag, const OncePerTemplateRenderingContext& context)
{
assert(fileTag == TAG_ALL_LOADERS);
const PerTemplate t(stream, context);
t.AllLoaders();
}
std::vector<CodeTemplateFile> ZoneLoadTemplate::GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) std::vector<CodeTemplateFile> ZoneLoadTemplate::GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context)
{ {
std::vector<CodeTemplateFile> files; std::vector<CodeTemplateFile> files;
@@ -2199,8 +2179,11 @@ std::vector<CodeTemplateFile> ZoneLoadTemplate::GetFilesToRenderOncePerAsset(con
auto assetName = context.m_asset->m_definition->m_name; auto assetName = context.m_asset->m_definition->m_name;
utils::MakeStringLowerCase(assetName); utils::MakeStringLowerCase(assetName);
files.emplace_back(std::format("XAssets/{0}/{0}_load_db.h", assetName), TAG_HEADER); auto gameName = context.m_game;
files.emplace_back(std::format("XAssets/{0}/{0}_load_db.cpp", assetName), TAG_SOURCE); utils::MakeStringLowerCase(gameName);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_load_db.h", assetName, gameName), TAG_HEADER);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_load_db.cpp", assetName, gameName), TAG_SOURCE);
return files; return files;
} }

View File

@@ -5,6 +5,9 @@
class ZoneLoadTemplate final : public ICodeTemplate class ZoneLoadTemplate final : public ICodeTemplate
{ {
public: public:
std::vector<CodeTemplateFile> GetFilesToRenderOncePerTemplate(const OncePerTemplateRenderingContext& context) override;
void RenderOncePerTemplateFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerTemplateRenderingContext& context) override;
std::vector<CodeTemplateFile> GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) override; std::vector<CodeTemplateFile> GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) override;
void RenderOncePerAssetFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerAssetRenderingContext& context) override; void RenderOncePerAssetFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerAssetRenderingContext& context) override;
}; };

View File

@@ -18,7 +18,7 @@ namespace
{ {
public: public:
PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context) PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context)
: BaseTemplate(stream), : BaseTemplate(stream, context),
m_env(context) m_env(context)
{ {
} }
@@ -32,10 +32,7 @@ namespace
for (const auto* asset : m_env.m_assets) for (const auto* asset : m_env.m_assets)
{ {
auto lowerAssetName = asset->m_definition->m_name; LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_mark_db.h\"", m_env.m_game, Lower(asset->m_definition->m_name), Lower(m_env.m_game))
utils::MakeStringLowerCase(lowerAssetName);
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_mark_db.h\"", m_env.m_game, lowerAssetName)
} }
} }
@@ -47,7 +44,7 @@ namespace
{ {
public: public:
PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context)
: BaseTemplate(stream), : BaseTemplate(stream, context),
m_env(context) m_env(context)
{ {
} }
@@ -142,7 +139,7 @@ namespace
{ {
AddGeneratedHint(); AddGeneratedHint();
LINEF("#include \"{0}_mark_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINEF("#include \"{0}_{1}_mark_db.h\"", Lower(m_env.m_asset->m_definition->m_name), Lower(m_env.m_game))
if (!m_env.m_referenced_assets.empty()) if (!m_env.m_referenced_assets.empty())
{ {
@@ -150,7 +147,7 @@ namespace
LINE("// Referenced Assets:") LINE("// Referenced Assets:")
for (const auto* type : m_env.m_referenced_assets) for (const auto* type : m_env.m_referenced_assets)
{ {
LINEF("#include \"../{0}/{0}_mark_db.h\"", Lower(type->m_type->m_name)) LINEF("#include \"../{0}/{0}_{1}_mark_db.h\"", Lower(type->m_type->m_name), Lower(m_env.m_game))
} }
} }
LINE("") LINE("")
@@ -673,7 +670,7 @@ namespace
{ {
const MemberComputations computations(member); const MemberComputations computations(member);
if (computations.IsFirstUsedMember()) if (computations.IsFirstUsedMember(false))
{ {
LINE("") LINE("")
if (member->m_condition) if (member->m_condition)
@@ -692,7 +689,7 @@ namespace
MarkMember_Reference(info, member, DeclarationModifierComputations(member)); MarkMember_Reference(info, member, DeclarationModifierComputations(member));
} }
} }
else if (computations.IsLastUsedMember()) else if (computations.IsLastUsedMember(false))
{ {
if (member->m_condition) if (member->m_condition)
{ {
@@ -802,7 +799,7 @@ void ZoneMarkTemplate::RenderOncePerTemplateFile(std::ostream& stream, const Cod
{ {
assert(fileTag == TAG_ALL_MARKERS); assert(fileTag == TAG_ALL_MARKERS);
PerTemplate t(stream, context); const PerTemplate t(stream, context);
t.AllMarkers(); t.AllMarkers();
} }
@@ -813,8 +810,11 @@ std::vector<CodeTemplateFile> ZoneMarkTemplate::GetFilesToRenderOncePerAsset(con
auto assetName = context.m_asset->m_definition->m_name; auto assetName = context.m_asset->m_definition->m_name;
utils::MakeStringLowerCase(assetName); utils::MakeStringLowerCase(assetName);
files.emplace_back(std::format("XAssets/{0}/{0}_mark_db.h", assetName), TAG_HEADER); auto gameName = context.m_game;
files.emplace_back(std::format("XAssets/{0}/{0}_mark_db.cpp", assetName), TAG_SOURCE); utils::MakeStringLowerCase(gameName);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_mark_db.h", assetName, gameName), TAG_HEADER);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_mark_db.cpp", assetName, gameName), TAG_SOURCE);
return files; return files;
} }

View File

@@ -2,6 +2,7 @@
#include "Domain/Computations/StructureComputations.h" #include "Domain/Computations/StructureComputations.h"
#include "Internal/BaseTemplate.h" #include "Internal/BaseTemplate.h"
#include "Utils/StringUtils.h"
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
@@ -11,12 +12,39 @@ namespace
{ {
constexpr CodeTemplateFileTag TAG_HEADER = 1; constexpr CodeTemplateFileTag TAG_HEADER = 1;
constexpr CodeTemplateFileTag TAG_SOURCE = 2; constexpr CodeTemplateFileTag TAG_SOURCE = 2;
constexpr CodeTemplateFileTag TAG_ALL_WRITERS = 3;
class PerTemplate final : BaseTemplate
{
public:
PerTemplate(std::ostream& stream, const OncePerTemplateRenderingContext& context)
: BaseTemplate(stream, context),
m_env(context)
{
}
void AllWriters() const
{
AddGeneratedHint();
LINE("#pragma once")
LINE("")
for (const auto* asset : m_env.m_assets)
{
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_write_db.h\"", m_env.m_game, Lower(asset->m_definition->m_name), Lower(m_env.m_game))
}
}
private:
const OncePerTemplateRenderingContext& m_env;
};
class PerAsset final : BaseTemplate class PerAsset final : BaseTemplate
{ {
public: public:
PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context) PerAsset(std::ostream& stream, const OncePerAssetRenderingContext& context)
: BaseTemplate(stream), : BaseTemplate(stream, context),
m_env(context) m_env(context)
{ {
} }
@@ -51,6 +79,16 @@ namespace
m_intendation++; m_intendation++;
// Method Declarations // Method Declarations
if (m_env.m_architecture_mismatch)
{
for (const auto* type : m_env.m_used_types)
{
if (ShouldGenerateFillMethod(*type))
{
PrintFillStructMethodDeclaration(type->m_info);
}
}
}
for (const auto* type : m_env.m_used_types) for (const auto* type : m_env.m_used_types)
{ {
if (type->m_pointer_array_reference_exists) if (type->m_pointer_array_reference_exists)
@@ -78,27 +116,35 @@ namespace
LINE("") LINE("")
LINE(VariableDecl(m_env.m_asset->m_definition)) LINE(VariableDecl(m_env.m_asset->m_definition))
LINE(WrittenVariableDecl(m_env.m_asset->m_definition))
LINE(PointerVariableDecl(m_env.m_asset->m_definition)) LINE(PointerVariableDecl(m_env.m_asset->m_definition))
LINE(WrittenVariableDecl(m_env.m_asset->m_definition))
LINE(WrittenPointerVariableDecl(m_env.m_asset->m_definition)) LINE(WrittenPointerVariableDecl(m_env.m_asset->m_definition))
LINE("") LINE("")
// Variable Declarations: type varType; // Variable Declarations: type varType;
for (const auto* type : m_env.m_used_types) 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)) LINE(VariableDecl(type->m_type))
LINE(WrittenVariableDecl(type->m_type))
}
} }
for (const auto* type : m_env.m_used_types) for (const auto* type : m_env.m_used_types)
{ {
if (type->m_pointer_array_reference_exists && !type->m_is_context_asset) if (type->m_pointer_array_reference_exists && !type->m_is_context_asset)
{
LINE(PointerVariableDecl(type->m_type)) LINE(PointerVariableDecl(type->m_type))
LINE(WrittenPointerVariableDecl(type->m_type))
} }
LINE("")
for (const auto* type : m_env.m_used_types)
{
if (type->m_info && !type->m_info->m_definition->m_anonymous && !type->m_info->m_is_leaf && !StructureComputations(type->m_info).IsAsset())
LINE(WrittenVariableDecl(type->m_type))
}
for (const auto* type : m_env.m_used_types)
{
if (type->m_pointer_array_reference_exists && !type->m_is_context_asset)
LINE(WrittenPointerVariableDecl(type->m_type))
} }
m_intendation--; m_intendation--;
@@ -111,7 +157,7 @@ namespace
{ {
AddGeneratedHint(); AddGeneratedHint();
LINEF("#include \"{0}_write_db.h\"", Lower(m_env.m_asset->m_definition->m_name)) LINEF("#include \"{0}_{1}_write_db.h\"", Lower(m_env.m_asset->m_definition->m_name), Lower(m_env.m_game))
if (!m_env.m_referenced_assets.empty()) if (!m_env.m_referenced_assets.empty())
{ {
@@ -119,7 +165,7 @@ namespace
LINE("// Referenced Assets:") LINE("// Referenced Assets:")
for (const auto* type : m_env.m_referenced_assets) for (const auto* type : m_env.m_referenced_assets)
{ {
LINEF("#include \"../{0}/{0}_write_db.h\"", Lower(type->m_type->m_name)) LINEF("#include \"../{0}/{0}_{1}_write_db.h\"", Lower(type->m_type->m_name), Lower(m_env.m_game))
} }
} }
@@ -132,6 +178,17 @@ namespace
LINE("") LINE("")
PrintMainWriteMethod(); PrintMainWriteMethod();
if (m_env.m_architecture_mismatch)
{
for (const auto* type : m_env.m_used_types)
{
if (ShouldGenerateFillMethod(*type))
{
LINE("")
PrintFillStructMethod(type->m_info);
}
}
}
for (const auto* type : m_env.m_used_types) for (const auto* type : m_env.m_used_types)
{ {
if (type->m_pointer_array_reference_exists) if (type->m_pointer_array_reference_exists)
@@ -185,7 +242,7 @@ namespace
static std::string WrittenVariableDecl(const DataDefinition* def) static std::string WrittenVariableDecl(const DataDefinition* def)
{ {
return std::format("{0}* var{1}Written;", def->GetFullName(), MakeSafeTypeName(def)); return std::format("ZoneOutputOffset var{0}Written;", MakeSafeTypeName(def));
} }
static std::string PointerVariableDecl(const DataDefinition* def) static std::string PointerVariableDecl(const DataDefinition* def)
@@ -195,7 +252,12 @@ namespace
static std::string WrittenPointerVariableDecl(const DataDefinition* def) static std::string WrittenPointerVariableDecl(const DataDefinition* def)
{ {
return std::format("{0}** var{1}PtrWritten;", def->GetFullName(), MakeSafeTypeName(def)); return std::format("ZoneOutputOffset var{0}PtrWritten;", MakeSafeTypeName(def));
}
void PrintFillStructMethodDeclaration(const StructureInformation* info) const
{
LINEF("void FillStruct_{0}(const ZoneStreamFillWriteAccessor& fillAccessor);", MakeSafeTypeName(info->m_definition))
} }
void PrintHeaderPtrArrayWriteMethodDeclaration(const DataDefinition* def) const void PrintHeaderPtrArrayWriteMethodDeclaration(const DataDefinition* def) const
@@ -220,12 +282,12 @@ namespace
void PrintHeaderMainWriteMethodDeclaration(const StructureInformation* info) const void PrintHeaderMainWriteMethodDeclaration(const StructureInformation* info) const
{ {
LINEF("void Write({0}** pAsset);", info->m_definition->GetFullName()) LINEF("void Write({0}* pAsset, ZoneOutputOffset pointerWrittenOffset);", info->m_definition->GetFullName())
} }
void PrintHeaderConstructor() const void PrintHeaderConstructor() const
{ {
LINEF("{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream);", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) LINEF("{0}({1}* asset, const Zone& zone, ZoneOutputStream& stream);", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName())
} }
void PrintVariableInitialization(const DataDefinition* def) const void PrintVariableInitialization(const DataDefinition* def) const
@@ -233,25 +295,66 @@ namespace
LINEF("var{0} = nullptr;", def->m_name) LINEF("var{0} = nullptr;", def->m_name)
} }
void PrintWrittenVariableInitialization(const DataDefinition* def) const
{
LINEF("var{0}Written = nullptr;", def->m_name)
}
void PrintPointerVariableInitialization(const DataDefinition* def) const void PrintPointerVariableInitialization(const DataDefinition* def) const
{ {
LINEF("var{0}Ptr = nullptr;", def->m_name) LINEF("var{0}Ptr = nullptr;", def->m_name)
} }
void PrintWrittenPointerVariableInitialization(const DataDefinition* def) const static void MakeTypeWrittenPtrVarNameInternal(const DataDefinition* def, std::ostringstream& str)
{ {
LINEF("var{0}PtrWritten = nullptr;", def->m_name) str << "var";
MakeSafeTypeNameInternal(def, str);
str << "PtrWritten";
}
static void MakeTypeWrittenVarNameInternal(const DataDefinition* def, std::ostringstream& str)
{
str << "var";
MakeSafeTypeNameInternal(def, str);
str << "Written";
}
static std::string MakeTypeWrittenVarName(const DataDefinition* def)
{
std::ostringstream str;
MakeTypeWrittenVarNameInternal(def, str);
return str.str();
}
static std::string MakeTypeWrittenPtrVarName(const DataDefinition* def)
{
std::ostringstream str;
MakeTypeWrittenPtrVarNameInternal(def, str);
return str.str();
}
std::string
MakeWrittenMemberAccess(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const
{
std::ostringstream str;
MakeTypeWrittenVarNameInternal(info->m_definition, str);
str << ".AtOffset(";
if (m_env.m_architecture_mismatch)
{
str << OffsetForMemberModifier(*member, modifier, 0);
}
else
{
str << "offsetof(" << info->m_definition->GetFullName() << ", " << member->m_member->m_name;
MakeArrayIndicesInternal(modifier, str);
str << ')';
}
str << ')';
return str.str();
} }
void PrintConstructorMethod() void PrintConstructorMethod()
{ {
LINEF( LINEF(
"{0}::{0}({1}* asset, const Zone& zone, IZoneOutputStream& stream)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) "{0}::{0}({1}* asset, const Zone& zone, ZoneOutputStream& stream)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName())
m_intendation++; m_intendation++;
LINEF(": AssetWriter(zone.m_pools->GetAssetOrAssetReference({0}::EnumEntry, NonReferenceAssetName(AssetName<{0}>(*asset))), zone, stream)", LINEF(": AssetWriter(zone.m_pools->GetAssetOrAssetReference({0}::EnumEntry, NonReferenceAssetName(AssetName<{0}>(*asset))), zone, stream)",
@@ -262,26 +365,19 @@ namespace
m_intendation++; m_intendation++;
PrintVariableInitialization(m_env.m_asset->m_definition); PrintVariableInitialization(m_env.m_asset->m_definition);
PrintWrittenVariableInitialization(m_env.m_asset->m_definition);
PrintPointerVariableInitialization(m_env.m_asset->m_definition); PrintPointerVariableInitialization(m_env.m_asset->m_definition);
PrintWrittenPointerVariableInitialization(m_env.m_asset->m_definition);
LINE("") LINE("")
for (const auto* type : m_env.m_used_types) 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())
PrintVariableInitialization(type->m_type); PrintVariableInitialization(type->m_type);
PrintWrittenVariableInitialization(type->m_type);
}
} }
for (const auto* type : m_env.m_used_types) for (const auto* type : m_env.m_used_types)
{ {
if (type->m_info && type->m_pointer_array_reference_exists && !type->m_is_context_asset) if (type->m_info && type->m_pointer_array_reference_exists && !type->m_is_context_asset)
{
PrintPointerVariableInitialization(type->m_type); PrintPointerVariableInitialization(type->m_type);
PrintWrittenPointerVariableInitialization(type->m_type);
}
} }
m_intendation--; m_intendation--;
@@ -301,12 +397,13 @@ namespace
} }
else if (writeType == MemberWriteType::EMBEDDED_ARRAY) else if (writeType == MemberWriteType::EMBEDDED_ARRAY)
{ {
LINEF("varScriptString = {0};", MakeMemberAccess(info, member, modifier))
LINEF("varScriptStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("varScriptStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier))
LINEF("WriteScriptStringArray(false, {0});", MakeArrayCount(dynamic_cast<ArrayDeclarationModifier*>(modifier.GetDeclarationModifier()))) LINEF("WriteScriptStringArray(false, {0});", MakeArrayCount(dynamic_cast<ArrayDeclarationModifier*>(modifier.GetDeclarationModifier())))
} }
else if (writeType == MemberWriteType::EMBEDDED) else if (writeType == MemberWriteType::EMBEDDED)
{ {
LINEF("{0} = UseScriptString({1});", MakeWrittenMemberAccess(info, member, modifier), MakeMemberAccess(info, member, modifier)) LINEF("UseScriptString({0}, {1});", MakeMemberAccess(info, member, modifier), MakeWrittenMemberAccess(info, member, modifier))
} }
else else
{ {
@@ -323,7 +420,7 @@ namespace
if (writeType == MemberWriteType::SINGLE_POINTER) if (writeType == MemberWriteType::SINGLE_POINTER)
{ {
LINEF("{0} writer({1}, m_zone, *m_stream);", WriterClassName(member->m_type), MakeMemberAccess(info, member, modifier)) LINEF("{0} writer({1}, m_zone, *m_stream);", WriterClassName(member->m_type), MakeMemberAccess(info, member, modifier))
LINEF("writer.Write(&{0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("writer.Write({0}, {1});", MakeMemberAccess(info, member, modifier), MakeWrittenMemberAccess(info, member, modifier))
} }
else if (writeType == MemberWriteType::POINTER_ARRAY) else if (writeType == MemberWriteType::POINTER_ARRAY)
{ {
@@ -345,18 +442,20 @@ namespace
{ {
if (member->m_member->m_type_declaration->m_is_const) if (member->m_member->m_type_declaration->m_is_const)
{ {
LINEF("varXStringWritten = &{0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("varXString = &{0};", MakeMemberAccess(info, member, modifier))
} }
else else
{ {
LINEF("varXStringWritten = const_cast<const char**>(&{0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("varXString = const_cast<const char**>(&{0});", MakeMemberAccess(info, member, modifier))
} }
LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier))
LINE("WriteXString(false);") LINE("WriteXString(false);")
} }
else if (writeType == MemberWriteType::POINTER_ARRAY) else if (writeType == MemberWriteType::POINTER_ARRAY)
{ {
if (modifier.IsArray()) if (modifier.IsArray())
{ {
LINEF("varXString = {0};", MakeMemberAccess(info, member, modifier))
LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier)) LINEF("varXStringWritten = {0};", MakeWrittenMemberAccess(info, member, modifier))
LINEF("WriteXStringArray(false, {0});", modifier.GetArraySize()) LINEF("WriteXStringArray(false, {0});", modifier.GetArraySize())
} }
@@ -374,7 +473,7 @@ namespace
} }
} }
void WriteMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier) const void WriteMember_ArrayPointer(const StructureInformation* info, const MemberInformation* member, const DeclarationModifierComputations& modifier)
{ {
const MemberComputations computations(member); const MemberComputations computations(member);
LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier)) LINEF("m_stream->MarkFollowing({0});", MakeWrittenMemberAccess(info, member, modifier))
@@ -385,6 +484,27 @@ namespace
MakeSafeTypeName(member->m_member->m_type_declaration->m_type), MakeSafeTypeName(member->m_member->m_type_declaration->m_type),
MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
} }
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
{
LINEF("const auto fillArraySize = static_cast<size_t>({0});", MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
if (!computations.IsInRuntimeBlock())
{
LINEF("const auto fill = m_stream->WriteWithFill({0} * fillArraySize);", member->m_member->m_type_declaration->m_type->GetSize())
LINE("for (auto i = 0uz; i < fillArraySize; i++)")
LINE("{")
m_intendation++;
LINEF("{0} = &{1}[i];", MakeTypeVarName(member->m_type->m_definition), MakeMemberAccess(info, member, modifier))
LINEF("FillStruct_{0}(fill.AtOffset(i * {1}));",
MakeSafeTypeName(member->m_type->m_definition),
member->m_member->m_type_declaration->m_type->GetSize())
m_intendation--;
LINE("}")
}
else
{
LINEF("m_stream->IncBlockPos({0} * fillArraySize);", member->m_member->m_type_declaration->m_type->GetSize())
}
}
else else
{ {
LINEF("m_stream->Write<{0}{1}>({2}, {3});", LINEF("m_stream->Write<{0}{1}>({2}, {3});",
@@ -479,7 +599,7 @@ namespace
else else
{ {
LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("{0} = &{1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
LINEF("{0} = &{1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier)) LINEF("{0} = {1};", MakeTypeWrittenVarName(member->m_member->m_type_declaration->m_type), MakeWrittenMemberAccess(info, member, modifier))
LINEF("Write_{0}(false);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type)) LINEF("Write_{0}(false);", MakeSafeTypeName(member->m_member->m_type_declaration->m_type))
} }
} }
@@ -501,6 +621,13 @@ namespace
LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier)) LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
LINEF("Write_{0}(true);", MakeSafeTypeName(member->m_type->m_definition)) LINEF("Write_{0}(true);", MakeSafeTypeName(member->m_type->m_definition))
} }
else if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
{
LINEF("{0} = {1};", MakeTypeVarName(member->m_member->m_type_declaration->m_type), MakeMemberAccess(info, member, modifier))
LINEF("FillStruct_{0}(m_stream->WriteWithFill({1}));",
MakeSafeTypeName(member->m_member->m_type_declaration->m_type),
member->m_member->m_type_declaration->m_type->GetSize())
}
else else
{ {
LINEF("m_stream->Write<{0}{1}>({2});", LINEF("m_stream->Write<{0}{1}>({2});",
@@ -513,7 +640,7 @@ namespace
void WriteMember_TypeCheck(const StructureInformation* info, void WriteMember_TypeCheck(const StructureInformation* info,
const MemberInformation* member, const MemberInformation* member,
const DeclarationModifierComputations& modifier, const DeclarationModifierComputations& modifier,
const MemberWriteType writeType) const const MemberWriteType writeType)
{ {
if (member->m_is_string) if (member->m_is_string)
{ {
@@ -597,7 +724,7 @@ namespace
void WriteMember_InsertReuse(const StructureInformation* info, void WriteMember_InsertReuse(const StructureInformation* info,
const MemberInformation* member, const MemberInformation* member,
const DeclarationModifierComputations& modifier, const DeclarationModifierComputations& modifier,
const MemberWriteType writeType) const const MemberWriteType writeType)
{ {
if (!WriteMember_ShouldMakeInsertReuse(member, modifier, writeType)) if (!WriteMember_ShouldMakeInsertReuse(member, modifier, writeType))
{ {
@@ -605,31 +732,37 @@ namespace
return; return;
} }
LINE_STARTF("m_stream->ReusableAddOffset({0}", MakeMemberAccess(info, member, modifier))
if (writeType == MemberWriteType::ARRAY_POINTER) if (writeType == MemberWriteType::ARRAY_POINTER)
{ {
LINEF("m_stream->ReusableAddOffset({0}, {1});", if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
MakeMemberAccess(info, member, modifier), {
MakeEvaluation(modifier.GetArrayPointerCountEvaluation())) LINE_MIDDLEF(", {0}", member->m_type->m_definition->GetSize())
}
LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetArrayPointerCountEvaluation()))
} }
else if (writeType == MemberWriteType::POINTER_ARRAY) else if (writeType == MemberWriteType::POINTER_ARRAY)
{ {
if (member->m_type && !member->m_type->m_has_matching_cross_platform_structure)
{
LINE_MIDDLEF(", {0}", m_env.m_pointer_size)
}
const auto* evaluation = modifier.GetPointerArrayCountEvaluation(); const auto* evaluation = modifier.GetPointerArrayCountEvaluation();
if (evaluation) if (evaluation)
{ {
LINEF("m_stream->ReusableAddOffset({0}, {1});", LINE_MIDDLEF(", {0}", MakeEvaluation(modifier.GetPointerArrayCountEvaluation()))
MakeMemberAccess(info, member, modifier),
MakeEvaluation(modifier.GetPointerArrayCountEvaluation()))
} }
else else
{ {
LINEF("m_stream->ReusableAddOffset({0}, {1});", MakeMemberAccess(info, member, modifier), modifier.GetArraySize()) LINE_MIDDLEF(", {0}", modifier.GetArraySize())
} }
} }
else
{ LINE_END(");")
LINEF("m_stream->ReusableAddOffset({0});", MakeMemberAccess(info, member, modifier))
}
WriteMember_TypeCheck(info, member, modifier, writeType); WriteMember_TypeCheck(info, member, modifier, writeType);
} }
@@ -663,7 +796,7 @@ namespace
void WriteMember_Align(const StructureInformation* info, void WriteMember_Align(const StructureInformation* info,
const MemberInformation* member, const MemberInformation* member,
const DeclarationModifierComputations& modifier, const DeclarationModifierComputations& modifier,
const MemberWriteType writeType) const const MemberWriteType writeType)
{ {
if (!WriteMember_ShouldMakeAlign(member, modifier, writeType)) if (!WriteMember_ShouldMakeAlign(member, modifier, writeType))
{ {
@@ -702,6 +835,14 @@ namespace
return member->m_is_reusable; return member->m_is_reusable;
} }
std::string MakeReusableInnerOffset(const DataDefinition* dataDefinition, const Variable* member) const
{
if (m_env.m_architecture_mismatch)
return std::to_string(member->m_offset);
return std::format("offsetof({0}, {1})", dataDefinition->GetFullName(), member->m_name);
}
void WriteMember_Reuse(const StructureInformation* info, void WriteMember_Reuse(const StructureInformation* info,
const MemberInformation* member, const MemberInformation* member,
const DeclarationModifierComputations& modifier, const DeclarationModifierComputations& modifier,
@@ -713,7 +854,10 @@ namespace
return; return;
} }
LINEF("if (m_stream->ReusableShouldWrite(&{0}))", MakeWrittenMemberAccess(info, member, modifier)) LINEF("if (m_stream->ReusableShouldWrite({0}, {1}.AtOffset({2})))",
MakeMemberAccess(info, member, modifier),
MakeTypeWrittenVarName(info->m_definition),
MakeReusableInnerOffset(info->m_definition, member->m_member))
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -867,7 +1011,7 @@ namespace
{ {
const MemberComputations computations(member); const MemberComputations computations(member);
if (computations.IsFirstUsedMember()) if (computations.IsFirstUsedMember(false))
{ {
LINE("") LINE("")
if (member->m_condition) if (member->m_condition)
@@ -886,7 +1030,7 @@ namespace
WriteMember_Reference(info, member, DeclarationModifierComputations(member)); WriteMember_Reference(info, member, DeclarationModifierComputations(member));
} }
} }
else if (computations.IsLastUsedMember()) else if (computations.IsLastUsedMember(false))
{ {
if (member->m_condition) if (member->m_condition)
{ {
@@ -961,8 +1105,10 @@ namespace
if (!(info->m_definition->GetType() == DataDefinitionType::UNION && dynamicMember)) if (!(info->m_definition->GetType() == DataDefinitionType::UNION && dynamicMember))
{ {
LINE("if (atStreamStart)") LINE("if (atStreamStart)")
m_intendation++;
if (info->m_has_matching_cross_platform_structure)
{
m_intendation++;
if (dynamicMember == nullptr) if (dynamicMember == nullptr)
{ {
LINEF("{0} = m_stream->Write<{1}>({2}); // Size: {3}", LINEF("{0} = m_stream->Write<{1}>({2}); // Size: {3}",
@@ -973,17 +1119,28 @@ namespace
} }
else else
{ {
LINEF("{0} = m_stream->WritePartial<{1}>({2}, offsetof({1}, {3}));", LINEF("{0} = m_stream->WritePartial({1}, offsetof({2}, {3}));",
MakeTypeWrittenVarName(info->m_definition), MakeTypeWrittenVarName(info->m_definition),
info->m_definition->GetFullName(),
MakeTypeVarName(info->m_definition), MakeTypeVarName(info->m_definition),
info->m_definition->GetFullName(),
dynamicMember->m_member->m_name) dynamicMember->m_member->m_name)
} }
m_intendation--; m_intendation--;
}
else
{
LINE("{")
m_intendation++;
LINEF("const auto fillAccessor = m_stream->WriteWithFill({0});",
dynamicMember == nullptr ? info->m_definition->GetSize() : dynamicMember->m_member->m_offset)
LINEF("{0} = fillAccessor.Offset();", MakeTypeWrittenVarName(info->m_definition))
LINEF("FillStruct_{0}(fillAccessor);", MakeSafeTypeName(info->m_definition))
m_intendation--;
LINE("}")
}
LINE("") LINE("")
LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(info->m_definition)) LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenVarName(info->m_definition))
} }
else else
{ {
@@ -1028,14 +1185,11 @@ namespace
LINE("if (atStreamStart)") LINE("if (atStreamStart)")
m_intendation++; m_intendation++;
LINEF("{0} = m_stream->Write<{1}*>({2});", LINEF("{0} = m_stream->WriteWithFill(m_stream->GetPointerByteCount()).Offset();", MakeTypeWrittenPtrVarName(info->m_definition))
MakeTypeWrittenPtrVarName(info->m_definition),
info->m_definition->GetFullName(),
MakeTypePtrVarName(info->m_definition))
m_intendation--; m_intendation--;
LINE("") LINE("")
LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(info->m_definition)) LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenPtrVarName(info->m_definition))
LINE("") LINE("")
if (inTemp) if (inTemp)
@@ -1043,7 +1197,7 @@ namespace
LINEF("m_stream->PushBlock({0});", m_env.m_default_temp_block->m_name) LINEF("m_stream->PushBlock({0});", m_env.m_default_temp_block->m_name)
LINE("") LINE("")
} }
LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(info->m_definition)) LINEF("if (m_stream->ReusableShouldWrite(*{0}, {1}))", MakeTypePtrVarName(info->m_definition), MakeTypeWrittenPtrVarName(info->m_definition))
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -1061,7 +1215,7 @@ namespace
} }
LINE("") LINE("")
LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(info->m_definition)) LINEF("m_stream->MarkFollowing({0});", MakeTypeWrittenPtrVarName(info->m_definition))
m_intendation--; m_intendation--;
LINE("}") LINE("}")
@@ -1078,7 +1232,9 @@ namespace
void PrintMainWriteMethod() void PrintMainWriteMethod()
{ {
LINEF("void {0}::Write({1}** pAsset)", WriterClassName(m_env.m_asset), m_env.m_asset->m_definition->GetFullName()) LINEF("void {0}::Write({1}* pAsset, const ZoneOutputOffset pointerWrittenOffset)",
WriterClassName(m_env.m_asset),
m_env.m_asset->m_definition->GetFullName())
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -1088,9 +1244,233 @@ namespace
LINE("") LINE("")
LINEF("auto* zoneAsset = static_cast<{0}*>(m_asset->m_ptr);", m_env.m_asset->m_definition->GetFullName()) LINEF("auto* zoneAsset = static_cast<{0}*>(m_asset->m_ptr);", m_env.m_asset->m_definition->GetFullName())
LINEF("{0} = &zoneAsset;", MakeTypePtrVarName(m_env.m_asset->m_definition)) LINEF("{0} = &zoneAsset;", MakeTypePtrVarName(m_env.m_asset->m_definition))
LINEF("{0} = &zoneAsset;", MakeTypeWrittenPtrVarName(m_env.m_asset->m_definition)) LINEF("{0} = pointerWrittenOffset;", MakeTypeWrittenPtrVarName(m_env.m_asset->m_definition))
LINEF("WritePtr_{0}(false);", MakeSafeTypeName(m_env.m_asset->m_definition)) LINEF("WritePtr_{0}(false);", MakeSafeTypeName(m_env.m_asset->m_definition))
LINE("*pAsset = zoneAsset;")
m_intendation--;
LINE("}")
}
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<decltype({0}::{1})>; 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)
{
const auto hasMismatchingStructure = memberInfo.m_type && !memberInfo.m_type->m_has_matching_cross_platform_structure;
const auto hasDynamicMember = memberInfo.m_type && StructureComputations(memberInfo.m_type).GetDynamicMember();
if (hasMismatchingStructure || hasDynamicMember)
{
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);
}
}
static bool ShouldFillMember(const DeclarationModifierComputations& modifier)
{
return !modifier.HasPointerModifier();
}
// nestedBaseOffset: Base offset in case member is part of a nested anonymous sub-struct
void PrintFillStruct_Member(const StructureInformation& structInfo,
const MemberInformation& memberInfo,
const DeclarationModifierComputations& modifier,
const size_t nestedBaseOffset)
{
if (!ShouldFillMember(modifier))
return;
if (modifier.IsDynamicArray())
{
}
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_Member_Condition_Union(const StructureInformation& structInfo,
const MemberInformation& member,
const DeclarationModifierComputations& modifier)
{
const MemberComputations computations(&member);
if (computations.IsFirstUsedMember(true))
{
if (member.m_condition)
{
LINEF("if ({0})", MakeEvaluation(member.m_condition.get()))
LINE("{")
m_intendation++;
PrintFillStruct_Member(structInfo, member, modifier, 0u);
m_intendation--;
LINE("}")
}
else
{
PrintFillStruct_Member(structInfo, member, modifier, 0u);
}
}
else if (computations.IsLastUsedMember(true))
{
if (member.m_condition)
{
LINEF("else if ({0})", MakeEvaluation(member.m_condition.get()))
LINE("{")
m_intendation++;
PrintFillStruct_Member(structInfo, member, modifier, 0u);
m_intendation--;
LINE("}")
}
else
{
LINE("else")
LINE("{")
m_intendation++;
PrintFillStruct_Member(structInfo, member, modifier, 0u);
m_intendation--;
LINE("}")
}
}
else
{
if (member.m_condition)
{
LINEF("else if ({0})", MakeEvaluation(member.m_condition.get()))
LINE("{")
m_intendation++;
PrintFillStruct_Member(structInfo, member, modifier, 0u);
m_intendation--;
LINE("}")
}
else
{
LINEF("#error Middle member of union2 must have condition ({0})", member.m_member->m_name)
}
}
}
void PrintFillStruct_Struct(const StructureInformation& info)
{
const auto* dynamicMember = StructureComputations(&info).GetDynamicMember();
if (info.m_definition->GetType() == DataDefinitionType::UNION)
{
for (const auto& member : info.m_ordered_members)
{
const MemberComputations computations(member.get());
if (computations.ShouldIgnore())
continue;
DeclarationModifierComputations modifier(member.get());
PrintFillStruct_Member_Condition_Union(info, *member, modifier);
}
}
else
{
for (const auto& member : info.m_ordered_members)
{
const MemberComputations computations(member.get());
if (computations.ShouldIgnore() || member.get() == dynamicMember)
continue;
DeclarationModifierComputations modifier(member.get());
PrintFillStruct_Member(info, *member, modifier, 0u);
}
}
}
void PrintFillStructMethod(const StructureInformation* info)
{
LINEF("void {0}::FillStruct_{1}(const ZoneStreamFillWriteAccessor& fillAccessor)",
WriterClassName(m_env.m_asset),
MakeSafeTypeName(info->m_definition))
LINE("{")
m_intendation++;
PrintFillStruct_Struct(*info);
m_intendation--; m_intendation--;
LINE("}") LINE("}")
@@ -1114,7 +1494,7 @@ namespace
{ {
LINEF("m_stream->Write<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def)) LINEF("m_stream->Write<{0}>(*{1});", def->GetFullName(), MakeTypePtrVarName(def))
} }
LINEF("m_stream->MarkFollowing(*{0});", MakeTypeWrittenPtrVarName(def)) LINEF("m_stream->MarkFollowing(varWritten);")
} }
void PrintWritePtrArrayMethod_PointerCheck(const DataDefinition* def, const StructureInformation* info, const bool reusable) void PrintWritePtrArrayMethod_PointerCheck(const DataDefinition* def, const StructureInformation* info, const bool reusable)
@@ -1126,13 +1506,13 @@ namespace
if (info && StructureComputations(info).IsAsset()) if (info && StructureComputations(info).IsAsset())
{ {
LINEF("{0} writer(*{1}, m_zone, *m_stream);", WriterClassName(info), MakeTypePtrVarName(def)) LINEF("{0} writer(*{1}, m_zone, *m_stream);", WriterClassName(info), MakeTypePtrVarName(def))
LINEF("writer.Write({0});", MakeTypeWrittenPtrVarName(def)) LINEF("writer.Write(*{0}, {1});", MakeTypePtrVarName(def), MakeTypeWrittenPtrVarName(def))
} }
else else
{ {
if (reusable) if (reusable)
{ {
LINEF("if (m_stream->ReusableShouldWrite({0}))", MakeTypeWrittenPtrVarName(def)) LINEF("if (m_stream->ReusableShouldWrite(*{0}, {1}))", MakeTypePtrVarName(def), MakeTypeWrittenPtrVarName(def))
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -1162,15 +1542,15 @@ namespace
LINE("if (atStreamStart)") LINE("if (atStreamStart)")
m_intendation++; m_intendation++;
LINEF("{0} = m_stream->Write<{1}*>({2}, count);", MakeTypeWrittenPtrVarName(def), def->GetFullName(), MakeTypePtrVarName(def)) LINEF("{0} = m_stream->WriteWithFill(m_stream->GetPointerByteCount() * count).Offset();", MakeTypeWrittenPtrVarName(def))
m_intendation--; m_intendation--;
LINE("") LINE("")
LINEF("assert({0} != nullptr);", MakeTypeWrittenPtrVarName(def)) LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenPtrVarName(def))
LINE("") LINE("")
LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def)) LINEF("{0}** var = {1};", def->GetFullName(), MakeTypePtrVarName(def))
LINEF("{0}** varWritten = {1};", def->GetFullName(), MakeTypeWrittenPtrVarName(def)) LINEF("ZoneOutputOffset varWritten = {1};", def->GetFullName(), MakeTypeWrittenPtrVarName(def))
LINE("for (size_t index = 0; index < count; index++)") LINE("for (size_t index = 0; index < count; index++)")
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -1180,7 +1560,7 @@ namespace
PrintWritePtrArrayMethod_PointerCheck(def, info, reusable); PrintWritePtrArrayMethod_PointerCheck(def, info, reusable);
LINE("") LINE("")
LINE("var++;") LINE("var++;")
LINE("varWritten++;") LINE("varWritten.Inc(m_stream->GetPointerByteCount());")
m_intendation--; m_intendation--;
LINE("}") LINE("}")
@@ -1197,16 +1577,45 @@ namespace
LINEF("assert({0} != nullptr);", MakeTypeVarName(def)) LINEF("assert({0} != nullptr);", MakeTypeVarName(def))
LINE("") LINE("")
LINE("if (atStreamStart)") LINE("if (atStreamStart)")
if (info->m_has_matching_cross_platform_structure)
{
m_intendation++; m_intendation++;
LINEF("{0} = m_stream->Write<{1}>({2}, count);", MakeTypeWrittenVarName(def), def->GetFullName(), MakeTypeVarName(def)) LINEF("{0} = m_stream->Write<{1}>({2}, count);", MakeTypeWrittenVarName(def), def->GetFullName(), MakeTypeVarName(def))
m_intendation--; m_intendation--;
}
else
{
LINE("{")
m_intendation++;
LINEF("const auto arrayFill = m_stream->WriteWithFill({0} * count);", def->GetSize())
LINEF("{0} = arrayFill.Offset();", MakeTypeWrittenVarName(def))
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(info->m_definition))
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("") LINE("")
LINEF("assert({0} != nullptr);", MakeTypeWrittenVarName(def)) LINEF("assert({0}.Offset() != nullptr);", MakeTypeWrittenVarName(def))
LINE("") LINE("")
LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def)) LINEF("{0}* var = {1};", def->GetFullName(), MakeTypeVarName(def))
LINEF("{0}* varWritten = {1};", def->GetFullName(), MakeTypeWrittenVarName(def)) LINEF("ZoneOutputOffset varWritten = {1};", def->GetFullName(), MakeTypeWrittenVarName(def))
LINE("for (size_t index = 0; index < count; index++)") LINE("for (size_t index = 0; index < count; index++)")
LINE("{") LINE("{")
m_intendation++; m_intendation++;
@@ -1215,7 +1624,7 @@ namespace
LINEF("{0} = varWritten;", MakeTypeWrittenVarName(info->m_definition)) LINEF("{0} = varWritten;", MakeTypeWrittenVarName(info->m_definition))
LINEF("Write_{0}(false);", info->m_definition->m_name) LINEF("Write_{0}(false);", info->m_definition->m_name)
LINE("var++;") LINE("var++;")
LINE("varWritten++;") LINEF("varWritten.Inc({0});", def->GetSize())
m_intendation--; m_intendation--;
LINE("}") LINE("}")
@@ -1228,16 +1637,35 @@ namespace
}; };
} // namespace } // namespace
std::vector<CodeTemplateFile> ZoneWriteTemplate::GetFilesToRenderOncePerTemplate(const OncePerTemplateRenderingContext& context)
{
std::vector<CodeTemplateFile> files;
files.emplace_back(std::format("AssetWriter{0}.h", context.m_game), TAG_ALL_WRITERS);
return files;
}
void ZoneWriteTemplate::RenderOncePerTemplateFile(std::ostream& stream, const CodeTemplateFileTag fileTag, const OncePerTemplateRenderingContext& context)
{
assert(fileTag == TAG_ALL_WRITERS);
const PerTemplate t(stream, context);
t.AllWriters();
}
std::vector<CodeTemplateFile> ZoneWriteTemplate::GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) std::vector<CodeTemplateFile> ZoneWriteTemplate::GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context)
{ {
std::vector<CodeTemplateFile> files; std::vector<CodeTemplateFile> files;
auto assetName = context.m_asset->m_definition->m_name; auto assetName = context.m_asset->m_definition->m_name;
for (auto& c : assetName) utils::MakeStringLowerCase(assetName);
c = static_cast<char>(tolower(c));
files.emplace_back(std::format("XAssets/{0}/{0}_write_db.h", assetName), TAG_HEADER); auto gameName = context.m_game;
files.emplace_back(std::format("XAssets/{0}/{0}_write_db.cpp", assetName), TAG_SOURCE); utils::MakeStringLowerCase(gameName);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_write_db.h", assetName, gameName), TAG_HEADER);
files.emplace_back(std::format("XAssets/{0}/{0}_{1}_write_db.cpp", assetName, gameName), TAG_SOURCE);
return files; return files;
} }

View File

@@ -5,6 +5,9 @@
class ZoneWriteTemplate final : public ICodeTemplate class ZoneWriteTemplate final : public ICodeTemplate
{ {
public: public:
std::vector<CodeTemplateFile> GetFilesToRenderOncePerTemplate(const OncePerTemplateRenderingContext& context) override;
void RenderOncePerTemplateFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerTemplateRenderingContext& context) override;
std::vector<CodeTemplateFile> GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) override; std::vector<CodeTemplateFile> GetFilesToRenderOncePerAsset(const OncePerAssetRenderingContext& context) override;
void RenderOncePerAssetFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerAssetRenderingContext& context) override; void RenderOncePerAssetFile(std::ostream& stream, CodeTemplateFileTag fileTag, const OncePerAssetRenderingContext& context) override;
}; };

View File

@@ -27,7 +27,7 @@ size_t XChunkProcessorInflate::Process(unsigned streamNumber, const uint8_t* inp
ret = inflate(&stream, Z_FULL_FLUSH); ret = inflate(&stream, Z_FULL_FLUSH);
if (ret != Z_STREAM_END) if (ret != Z_STREAM_END)
{ {
con::error("inflate of stream failed with error code {}: {}", streamNumber, ret, stream.msg); con::error("inflate of stream {} failed with error code {}: {}", streamNumber, ret, stream.msg);
throw XChunkException(std::format("Zone has invalid or unsupported compression: {}", stream.msg)); throw XChunkException(std::format("Zone has invalid or unsupported compression: {}", stream.msg));
} }

View File

@@ -1,31 +1,7 @@
#include "ContentLoaderIW3.h" #include "ContentLoaderIW3.h"
#include "Game/IW3/AssetLoaderIW3.h"
#include "Game/IW3/IW3.h" #include "Game/IW3/IW3.h"
#include "Game/IW3/XAssets/clipmap_t/clipmap_t_load_db.h"
#include "Game/IW3/XAssets/comworld/comworld_load_db.h"
#include "Game/IW3/XAssets/font_s/font_s_load_db.h"
#include "Game/IW3/XAssets/fxeffectdef/fxeffectdef_load_db.h"
#include "Game/IW3/XAssets/fximpacttable/fximpacttable_load_db.h"
#include "Game/IW3/XAssets/gameworldmp/gameworldmp_load_db.h"
#include "Game/IW3/XAssets/gameworldsp/gameworldsp_load_db.h"
#include "Game/IW3/XAssets/gfximage/gfximage_load_db.h"
#include "Game/IW3/XAssets/gfxlightdef/gfxlightdef_load_db.h"
#include "Game/IW3/XAssets/gfxworld/gfxworld_load_db.h"
#include "Game/IW3/XAssets/loadedsound/loadedsound_load_db.h"
#include "Game/IW3/XAssets/localizeentry/localizeentry_load_db.h"
#include "Game/IW3/XAssets/mapents/mapents_load_db.h"
#include "Game/IW3/XAssets/material/material_load_db.h"
#include "Game/IW3/XAssets/materialtechniqueset/materialtechniqueset_load_db.h"
#include "Game/IW3/XAssets/menudef_t/menudef_t_load_db.h"
#include "Game/IW3/XAssets/menulist/menulist_load_db.h"
#include "Game/IW3/XAssets/physpreset/physpreset_load_db.h"
#include "Game/IW3/XAssets/rawfile/rawfile_load_db.h"
#include "Game/IW3/XAssets/snd_alias_list_t/snd_alias_list_t_load_db.h"
#include "Game/IW3/XAssets/sndcurve/sndcurve_load_db.h"
#include "Game/IW3/XAssets/stringtable/stringtable_load_db.h"
#include "Game/IW3/XAssets/weapondef/weapondef_load_db.h"
#include "Game/IW3/XAssets/xanimparts/xanimparts_load_db.h"
#include "Game/IW3/XAssets/xmodel/xmodel_load_db.h"
#include "Loading/Exception/UnsupportedAssetTypeException.h" #include "Loading/Exception/UnsupportedAssetTypeException.h"
#include <cassert> #include <cassert>

View File

@@ -1,41 +1,7 @@
#include "ContentLoaderIW4.h" #include "ContentLoaderIW4.h"
#include "Game/IW4/AssetLoaderIW4.h"
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
#include "Game/IW4/XAssets/addonmapents/addonmapents_load_db.h"
#include "Game/IW4/XAssets/clipmap_t/clipmap_t_load_db.h"
#include "Game/IW4/XAssets/comworld/comworld_load_db.h"
#include "Game/IW4/XAssets/font_s/font_s_load_db.h"
#include "Game/IW4/XAssets/fxeffectdef/fxeffectdef_load_db.h"
#include "Game/IW4/XAssets/fximpacttable/fximpacttable_load_db.h"
#include "Game/IW4/XAssets/fxworld/fxworld_load_db.h"
#include "Game/IW4/XAssets/gameworldmp/gameworldmp_load_db.h"
#include "Game/IW4/XAssets/gameworldsp/gameworldsp_load_db.h"
#include "Game/IW4/XAssets/gfximage/gfximage_load_db.h"
#include "Game/IW4/XAssets/gfxlightdef/gfxlightdef_load_db.h"
#include "Game/IW4/XAssets/gfxworld/gfxworld_load_db.h"
#include "Game/IW4/XAssets/leaderboarddef/leaderboarddef_load_db.h"
#include "Game/IW4/XAssets/loadedsound/loadedsound_load_db.h"
#include "Game/IW4/XAssets/localizeentry/localizeentry_load_db.h"
#include "Game/IW4/XAssets/mapents/mapents_load_db.h"
#include "Game/IW4/XAssets/material/material_load_db.h"
#include "Game/IW4/XAssets/materialpixelshader/materialpixelshader_load_db.h"
#include "Game/IW4/XAssets/materialtechniqueset/materialtechniqueset_load_db.h"
#include "Game/IW4/XAssets/materialvertexdeclaration/materialvertexdeclaration_load_db.h"
#include "Game/IW4/XAssets/materialvertexshader/materialvertexshader_load_db.h"
#include "Game/IW4/XAssets/menudef_t/menudef_t_load_db.h"
#include "Game/IW4/XAssets/menulist/menulist_load_db.h"
#include "Game/IW4/XAssets/physcollmap/physcollmap_load_db.h"
#include "Game/IW4/XAssets/physpreset/physpreset_load_db.h"
#include "Game/IW4/XAssets/rawfile/rawfile_load_db.h"
#include "Game/IW4/XAssets/snd_alias_list_t/snd_alias_list_t_load_db.h"
#include "Game/IW4/XAssets/sndcurve/sndcurve_load_db.h"
#include "Game/IW4/XAssets/stringtable/stringtable_load_db.h"
#include "Game/IW4/XAssets/structureddatadefset/structureddatadefset_load_db.h"
#include "Game/IW4/XAssets/tracerdef/tracerdef_load_db.h"
#include "Game/IW4/XAssets/vehicledef/vehicledef_load_db.h"
#include "Game/IW4/XAssets/weaponcompletedef/weaponcompletedef_load_db.h"
#include "Game/IW4/XAssets/xanimparts/xanimparts_load_db.h"
#include "Game/IW4/XAssets/xmodel/xmodel_load_db.h"
#include "Loading/Exception/UnsupportedAssetTypeException.h" #include "Loading/Exception/UnsupportedAssetTypeException.h"
#include <cassert> #include <cassert>

View File

@@ -1,46 +1,7 @@
#include "ContentLoaderIW5.h" #include "ContentLoaderIW5.h"
#include "Game/IW5/AssetLoaderIW5.h"
#include "Game/IW5/IW5.h" #include "Game/IW5/IW5.h"
#include "Game/IW5/XAssets/addonmapents/addonmapents_load_db.h"
#include "Game/IW5/XAssets/clipmap_t/clipmap_t_load_db.h"
#include "Game/IW5/XAssets/comworld/comworld_load_db.h"
#include "Game/IW5/XAssets/font_s/font_s_load_db.h"
#include "Game/IW5/XAssets/fxeffectdef/fxeffectdef_load_db.h"
#include "Game/IW5/XAssets/fximpacttable/fximpacttable_load_db.h"
#include "Game/IW5/XAssets/fxworld/fxworld_load_db.h"
#include "Game/IW5/XAssets/gfximage/gfximage_load_db.h"
#include "Game/IW5/XAssets/gfxlightdef/gfxlightdef_load_db.h"
#include "Game/IW5/XAssets/gfxworld/gfxworld_load_db.h"
#include "Game/IW5/XAssets/glassworld/glassworld_load_db.h"
#include "Game/IW5/XAssets/leaderboarddef/leaderboarddef_load_db.h"
#include "Game/IW5/XAssets/loadedsound/loadedsound_load_db.h"
#include "Game/IW5/XAssets/localizeentry/localizeentry_load_db.h"
#include "Game/IW5/XAssets/mapents/mapents_load_db.h"
#include "Game/IW5/XAssets/material/material_load_db.h"
#include "Game/IW5/XAssets/materialpixelshader/materialpixelshader_load_db.h"
#include "Game/IW5/XAssets/materialtechniqueset/materialtechniqueset_load_db.h"
#include "Game/IW5/XAssets/materialvertexdeclaration/materialvertexdeclaration_load_db.h"
#include "Game/IW5/XAssets/materialvertexshader/materialvertexshader_load_db.h"
#include "Game/IW5/XAssets/menudef_t/menudef_t_load_db.h"
#include "Game/IW5/XAssets/menulist/menulist_load_db.h"
#include "Game/IW5/XAssets/pathdata/pathdata_load_db.h"
#include "Game/IW5/XAssets/physcollmap/physcollmap_load_db.h"
#include "Game/IW5/XAssets/physpreset/physpreset_load_db.h"
#include "Game/IW5/XAssets/rawfile/rawfile_load_db.h"
#include "Game/IW5/XAssets/scriptfile/scriptfile_load_db.h"
#include "Game/IW5/XAssets/snd_alias_list_t/snd_alias_list_t_load_db.h"
#include "Game/IW5/XAssets/sndcurve/sndcurve_load_db.h"
#include "Game/IW5/XAssets/stringtable/stringtable_load_db.h"
#include "Game/IW5/XAssets/structureddatadefset/structureddatadefset_load_db.h"
#include "Game/IW5/XAssets/surfacefxtable/surfacefxtable_load_db.h"
#include "Game/IW5/XAssets/tracerdef/tracerdef_load_db.h"
#include "Game/IW5/XAssets/vehicledef/vehicledef_load_db.h"
#include "Game/IW5/XAssets/vehicletrack/vehicletrack_load_db.h"
#include "Game/IW5/XAssets/weaponattachment/weaponattachment_load_db.h"
#include "Game/IW5/XAssets/weaponcompletedef/weaponcompletedef_load_db.h"
#include "Game/IW5/XAssets/xanimparts/xanimparts_load_db.h"
#include "Game/IW5/XAssets/xmodel/xmodel_load_db.h"
#include "Game/IW5/XAssets/xmodelsurfs/xmodelsurfs_load_db.h"
#include "Loading/Exception/UnsupportedAssetTypeException.h" #include "Loading/Exception/UnsupportedAssetTypeException.h"
#include <cassert> #include <cassert>

View File

@@ -1,38 +1,7 @@
#include "ContentLoaderT5.h" #include "ContentLoaderT5.h"
#include "Game/T5/AssetLoaderT5.h"
#include "Game/T5/T5.h" #include "Game/T5/T5.h"
#include "Game/T5/XAssets/clipmap_t/clipmap_t_load_db.h"
#include "Game/T5/XAssets/comworld/comworld_load_db.h"
#include "Game/T5/XAssets/ddlroot_t/ddlroot_t_load_db.h"
#include "Game/T5/XAssets/destructibledef/destructibledef_load_db.h"
#include "Game/T5/XAssets/emblemset/emblemset_load_db.h"
#include "Game/T5/XAssets/font_s/font_s_load_db.h"
#include "Game/T5/XAssets/fxeffectdef/fxeffectdef_load_db.h"
#include "Game/T5/XAssets/fximpacttable/fximpacttable_load_db.h"
#include "Game/T5/XAssets/gameworldmp/gameworldmp_load_db.h"
#include "Game/T5/XAssets/gameworldsp/gameworldsp_load_db.h"
#include "Game/T5/XAssets/gfximage/gfximage_load_db.h"
#include "Game/T5/XAssets/gfxlightdef/gfxlightdef_load_db.h"
#include "Game/T5/XAssets/gfxworld/gfxworld_load_db.h"
#include "Game/T5/XAssets/glasses/glasses_load_db.h"
#include "Game/T5/XAssets/localizeentry/localizeentry_load_db.h"
#include "Game/T5/XAssets/mapents/mapents_load_db.h"
#include "Game/T5/XAssets/material/material_load_db.h"
#include "Game/T5/XAssets/materialtechniqueset/materialtechniqueset_load_db.h"
#include "Game/T5/XAssets/menudef_t/menudef_t_load_db.h"
#include "Game/T5/XAssets/menulist/menulist_load_db.h"
#include "Game/T5/XAssets/packindex/packindex_load_db.h"
#include "Game/T5/XAssets/physconstraints/physconstraints_load_db.h"
#include "Game/T5/XAssets/physpreset/physpreset_load_db.h"
#include "Game/T5/XAssets/rawfile/rawfile_load_db.h"
#include "Game/T5/XAssets/sndbank/sndbank_load_db.h"
#include "Game/T5/XAssets/snddriverglobals/snddriverglobals_load_db.h"
#include "Game/T5/XAssets/sndpatch/sndpatch_load_db.h"
#include "Game/T5/XAssets/stringtable/stringtable_load_db.h"
#include "Game/T5/XAssets/weaponvariantdef/weaponvariantdef_load_db.h"
#include "Game/T5/XAssets/xanimparts/xanimparts_load_db.h"
#include "Game/T5/XAssets/xglobals/xglobals_load_db.h"
#include "Game/T5/XAssets/xmodel/xmodel_load_db.h"
#include "Loading/Exception/UnsupportedAssetTypeException.h" #include "Loading/Exception/UnsupportedAssetTypeException.h"
#include <cassert> #include <cassert>

View File

@@ -1,54 +1,7 @@
#include "ContentLoaderT6.h" #include "ContentLoaderT6.h"
#include "Game/T6/AssetLoaderT6.h"
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Game/T6/XAssets/addonmapents/addonmapents_load_db.h"
#include "Game/T6/XAssets/clipmap_t/clipmap_t_load_db.h"
#include "Game/T6/XAssets/comworld/comworld_load_db.h"
#include "Game/T6/XAssets/ddlroot_t/ddlroot_t_load_db.h"
#include "Game/T6/XAssets/destructibledef/destructibledef_load_db.h"
#include "Game/T6/XAssets/emblemset/emblemset_load_db.h"
#include "Game/T6/XAssets/font_s/font_s_load_db.h"
#include "Game/T6/XAssets/fonticon/fonticon_load_db.h"
#include "Game/T6/XAssets/footstepfxtabledef/footstepfxtabledef_load_db.h"
#include "Game/T6/XAssets/footsteptabledef/footsteptabledef_load_db.h"
#include "Game/T6/XAssets/fxeffectdef/fxeffectdef_load_db.h"
#include "Game/T6/XAssets/fximpacttable/fximpacttable_load_db.h"
#include "Game/T6/XAssets/gameworldmp/gameworldmp_load_db.h"
#include "Game/T6/XAssets/gameworldsp/gameworldsp_load_db.h"
#include "Game/T6/XAssets/gfximage/gfximage_load_db.h"
#include "Game/T6/XAssets/gfxlightdef/gfxlightdef_load_db.h"
#include "Game/T6/XAssets/gfxworld/gfxworld_load_db.h"
#include "Game/T6/XAssets/glasses/glasses_load_db.h"
#include "Game/T6/XAssets/keyvaluepairs/keyvaluepairs_load_db.h"
#include "Game/T6/XAssets/leaderboarddef/leaderboarddef_load_db.h"
#include "Game/T6/XAssets/localizeentry/localizeentry_load_db.h"
#include "Game/T6/XAssets/mapents/mapents_load_db.h"
#include "Game/T6/XAssets/material/material_load_db.h"
#include "Game/T6/XAssets/materialtechniqueset/materialtechniqueset_load_db.h"
#include "Game/T6/XAssets/memoryblock/memoryblock_load_db.h"
#include "Game/T6/XAssets/menudef_t/menudef_t_load_db.h"
#include "Game/T6/XAssets/menulist/menulist_load_db.h"
#include "Game/T6/XAssets/physconstraints/physconstraints_load_db.h"
#include "Game/T6/XAssets/physpreset/physpreset_load_db.h"
#include "Game/T6/XAssets/qdb/qdb_load_db.h"
#include "Game/T6/XAssets/rawfile/rawfile_load_db.h"
#include "Game/T6/XAssets/scriptparsetree/scriptparsetree_load_db.h"
#include "Game/T6/XAssets/skinnedvertsdef/skinnedvertsdef_load_db.h"
#include "Game/T6/XAssets/slug/slug_load_db.h"
#include "Game/T6/XAssets/sndbank/sndbank_load_db.h"
#include "Game/T6/XAssets/snddriverglobals/snddriverglobals_load_db.h"
#include "Game/T6/XAssets/sndpatch/sndpatch_load_db.h"
#include "Game/T6/XAssets/stringtable/stringtable_load_db.h"
#include "Game/T6/XAssets/tracerdef/tracerdef_load_db.h"
#include "Game/T6/XAssets/vehicledef/vehicledef_load_db.h"
#include "Game/T6/XAssets/weaponattachment/weaponattachment_load_db.h"
#include "Game/T6/XAssets/weaponattachmentunique/weaponattachmentunique_load_db.h"
#include "Game/T6/XAssets/weaponcamo/weaponcamo_load_db.h"
#include "Game/T6/XAssets/weaponvariantdef/weaponvariantdef_load_db.h"
#include "Game/T6/XAssets/xanimparts/xanimparts_load_db.h"
#include "Game/T6/XAssets/xglobals/xglobals_load_db.h"
#include "Game/T6/XAssets/xmodel/xmodel_load_db.h"
#include "Game/T6/XAssets/zbarrierdef/zbarrierdef_load_db.h"
#include "Loading/Exception/UnsupportedAssetTypeException.h" #include "Loading/Exception/UnsupportedAssetTypeException.h"
#include <cassert> #include <cassert>

View File

@@ -2,7 +2,7 @@
#include <format> #include <format>
InvalidLookupPositionException::InvalidLookupPositionException(block_t block, size_t offset) InvalidLookupPositionException::InvalidLookupPositionException(const block_t block, const size_t offset)
: m_block(block), : m_block(block),
m_offset(offset) m_offset(offset)
{ {

View File

@@ -13,8 +13,8 @@ namespace
{ {
const auto blockCount = static_cast<unsigned>(zoneLoader.m_blocks.size()); const auto blockCount = static_cast<unsigned>(zoneLoader.m_blocks.size());
const auto blockSizes = std::make_unique<xblock_size_t[]>(blockCount); std::vector<xblock_size_t> blockSizes(blockCount);
stream.Load(blockSizes.get(), sizeof(xblock_size_t) * blockCount); stream.Load(blockSizes.data(), sizeof(xblock_size_t) * blockCount);
uint64_t totalMemory = 0; uint64_t totalMemory = 0;
for (unsigned int block = 0; block < blockCount; block++) for (unsigned int block = 0; block < blockCount; block++)

View File

@@ -53,6 +53,7 @@ namespace
MemoryManager& memory, MemoryManager& memory,
std::optional<std::unique_ptr<ProgressCallback>> progressCallback) std::optional<std::unique_ptr<ProgressCallback>> progressCallback)
: m_blocks(blocks), : m_blocks(blocks),
m_block_offsets(blocks.size()),
m_stream(stream), m_stream(stream),
m_memory(memory), m_memory(memory),
m_pointer_byte_count(pointerBitCount / 8u), m_pointer_byte_count(pointerBitCount / 8u),
@@ -67,9 +68,7 @@ namespace
assert(pointerBitCount % 8u == 0u); assert(pointerBitCount % 8u == 0u);
assert(insertBlock < static_cast<block_t>(blocks.size())); assert(insertBlock < static_cast<block_t>(blocks.size()));
const auto blockCount = static_cast<unsigned>(blocks.size()); std::memset(m_block_offsets.data(), 0, sizeof(decltype(m_block_offsets)::value_type) * m_block_offsets.size());
m_block_offsets = std::make_unique<size_t[]>(blockCount);
std::memset(m_block_offsets.get(), 0, sizeof(size_t) * blockCount);
m_insert_block = blocks[insertBlock]; m_insert_block = blocks[insertBlock];
@@ -488,7 +487,7 @@ namespace
} }
std::vector<XBlock*>& m_blocks; std::vector<XBlock*>& m_blocks;
std::unique_ptr<size_t[]> m_block_offsets; std::vector<size_t> m_block_offsets;
std::stack<XBlock*> m_block_stack; std::stack<XBlock*> m_block_stack;
std::stack<size_t> m_temp_offsets; std::stack<size_t> m_temp_offsets;

View File

@@ -7,7 +7,9 @@
#include <filesystem> #include <filesystem>
#include <format> #include <format>
#include <fstream> #include <fstream>
#include <string>
using namespace std::string_literals;
namespace fs = std::filesystem; namespace fs = std::filesystem;
result::Expected<std::unique_ptr<Zone>, std::string> ZoneLoading::LoadZone(const std::string& path, result::Expected<std::unique_ptr<Zone>, std::string> ZoneLoading::LoadZone(const std::string& path,
@@ -41,5 +43,9 @@ result::Expected<std::unique_ptr<Zone>, std::string> ZoneLoading::LoadZone(const
auto loadedZone = zoneLoader->LoadZone(file); auto loadedZone = zoneLoader->LoadZone(file);
file.close(); file.close();
if (!loadedZone)
return result::Unexpected("Loading zone failed."s);
return std::move(loadedZone); return std::move(loadedZone);
} }

View File

@@ -1,30 +1,6 @@
#include "ContentWriterIW3.h" #include "ContentWriterIW3.h"
#include "Game/IW3/XAssets/clipmap_t/clipmap_t_write_db.h" #include "Game/IW3/AssetWriterIW3.h"
#include "Game/IW3/XAssets/comworld/comworld_write_db.h"
#include "Game/IW3/XAssets/font_s/font_s_write_db.h"
#include "Game/IW3/XAssets/fxeffectdef/fxeffectdef_write_db.h"
#include "Game/IW3/XAssets/fximpacttable/fximpacttable_write_db.h"
#include "Game/IW3/XAssets/gameworldmp/gameworldmp_write_db.h"
#include "Game/IW3/XAssets/gameworldsp/gameworldsp_write_db.h"
#include "Game/IW3/XAssets/gfximage/gfximage_write_db.h"
#include "Game/IW3/XAssets/gfxlightdef/gfxlightdef_write_db.h"
#include "Game/IW3/XAssets/gfxworld/gfxworld_write_db.h"
#include "Game/IW3/XAssets/loadedsound/loadedsound_write_db.h"
#include "Game/IW3/XAssets/localizeentry/localizeentry_write_db.h"
#include "Game/IW3/XAssets/mapents/mapents_write_db.h"
#include "Game/IW3/XAssets/material/material_write_db.h"
#include "Game/IW3/XAssets/materialtechniqueset/materialtechniqueset_write_db.h"
#include "Game/IW3/XAssets/menudef_t/menudef_t_write_db.h"
#include "Game/IW3/XAssets/menulist/menulist_write_db.h"
#include "Game/IW3/XAssets/physpreset/physpreset_write_db.h"
#include "Game/IW3/XAssets/rawfile/rawfile_write_db.h"
#include "Game/IW3/XAssets/snd_alias_list_t/snd_alias_list_t_write_db.h"
#include "Game/IW3/XAssets/sndcurve/sndcurve_write_db.h"
#include "Game/IW3/XAssets/stringtable/stringtable_write_db.h"
#include "Game/IW3/XAssets/weapondef/weapondef_write_db.h"
#include "Game/IW3/XAssets/xanimparts/xanimparts_write_db.h"
#include "Game/IW3/XAssets/xmodel/xmodel_write_db.h"
#include "Writing/WritingException.h" #include "Writing/WritingException.h"
#include <cassert> #include <cassert>
@@ -81,30 +57,31 @@ void ContentWriter::CreateXAssetList(XAssetList& xAssetList, MemoryManager& memo
void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteScriptStringList(const bool atStreamStart)
{ {
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); assert(!atStreamStart);
if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); WriteXStringArray(true, varScriptStringList->count);
m_stream->MarkFollowing(varScriptStringList->strings); #ifdef ARCH_x86
static_assert(offsetof(ScriptStringList, strings) == 4u);
#endif
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
} }
m_stream->PopBlock();
} }
void ContentWriter::WriteXAsset(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart)
{ {
#ifdef ARCH_x86
static_assert(offsetof(XAsset, header.data) == 4u);
#endif
#define WRITE_ASSET(type_index, typeName, headerEntry) \ #define WRITE_ASSET(type_index, typeName, headerEntry) \
case type_index: \ case type_index: \
{ \ { \
Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
writer.Write(&varXAsset->header.headerEntry); \ writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
break; \ break; \
} }
#define SKIP_ASSET(type_index, typeName, headerEntry) \ #define SKIP_ASSET(type_index, typeName, headerEntry) \
@@ -114,7 +91,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -160,38 +137,75 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
{ {
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
#ifdef ARCH_x86
static_assert(sizeof(XAsset) == 8u);
#endif
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); {
#ifdef ARCH_x86
varXAssetWritten = m_stream->Write(varXAsset, count);
#else
const auto fill = m_stream->WriteWithFill(8u * count);
varXAssetWritten = fill.Offset();
for (size_t index = 0; index < count; index++)
fill.Fill(varXAsset[index].type, 8u * index);
#endif
}
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; varXAsset++;
varXAssetWritten.Inc(8u);
} }
} }
void ContentWriter::WriteContent(IZoneOutputStream& stream) void ContentWriter::WriteContent(ZoneOutputStream& stream)
{ {
m_stream = &stream; m_stream = &stream;
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
MemoryManager memory; MemoryManager memory;
XAssetList assetList{}; XAssetList assetList{};
CreateXAssetList(assetList, memory); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); varXAssetList = &assetList;
#ifdef ARCH_x86
static_assert(sizeof(XAssetList) == 16);
static_assert(offsetof(XAssetList, assetCount) == 8u);
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
#else
const auto fillAccessor = m_stream->WriteWithFill(16u);
varXAssetListWritten = fillAccessor.Offset();
varScriptStringList = &varXAssetList->stringList; varScriptStringList = &varXAssetList->stringList;
fillAccessor.Fill(varScriptStringList->count, 0u);
fillAccessor.Fill(varXAssetList->assetCount, 8u);
#endif
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, stringList) == 0u);
#endif
varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.AtOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); WriteXAssetArray(true, varXAssetList->assetCount);
m_stream->MarkFollowing(varXAssetList->assets);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, assets) == 12u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
} }
m_stream->PopBlock(); m_stream->PopBlock();

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Game/IW3/IW3.h" #include "Game/IW3/IW3.h"
#include "Writing/ContentWriterBase.h" #include "Writing/ContentWriterBase.h"
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
@@ -10,7 +11,7 @@ namespace IW3
public: public:
explicit ContentWriter(const Zone& zone); explicit ContentWriter(const Zone& zone);
void WriteContent(IZoneOutputStream& stream) override; void WriteContent(ZoneOutputStream& stream) override;
private: private:
void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const;
@@ -23,5 +24,9 @@ namespace IW3
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW3 } // namespace IW3

View File

@@ -52,7 +52,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
SetupBlocks(*writer); SetupBlocks(*writer);
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>( auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
std::make_unique<ContentWriter>(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); std::make_unique<ContentWriter>(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
auto* contentInMemoryPtr = contentInMemory.get(); auto* contentInMemoryPtr = contentInMemory.get();
writer->AddWritingStep(std::move(contentInMemory)); writer->AddWritingStep(std::move(contentInMemory));

View File

@@ -1,40 +1,6 @@
#include "ContentWriterIW4.h" #include "ContentWriterIW4.h"
#include "Game/IW4/XAssets/addonmapents/addonmapents_write_db.h" #include "Game/IW4/AssetWriterIW4.h"
#include "Game/IW4/XAssets/clipmap_t/clipmap_t_write_db.h"
#include "Game/IW4/XAssets/comworld/comworld_write_db.h"
#include "Game/IW4/XAssets/font_s/font_s_write_db.h"
#include "Game/IW4/XAssets/fxeffectdef/fxeffectdef_write_db.h"
#include "Game/IW4/XAssets/fximpacttable/fximpacttable_write_db.h"
#include "Game/IW4/XAssets/fxworld/fxworld_write_db.h"
#include "Game/IW4/XAssets/gameworldmp/gameworldmp_write_db.h"
#include "Game/IW4/XAssets/gameworldsp/gameworldsp_write_db.h"
#include "Game/IW4/XAssets/gfximage/gfximage_write_db.h"
#include "Game/IW4/XAssets/gfxlightdef/gfxlightdef_write_db.h"
#include "Game/IW4/XAssets/gfxworld/gfxworld_write_db.h"
#include "Game/IW4/XAssets/leaderboarddef/leaderboarddef_write_db.h"
#include "Game/IW4/XAssets/loadedsound/loadedsound_write_db.h"
#include "Game/IW4/XAssets/localizeentry/localizeentry_write_db.h"
#include "Game/IW4/XAssets/mapents/mapents_write_db.h"
#include "Game/IW4/XAssets/material/material_write_db.h"
#include "Game/IW4/XAssets/materialpixelshader/materialpixelshader_write_db.h"
#include "Game/IW4/XAssets/materialtechniqueset/materialtechniqueset_write_db.h"
#include "Game/IW4/XAssets/materialvertexdeclaration/materialvertexdeclaration_write_db.h"
#include "Game/IW4/XAssets/materialvertexshader/materialvertexshader_write_db.h"
#include "Game/IW4/XAssets/menudef_t/menudef_t_write_db.h"
#include "Game/IW4/XAssets/menulist/menulist_write_db.h"
#include "Game/IW4/XAssets/physcollmap/physcollmap_write_db.h"
#include "Game/IW4/XAssets/physpreset/physpreset_write_db.h"
#include "Game/IW4/XAssets/rawfile/rawfile_write_db.h"
#include "Game/IW4/XAssets/snd_alias_list_t/snd_alias_list_t_write_db.h"
#include "Game/IW4/XAssets/sndcurve/sndcurve_write_db.h"
#include "Game/IW4/XAssets/stringtable/stringtable_write_db.h"
#include "Game/IW4/XAssets/structureddatadefset/structureddatadefset_write_db.h"
#include "Game/IW4/XAssets/tracerdef/tracerdef_write_db.h"
#include "Game/IW4/XAssets/vehicledef/vehicledef_write_db.h"
#include "Game/IW4/XAssets/weaponcompletedef/weaponcompletedef_write_db.h"
#include "Game/IW4/XAssets/xanimparts/xanimparts_write_db.h"
#include "Game/IW4/XAssets/xmodel/xmodel_write_db.h"
#include "Writing/WritingException.h" #include "Writing/WritingException.h"
#include <cassert> #include <cassert>
@@ -91,30 +57,31 @@ void ContentWriter::CreateXAssetList(XAssetList& xAssetList, MemoryManager& memo
void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteScriptStringList(const bool atStreamStart)
{ {
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); assert(!atStreamStart);
if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); WriteXStringArray(true, varScriptStringList->count);
m_stream->MarkFollowing(varScriptStringList->strings); #ifdef ARCH_x86
static_assert(offsetof(ScriptStringList, strings) == 4u);
#endif
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
} }
m_stream->PopBlock();
} }
void ContentWriter::WriteXAsset(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart)
{ {
#ifdef ARCH_x86
static_assert(offsetof(XAsset, header.data) == 4u);
#endif
#define WRITE_ASSET(type_index, typeName, headerEntry) \ #define WRITE_ASSET(type_index, typeName, headerEntry) \
case type_index: \ case type_index: \
{ \ { \
Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
writer.Write(&varXAsset->header.headerEntry); \ writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
break; \ break; \
} }
#define SKIP_ASSET(type_index, typeName, headerEntry) \ #define SKIP_ASSET(type_index, typeName, headerEntry) \
@@ -124,7 +91,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -180,38 +147,75 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
{ {
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
#ifdef ARCH_x86
static_assert(sizeof(XAsset) == 8u);
#endif
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); {
#ifdef ARCH_x86
varXAssetWritten = m_stream->Write(varXAsset, count);
#else
const auto fill = m_stream->WriteWithFill(8u * count);
varXAssetWritten = fill.Offset();
for (size_t index = 0; index < count; index++)
fill.Fill(varXAsset[index].type, 8u * index);
#endif
}
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; varXAsset++;
varXAssetWritten.Inc(8u);
} }
} }
void ContentWriter::WriteContent(IZoneOutputStream& stream) void ContentWriter::WriteContent(ZoneOutputStream& stream)
{ {
m_stream = &stream; m_stream = &stream;
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
MemoryManager memory; MemoryManager memory;
XAssetList assetList{}; XAssetList assetList{};
CreateXAssetList(assetList, memory); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); varXAssetList = &assetList;
#ifdef ARCH_x86
static_assert(sizeof(XAssetList) == 16);
static_assert(offsetof(XAssetList, assetCount) == 8u);
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
#else
const auto fillAccessor = m_stream->WriteWithFill(16u);
varXAssetListWritten = fillAccessor.Offset();
varScriptStringList = &varXAssetList->stringList; varScriptStringList = &varXAssetList->stringList;
fillAccessor.Fill(varScriptStringList->count, 0u);
fillAccessor.Fill(varXAssetList->assetCount, 8u);
#endif
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, stringList) == 0u);
#endif
varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.AtOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); WriteXAssetArray(true, varXAssetList->assetCount);
m_stream->MarkFollowing(varXAssetList->assets);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, assets) == 12u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
} }
m_stream->PopBlock(); m_stream->PopBlock();

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
#include "Writing/ContentWriterBase.h" #include "Writing/ContentWriterBase.h"
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
@@ -10,7 +11,7 @@ namespace IW4
public: public:
explicit ContentWriter(const Zone& zone); explicit ContentWriter(const Zone& zone);
void WriteContent(IZoneOutputStream& stream) override; void WriteContent(ZoneOutputStream& stream) override;
private: private:
void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const;
@@ -23,5 +24,9 @@ namespace IW4
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW4 } // namespace IW4

View File

@@ -67,7 +67,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
SetupBlocks(*writer); SetupBlocks(*writer);
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>( auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
std::make_unique<ContentWriter>(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); std::make_unique<ContentWriter>(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
auto* contentInMemoryPtr = contentInMemory.get(); auto* contentInMemoryPtr = contentInMemory.get();
writer->AddWritingStep(std::move(contentInMemory)); writer->AddWritingStep(std::move(contentInMemory));

View File

@@ -1,45 +1,6 @@
#include "ContentWriterIW5.h" #include "ContentWriterIW5.h"
#include "Game/IW5/XAssets/addonmapents/addonmapents_write_db.h" #include "Game/IW5/AssetWriterIW5.h"
#include "Game/IW5/XAssets/clipmap_t/clipmap_t_write_db.h"
#include "Game/IW5/XAssets/comworld/comworld_write_db.h"
#include "Game/IW5/XAssets/font_s/font_s_write_db.h"
#include "Game/IW5/XAssets/fxeffectdef/fxeffectdef_write_db.h"
#include "Game/IW5/XAssets/fximpacttable/fximpacttable_write_db.h"
#include "Game/IW5/XAssets/fxworld/fxworld_write_db.h"
#include "Game/IW5/XAssets/gfximage/gfximage_write_db.h"
#include "Game/IW5/XAssets/gfxlightdef/gfxlightdef_write_db.h"
#include "Game/IW5/XAssets/gfxworld/gfxworld_write_db.h"
#include "Game/IW5/XAssets/glassworld/glassworld_write_db.h"
#include "Game/IW5/XAssets/leaderboarddef/leaderboarddef_write_db.h"
#include "Game/IW5/XAssets/loadedsound/loadedsound_write_db.h"
#include "Game/IW5/XAssets/localizeentry/localizeentry_write_db.h"
#include "Game/IW5/XAssets/mapents/mapents_write_db.h"
#include "Game/IW5/XAssets/material/material_write_db.h"
#include "Game/IW5/XAssets/materialpixelshader/materialpixelshader_write_db.h"
#include "Game/IW5/XAssets/materialtechniqueset/materialtechniqueset_write_db.h"
#include "Game/IW5/XAssets/materialvertexdeclaration/materialvertexdeclaration_write_db.h"
#include "Game/IW5/XAssets/materialvertexshader/materialvertexshader_write_db.h"
#include "Game/IW5/XAssets/menudef_t/menudef_t_write_db.h"
#include "Game/IW5/XAssets/menulist/menulist_write_db.h"
#include "Game/IW5/XAssets/pathdata/pathdata_write_db.h"
#include "Game/IW5/XAssets/physcollmap/physcollmap_write_db.h"
#include "Game/IW5/XAssets/physpreset/physpreset_write_db.h"
#include "Game/IW5/XAssets/rawfile/rawfile_write_db.h"
#include "Game/IW5/XAssets/scriptfile/scriptfile_write_db.h"
#include "Game/IW5/XAssets/snd_alias_list_t/snd_alias_list_t_write_db.h"
#include "Game/IW5/XAssets/sndcurve/sndcurve_write_db.h"
#include "Game/IW5/XAssets/stringtable/stringtable_write_db.h"
#include "Game/IW5/XAssets/structureddatadefset/structureddatadefset_write_db.h"
#include "Game/IW5/XAssets/surfacefxtable/surfacefxtable_write_db.h"
#include "Game/IW5/XAssets/tracerdef/tracerdef_write_db.h"
#include "Game/IW5/XAssets/vehicledef/vehicledef_write_db.h"
#include "Game/IW5/XAssets/vehicletrack/vehicletrack_write_db.h"
#include "Game/IW5/XAssets/weaponattachment/weaponattachment_write_db.h"
#include "Game/IW5/XAssets/weaponcompletedef/weaponcompletedef_write_db.h"
#include "Game/IW5/XAssets/xanimparts/xanimparts_write_db.h"
#include "Game/IW5/XAssets/xmodel/xmodel_write_db.h"
#include "Game/IW5/XAssets/xmodelsurfs/xmodelsurfs_write_db.h"
#include "Writing/WritingException.h" #include "Writing/WritingException.h"
#include <cassert> #include <cassert>
@@ -96,30 +57,31 @@ void ContentWriter::CreateXAssetList(XAssetList& xAssetList, MemoryManager& memo
void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteScriptStringList(const bool atStreamStart)
{ {
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); assert(!atStreamStart);
if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); WriteXStringArray(true, varScriptStringList->count);
m_stream->MarkFollowing(varScriptStringList->strings); #ifdef ARCH_x86
static_assert(offsetof(ScriptStringList, strings) == 4u);
#endif
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
} }
m_stream->PopBlock();
} }
void ContentWriter::WriteXAsset(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart)
{ {
#ifdef ARCH_x86
static_assert(offsetof(XAsset, header.data) == 4u);
#endif
#define WRITE_ASSET(type_index, typeName, headerEntry) \ #define WRITE_ASSET(type_index, typeName, headerEntry) \
case type_index: \ case type_index: \
{ \ { \
Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
writer.Write(&varXAsset->header.headerEntry); \ writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
break; \ break; \
} }
#define SKIP_ASSET(type_index, typeName, headerEntry) \ #define SKIP_ASSET(type_index, typeName, headerEntry) \
@@ -129,7 +91,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -188,38 +150,75 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
{ {
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
#ifdef ARCH_x86
static_assert(sizeof(XAsset) == 8u);
#endif
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); {
#ifdef ARCH_x86
varXAssetWritten = m_stream->Write(varXAsset, count);
#else
const auto fill = m_stream->WriteWithFill(8u * count);
varXAssetWritten = fill.Offset();
for (size_t index = 0; index < count; index++)
fill.Fill(varXAsset[index].type, 8u * index);
#endif
}
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; varXAsset++;
varXAssetWritten.Inc(8u);
} }
} }
void ContentWriter::WriteContent(IZoneOutputStream& stream) void ContentWriter::WriteContent(ZoneOutputStream& stream)
{ {
m_stream = &stream; m_stream = &stream;
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
MemoryManager memory; MemoryManager memory;
XAssetList assetList{}; XAssetList assetList{};
CreateXAssetList(assetList, memory); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); varXAssetList = &assetList;
#ifdef ARCH_x86
static_assert(sizeof(XAssetList) == 16);
static_assert(offsetof(XAssetList, assetCount) == 8u);
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
#else
const auto fillAccessor = m_stream->WriteWithFill(16u);
varXAssetListWritten = fillAccessor.Offset();
varScriptStringList = &varXAssetList->stringList; varScriptStringList = &varXAssetList->stringList;
fillAccessor.Fill(varScriptStringList->count, 0u);
fillAccessor.Fill(varXAssetList->assetCount, 8u);
#endif
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, stringList) == 0u);
#endif
varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.AtOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); WriteXAssetArray(true, varXAssetList->assetCount);
m_stream->MarkFollowing(varXAssetList->assets);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, assets) == 12u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
} }
m_stream->PopBlock(); m_stream->PopBlock();

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Game/IW5/IW5.h" #include "Game/IW5/IW5.h"
#include "Writing/ContentWriterBase.h" #include "Writing/ContentWriterBase.h"
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
@@ -10,7 +11,7 @@ namespace IW5
public: public:
explicit ContentWriter(const Zone& zone); explicit ContentWriter(const Zone& zone);
void WriteContent(IZoneOutputStream& stream) override; void WriteContent(ZoneOutputStream& stream) override;
private: private:
void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const;
@@ -23,5 +24,9 @@ namespace IW5
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace IW5 } // namespace IW5

View File

@@ -68,7 +68,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
SetupBlocks(*writer); SetupBlocks(*writer);
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>( auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
std::make_unique<ContentWriter>(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); std::make_unique<ContentWriter>(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
auto* contentInMemoryPtr = contentInMemory.get(); auto* contentInMemoryPtr = contentInMemory.get();
writer->AddWritingStep(std::move(contentInMemory)); writer->AddWritingStep(std::move(contentInMemory));

View File

@@ -1,37 +1,6 @@
#include "ContentWriterT5.h" #include "ContentWriterT5.h"
#include "Game/T5/XAssets/clipmap_t/clipmap_t_write_db.h" #include "Game/T5/AssetWriterT5.h"
#include "Game/T5/XAssets/comworld/comworld_write_db.h"
#include "Game/T5/XAssets/ddlroot_t/ddlroot_t_write_db.h"
#include "Game/T5/XAssets/destructibledef/destructibledef_write_db.h"
#include "Game/T5/XAssets/emblemset/emblemset_write_db.h"
#include "Game/T5/XAssets/font_s/font_s_write_db.h"
#include "Game/T5/XAssets/fxeffectdef/fxeffectdef_write_db.h"
#include "Game/T5/XAssets/fximpacttable/fximpacttable_write_db.h"
#include "Game/T5/XAssets/gameworldmp/gameworldmp_write_db.h"
#include "Game/T5/XAssets/gameworldsp/gameworldsp_write_db.h"
#include "Game/T5/XAssets/gfximage/gfximage_write_db.h"
#include "Game/T5/XAssets/gfxlightdef/gfxlightdef_write_db.h"
#include "Game/T5/XAssets/gfxworld/gfxworld_write_db.h"
#include "Game/T5/XAssets/glasses/glasses_write_db.h"
#include "Game/T5/XAssets/localizeentry/localizeentry_write_db.h"
#include "Game/T5/XAssets/mapents/mapents_write_db.h"
#include "Game/T5/XAssets/material/material_write_db.h"
#include "Game/T5/XAssets/materialtechniqueset/materialtechniqueset_write_db.h"
#include "Game/T5/XAssets/menudef_t/menudef_t_write_db.h"
#include "Game/T5/XAssets/menulist/menulist_write_db.h"
#include "Game/T5/XAssets/packindex/packindex_write_db.h"
#include "Game/T5/XAssets/physconstraints/physconstraints_write_db.h"
#include "Game/T5/XAssets/physpreset/physpreset_write_db.h"
#include "Game/T5/XAssets/rawfile/rawfile_write_db.h"
#include "Game/T5/XAssets/sndbank/sndbank_write_db.h"
#include "Game/T5/XAssets/snddriverglobals/snddriverglobals_write_db.h"
#include "Game/T5/XAssets/sndpatch/sndpatch_write_db.h"
#include "Game/T5/XAssets/stringtable/stringtable_write_db.h"
#include "Game/T5/XAssets/weaponvariantdef/weaponvariantdef_write_db.h"
#include "Game/T5/XAssets/xanimparts/xanimparts_write_db.h"
#include "Game/T5/XAssets/xglobals/xglobals_write_db.h"
#include "Game/T5/XAssets/xmodel/xmodel_write_db.h"
#include "Writing/WritingException.h" #include "Writing/WritingException.h"
#include <cassert> #include <cassert>
@@ -88,30 +57,31 @@ void ContentWriter::CreateXAssetList(XAssetList& xAssetList, MemoryManager& memo
void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteScriptStringList(const bool atStreamStart)
{ {
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); assert(!atStreamStart);
if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); WriteXStringArray(true, varScriptStringList->count);
m_stream->MarkFollowing(varScriptStringList->strings); #ifdef ARCH_x86
static_assert(offsetof(ScriptStringList, strings) == 4u);
#endif
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
} }
m_stream->PopBlock();
} }
void ContentWriter::WriteXAsset(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart)
{ {
#ifdef ARCH_x86
static_assert(offsetof(XAsset, header.data) == 4u);
#endif
#define WRITE_ASSET(type_index, typeName, headerEntry) \ #define WRITE_ASSET(type_index, typeName, headerEntry) \
case type_index: \ case type_index: \
{ \ { \
Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
writer.Write(&varXAsset->header.headerEntry); \ writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
break; \ break; \
} }
#define SKIP_ASSET(type_index, typeName, headerEntry) \ #define SKIP_ASSET(type_index, typeName, headerEntry) \
@@ -121,7 +91,7 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -173,38 +143,75 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
{ {
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
#ifdef ARCH_x86
static_assert(sizeof(XAsset) == 8u);
#endif
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); {
#ifdef ARCH_x86
varXAssetWritten = m_stream->Write(varXAsset, count);
#else
const auto fill = m_stream->WriteWithFill(8u * count);
varXAssetWritten = fill.Offset();
for (size_t index = 0; index < count; index++)
fill.Fill(varXAsset[index].type, 8u * index);
#endif
}
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; varXAsset++;
varXAssetWritten.Inc(8u);
} }
} }
void ContentWriter::WriteContent(IZoneOutputStream& stream) void ContentWriter::WriteContent(ZoneOutputStream& stream)
{ {
m_stream = &stream; m_stream = &stream;
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
MemoryManager memory; MemoryManager memory;
XAssetList assetList{}; XAssetList assetList{};
CreateXAssetList(assetList, memory); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); varXAssetList = &assetList;
#ifdef ARCH_x86
static_assert(sizeof(XAssetList) == 16);
static_assert(offsetof(XAssetList, assetCount) == 8u);
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
#else
const auto fillAccessor = m_stream->WriteWithFill(16u);
varXAssetListWritten = fillAccessor.Offset();
varScriptStringList = &varXAssetList->stringList; varScriptStringList = &varXAssetList->stringList;
fillAccessor.Fill(varScriptStringList->count, 0u);
fillAccessor.Fill(varXAssetList->assetCount, 8u);
#endif
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, stringList) == 0u);
#endif
varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.AtOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); WriteXAssetArray(true, varXAssetList->assetCount);
m_stream->MarkFollowing(varXAssetList->assets);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, assets) == 12u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
} }
m_stream->PopBlock(); m_stream->PopBlock();

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Game/T5/T5.h" #include "Game/T5/T5.h"
#include "Writing/ContentWriterBase.h" #include "Writing/ContentWriterBase.h"
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
@@ -8,9 +9,9 @@ namespace T5
class ContentWriter final : public ContentWriterBase, public IContentWritingEntryPoint class ContentWriter final : public ContentWriterBase, public IContentWritingEntryPoint
{ {
public: public:
ContentWriter(const Zone& zone); explicit ContentWriter(const Zone& zone);
void WriteContent(IZoneOutputStream& stream) override; void WriteContent(ZoneOutputStream& stream) override;
private: private:
void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const;
@@ -23,5 +24,9 @@ namespace T5
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace T5 } // namespace T5

View File

@@ -50,7 +50,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
SetupBlocks(*writer); SetupBlocks(*writer);
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>( auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
std::make_unique<ContentWriter>(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); std::make_unique<ContentWriter>(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
auto* contentInMemoryPtr = contentInMemory.get(); auto* contentInMemoryPtr = contentInMemory.get();
writer->AddWritingStep(std::move(contentInMemory)); writer->AddWritingStep(std::move(contentInMemory));

View File

@@ -1,53 +1,6 @@
#include "ContentWriterT6.h" #include "ContentWriterT6.h"
#include "Game/T6/XAssets/addonmapents/addonmapents_write_db.h" #include "Game/T6/AssetWriterT6.h"
#include "Game/T6/XAssets/clipmap_t/clipmap_t_write_db.h"
#include "Game/T6/XAssets/comworld/comworld_write_db.h"
#include "Game/T6/XAssets/ddlroot_t/ddlroot_t_write_db.h"
#include "Game/T6/XAssets/destructibledef/destructibledef_write_db.h"
#include "Game/T6/XAssets/emblemset/emblemset_write_db.h"
#include "Game/T6/XAssets/font_s/font_s_write_db.h"
#include "Game/T6/XAssets/fonticon/fonticon_write_db.h"
#include "Game/T6/XAssets/footstepfxtabledef/footstepfxtabledef_write_db.h"
#include "Game/T6/XAssets/footsteptabledef/footsteptabledef_write_db.h"
#include "Game/T6/XAssets/fxeffectdef/fxeffectdef_write_db.h"
#include "Game/T6/XAssets/fximpacttable/fximpacttable_write_db.h"
#include "Game/T6/XAssets/gameworldmp/gameworldmp_write_db.h"
#include "Game/T6/XAssets/gameworldsp/gameworldsp_write_db.h"
#include "Game/T6/XAssets/gfximage/gfximage_write_db.h"
#include "Game/T6/XAssets/gfxlightdef/gfxlightdef_write_db.h"
#include "Game/T6/XAssets/gfxworld/gfxworld_write_db.h"
#include "Game/T6/XAssets/glasses/glasses_write_db.h"
#include "Game/T6/XAssets/keyvaluepairs/keyvaluepairs_write_db.h"
#include "Game/T6/XAssets/leaderboarddef/leaderboarddef_write_db.h"
#include "Game/T6/XAssets/localizeentry/localizeentry_write_db.h"
#include "Game/T6/XAssets/mapents/mapents_write_db.h"
#include "Game/T6/XAssets/material/material_write_db.h"
#include "Game/T6/XAssets/materialtechniqueset/materialtechniqueset_write_db.h"
#include "Game/T6/XAssets/memoryblock/memoryblock_write_db.h"
#include "Game/T6/XAssets/menudef_t/menudef_t_write_db.h"
#include "Game/T6/XAssets/menulist/menulist_write_db.h"
#include "Game/T6/XAssets/physconstraints/physconstraints_write_db.h"
#include "Game/T6/XAssets/physpreset/physpreset_write_db.h"
#include "Game/T6/XAssets/qdb/qdb_write_db.h"
#include "Game/T6/XAssets/rawfile/rawfile_write_db.h"
#include "Game/T6/XAssets/scriptparsetree/scriptparsetree_write_db.h"
#include "Game/T6/XAssets/skinnedvertsdef/skinnedvertsdef_write_db.h"
#include "Game/T6/XAssets/slug/slug_write_db.h"
#include "Game/T6/XAssets/sndbank/sndbank_write_db.h"
#include "Game/T6/XAssets/snddriverglobals/snddriverglobals_write_db.h"
#include "Game/T6/XAssets/sndpatch/sndpatch_write_db.h"
#include "Game/T6/XAssets/stringtable/stringtable_write_db.h"
#include "Game/T6/XAssets/tracerdef/tracerdef_write_db.h"
#include "Game/T6/XAssets/vehicledef/vehicledef_write_db.h"
#include "Game/T6/XAssets/weaponattachment/weaponattachment_write_db.h"
#include "Game/T6/XAssets/weaponattachmentunique/weaponattachmentunique_write_db.h"
#include "Game/T6/XAssets/weaponcamo/weaponcamo_write_db.h"
#include "Game/T6/XAssets/weaponvariantdef/weaponvariantdef_write_db.h"
#include "Game/T6/XAssets/xanimparts/xanimparts_write_db.h"
#include "Game/T6/XAssets/xglobals/xglobals_write_db.h"
#include "Game/T6/XAssets/xmodel/xmodel_write_db.h"
#include "Game/T6/XAssets/zbarrierdef/zbarrierdef_write_db.h"
#include "Writing/WritingException.h" #include "Writing/WritingException.h"
#include <cassert> #include <cassert>
@@ -107,37 +60,38 @@ void ContentWriter::CreateXAssetList(XAssetList& xAssetList, MemoryManager& memo
void ContentWriter::WriteScriptStringList(const bool atStreamStart) void ContentWriter::WriteScriptStringList(const bool atStreamStart)
{ {
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL); assert(!atStreamStart);
if (atStreamStart)
varScriptStringList = m_stream->Write(varScriptStringList);
if (varScriptStringList->strings != nullptr) if (varScriptStringList->strings != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varScriptStringList->strings; varXString = varScriptStringList->strings;
WriteXStringArray(true, varScriptStringList->count); WriteXStringArray(true, varScriptStringList->count);
m_stream->MarkFollowing(varScriptStringList->strings); #ifdef ARCH_x86
static_assert(offsetof(ScriptStringList, strings) == 4u);
#endif
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
} }
m_stream->PopBlock();
} }
void ContentWriter::WriteXAsset(const bool atStreamStart) void ContentWriter::WriteXAsset(const bool atStreamStart)
{ {
#ifdef ARCH_x86
static_assert(offsetof(XAsset, header.data) == 4u);
#endif
#define WRITE_ASSET(type_index, typeName, headerEntry) \ #define WRITE_ASSET(type_index, typeName, headerEntry) \
case type_index: \ case type_index: \
{ \ { \
Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \ Writer_##typeName writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
writer.Write(&varXAsset->header.headerEntry); \ writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
break; \ break; \
} }
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset); varXAssetWritten = m_stream->Write(varXAsset);
switch (varXAsset->type) switch (varXAsset->type)
{ {
@@ -203,47 +157,89 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t count) void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t count)
{ {
assert(varXAsset != nullptr); assert(varXAsset != nullptr);
#ifdef ARCH_x86
static_assert(sizeof(XAsset) == 8u);
#endif
if (atStreamStart) if (atStreamStart)
varXAsset = m_stream->Write(varXAsset, count); {
#ifdef ARCH_x86
varXAssetWritten = m_stream->Write(varXAsset, count);
#else
const auto fill = m_stream->WriteWithFill(8u * count);
varXAssetWritten = fill.Offset();
for (size_t index = 0; index < count; index++)
fill.Fill(varXAsset[index].type, 8u * index);
#endif
}
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXAsset(false); WriteXAsset(false);
varXAsset++; varXAsset++;
varXAssetWritten.Inc(8u);
} }
} }
void ContentWriter::WriteContent(IZoneOutputStream& stream) void ContentWriter::WriteContent(ZoneOutputStream& stream)
{ {
m_stream = &stream; m_stream = &stream;
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
MemoryManager memory; MemoryManager memory;
XAssetList assetList{}; XAssetList assetList{};
CreateXAssetList(assetList, memory); CreateXAssetList(assetList, memory);
varXAssetList = static_cast<XAssetList*>(m_stream->WriteDataRaw(&assetList, sizeof(assetList))); varXAssetList = &assetList;
#ifdef ARCH_x86
static_assert(sizeof(XAssetList) == 24);
static_assert(offsetof(XAssetList, dependCount) == 8u);
static_assert(offsetof(XAssetList, assetCount) == 16u);
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
#else
const auto fillAccessor = m_stream->WriteWithFill(24u);
varXAssetListWritten = fillAccessor.Offset();
varScriptStringList = &varXAssetList->stringList; varScriptStringList = &varXAssetList->stringList;
fillAccessor.Fill(varScriptStringList->count, 0u);
fillAccessor.Fill(varXAssetList->dependCount, 8u);
fillAccessor.Fill(varXAssetList->assetCount, 16u);
#endif
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, stringList) == 0u);
#endif
varScriptStringList = &varXAssetList->stringList;
varScriptStringListWritten = varXAssetListWritten.AtOffset(0);
WriteScriptStringList(false); WriteScriptStringList(false);
if (varXAssetList->depends != nullptr) if (varXAssetList->depends != nullptr)
{ {
m_stream->Align(alignof(const char*)); m_stream->Align(4);
varXString = varXAssetList->depends; varXString = varXAssetList->depends;
WriteXStringArray(true, varXAssetList->dependCount); WriteXStringArray(true, varXAssetList->dependCount);
m_stream->MarkFollowing(varXAssetList->depends);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, depends) == 12u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
} }
if (varXAssetList->assets != nullptr) if (varXAssetList->assets != nullptr)
{ {
m_stream->Align(alignof(XAsset)); m_stream->Align(4);
varXAsset = varXAssetList->assets; varXAsset = varXAssetList->assets;
WriteXAssetArray(true, varXAssetList->assetCount); WriteXAssetArray(true, varXAssetList->assetCount);
m_stream->MarkFollowing(varXAssetList->assets);
#ifdef ARCH_x86
static_assert(offsetof(XAssetList, assets) == 20u);
#endif
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(20));
} }
m_stream->PopBlock(); m_stream->PopBlock();

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Writing/ContentWriterBase.h" #include "Writing/ContentWriterBase.h"
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
@@ -10,7 +11,7 @@ namespace T6
public: public:
explicit ContentWriter(const Zone& zone); explicit ContentWriter(const Zone& zone);
void WriteContent(IZoneOutputStream& stream) override; void WriteContent(ZoneOutputStream& stream) override;
private: private:
void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const; void CreateXAssetList(XAssetList& xAssetList, MemoryManager& memory) const;
@@ -23,5 +24,9 @@ namespace T6
XAssetList* varXAssetList; XAssetList* varXAssetList;
XAsset* varXAsset; XAsset* varXAsset;
ScriptStringList* varScriptStringList; ScriptStringList* varScriptStringList;
ZoneOutputOffset varXAssetListWritten;
ZoneOutputOffset varXAssetWritten;
ZoneOutputOffset varScriptStringListWritten;
}; };
} // namespace T6 } // namespace T6

View File

@@ -106,7 +106,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
SetupBlocks(*writer); SetupBlocks(*writer);
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>( auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(
std::make_unique<ContentWriter>(zone), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK); std::make_unique<ContentWriter>(zone), zone, 32u, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
auto* contentInMemoryPtr = contentInMemory.get(); auto* contentInMemoryPtr = contentInMemory.get();
writer->AddWritingStep(std::move(contentInMemory)); writer->AddWritingStep(std::move(contentInMemory));
@@ -119,7 +119,6 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
AddXChunkProcessor(*writer, zone, isEncrypted, &dataToSignProvider, &xChunksProcessor); AddXChunkProcessor(*writer, zone, isEncrypted, &dataToSignProvider, &xChunksProcessor);
// Start of the XFile struct // Start of the XFile struct
// m_writer->AddWritingStep(std::make_unique<StepSkipBytes>(8)); // Skip size and externalSize fields since they are not interesting for us
writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr)); writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone)); writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(zone));

View File

@@ -2,7 +2,7 @@
#include <cassert> #include <cassert>
AssetWriter::AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, IZoneOutputStream& stream) AssetWriter::AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, ZoneOutputStream& stream)
: ContentWriterBase(zone, stream), : ContentWriterBase(zone, stream),
m_asset(asset), m_asset(asset),
varScriptString(nullptr), varScriptString(nullptr),
@@ -18,16 +18,16 @@ const char* AssetWriter::NonReferenceAssetName(const char* assetName)
return assetName; return assetName;
} }
scr_string_t AssetWriter::UseScriptString(const scr_string_t scrString) const void AssetWriter::UseScriptString(const scr_string_t scrString, const ZoneOutputOffset written) const
{ {
assert(scrString < m_asset->m_zone->m_script_strings.Count()); assert(scrString < m_asset->m_zone->m_script_strings.Count());
if (m_asset->m_zone == &m_zone) if (m_asset->m_zone == &m_zone)
return scrString; return;
// The asset comes from a different zone, we need to translate it // The asset comes from a different zone, we need to translate it
const auto strValue = m_asset->m_zone->m_script_strings.CValue(scrString); const auto strValue = m_asset->m_zone->m_script_strings.CValue(scrString);
return m_zone.m_script_strings.GetScriptString(strValue); *static_cast<scr_string_t*>(written.Offset()) = m_zone.m_script_strings.GetScriptString(strValue);
} }
void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t count) void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t count)
@@ -38,12 +38,13 @@ void AssetWriter::WriteScriptStringArray(const bool atStreamStart, const size_t
varScriptStringWritten = m_stream->Write<scr_string_t>(varScriptString, count); varScriptStringWritten = m_stream->Write<scr_string_t>(varScriptString, count);
} }
assert(varScriptStringWritten != nullptr); assert(varScriptStringWritten.Offset() != nullptr);
auto* ptr = varScriptStringWritten;
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
*ptr = UseScriptString(*ptr); UseScriptString(*varScriptString, varScriptStringWritten);
ptr++;
varScriptString++;
varScriptStringWritten.Inc(sizeof(scr_string_t));
} }
} }

View File

@@ -2,21 +2,20 @@
#include "ContentWriterBase.h" #include "ContentWriterBase.h"
#include "Pool/XAssetInfo.h" #include "Pool/XAssetInfo.h"
#include "Utils/ClassUtils.h"
#include "Zone/Zone.h" #include "Zone/Zone.h"
#include "Zone/ZoneTypes.h" #include "Zone/ZoneTypes.h"
class AssetWriter : public ContentWriterBase class AssetWriter : public ContentWriterBase
{ {
protected: protected:
AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, IZoneOutputStream& stream); AssetWriter(XAssetInfoGeneric* asset, const Zone& zone, ZoneOutputStream& stream);
[[nodiscard]] static const char* NonReferenceAssetName(const char* assetName); [[nodiscard]] static const char* NonReferenceAssetName(const char* assetName);
[[nodiscard]] scr_string_t UseScriptString(scr_string_t scrString) const; void UseScriptString(scr_string_t scrString, ZoneOutputOffset written) const;
void WriteScriptStringArray(bool atStreamStart, size_t count); void WriteScriptStringArray(bool atStreamStart, size_t count);
XAssetInfoGeneric* m_asset; XAssetInfoGeneric* m_asset;
scr_string_t* varScriptString; scr_string_t* varScriptString;
scr_string_t* varScriptStringWritten; ZoneOutputOffset varScriptStringWritten;
}; };

View File

@@ -10,7 +10,7 @@ ContentWriterBase::ContentWriterBase(const Zone& zone)
{ {
} }
ContentWriterBase::ContentWriterBase(const Zone& zone, IZoneOutputStream& stream) ContentWriterBase::ContentWriterBase(const Zone& zone, ZoneOutputStream& stream)
: m_zone(zone), : m_zone(zone),
m_stream(&stream), m_stream(&stream),
varXString(nullptr), varXString(nullptr),
@@ -23,34 +23,36 @@ void ContentWriterBase::WriteXString(const bool atStreamStart)
if (atStreamStart) if (atStreamStart)
{ {
assert(varXString != nullptr); assert(varXString != nullptr);
varXStringWritten = m_stream->Write<const char*>(varXString); varXStringWritten = m_stream->WriteWithFill(m_stream->GetPointerByteCount()).Offset();
} }
assert(varXStringWritten != nullptr); assert(varXStringWritten.Offset() != nullptr);
if (m_stream->ReusableShouldWrite(varXStringWritten)) if (m_stream->ReusableShouldWrite(*varXString, varXStringWritten))
{ {
m_stream->Align(alignof(const char)); m_stream->Align(1);
m_stream->ReusableAddOffset(*varXStringWritten); m_stream->ReusableAddOffset(*varXString);
m_stream->WriteNullTerminated(*varXStringWritten); m_stream->WriteNullTerminated(*varXString);
m_stream->MarkFollowing(*varXStringWritten); m_stream->MarkFollowing(varXStringWritten);
} }
} }
void ContentWriterBase::WriteXStringArray(const bool atStreamStart, const size_t count) void ContentWriterBase::WriteXStringArray(const bool atStreamStart, const size_t count)
{ {
const auto pointerByteCount = m_stream->GetPointerByteCount();
if (atStreamStart) if (atStreamStart)
{ {
assert(varXString != nullptr); assert(varXString != nullptr);
varXStringWritten = m_stream->Write<const char*>(varXString, count); varXStringWritten = m_stream->WriteWithFill(pointerByteCount * count).Offset();
} }
assert(varXStringWritten != nullptr); assert(varXStringWritten.Offset() != nullptr);
for (size_t index = 0; index < count; index++) for (size_t index = 0; index < count; index++)
{ {
WriteXString(false); WriteXString(false);
varXStringWritten++; varXString++;
varXStringWritten.Inc(pointerByteCount);
} }
} }

View File

@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "Zone/Stream/IZoneOutputStream.h" #include "Zone/Stream/ZoneOutputStream.h"
#include "Zone/Zone.h" #include "Zone/Zone.h"
class ContentWriterBase class ContentWriterBase
{ {
protected: protected:
explicit ContentWriterBase(const Zone& zone); explicit ContentWriterBase(const Zone& zone);
ContentWriterBase(const Zone& zone, IZoneOutputStream& stream); ContentWriterBase(const Zone& zone, ZoneOutputStream& stream);
public: public:
virtual ~ContentWriterBase() = default; virtual ~ContentWriterBase() = default;
@@ -21,8 +21,8 @@ protected:
void WriteXStringArray(bool atStreamStart, size_t count); void WriteXStringArray(bool atStreamStart, size_t count);
const Zone& m_zone; const Zone& m_zone;
IZoneOutputStream* m_stream; ZoneOutputStream* m_stream;
const char** varXString; const char** varXString;
const char** varXStringWritten; ZoneOutputOffset varXStringWritten;
}; };

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Zone/Stream/IZoneOutputStream.h" #include "Zone/Stream/ZoneOutputStream.h"
class IContentWritingEntryPoint class IContentWritingEntryPoint
{ {
@@ -12,5 +12,5 @@ public:
IContentWritingEntryPoint& operator=(const IContentWritingEntryPoint& other) = default; IContentWritingEntryPoint& operator=(const IContentWritingEntryPoint& other) = default;
IContentWritingEntryPoint& operator=(IContentWritingEntryPoint&& other) noexcept = default; IContentWritingEntryPoint& operator=(IContentWritingEntryPoint&& other) noexcept = default;
virtual void WriteContent(IZoneOutputStream& stream) = 0; virtual void WriteContent(ZoneOutputStream& stream) = 0;
}; };

View File

@@ -1,14 +1,16 @@
#include "StepWriteZoneContentToMemory.h" #include "StepWriteZoneContentToMemory.h"
#include "Zone/Stream/Impl/InMemoryZoneOutputStream.h" #include "Zone/Stream/ZoneOutputStream.h"
StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr<IContentWritingEntryPoint> entryPoint, StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr<IContentWritingEntryPoint> entryPoint,
const Zone& zone, const Zone& zone,
const int offsetBlockBitCount, const unsigned pointerBitCount,
const unsigned offsetBlockBitCount,
const block_t insertBlock) const block_t insertBlock)
: m_content_loader(std::move(entryPoint)), : m_content_loader(std::move(entryPoint)),
m_zone_data(std::make_unique<InMemoryZoneData>()), m_zone_data(std::make_unique<InMemoryZoneData>()),
m_zone(zone), m_zone(zone),
m_pointer_bit_count(pointerBitCount),
m_offset_block_bit_count(offsetBlockBitCount), m_offset_block_bit_count(offsetBlockBitCount),
m_insert_block(insertBlock) m_insert_block(insertBlock)
{ {
@@ -16,12 +18,11 @@ StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr<ICont
void StepWriteZoneContentToMemory::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) void StepWriteZoneContentToMemory::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
{ {
std::vector<XBlock*> blocks; m_blocks.reserve(zoneWriter->m_blocks.size());
blocks.reserve(zoneWriter->m_blocks.size());
for (const auto& block : zoneWriter->m_blocks) for (const auto& block : zoneWriter->m_blocks)
blocks.emplace_back(block.get()); m_blocks.emplace_back(block.get());
const auto zoneOutputStream = std::make_unique<InMemoryZoneOutputStream>(m_zone_data.get(), std::move(blocks), m_offset_block_bit_count, m_insert_block); const auto zoneOutputStream = ZoneOutputStream::Create(m_pointer_bit_count, m_offset_block_bit_count, m_blocks, m_insert_block, *m_zone_data);
m_content_loader->WriteContent(*zoneOutputStream); m_content_loader->WriteContent(*zoneOutputStream);
} }

View File

@@ -2,14 +2,15 @@
#include "Writing/IContentWritingEntryPoint.h" #include "Writing/IContentWritingEntryPoint.h"
#include "Writing/IWritingStep.h" #include "Writing/IWritingStep.h"
#include "Writing/InMemoryZoneData.h" #include "Zone/Stream/InMemoryZoneData.h"
#include <memory> #include <memory>
class StepWriteZoneContentToMemory final : public IWritingStep class StepWriteZoneContentToMemory final : public IWritingStep
{ {
public: public:
StepWriteZoneContentToMemory(std::unique_ptr<IContentWritingEntryPoint> entryPoint, const Zone& zone, int offsetBlockBitCount, block_t insertBlock); StepWriteZoneContentToMemory(
std::unique_ptr<IContentWritingEntryPoint> entryPoint, const Zone& zone, unsigned pointerBitCount, unsigned offsetBlockBitCount, block_t insertBlock);
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override; void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
[[nodiscard]] InMemoryZoneData* GetData() const; [[nodiscard]] InMemoryZoneData* GetData() const;
@@ -18,6 +19,9 @@ private:
std::unique_ptr<IContentWritingEntryPoint> m_content_loader; std::unique_ptr<IContentWritingEntryPoint> m_content_loader;
std::unique_ptr<InMemoryZoneData> m_zone_data; std::unique_ptr<InMemoryZoneData> m_zone_data;
const Zone& m_zone; const Zone& m_zone;
int m_offset_block_bit_count; std::vector<XBlock*> m_blocks;
unsigned m_pointer_bit_count;
unsigned m_offset_block_bit_count;
block_t m_insert_block; block_t m_insert_block;
}; };

View File

@@ -1,5 +1,7 @@
#include "StepWriteZoneSizes.h" #include "StepWriteZoneSizes.h"
#include <cstdint>
StepWriteZoneSizes::StepWriteZoneSizes(StepWriteZoneContentToMemory* memory) StepWriteZoneSizes::StepWriteZoneSizes(StepWriteZoneContentToMemory* memory)
: m_memory(memory) : m_memory(memory)
{ {
@@ -7,8 +9,8 @@ StepWriteZoneSizes::StepWriteZoneSizes(StepWriteZoneContentToMemory* memory)
void StepWriteZoneSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) void StepWriteZoneSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
{ {
auto totalSize = static_cast<size_t>(m_memory->GetData()->m_total_size); const auto totalSize = static_cast<uint32_t>(m_memory->GetData()->m_total_size);
size_t externalSize = 0; constexpr uint32_t externalSize = 0;
stream->Write(&totalSize, sizeof(totalSize)); stream->Write(&totalSize, sizeof(totalSize));
stream->Write(&externalSize, sizeof(externalSize)); stream->Write(&externalSize, sizeof(externalSize));

View File

@@ -1,60 +0,0 @@
#pragma once
#include "Zone/Stream/IZoneStream.h"
#include <cstddef>
#include <typeindex>
#include <typeinfo>
class IZoneOutputStream : public IZoneStream
{
public:
inline static void* const PTR_FOLLOWING = reinterpret_cast<void*>(-1);
inline static void* const PTR_INSERT = reinterpret_cast<void*>(-2);
virtual void Align(int alignTo) = 0;
virtual void* WriteDataRaw(const void* dst, size_t size) = 0;
virtual void* WriteDataInBlock(const void* dst, size_t size) = 0;
virtual void IncBlockPos(size_t size) = 0;
virtual void WriteNullTerminated(const void* dst) = 0;
virtual bool ReusableShouldWrite(void** pPtr, size_t size, std::type_index type) = 0;
virtual void ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) = 0;
virtual void MarkFollowing(void** pPtr) = 0;
template<typename T> bool ReusableShouldWrite(T** pPtr)
{
return ReusableShouldWrite(reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(pPtr)), sizeof(T), std::type_index(typeid(T)));
}
template<typename T> void ReusableAddOffset(T* ptr)
{
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), 1, std::type_index(typeid(T)));
}
template<typename T> void ReusableAddOffset(T* ptr, const size_t count)
{
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), count, std::type_index(typeid(T)));
}
template<typename T> T* Write(T* dst)
{
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), sizeof(T)));
}
template<typename T> T* Write(T* dst, const size_t count)
{
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), count * sizeof(T)));
}
template<typename T> T* WritePartial(T* dst, const size_t size)
{
return static_cast<T*>(WriteDataInBlock(reinterpret_cast<const void*>(dst), size));
}
template<typename T> void MarkFollowing(T*& ptr)
{
MarkFollowing(reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(&ptr)));
}
};

View File

@@ -1,218 +0,0 @@
#include "InMemoryZoneOutputStream.h"
#include <cassert>
#include <cstring>
InMemoryZoneOutputStream::InMemoryZoneOutputStream(InMemoryZoneData* zoneData, std::vector<XBlock*> blocks, const int blockBitCount, const block_t insertBlock)
: m_zone_data(zoneData),
m_blocks(std::move(blocks)),
m_block_bit_count(blockBitCount),
m_insert_block(m_blocks[insertBlock])
{
}
InMemoryZoneOutputStream::ReusableEntry::ReusableEntry(void* startPtr, const size_t entrySize, const size_t entryCount, const uintptr_t startZonePtr)
: m_start_ptr(startPtr),
m_end_ptr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(startPtr) + entrySize * entryCount)),
m_start_zone_ptr(startZonePtr),
m_entry_size(entrySize),
m_entry_count(entryCount)
{
}
void InMemoryZoneOutputStream::PushBlock(const block_t block)
{
assert(block >= 0 && block < static_cast<block_t>(m_blocks.size()));
auto* newBlock = m_blocks[block];
assert(newBlock->m_index == block);
m_block_stack.push(newBlock);
if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP)
{
if (m_temp_sizes.empty())
m_temp_sizes.push(0);
else
m_temp_sizes.push(m_temp_sizes.top());
}
}
block_t InMemoryZoneOutputStream::PopBlock()
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return -1;
auto* poppedBlock = m_block_stack.top();
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 == XBlockType::BLOCK_TYPE_TEMP)
{
const auto tempSize = m_temp_sizes.top();
m_temp_sizes.pop();
if (tempSize > poppedBlock->m_buffer_size)
poppedBlock->m_buffer_size = tempSize;
}
return poppedBlock->m_index;
}
void InMemoryZoneOutputStream::Align(const int align)
{
assert(!m_block_stack.empty());
if (align > 1)
{
auto* block = m_block_stack.top();
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;
}
}
void* InMemoryZoneOutputStream::WriteDataRaw(const void* src, const size_t size)
{
auto* result = m_zone_data->GetBufferOfSize(size);
memcpy(result, src, size);
return result;
}
void* InMemoryZoneOutputStream::WriteDataInBlock(const void* src, const size_t size)
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return nullptr;
auto* block = m_block_stack.top();
void* result = nullptr;
switch (block->m_type)
{
case XBlockType::BLOCK_TYPE_TEMP:
case XBlockType::BLOCK_TYPE_NORMAL:
result = m_zone_data->GetBufferOfSize(size);
memcpy(result, src, size);
break;
case XBlockType::BLOCK_TYPE_RUNTIME:
break;
case XBlockType::BLOCK_TYPE_DELAY:
assert(false);
break;
}
IncBlockPos(size);
return result;
}
void InMemoryZoneOutputStream::IncBlockPos(const size_t size)
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return;
auto* block = m_block_stack.top();
if (block->m_type == XBlockType::BLOCK_TYPE_TEMP)
{
m_temp_sizes.top() += size;
}
else
{
block->m_buffer_size += size;
}
}
void InMemoryZoneOutputStream::WriteNullTerminated(const void* src)
{
const auto len = strlen(static_cast<const char*>(src));
WriteDataInBlock(src, len + 1);
}
uintptr_t InMemoryZoneOutputStream::GetCurrentZonePointer()
{
assert(!m_block_stack.empty());
assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL);
uintptr_t ptr = 0;
ptr |= static_cast<uintptr_t>(m_block_stack.top()->m_index) << (sizeof(uintptr_t) * 8 - m_block_bit_count);
ptr |= m_block_stack.top()->m_buffer_size & (UINTPTR_MAX >> m_block_bit_count);
ptr++;
return ptr;
}
uintptr_t InMemoryZoneOutputStream::InsertPointer()
{
PushBlock(m_insert_block->m_index);
Align(sizeof(uintptr_t));
const auto result = GetCurrentZonePointer();
IncBlockPos(sizeof(uintptr_t));
PopBlock();
return result;
}
void InMemoryZoneOutputStream::MarkFollowing(void** pPtr)
{
assert(!m_block_stack.empty());
assert(pPtr != nullptr);
*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)
{
assert(!m_block_stack.empty());
assert(pPtr != nullptr);
if (*pPtr == nullptr)
return false;
const auto foundEntriesForType = m_reusable_entries.find(type);
if (foundEntriesForType == m_reusable_entries.end())
{
return true;
}
for (const auto& entry : foundEntriesForType->second)
{
if (*pPtr >= entry.m_start_ptr && *pPtr < entry.m_end_ptr)
{
assert((reinterpret_cast<uintptr_t>(*pPtr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)) % entrySize == 0);
*pPtr = reinterpret_cast<void*>(entry.m_start_zone_ptr + (reinterpret_cast<uintptr_t>(*pPtr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)));
return false;
}
}
return true;
}
void InMemoryZoneOutputStream::ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type)
{
assert(!m_block_stack.empty());
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())
{
std::vector<ReusableEntry> entries;
entries.emplace_back(ptr, size, count, zoneOffset);
m_reusable_entries.emplace(std::make_pair(type, std::move(entries)));
}
else
{
foundEntriesForType->second.emplace_back(ptr, size, count, zoneOffset);
}
}

View File

@@ -1,51 +0,0 @@
#pragma once
#include "Writing/InMemoryZoneData.h"
#include "Zone/Stream/IZoneOutputStream.h"
#include "Zone/XBlock.h"
#include <stack>
#include <unordered_map>
#include <vector>
class InMemoryZoneOutputStream final : public IZoneOutputStream
{
class ReusableEntry
{
public:
void* m_start_ptr;
void* m_end_ptr;
uintptr_t m_start_zone_ptr;
size_t m_entry_size;
size_t m_entry_count;
ReusableEntry(void* startPtr, size_t entrySize, size_t entryCount, uintptr_t startZonePtr);
};
InMemoryZoneData* m_zone_data;
std::vector<XBlock*> m_blocks;
std::stack<XBlock*> m_block_stack;
std::stack<size_t> m_temp_sizes;
int m_block_bit_count;
XBlock* m_insert_block;
std::unordered_map<std::type_index, std::vector<ReusableEntry>> m_reusable_entries;
uintptr_t GetCurrentZonePointer();
uintptr_t InsertPointer();
public:
InMemoryZoneOutputStream(InMemoryZoneData* zoneData, std::vector<XBlock*> blocks, int blockBitCount, block_t insertBlock);
void PushBlock(block_t block) override;
block_t PopBlock() override;
void Align(int align) override;
void* WriteDataRaw(const void* src, size_t size) override;
void* WriteDataInBlock(const void* src, size_t size) override;
void IncBlockPos(size_t size) override;
void WriteNullTerminated(const void* src) override;
void MarkFollowing(void** pPtr) override;
bool ReusableShouldWrite(void** pPtr, size_t entrySize, std::type_index type) override;
void ReusableAddOffset(void* ptr, size_t size, size_t count, std::type_index type) override;
};

View File

@@ -0,0 +1,375 @@
#include "ZoneOutputStream.h"
#include "InMemoryZoneData.h"
#include "Utils/Alignment.h"
#include "Zone/XBlock.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <stack>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace
{
class ReusableEntry
{
public:
ReusableEntry(void* startPtr, const size_t entrySize, const size_t entryCount, const size_t blockSize, const uintptr_t startZonePtr)
: m_start_ptr(startPtr),
m_end_ptr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(startPtr) + entrySize * entryCount)),
m_start_zone_ptr(startZonePtr),
m_entry_size(entrySize),
m_entry_count(entryCount),
m_block_size(blockSize)
{
}
void* m_start_ptr;
void* m_end_ptr;
uintptr_t m_start_zone_ptr;
size_t m_entry_size;
size_t m_entry_count;
size_t m_block_size;
};
class InMemoryZoneOutputStream final : public ZoneOutputStream
{
public:
InMemoryZoneOutputStream(
const unsigned pointerBitCount, const unsigned blockBitCount, std::vector<XBlock*>& blocks, const block_t insertBlock, InMemoryZoneData& zoneData)
: m_zone_data(zoneData),
m_blocks(blocks),
m_block_bit_count(blockBitCount),
m_pointer_byte_count(pointerBitCount / 8u),
// -1
m_zone_ptr_following(std::numeric_limits<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)),
// -2
m_zone_ptr_insert((std::numeric_limits<std::uintptr_t>::max() >> ((sizeof(std::uintptr_t) * 8u) - pointerBitCount)) - 1u)
{
assert(pointerBitCount % 8u == 0u);
assert(insertBlock < static_cast<block_t>(blocks.size()));
m_insert_block = blocks[insertBlock];
}
[[nodiscard]] unsigned GetPointerByteCount() const override
{
return m_pointer_byte_count;
}
void PushBlock(const block_t block) override
{
assert(block < static_cast<block_t>(m_blocks.size()));
auto* newBlock = m_blocks[block];
assert(newBlock->m_index == block);
m_block_stack.push(newBlock);
if (newBlock->m_type == XBlockType::BLOCK_TYPE_TEMP)
{
if (m_temp_sizes.empty())
m_temp_sizes.push(0);
else
m_temp_sizes.push(m_temp_sizes.top());
}
}
block_t PopBlock() override
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return -1;
auto* poppedBlock = m_block_stack.top();
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 == XBlockType::BLOCK_TYPE_TEMP)
{
const auto tempSize = m_temp_sizes.top();
m_temp_sizes.pop();
poppedBlock->m_buffer_size = std::max(tempSize, poppedBlock->m_buffer_size);
}
return poppedBlock->m_index;
}
void Align(const unsigned align) override
{
assert(!m_block_stack.empty());
if (align > 1)
{
auto* block = m_block_stack.top();
if (block->m_type == XBlockType::BLOCK_TYPE_TEMP)
m_temp_sizes.top() = utils::Align(m_temp_sizes.top(), static_cast<size_t>(align));
else
block->m_buffer_size = utils::Align(block->m_buffer_size, static_cast<size_t>(align));
}
}
ZoneOutputOffset WriteDataRaw(const void* src, const size_t size) override
{
auto* result = m_zone_data.GetBufferOfSize(size);
memcpy(result, src, size);
return ZoneOutputOffset(result);
}
ZoneOutputOffset WriteDataInBlock(const void* src, const size_t size) override
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return ZoneOutputOffset();
const auto* block = m_block_stack.top();
void* result = nullptr;
switch (block->m_type)
{
case XBlockType::BLOCK_TYPE_TEMP:
case XBlockType::BLOCK_TYPE_NORMAL:
result = m_zone_data.GetBufferOfSize(size);
memcpy(result, src, size);
break;
case XBlockType::BLOCK_TYPE_RUNTIME:
break;
case XBlockType::BLOCK_TYPE_DELAY:
assert(false);
break;
}
IncBlockPos(size);
return ZoneOutputOffset(result);
}
void IncBlockPos(const size_t size) override
{
assert(!m_block_stack.empty());
if (m_block_stack.empty())
return;
auto* block = m_block_stack.top();
if (block->m_type == XBlockType::BLOCK_TYPE_TEMP)
{
m_temp_sizes.top() += size;
}
else
{
block->m_buffer_size += size;
}
}
void WriteNullTerminated(const void* src) override
{
const auto len = strlen(static_cast<const char*>(src));
WriteDataInBlock(src, len + 1);
}
ZoneStreamFillWriteAccessor WriteWithFill(const size_t size) override
{
// If no block has been pushed, load raw
if (!m_block_stack.empty())
{
const auto* block = m_block_stack.top();
void* result = nullptr;
switch (block->m_type)
{
case XBlockType::BLOCK_TYPE_TEMP:
case XBlockType::BLOCK_TYPE_NORMAL:
result = m_zone_data.GetBufferOfSize(size);
break;
case XBlockType::BLOCK_TYPE_RUNTIME:
case XBlockType::BLOCK_TYPE_DELAY:
assert(false);
break;
}
IncBlockPos(size);
return ZoneStreamFillWriteAccessor(result, size);
}
return ZoneStreamFillWriteAccessor(m_zone_data.GetBufferOfSize(size), size);
}
void MarkFollowing(const ZoneOutputOffset outputOffset) override
{
assert(!m_block_stack.empty());
auto* ptr = static_cast<char*>(outputOffset.Offset());
assert(ptr != nullptr);
if (m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_TEMP)
{
for (auto i = 0u; i < m_pointer_byte_count; i++)
ptr[i] = reinterpret_cast<const char*>(&m_zone_ptr_insert)[i];
}
else
{
for (auto i = 0u; i < m_pointer_byte_count; i++)
ptr[i] = reinterpret_cast<const char*>(&m_zone_ptr_following)[i];
}
}
bool ReusableShouldWrite(void* ptr, const ZoneOutputOffset outputOffset, const size_t entrySize, const std::type_index type) override
{
assert(!m_block_stack.empty());
if (ptr == nullptr)
return false;
const auto foundEntriesForType = m_reusable_entries.find(type);
if (foundEntriesForType == m_reusable_entries.end())
{
return true;
}
for (const auto& entry : foundEntriesForType->second)
{
if (ptr >= entry.m_start_ptr && ptr < entry.m_end_ptr)
{
assert((reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)) % entrySize == 0);
const auto entryIndex = (reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(entry.m_start_ptr)) / entry.m_entry_size;
const auto finalZonePointer = entry.m_start_zone_ptr + entryIndex * entry.m_block_size;
auto* writtenPtrOffset = outputOffset.Offset();
for (auto i = 0u; i < m_pointer_byte_count; i++)
static_cast<char*>(writtenPtrOffset)[i] = reinterpret_cast<const char*>(&finalZonePointer)[i];
return false;
}
}
return true;
}
void ReusableAddOffset(void* ptr, const size_t size, const size_t count, const size_t blockSize, std::type_index type) override
{
assert(!m_block_stack.empty());
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())
{
std::vector<ReusableEntry> entries;
entries.emplace_back(ptr, size, count, blockSize, zoneOffset);
m_reusable_entries.emplace(std::make_pair(type, std::move(entries)));
}
else
{
foundEntriesForType->second.emplace_back(ptr, size, count, blockSize, zoneOffset);
}
}
private:
uintptr_t GetCurrentZonePointer()
{
assert(!m_block_stack.empty());
assert(m_block_stack.top()->m_type == XBlockType::BLOCK_TYPE_NORMAL);
uintptr_t ptr = 0;
ptr |= static_cast<uintptr_t>(m_block_stack.top()->m_index) << (m_pointer_byte_count * 8 - m_block_bit_count);
ptr |= m_block_stack.top()->m_buffer_size & (UINTPTR_MAX >> (m_block_bit_count + (sizeof(uintptr_t) - m_pointer_byte_count) * 8));
ptr++;
return ptr;
}
uintptr_t InsertPointer()
{
PushBlock(m_insert_block->m_index);
Align(m_pointer_byte_count);
const auto result = GetCurrentZonePointer();
IncBlockPos(m_pointer_byte_count);
PopBlock();
return result;
}
InMemoryZoneData& m_zone_data;
std::vector<XBlock*>& m_blocks;
std::stack<XBlock*> m_block_stack;
std::stack<size_t> m_temp_sizes;
unsigned m_block_bit_count;
unsigned m_pointer_byte_count;
XBlock* m_insert_block;
uintptr_t m_zone_ptr_following;
uintptr_t m_zone_ptr_insert;
std::unordered_map<std::type_index, std::vector<ReusableEntry>> m_reusable_entries;
};
} // namespace
ZoneOutputOffset::ZoneOutputOffset()
: m_offset(nullptr)
{
}
ZoneOutputOffset::ZoneOutputOffset(void* offset)
: m_offset(offset)
{
}
ZoneOutputOffset ZoneOutputOffset::AtOffset(const size_t innerOffset) const
{
return ZoneOutputOffset(static_cast<char*>(m_offset) + innerOffset);
}
void ZoneOutputOffset::Inc(const size_t size)
{
m_offset = static_cast<void*>(static_cast<char*>(m_offset) + size);
}
void* ZoneOutputOffset::Offset() const
{
return m_offset;
}
std::unique_ptr<ZoneOutputStream>
ZoneOutputStream::Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector<XBlock*>& blocks, block_t insertBlock, InMemoryZoneData& zoneData)
{
return std::make_unique<InMemoryZoneOutputStream>(pointerBitCount, blockBitCount, blocks, insertBlock, zoneData);
}
ZoneStreamFillWriteAccessor::ZoneStreamFillWriteAccessor(void* blockBuffer, const size_t bufferSize)
: m_block_buffer(blockBuffer),
m_buffer_size(bufferSize)
{
}
ZoneStreamFillWriteAccessor ZoneStreamFillWriteAccessor::AtOffset(const size_t offset) const
{
assert(m_block_buffer);
return ZoneStreamFillWriteAccessor(static_cast<char*>(m_block_buffer) + offset, m_buffer_size - offset);
}
ZoneOutputOffset ZoneStreamFillWriteAccessor::Offset() const
{
assert(m_block_buffer);
return ZoneOutputOffset(m_block_buffer);
}

View File

@@ -0,0 +1,148 @@
#pragma once
#include "InMemoryZoneData.h"
#include "Zone/Stream/IZoneStream.h"
#include "Zone/XBlock.h"
#include <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <typeindex>
#include <typeinfo>
#include <vector>
class ZoneOutputOffset
{
public:
ZoneOutputOffset();
explicit ZoneOutputOffset(void* offset);
[[nodiscard]] ZoneOutputOffset AtOffset(size_t innerOffset) const;
void Inc(size_t size);
[[nodiscard]] void* Offset() const;
private:
void* m_offset;
};
class ZoneStreamFillWriteAccessor
{
public:
ZoneStreamFillWriteAccessor(void* blockBuffer, size_t bufferSize);
[[nodiscard]] ZoneStreamFillWriteAccessor AtOffset(size_t offset) const;
[[nodiscard]] ZoneOutputOffset Offset() const;
template<typename T>
requires(sizeof(T) <= sizeof(uintptr_t))
void Fill(const T& value, const size_t offset) const
{
assert(m_block_buffer);
assert(offset + sizeof(T) <= m_buffer_size);
*reinterpret_cast<T*>(static_cast<char*>(m_block_buffer) + offset) = value;
}
template<typename T>
requires(sizeof(T) > sizeof(uintptr_t))
void Fill(const T& value, const size_t offset) const
{
assert(m_block_buffer);
assert(offset + sizeof(T) <= m_buffer_size);
std::memcpy(static_cast<char*>(m_block_buffer) + offset, &value, sizeof(T));
}
template<typename T, size_t S> void FillArray(T (&value)[S], const size_t offset) const
{
assert(m_block_buffer);
assert(offset + sizeof(T) * S <= m_buffer_size);
std::memcpy(static_cast<char*>(m_block_buffer) + offset, value, sizeof(T) * S);
}
private:
void* m_block_buffer;
size_t m_buffer_size;
};
class ZoneOutputStream : public IZoneStream
{
public:
/**
* \brief Returns the configured bits that make up a pointer.
*/
[[nodiscard]] virtual unsigned GetPointerByteCount() const = 0;
/**
* \brief Aligns the write position in the current block with the specified value.
* \param align The alignment value that the write position is aligned with. This should typically be the alignment of the struct that
* should be written afterward.
*/
virtual void Align(unsigned align) = 0;
/**
* \brief Write data to the zone data without considering the current block or advancing the block position.
* The data is written directly to the specified location instead of block memory.
* \param dst The memory location to write data to.
* \param size The amount of data to write.
*/
virtual ZoneOutputOffset WriteDataRaw(const void* dst, size_t size) = 0;
/**
* \brief Write data with the current blocks write operation into its block memory.
* Depending on the block type, the underlying stream might be written to or not.
* The current block position is advanced by the number of bytes written.
* The destination must be inside the current block's memory space, otherwise an exception is thrown.
* \param dst The destination where the data is written to. Must be inside the current block's memory bounds.
* \param size The amount of data to write.
*/
virtual ZoneOutputOffset WriteDataInBlock(const void* dst, size_t size) = 0;
virtual void IncBlockPos(size_t size) = 0;
virtual void WriteNullTerminated(const void* dst) = 0;
virtual ZoneStreamFillWriteAccessor WriteWithFill(size_t size) = 0;
virtual bool ReusableShouldWrite(void* pPtr, ZoneOutputOffset outputOffset, size_t size, std::type_index type) = 0;
virtual void ReusableAddOffset(void* ptr, size_t size, size_t count, size_t blockSize, std::type_index type) = 0;
virtual void MarkFollowing(ZoneOutputOffset offset) = 0;
template<typename T> bool ReusableShouldWrite(T* pPtr, const ZoneOutputOffset outputOffset)
{
return ReusableShouldWrite(const_cast<void*>(reinterpret_cast<const void*>(pPtr)), outputOffset, sizeof(T), std::type_index(typeid(T)));
}
template<typename T> void ReusableAddOffset(T* ptr)
{
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), 1, sizeof(T), std::type_index(typeid(T)));
}
template<typename T> void ReusableAddOffset(T* ptr, const size_t count)
{
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), count, sizeof(T), std::type_index(typeid(T)));
}
template<typename T> void ReusableAddOffset(T* ptr, const size_t blockSize, const size_t count)
{
ReusableAddOffset(const_cast<void*>(reinterpret_cast<const void*>(ptr)), sizeof(T), count, blockSize, std::type_index(typeid(T)));
}
template<typename T> ZoneOutputOffset Write(T* dst)
{
return WriteDataInBlock(reinterpret_cast<const void*>(dst), sizeof(T));
}
template<typename T> ZoneOutputOffset Write(T* dst, const size_t count)
{
return WriteDataInBlock(reinterpret_cast<const void*>(dst), count * sizeof(T));
}
ZoneOutputOffset WritePartial(const void* dst, const size_t size)
{
return WriteDataInBlock(dst, size);
}
static std::unique_ptr<ZoneOutputStream>
Create(unsigned pointerBitCount, unsigned blockBitCount, std::vector<XBlock*>& blocks, block_t insertBlock, InMemoryZoneData& zoneData);
};

View File

@@ -46,8 +46,6 @@ namespace
REQUIRE(linkerResult); REQUIRE(linkerResult);
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW3.ff").string(); const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW3.ff").string();
auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt); auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt);
REQUIRE(maybeZone); REQUIRE(maybeZone);
@@ -60,6 +58,5 @@ namespace
REQUIRE(zone->m_name == "SimpleZoneIW3"); REQUIRE(zone->m_name == "SimpleZoneIW3");
REQUIRE(pools->GetTotalAssetCount() == 1); REQUIRE(pools->GetTotalAssetCount() == 1);
REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt")); REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt"));
#endif
} }
} // namespace } // namespace

View File

@@ -46,8 +46,6 @@ namespace
REQUIRE(linkerResult); REQUIRE(linkerResult);
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW4.ff").string(); const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW4.ff").string();
auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt); auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt);
REQUIRE(maybeZone); REQUIRE(maybeZone);
@@ -60,6 +58,5 @@ namespace
REQUIRE(zone->m_name == "SimpleZoneIW4"); REQUIRE(zone->m_name == "SimpleZoneIW4");
REQUIRE(pools->GetTotalAssetCount() == 1); REQUIRE(pools->GetTotalAssetCount() == 1);
REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt")); REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt"));
#endif
} }
} // namespace } // namespace

View File

@@ -46,8 +46,6 @@ namespace
REQUIRE(linkerResult); REQUIRE(linkerResult);
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW5.ff").string(); const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneIW5.ff").string();
auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt); auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt);
REQUIRE(maybeZone); REQUIRE(maybeZone);
@@ -60,6 +58,5 @@ namespace
REQUIRE(zone->m_name == "SimpleZoneIW5"); REQUIRE(zone->m_name == "SimpleZoneIW5");
REQUIRE(pools->GetTotalAssetCount() == 1); REQUIRE(pools->GetTotalAssetCount() == 1);
REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt")); REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt"));
#endif
} }
} // namespace } // namespace

View File

@@ -46,8 +46,6 @@ namespace
REQUIRE(linkerResult); REQUIRE(linkerResult);
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneT5.ff").string(); const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneT5.ff").string();
auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt); auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt);
REQUIRE(maybeZone); REQUIRE(maybeZone);
@@ -60,6 +58,5 @@ namespace
REQUIRE(zone->m_name == "SimpleZoneT5"); REQUIRE(zone->m_name == "SimpleZoneT5");
REQUIRE(pools->GetTotalAssetCount() == 1); REQUIRE(pools->GetTotalAssetCount() == 1);
REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt")); REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt"));
#endif
} }
} // namespace } // namespace

View File

@@ -115,8 +115,6 @@ namespace
REQUIRE(material->Asset()->techniqueSet->techniques[T6::TECHNIQUE_UNLIT]); REQUIRE(material->Asset()->techniqueSet->techniques[T6::TECHNIQUE_UNLIT]);
} }
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
TEST_CASE("Extend and dereference(T6)", "[t6][system][simple]") TEST_CASE("Extend and dereference(T6)", "[t6][system][simple]")
{ {
const auto testDir = oat::paths::GetSystemTestsDirectory() / "Game/T6/ExtendAndDereference"; const auto testDir = oat::paths::GetSystemTestsDirectory() / "Game/T6/ExtendAndDereference";
@@ -126,5 +124,4 @@ namespace
BuildCombinedZone(testDir, outputPath); BuildCombinedZone(testDir, outputPath);
CheckCombinedZoneContent(outputPath); CheckCombinedZoneContent(outputPath);
} }
#endif
} // namespace } // namespace

View File

@@ -122,8 +122,6 @@ namespace
REQUIRE(zone->m_script_strings.Value(xmodel->Asset()->boneNames[2]) == "EarRight2"); REQUIRE(zone->m_script_strings.Value(xmodel->Asset()->boneNames[2]) == "EarRight2");
} }
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
TEST_CASE("Reuse assets from global asset pool(T6)", "[t6][system][simple]") TEST_CASE("Reuse assets from global asset pool(T6)", "[t6][system][simple]")
{ {
const auto testDir = oat::paths::GetSystemTestsDirectory() / "Game/T6/ReuseGlobalAssetPoolsAssets"; const auto testDir = oat::paths::GetSystemTestsDirectory() / "Game/T6/ReuseGlobalAssetPoolsAssets";
@@ -133,5 +131,4 @@ namespace
BuildTestZone(testDir, outputPath); BuildTestZone(testDir, outputPath);
CheckTestZoneContent(outputPath); CheckTestZoneContent(outputPath);
} }
#endif
} // namespace } // namespace

View File

@@ -46,8 +46,6 @@ namespace
REQUIRE(linkerResult); REQUIRE(linkerResult);
// x64 for now produces invalid zones, don't try to load them yet
#ifdef ARCH_x86
const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneT6.ff").string(); const auto expectedZonePath = (fs::path(outputPath) / "SimpleZoneT6.ff").string();
auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt); auto maybeZone = ZoneLoading::LoadZone(expectedZonePath, std::nullopt);
REQUIRE(maybeZone); REQUIRE(maybeZone);
@@ -60,6 +58,5 @@ namespace
REQUIRE(zone->m_name == "SimpleZoneT6"); REQUIRE(zone->m_name == "SimpleZoneT6");
REQUIRE(pools->GetTotalAssetCount() == 1); REQUIRE(pools->GetTotalAssetCount() == 1);
REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt")); REQUIRE(pools->m_raw_file->GetAsset("SimpleZone.txt"));
#endif
} }
} // namespace } // namespace

View File

@@ -0,0 +1,96 @@
#include "Game/T6/GameAssetPoolT6.h"
#include "OatTestPaths.h"
#include "Utils/Logging/Log.h"
#include "Utils/StringUtils.h"
#include "ZoneLoading.h"
#include "ZoneWriting.h"
#include <catch2/catch_test_macros.hpp>
#include <filesystem>
#include <format>
#include <fstream>
#include <memory>
#include <string>
namespace fs = std::filesystem;
using namespace std::literals;
/*
* This test is only run when the user defines the environment variable OAT_FASTFILE_DIR containing the path to a folder containing fastfiles.
*/
namespace
{
void EnsureCanRebuildFastFile(const fs::path& outputPath, const fs::path& fastFilePath)
{
const auto fastFilePathStr = fastFilePath.string();
const auto tempFilePath = outputPath / "temp.ff";
const auto tempFilePathStr = tempFilePath.string();
con::info("Testing for rebuild: {}", fastFilePathStr);
auto maybeZone = ZoneLoading::LoadZone(fastFilePathStr, std::nullopt);
REQUIRE(maybeZone.has_value());
auto zone = std::move(*maybeZone);
zone->m_name = "temp";
{
std::ofstream outStream(tempFilePath, std::ios::out | std::ios::binary);
REQUIRE(outStream.is_open());
const auto linkingResult = ZoneWriting::WriteZone(outStream, *zone);
REQUIRE(linkingResult);
}
auto maybeRebuiltZone = ZoneLoading::LoadZone(tempFilePathStr, std::nullopt);
REQUIRE(maybeRebuiltZone.has_value());
auto rebuiltZone = std::move(*maybeRebuiltZone);
const auto& pools = *zone->m_pools;
const auto& rebuiltPools = *rebuiltZone->m_pools;
const auto totalAssetCount = pools.GetTotalAssetCount();
REQUIRE(totalAssetCount == rebuiltPools.GetTotalAssetCount());
auto zoneIter = pools.begin();
auto zoneEnd = pools.end();
auto rebuiltZoneIter = rebuiltPools.begin();
auto rebuiltZoneEnd = rebuiltPools.end();
while (zoneIter != zoneEnd)
{
REQUIRE(rebuiltZoneIter != rebuiltZoneEnd);
REQUIRE((*zoneIter)->m_type == (*rebuiltZoneIter)->m_type);
REQUIRE((*zoneIter)->m_name == (*rebuiltZoneIter)->m_name);
++zoneIter;
++rebuiltZoneIter;
}
}
TEST_CASE("Rebuild vanilla zones", "[custom]")
{
auto* fastFilePathStr = std::getenv("OAT_FASTFILE_DIR");
if (!fastFilePathStr)
return;
const auto outputPath = oat::paths::GetTempDirectory("RebuildVanillaZones");
const fs::path fastFilePath(fastFilePathStr);
fs::directory_iterator iterator(fastFilePath);
const auto end = fs::end(iterator);
for (auto i = fs::begin(iterator); i != end; ++i)
{
if (!i->is_regular_file())
continue;
const auto path = i->path();
auto extension = path.extension().string();
utils::MakeStringLowerCase(extension);
if (extension == ".ff")
EnsureCanRebuildFastFile(outputPath, path);
}
}
} // namespace