mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-12 07:48:16 -05:00
Add ZoneWriting basis
This commit is contained in:
0
src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp
Normal file
0
src/ZoneWriting/Game/IW4/ContentWriterIW4.cpp
Normal file
0
src/ZoneWriting/Game/IW4/ContentWriterIW4.h
Normal file
0
src/ZoneWriting/Game/IW4/ContentWriterIW4.h
Normal file
0
src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp
Normal file
0
src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.cpp
Normal file
12
src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h
Normal file
12
src/ZoneWriting/Game/IW4/ZoneWriterFactoryIW4.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "Writing/IZoneWriterFactory.h"
|
||||
|
||||
namespace IW4
|
||||
{
|
||||
class ZoneWriterFactory final : public IZoneWriterFactory
|
||||
{
|
||||
public:
|
||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||
};
|
||||
}
|
0
src/ZoneWriting/Game/T6/ContentWriterT6.cpp
Normal file
0
src/ZoneWriting/Game/T6/ContentWriterT6.cpp
Normal file
23
src/ZoneWriting/Game/T6/ContentWriterT6.h
Normal file
23
src/ZoneWriting/Game/T6/ContentWriterT6.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "Writing/ContentWriterBase.h"
|
||||
#include "Writing/IContentWritingEntryPoint.h"
|
||||
#include "Game/T6/T6.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
class ContentWriter final : public ContentWriterBase, public IContentWritingEntryPoint
|
||||
{
|
||||
XAsset* varXAsset;
|
||||
ScriptStringList* varScriptStringList;
|
||||
|
||||
void LoadScriptStringList(bool atStreamStart);
|
||||
|
||||
void LoadXAsset(bool atStreamStart);
|
||||
void LoadXAssetArray(bool atStreamStart, size_t count);
|
||||
|
||||
public:
|
||||
ContentWriter();
|
||||
|
||||
void WriteContent(Zone* zone, IZoneOutputStream* stream) override;
|
||||
};
|
||||
}
|
133
src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp
Normal file
133
src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "ZoneWriterFactoryT6.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "ContentWriterT6.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
#include "Game/T6/T6.h"
|
||||
#include "Game/T6/GameT6.h"
|
||||
#include "Game/T6/ZoneConstantsT6.h"
|
||||
#include "Writing/Processor/OutputProcessorXChunks.h"
|
||||
#include "Writing/Processor/XChunks/XChunkOutputProcessorDeflate.h"
|
||||
#include "Writing/Processor/XChunks/XChunkOutputProcessorSalsa20.h"
|
||||
#include "Writing/Steps/StepAddOutputProcessor.h"
|
||||
#include "Writing/Steps/StepWriteXBlockSizes.h"
|
||||
#include "Writing/Steps/StepWriteZoneContentToFile.h"
|
||||
#include "Writing/Steps/StepWriteZoneContentToMemory.h"
|
||||
#include "Writing/Steps/StepWriteZoneHeader.h"
|
||||
|
||||
using namespace T6;
|
||||
|
||||
class ZoneWriterFactory::Impl
|
||||
{
|
||||
Zone* m_zone;
|
||||
std::unique_ptr<ZoneWriter> m_writer;
|
||||
|
||||
public:
|
||||
explicit Impl(Zone* zone)
|
||||
: m_zone(zone),
|
||||
m_writer(std::make_unique<ZoneWriter>())
|
||||
{
|
||||
}
|
||||
|
||||
void SetupBlocks() const
|
||||
{
|
||||
#define XBLOCK_DEF(name, type) std::make_unique<XBlock>(STR(name), name, type)
|
||||
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_TEMP, XBlock::Type::BLOCK_TYPE_TEMP));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_VIRTUAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_RUNTIME_PHYSICAL, XBlock::Type::BLOCK_TYPE_RUNTIME));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_VIRTUAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_DELAY_PHYSICAL, XBlock::Type::BLOCK_TYPE_DELAY));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_VIRTUAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_PHYSICAL, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||
m_writer->AddXBlock(XBLOCK_DEF(T6::XFILE_BLOCK_STREAMER_RESERVE, XBlock::Type::BLOCK_TYPE_NORMAL));
|
||||
|
||||
#undef XBLOCK_DEF
|
||||
}
|
||||
|
||||
static ZoneHeader CreateHeaderForParams(const bool isSecure, const bool isOfficial, const bool isEncrypted)
|
||||
{
|
||||
ZoneHeader header{};
|
||||
header.m_version = ZoneConstants::ZONE_VERSION;
|
||||
|
||||
if(isSecure)
|
||||
{
|
||||
if (isOfficial)
|
||||
memcpy(header.m_magic, ZoneConstants::MAGIC_SIGNED_TREYARCH, sizeof(ZoneHeader::m_magic));
|
||||
else
|
||||
memcpy(header.m_magic, ZoneConstants::MAGIC_SIGNED_OAT, sizeof(ZoneHeader::m_magic));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isEncrypted)
|
||||
memcpy(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, sizeof(ZoneHeader::m_magic));
|
||||
else
|
||||
memcpy(header.m_magic, ZoneConstants::MAGIC_UNSIGNED_SERVER, sizeof(ZoneHeader::m_magic));
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
ICapturedDataProvider* AddXChunkProcessor(const bool isEncrypted)
|
||||
{
|
||||
ICapturedDataProvider* result = nullptr;
|
||||
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
||||
|
||||
if (isEncrypted)
|
||||
{
|
||||
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
||||
auto chunkProcessorSalsa20 = std::make_unique<XChunkOutputProcessorSalsa20>(ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH,
|
||||
sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
||||
result = chunkProcessorSalsa20.get();
|
||||
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
||||
}
|
||||
|
||||
// Decompress the chunks using zlib
|
||||
xChunkProcessor->AddChunkProcessor(std::make_unique<XChunkOutputProcessorDeflate>());
|
||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::move(xChunkProcessor)));
|
||||
|
||||
// If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<ZoneWriter> CreateWriter()
|
||||
{
|
||||
// TODO Support signed fastfiles
|
||||
bool isSecure = false;
|
||||
bool isEncrypted = true;
|
||||
|
||||
SetupBlocks();
|
||||
|
||||
auto contentInMemory = std::make_unique<StepWriteZoneContentToMemory>(std::make_unique<ContentWriter>(), m_zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK);
|
||||
auto* contentInMemoryPtr = contentInMemory.get();
|
||||
m_writer->AddWritingStep(std::move(contentInMemory));
|
||||
|
||||
// Write zone header
|
||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false, isEncrypted)));
|
||||
|
||||
// Setup loading XChunks from the zone from this point on.
|
||||
auto* signatureDataProvider = AddXChunkProcessor(isEncrypted);
|
||||
|
||||
// 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
|
||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
||||
|
||||
// Start of the zone content
|
||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||
|
||||
// Return the fully setup zoneloader
|
||||
return std::move(m_writer);
|
||||
}
|
||||
};
|
||||
|
||||
bool ZoneWriterFactory::SupportsZone(Zone* zone) const
|
||||
{
|
||||
return zone->m_game == &g_GameT6;
|
||||
}
|
||||
|
||||
std::unique_ptr<ZoneWriter> ZoneWriterFactory::CreateWriter(Zone* zone) const
|
||||
{
|
||||
Impl impl(zone);
|
||||
return impl.CreateWriter();
|
||||
}
|
17
src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h
Normal file
17
src/ZoneWriting/Game/T6/ZoneWriterFactoryT6.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Writing/IZoneWriterFactory.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
class ZoneWriterFactory final : public IZoneWriterFactory
|
||||
{
|
||||
class Impl;
|
||||
|
||||
public:
|
||||
_NODISCARD bool SupportsZone(Zone* zone) const override;
|
||||
_NODISCARD std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const override;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user