mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-10-23 20:18:10 +00:00
refactor: adapt iw4 and iw5 content writer and zone writer factory for both pc variants
This commit is contained in:
12 files changed
+142
-37
No files matched your search
@@ -1,6 +1,7 @@
|
||||
#include "ContentWriterIW4.h"
|
||||
|
||||
#include "Game/IW4/AssetWriter_iw4_pc32.h"
|
||||
#include "Game/IW4/AssetWriter_iw4_pc64.h"
|
||||
#include "Writing/WritingException.h"
|
||||
|
||||
#include <cassert>
|
||||
@@ -67,8 +68,13 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
|
||||
|
||||
#ifdef ARCH_x86
|
||||
static_assert(offsetof(ScriptStringList, strings) == 4u);
|
||||
#endif
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
|
||||
#else
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(8));
|
||||
else
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +86,19 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
|
||||
#define WRITE_ASSET(type_index, typeName, headerEntry) \
|
||||
case type_index: \
|
||||
{ \
|
||||
Writer_##typeName##_pc32 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
|
||||
if (m_word_size == GameWordSize::ARCH_64) \
|
||||
{ \
|
||||
Writer_##typeName##_pc64 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(8)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Writer_##typeName##_pc32 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define SKIP_ASSET(type_index, typeName, headerEntry) \
|
||||
case type_index: \
|
||||
break;
|
||||
@@ -156,11 +171,18 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
|
||||
#ifdef ARCH_x86
|
||||
varXAssetWritten = m_stream->Write(varXAsset, count);
|
||||
#else
|
||||
const auto fill = m_stream->WriteWithFill(8u * count);
|
||||
varXAssetWritten = fill.Offset();
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
{
|
||||
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);
|
||||
for (size_t index = 0; index < count; index++)
|
||||
fill.Fill(varXAsset[index].type, 8u * index);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -188,13 +210,20 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream)
|
||||
static_assert(offsetof(XAssetList, assetCount) == 8u);
|
||||
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
|
||||
#else
|
||||
const auto fillAccessor = m_stream->WriteWithFill(16u);
|
||||
varXAssetListWritten = fillAccessor.Offset();
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
{
|
||||
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto fillAccessor = m_stream->WriteWithFill(16u);
|
||||
varXAssetListWritten = fillAccessor.Offset();
|
||||
|
||||
varScriptStringList = &varXAssetList->stringList;
|
||||
fillAccessor.Fill(varScriptStringList->count, 0u);
|
||||
varScriptStringList = &varXAssetList->stringList;
|
||||
fillAccessor.Fill(varScriptStringList->count, 0u);
|
||||
|
||||
fillAccessor.Fill(varXAssetList->assetCount, 8u);
|
||||
fillAccessor.Fill(varXAssetList->assetCount, 8u);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
|
||||
@@ -214,8 +243,13 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream)
|
||||
|
||||
#ifdef ARCH_x86
|
||||
static_assert(offsetof(XAssetList, assets) == 12u);
|
||||
#endif
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
|
||||
#else
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(24));
|
||||
else
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
|
||||
#endif
|
||||
}
|
||||
|
||||
m_stream->PopBlock();
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace
|
||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) const
|
||||
{
|
||||
auto writer = std::make_unique<ZoneWriter>();
|
||||
const auto* variant = IGameVariant::GetVariantById(zone.m_variant_id);
|
||||
|
||||
// TODO Support signed fastfiles
|
||||
bool isSecure = false;
|
||||
@@ -69,7 +70,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
|
||||
|
||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(std::make_unique<ContentWriter>(zone),
|
||||
zone,
|
||||
32u,
|
||||
variant->GetWordSize() == GameWordSize::ARCH_64 ? 64u : 32u,
|
||||
ZoneConstants::ZONE_POINTER_OFFSET_BIT_COUNT,
|
||||
ZoneConstants::ZONE_POINTER_BLOCK_BIT_COUNT,
|
||||
ZoneConstants::INSERT_BLOCK);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "ContentWriterIW5.h"
|
||||
|
||||
#include "Game/IW5/AssetWriter_iw5_pc32.h"
|
||||
#include "Game/IW5/AssetWriter_iw5_pc64.h"
|
||||
#include "Writing/WritingException.h"
|
||||
|
||||
#include <cassert>
|
||||
@@ -67,8 +68,13 @@ void ContentWriter::WriteScriptStringList(const bool atStreamStart)
|
||||
|
||||
#ifdef ARCH_x86
|
||||
static_assert(offsetof(ScriptStringList, strings) == 4u);
|
||||
#endif
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
|
||||
#else
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(8));
|
||||
else
|
||||
m_stream->MarkFollowing(varScriptStringListWritten.AtOffset(4));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,13 +86,18 @@ void ContentWriter::WriteXAsset(const bool atStreamStart)
|
||||
#define WRITE_ASSET(type_index, typeName, headerEntry) \
|
||||
case type_index: \
|
||||
{ \
|
||||
Writer_##typeName##_pc32 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
|
||||
if (m_word_size == GameWordSize::ARCH_64) \
|
||||
{ \
|
||||
Writer_##typeName##_pc64 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(8)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
Writer_##typeName##_pc32 writer(varXAsset->header.headerEntry, m_zone, *m_stream); \
|
||||
writer.Write(varXAsset->header.headerEntry, varXAssetWritten.AtOffset(4)); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
#define SKIP_ASSET(type_index, typeName, headerEntry) \
|
||||
case type_index: \
|
||||
break;
|
||||
|
||||
assert(varXAsset != nullptr);
|
||||
|
||||
@@ -159,11 +170,18 @@ void ContentWriter::WriteXAssetArray(const bool atStreamStart, const size_t coun
|
||||
#ifdef ARCH_x86
|
||||
varXAssetWritten = m_stream->Write(varXAsset, count);
|
||||
#else
|
||||
const auto fill = m_stream->WriteWithFill(8u * count);
|
||||
varXAssetWritten = fill.Offset();
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
{
|
||||
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);
|
||||
for (size_t index = 0; index < count; index++)
|
||||
fill.Fill(varXAsset[index].type, 8u * index);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -191,13 +209,20 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream)
|
||||
static_assert(offsetof(XAssetList, assetCount) == 8u);
|
||||
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
|
||||
#else
|
||||
const auto fillAccessor = m_stream->WriteWithFill(16u);
|
||||
varXAssetListWritten = fillAccessor.Offset();
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
{
|
||||
varXAssetListWritten = m_stream->WriteDataRaw(&assetList, sizeof(assetList));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto fillAccessor = m_stream->WriteWithFill(16u);
|
||||
varXAssetListWritten = fillAccessor.Offset();
|
||||
|
||||
varScriptStringList = &varXAssetList->stringList;
|
||||
fillAccessor.Fill(varScriptStringList->count, 0u);
|
||||
varScriptStringList = &varXAssetList->stringList;
|
||||
fillAccessor.Fill(varScriptStringList->count, 0u);
|
||||
|
||||
fillAccessor.Fill(varXAssetList->assetCount, 8u);
|
||||
fillAccessor.Fill(varXAssetList->assetCount, 8u);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_stream->PushBlock(XFILE_BLOCK_VIRTUAL);
|
||||
@@ -217,8 +242,13 @@ void ContentWriter::WriteContent(ZoneOutputStream& stream)
|
||||
|
||||
#ifdef ARCH_x86
|
||||
static_assert(offsetof(XAssetList, assets) == 12u);
|
||||
#endif
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
|
||||
#else
|
||||
if (m_word_size == GameWordSize::ARCH_64)
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(24));
|
||||
else
|
||||
m_stream->MarkFollowing(varXAssetListWritten.AtOffset(12));
|
||||
#endif
|
||||
}
|
||||
|
||||
m_stream->PopBlock();
|
||||
|
||||
@@ -62,6 +62,7 @@ namespace
|
||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) const
|
||||
{
|
||||
auto writer = std::make_unique<ZoneWriter>();
|
||||
const auto* variant = IGameVariant::GetVariantById(zone.m_variant_id);
|
||||
|
||||
// TODO Support signed fastfiles
|
||||
bool isSecure = false;
|
||||
@@ -70,7 +71,7 @@ std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(const Zone& zone) co
|
||||
|
||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(std::make_unique<ContentWriter>(zone),
|
||||
zone,
|
||||
32u,
|
||||
variant->GetWordSize() == GameWordSize::ARCH_64 ? 64u : 32u,
|
||||
ZoneConstants::ZONE_POINTER_OFFSET_BIT_COUNT,
|
||||
ZoneConstants::ZONE_POINTER_BLOCK_BIT_COUNT,
|
||||
ZoneConstants::INSERT_BLOCK);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
ContentWriterBase::ContentWriterBase(const Zone& zone)
|
||||
: m_zone(zone),
|
||||
m_word_size(GameVariant::GetVariantById(zone.m_variant_id)->GetWordSize()),
|
||||
m_stream(nullptr),
|
||||
varXString(nullptr),
|
||||
varXStringWritten(nullptr)
|
||||
@@ -12,6 +13,7 @@ ContentWriterBase::ContentWriterBase(const Zone& zone)
|
||||
|
||||
ContentWriterBase::ContentWriterBase(const Zone& zone, ZoneOutputStream& stream)
|
||||
: m_zone(zone),
|
||||
m_word_size(GameVariant::GetVariantById(zone.m_variant_id)->GetWordSize()),
|
||||
m_stream(&stream),
|
||||
varXString(nullptr),
|
||||
varXStringWritten(nullptr)
|
||||
|
||||
@@ -21,6 +21,7 @@ protected:
|
||||
void WriteXStringArray(bool atStreamStart, size_t count);
|
||||
|
||||
const Zone& m_zone;
|
||||
GameWordSize m_word_size;
|
||||
ZoneOutputStream* m_stream;
|
||||
|
||||
const char** varXString;
|
||||
|
||||
+2
@@ -1,4 +1,6 @@
|
||||
>game,IW4
|
||||
>variant,pc32
|
||||
>name,SimpleZoneIW4
|
||||
|
||||
rawfile,SimpleZone.txt
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
>game,IW4
|
||||
>variant,pc64
|
||||
>name,SimpleZoneIW4
|
||||
|
||||
rawfile,SimpleZone.txt
|
||||
|
||||
@@ -15,7 +15,7 @@ using namespace std::literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
TEST_CASE("Simple Zone(IW4)", "[iw4][system][simple]")
|
||||
void PerformTest(const std::string& zoneFileName, GameVariantId expectedGameVariantId)
|
||||
{
|
||||
const auto assetSearchPath = (oat::paths::GetSystemTestsDirectory() / "Game/IW4/Simple").string();
|
||||
const auto sourceSearchPath = (oat::paths::GetSystemTestsDirectory() / "Game/IW4/Simple").string();
|
||||
@@ -30,7 +30,7 @@ namespace
|
||||
sourceSearchPath.c_str(),
|
||||
"--output-folder",
|
||||
outputPath.c_str(),
|
||||
"SimpleZoneIW4",
|
||||
zoneFileName.c_str(),
|
||||
};
|
||||
|
||||
LinkerArgs args;
|
||||
@@ -53,9 +53,19 @@ namespace
|
||||
auto zone = std::move(*maybeZone);
|
||||
|
||||
REQUIRE(zone->m_game_id == GameId::IW4);
|
||||
REQUIRE(zone->m_variant_id == GameVariantId::IW4_PC32);
|
||||
REQUIRE(zone->m_variant_id == expectedGameVariantId);
|
||||
REQUIRE(zone->m_name == "SimpleZoneIW4");
|
||||
REQUIRE(zone->m_pools.GetTotalAssetCount() == 1);
|
||||
REQUIRE(zone->m_pools.GetAsset<IW4::AssetRawFile>("SimpleZone.txt"));
|
||||
}
|
||||
|
||||
TEST_CASE("Simple Zone(IW4|pc32)", "[iw4][pc32][system][simple]")
|
||||
{
|
||||
PerformTest("SimpleZoneIW4_32", GameVariantId::IW4_PC32);
|
||||
}
|
||||
|
||||
TEST_CASE("Simple Zone(IW4|pc64)", "[iw4][pc64][system][simple]")
|
||||
{
|
||||
PerformTest("SimpleZoneIW4_64", GameVariantId::IW4_PC64);
|
||||
}
|
||||
} // namespace
|
||||
+2
@@ -1,4 +1,6 @@
|
||||
>game,IW5
|
||||
>variant,pc32
|
||||
>name,SimpleZoneIW5
|
||||
|
||||
rawfile,SimpleZone.txt
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
>game,IW5
|
||||
>variant,pc64
|
||||
>name,SimpleZoneIW5
|
||||
|
||||
rawfile,SimpleZone.txt
|
||||
|
||||
@@ -16,7 +16,7 @@ using namespace std::literals;
|
||||
|
||||
namespace
|
||||
{
|
||||
TEST_CASE("Simple Zone(IW5)", "[iw5][system][simple]")
|
||||
void PerformTest(const std::string& zoneFileName, GameVariantId expectedGameVariantId)
|
||||
{
|
||||
const auto assetSearchPath = (oat::paths::GetSystemTestsDirectory() / "Game/IW5/Simple").string();
|
||||
const auto sourceSearchPath = (oat::paths::GetSystemTestsDirectory() / "Game/IW5/Simple").string();
|
||||
@@ -31,7 +31,7 @@ namespace
|
||||
sourceSearchPath.c_str(),
|
||||
"--output-folder",
|
||||
outputPath.c_str(),
|
||||
"SimpleZoneIW5",
|
||||
zoneFileName.c_str(),
|
||||
};
|
||||
|
||||
LinkerArgs args;
|
||||
@@ -54,9 +54,19 @@ namespace
|
||||
auto zone = std::move(*maybeZone);
|
||||
|
||||
REQUIRE(zone->m_game_id == GameId::IW5);
|
||||
REQUIRE(zone->m_variant_id == GameVariantId::IW5_PC32);
|
||||
REQUIRE(zone->m_variant_id == expectedGameVariantId);
|
||||
REQUIRE(zone->m_name == "SimpleZoneIW5");
|
||||
REQUIRE(zone->m_pools.GetTotalAssetCount() == 1);
|
||||
REQUIRE(zone->m_pools.GetAsset<IW5::AssetRawFile>("SimpleZone.txt"));
|
||||
}
|
||||
|
||||
TEST_CASE("Simple Zone(IW5|pc32)", "[iw5][pc32][system][simple]")
|
||||
{
|
||||
PerformTest("SimpleZoneIW5_32", GameVariantId::IW5_PC32);
|
||||
}
|
||||
|
||||
TEST_CASE("Simple Zone(IW5|pc64)", "[iw5][pc64][system][simple]")
|
||||
{
|
||||
PerformTest("SimpleZoneIW5_64", GameVariantId::IW5_PC64);
|
||||
}
|
||||
} // namespace
|
||||
Reference in new issue
Block a user