mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Add ZoneWriting basis
This commit is contained in:
parent
301f6e3e7a
commit
9d26c9c927
0
src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h
Normal file
0
src/ZoneCommon/Game/IW4/ZoneConstantsIW4.h
Normal file
83
src/ZoneCommon/Game/T6/ZoneConstantsT6.h
Normal file
83
src/ZoneCommon/Game/T6/ZoneConstantsT6.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "Zone/ZoneTypes.h"
|
||||
#include "Game/T6/T6.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
class ZoneConstants final
|
||||
{
|
||||
ZoneConstants() = default;
|
||||
|
||||
public:
|
||||
static constexpr const char* MAGIC_SIGNED_TREYARCH = "TAff0100";
|
||||
static constexpr const char* MAGIC_SIGNED_OAT = "ABff0100";
|
||||
static constexpr const char* MAGIC_UNSIGNED = "TAffu100";
|
||||
static constexpr const char* MAGIC_UNSIGNED_SERVER = "TAsvu100";
|
||||
|
||||
static_assert(std::char_traits<char>::length(MAGIC_SIGNED_TREYARCH) == sizeof(ZoneHeader::m_magic));
|
||||
static_assert(std::char_traits<char>::length(MAGIC_SIGNED_OAT) == sizeof(ZoneHeader::m_magic));
|
||||
static_assert(std::char_traits<char>::length(MAGIC_UNSIGNED) == sizeof(ZoneHeader::m_magic));
|
||||
static_assert(std::char_traits<char>::length(MAGIC_UNSIGNED_SERVER) == sizeof(ZoneHeader::m_magic));
|
||||
|
||||
static constexpr int ZONE_VERSION = 147;
|
||||
static constexpr int STREAM_COUNT = 4;
|
||||
static constexpr int XCHUNK_SIZE = 0x8000;
|
||||
static constexpr int VANILLA_BUFFER_SIZE = 0x80000;
|
||||
static constexpr int OFFSET_BLOCK_BIT_COUNT = 3;
|
||||
static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL;
|
||||
|
||||
static constexpr const char* MAGIC_AUTH_HEADER = "PHEEBs71";
|
||||
inline static const uint8_t SALSA20_KEY_TREYARCH[]
|
||||
{
|
||||
0x64, 0x1D, 0x8A, 0x2F,
|
||||
0xE3, 0x1D, 0x3A, 0xA6,
|
||||
0x36, 0x22, 0xBB, 0xC9,
|
||||
0xCE, 0x85, 0x87, 0x22,
|
||||
0x9D, 0x42, 0xB0, 0xF8,
|
||||
0xED, 0x9B, 0x92, 0x41,
|
||||
0x30, 0xBF, 0x88, 0xB6,
|
||||
0x5E, 0xDC, 0x50, 0xBE
|
||||
};
|
||||
|
||||
inline static const uint8_t RSA_PUBLIC_KEY_TREYARCH[]
|
||||
{
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xc7, 0x9d, 0x33, 0xe0, 0x75, 0xaf, 0xef,
|
||||
0x08, 0x08, 0x2b, 0x89, 0xd9, 0x3b, 0xf3, 0xd5,
|
||||
0x9a, 0x65, 0xa6, 0xde, 0x3b, 0x1e, 0x20, 0xde,
|
||||
0x59, 0x19, 0x43, 0x88, 0x1a, 0x8b, 0x39, 0x13,
|
||||
0x60, 0x12, 0xd3, 0xb2, 0x77, 0x6d, 0xe1, 0x99,
|
||||
0x75, 0x24, 0xb4, 0x0d, 0x8c, 0xb7, 0x84, 0xf2,
|
||||
0x48, 0x8f, 0xd5, 0x4c, 0xb7, 0x64, 0x44, 0xa3,
|
||||
0xa8, 0x4a, 0xac, 0x2d, 0x54, 0x15, 0x2b, 0x1f,
|
||||
0xb3, 0xf4, 0x4c, 0x16, 0xa0, 0x92, 0x8e, 0xd2,
|
||||
0xfa, 0xcc, 0x11, 0x6a, 0x74, 0x6a, 0x70, 0xb8,
|
||||
0xd3, 0x34, 0x6b, 0x39, 0xc6, 0x2a, 0x69, 0xde,
|
||||
0x31, 0x34, 0xdf, 0xe7, 0x8b, 0x7e, 0x17, 0xa3,
|
||||
0x17, 0xd9, 0x5e, 0x88, 0x39, 0x21, 0xf8, 0x7d,
|
||||
0x3c, 0x29, 0x21, 0x6c, 0x0e, 0xf1, 0xb4, 0x09,
|
||||
0x54, 0xe8, 0x20, 0x34, 0x90, 0x2e, 0xb4, 0x1a,
|
||||
0x95, 0x95, 0x90, 0xe5, 0xfb, 0xce, 0xfe, 0x8a,
|
||||
0xbf, 0xea, 0xaf, 0x09, 0x0c, 0x0b, 0x87, 0x22,
|
||||
0xe1, 0xfe, 0x82, 0x6e, 0x91, 0xe8, 0xd1, 0xb6,
|
||||
0x35, 0x03, 0x4f, 0xdb, 0xc1, 0x31, 0xe2, 0xba,
|
||||
0xa0, 0x13, 0xf6, 0xdb, 0x07, 0x9b, 0xcb, 0x99,
|
||||
0xce, 0x9f, 0x49, 0xc4, 0x51, 0x8e, 0xf1, 0x04,
|
||||
0x9b, 0x30, 0xc3, 0x02, 0xff, 0x7b, 0x94, 0xca,
|
||||
0x12, 0x69, 0x1e, 0xdb, 0x2d, 0x3e, 0xbd, 0x48,
|
||||
0x16, 0xe1, 0x72, 0x37, 0xb8, 0x5f, 0x61, 0xfa,
|
||||
0x24, 0x16, 0x3a, 0xde, 0xbf, 0x6a, 0x71, 0x62,
|
||||
0x32, 0xf3, 0xaa, 0x7f, 0x28, 0x3a, 0x0c, 0x27,
|
||||
0xeb, 0xa9, 0x0a, 0x4c, 0x79, 0x88, 0x84, 0xb3,
|
||||
0xe2, 0x52, 0xb9, 0x68, 0x1e, 0x82, 0xcf, 0x67,
|
||||
0x43, 0xf3, 0x68, 0xf7, 0x26, 0x19, 0xaa, 0xdd,
|
||||
0x3f, 0x1e, 0xc6, 0x46, 0x11, 0x9f, 0x24, 0x23,
|
||||
0xa7, 0xb0, 0x1b, 0x79, 0xa7, 0x0c, 0x5a, 0xfe,
|
||||
0x96, 0xf7, 0xe7, 0x88, 0x09, 0xa6, 0x69, 0xe3,
|
||||
0x8b, 0x02, 0x03, 0x01, 0x00, 0x01
|
||||
};
|
||||
};
|
||||
}
|
@ -4,7 +4,12 @@
|
||||
class IZoneStream
|
||||
{
|
||||
public:
|
||||
IZoneStream() = default;
|
||||
virtual ~IZoneStream() = default;
|
||||
IZoneStream(const IZoneStream& other) = default;
|
||||
IZoneStream(IZoneStream&& other) noexcept = default;
|
||||
IZoneStream& operator=(const IZoneStream& other) = default;
|
||||
IZoneStream& operator=(IZoneStream&& other) noexcept = default;
|
||||
|
||||
virtual void PushBlock(block_t block) = 0;
|
||||
virtual block_t PopBlock() = 0;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "Game/T6/T6.h"
|
||||
#include "Game/T6/ZoneConstantsT6.h"
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "ContentLoaderT6.h"
|
||||
@ -21,81 +22,19 @@
|
||||
#include "Loading/Steps/StepAddProcessor.h"
|
||||
#include "Loading/Steps/StepAllocXBlocks.h"
|
||||
#include "Loading/Steps/StepLoadZoneContent.h"
|
||||
#include "Loading/Steps/StepLoadZoneSizes.h"
|
||||
|
||||
using namespace T6;
|
||||
|
||||
const std::string ZoneLoaderFactory::MAGIC_SIGNED_TREYARCH = "TAff0100";
|
||||
const std::string ZoneLoaderFactory::MAGIC_SIGNED_ASSET_BUILDER = "ABff0100";
|
||||
const std::string ZoneLoaderFactory::MAGIC_UNSIGNED = "TAffu100";
|
||||
const std::string ZoneLoaderFactory::MAGIC_UNSIGNED_SERVER = "TAsvu100";
|
||||
const int ZoneLoaderFactory::VERSION = 147;
|
||||
|
||||
const int ZoneLoaderFactory::STREAM_COUNT = 4;
|
||||
const int ZoneLoaderFactory::XCHUNK_SIZE = 0x8000;
|
||||
const int ZoneLoaderFactory::VANILLA_BUFFER_SIZE = 0x80000;
|
||||
const int ZoneLoaderFactory::OFFSET_BLOCK_BIT_COUNT = 3;
|
||||
const block_t ZoneLoaderFactory::INSERT_BLOCK = T6::XFILE_BLOCK_VIRTUAL;
|
||||
|
||||
const std::string ZoneLoaderFactory::MAGIC_AUTH_HEADER = "PHEEBs71";
|
||||
const uint8_t ZoneLoaderFactory::SALSA20_KEY_TREYARCH[]
|
||||
{
|
||||
0x64, 0x1D, 0x8A, 0x2F,
|
||||
0xE3, 0x1D, 0x3A, 0xA6,
|
||||
0x36, 0x22, 0xBB, 0xC9,
|
||||
0xCE, 0x85, 0x87, 0x22,
|
||||
0x9D, 0x42, 0xB0, 0xF8,
|
||||
0xED, 0x9B, 0x92, 0x41,
|
||||
0x30, 0xBF, 0x88, 0xB6,
|
||||
0x5E, 0xDC, 0x50, 0xBE
|
||||
};
|
||||
|
||||
const uint8_t ZoneLoaderFactory::RSA_PUBLIC_KEY_TREYARCH[]
|
||||
{
|
||||
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xc7, 0x9d, 0x33, 0xe0, 0x75, 0xaf, 0xef,
|
||||
0x08, 0x08, 0x2b, 0x89, 0xd9, 0x3b, 0xf3, 0xd5,
|
||||
0x9a, 0x65, 0xa6, 0xde, 0x3b, 0x1e, 0x20, 0xde,
|
||||
0x59, 0x19, 0x43, 0x88, 0x1a, 0x8b, 0x39, 0x13,
|
||||
0x60, 0x12, 0xd3, 0xb2, 0x77, 0x6d, 0xe1, 0x99,
|
||||
0x75, 0x24, 0xb4, 0x0d, 0x8c, 0xb7, 0x84, 0xf2,
|
||||
0x48, 0x8f, 0xd5, 0x4c, 0xb7, 0x64, 0x44, 0xa3,
|
||||
0xa8, 0x4a, 0xac, 0x2d, 0x54, 0x15, 0x2b, 0x1f,
|
||||
0xb3, 0xf4, 0x4c, 0x16, 0xa0, 0x92, 0x8e, 0xd2,
|
||||
0xfa, 0xcc, 0x11, 0x6a, 0x74, 0x6a, 0x70, 0xb8,
|
||||
0xd3, 0x34, 0x6b, 0x39, 0xc6, 0x2a, 0x69, 0xde,
|
||||
0x31, 0x34, 0xdf, 0xe7, 0x8b, 0x7e, 0x17, 0xa3,
|
||||
0x17, 0xd9, 0x5e, 0x88, 0x39, 0x21, 0xf8, 0x7d,
|
||||
0x3c, 0x29, 0x21, 0x6c, 0x0e, 0xf1, 0xb4, 0x09,
|
||||
0x54, 0xe8, 0x20, 0x34, 0x90, 0x2e, 0xb4, 0x1a,
|
||||
0x95, 0x95, 0x90, 0xe5, 0xfb, 0xce, 0xfe, 0x8a,
|
||||
0xbf, 0xea, 0xaf, 0x09, 0x0c, 0x0b, 0x87, 0x22,
|
||||
0xe1, 0xfe, 0x82, 0x6e, 0x91, 0xe8, 0xd1, 0xb6,
|
||||
0x35, 0x03, 0x4f, 0xdb, 0xc1, 0x31, 0xe2, 0xba,
|
||||
0xa0, 0x13, 0xf6, 0xdb, 0x07, 0x9b, 0xcb, 0x99,
|
||||
0xce, 0x9f, 0x49, 0xc4, 0x51, 0x8e, 0xf1, 0x04,
|
||||
0x9b, 0x30, 0xc3, 0x02, 0xff, 0x7b, 0x94, 0xca,
|
||||
0x12, 0x69, 0x1e, 0xdb, 0x2d, 0x3e, 0xbd, 0x48,
|
||||
0x16, 0xe1, 0x72, 0x37, 0xb8, 0x5f, 0x61, 0xfa,
|
||||
0x24, 0x16, 0x3a, 0xde, 0xbf, 0x6a, 0x71, 0x62,
|
||||
0x32, 0xf3, 0xaa, 0x7f, 0x28, 0x3a, 0x0c, 0x27,
|
||||
0xeb, 0xa9, 0x0a, 0x4c, 0x79, 0x88, 0x84, 0xb3,
|
||||
0xe2, 0x52, 0xb9, 0x68, 0x1e, 0x82, 0xcf, 0x67,
|
||||
0x43, 0xf3, 0x68, 0xf7, 0x26, 0x19, 0xaa, 0xdd,
|
||||
0x3f, 0x1e, 0xc6, 0x46, 0x11, 0x9f, 0x24, 0x23,
|
||||
0xa7, 0xb0, 0x1b, 0x79, 0xa7, 0x0c, 0x5a, 0xfe,
|
||||
0x96, 0xf7, 0xe7, 0x88, 0x09, 0xa6, 0x69, 0xe3,
|
||||
0x8b, 0x02, 0x03, 0x01, 0x00, 0x01
|
||||
};
|
||||
|
||||
class ZoneLoaderFactory::Impl
|
||||
{
|
||||
static GameLanguage GetZoneLanguage(std::string& zoneName)
|
||||
{
|
||||
auto languagePrefixes = g_GameT6.GetLanguagePrefixes();
|
||||
|
||||
for(const auto& languagePrefix : languagePrefixes)
|
||||
for (const auto& languagePrefix : languagePrefixes)
|
||||
{
|
||||
if(zoneName.compare(0, languagePrefix.m_prefix.length(), languagePrefix.m_prefix) == 0)
|
||||
if (zoneName.compare(0, languagePrefix.m_prefix.length(), languagePrefix.m_prefix) == 0)
|
||||
{
|
||||
return languagePrefix.m_language;
|
||||
}
|
||||
@ -109,12 +48,12 @@ class ZoneLoaderFactory::Impl
|
||||
assert(isSecure != nullptr);
|
||||
assert(isOfficial != nullptr);
|
||||
|
||||
if(header.m_version != VERSION)
|
||||
if (header.m_version != ZoneConstants::ZONE_VERSION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!memcmp(header.m_magic, MAGIC_SIGNED_TREYARCH.c_str(), 8))
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_TREYARCH, 8))
|
||||
{
|
||||
*isSecure = true;
|
||||
*isOfficial = true;
|
||||
@ -122,7 +61,7 @@ class ZoneLoaderFactory::Impl
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!memcmp(header.m_magic, MAGIC_SIGNED_ASSET_BUILDER.c_str(), 8))
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_OAT, 8))
|
||||
{
|
||||
*isSecure = true;
|
||||
*isOfficial = false;
|
||||
@ -130,7 +69,7 @@ class ZoneLoaderFactory::Impl
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!memcmp(header.m_magic, MAGIC_UNSIGNED.c_str(), 8))
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, 8))
|
||||
{
|
||||
*isSecure = false;
|
||||
*isOfficial = true;
|
||||
@ -138,7 +77,7 @@ class ZoneLoaderFactory::Impl
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!memcmp(header.m_magic, MAGIC_UNSIGNED_SERVER.c_str(), 8))
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED_SERVER, 8))
|
||||
{
|
||||
*isSecure = false;
|
||||
*isOfficial = true;
|
||||
@ -167,11 +106,11 @@ class ZoneLoaderFactory::Impl
|
||||
|
||||
static IPublicKeyAlgorithm* SetupRSA(const bool isOfficial)
|
||||
{
|
||||
if(isOfficial)
|
||||
if (isOfficial)
|
||||
{
|
||||
auto* rsa = Crypto::CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm::RSA_HASH_SHA256, Crypto::RSAPaddingMode::RSA_PADDING_PSS);
|
||||
|
||||
if(!rsa->SetKey(RSA_PUBLIC_KEY_TREYARCH, sizeof(RSA_PUBLIC_KEY_TREYARCH)))
|
||||
if (!rsa->SetKey(ZoneConstants::RSA_PUBLIC_KEY_TREYARCH, sizeof(ZoneConstants::RSA_PUBLIC_KEY_TREYARCH)))
|
||||
{
|
||||
printf("Invalid public key for signature checking\n");
|
||||
|
||||
@ -193,10 +132,10 @@ class ZoneLoaderFactory::Impl
|
||||
static ISignatureProvider* AddAuthHeaderSteps(const bool isSecure, ZoneLoader* zoneLoader, std::string& fileName)
|
||||
{
|
||||
// Unsigned zones do not have an auth header
|
||||
if(!isSecure)
|
||||
if (!isSecure)
|
||||
return nullptr;
|
||||
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepVerifyMagic>(MAGIC_AUTH_HEADER.c_str()));
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepVerifyMagic>(ZoneConstants::MAGIC_AUTH_HEADER));
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(4)); // Loading Flags which are always zero
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepVerifyFileName>(fileName, 32));
|
||||
|
||||
@ -210,12 +149,13 @@ class ZoneLoaderFactory::Impl
|
||||
static ICapturedDataProvider* AddXChunkProcessor(bool isEncrypted, ZoneLoader* zoneLoader, std::string& fileName)
|
||||
{
|
||||
ICapturedDataProvider* result = nullptr;
|
||||
auto xChunkProcessor = std::make_unique<ProcessorXChunks>(STREAM_COUNT, XCHUNK_SIZE, VANILLA_BUFFER_SIZE);
|
||||
auto xChunkProcessor = std::make_unique<ProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
||||
|
||||
if(isEncrypted)
|
||||
if (isEncrypted)
|
||||
{
|
||||
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
||||
auto chunkProcessorSalsa20 = std::make_unique<ChunkProcessorSalsa20>(STREAM_COUNT, fileName, SALSA20_KEY_TREYARCH, sizeof(SALSA20_KEY_TREYARCH));
|
||||
auto chunkProcessorSalsa20 = std::make_unique<ChunkProcessorSalsa20>(ZoneConstants::STREAM_COUNT, fileName, ZoneConstants::SALSA20_KEY_TREYARCH,
|
||||
sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
||||
result = chunkProcessorSalsa20.get();
|
||||
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
||||
}
|
||||
@ -236,7 +176,7 @@ public:
|
||||
bool isEncrypted;
|
||||
|
||||
// Check if this file is a supported T6 zone.
|
||||
if(!CanLoad(header, &isSecure, &isOfficial, &isEncrypted))
|
||||
if (!CanLoad(header, &isSecure, &isOfficial, &isEncrypted))
|
||||
return nullptr;
|
||||
|
||||
// Create new zone
|
||||
@ -259,13 +199,13 @@ public:
|
||||
ICapturedDataProvider* signatureDataProvider = AddXChunkProcessor(isEncrypted, zoneLoader, fileName);
|
||||
|
||||
// Start of the XFile struct
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(8)); // Skip size and externalSize fields since they are not interesting for us
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepLoadZoneSizes>());
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepAllocXBlocks>());
|
||||
|
||||
// Start of the zone content
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepLoadZoneContent>(std::make_unique<ContentLoader>(), zone, OFFSET_BLOCK_BIT_COUNT, INSERT_BLOCK));
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepLoadZoneContent>(std::make_unique<ContentLoader>(), zone, ZoneConstants::OFFSET_BLOCK_BIT_COUNT, ZoneConstants::INSERT_BLOCK));
|
||||
|
||||
if(isSecure)
|
||||
if (isSecure)
|
||||
{
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepVerifySignature>(rsa, signatureProvider, signatureDataProvider));
|
||||
}
|
||||
|
@ -7,22 +7,6 @@ namespace T6
|
||||
{
|
||||
class ZoneLoaderFactory final : public IZoneLoaderFactory
|
||||
{
|
||||
static const std::string MAGIC_SIGNED_TREYARCH;
|
||||
static const std::string MAGIC_SIGNED_ASSET_BUILDER;
|
||||
static const std::string MAGIC_UNSIGNED;
|
||||
static const std::string MAGIC_UNSIGNED_SERVER;
|
||||
static const int VERSION;
|
||||
|
||||
static const int STREAM_COUNT;
|
||||
static const int XCHUNK_SIZE;
|
||||
static const int VANILLA_BUFFER_SIZE;
|
||||
static const int OFFSET_BLOCK_BIT_COUNT;
|
||||
static const block_t INSERT_BLOCK;
|
||||
|
||||
static const std::string MAGIC_AUTH_HEADER;
|
||||
static const uint8_t SALSA20_KEY_TREYARCH[];
|
||||
static const uint8_t RSA_PUBLIC_KEY_TREYARCH[];
|
||||
|
||||
class Impl;
|
||||
|
||||
public:
|
||||
|
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
|
||||
#include "ILoadingStream.h"
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "Loading/StreamProcessor.h"
|
||||
#include "Loading/ICapturedDataProvider.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
|
||||
class ProcessorCaptureData final : public StreamProcessor, public ICapturedDataProvider
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "IXChunkProcessor.h"
|
||||
#include "Loading/ICapturedDataProvider.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
#include <string>
|
||||
|
||||
class ChunkProcessorSalsa20 : public IXChunkProcessor, public ICapturedDataProvider
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Loading/ICapturedDataProvider.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Loading/IHashProvider.h"
|
||||
|
||||
|
23
src/ZoneLoading/Loading/Steps/StepLoadZoneSizes.cpp
Normal file
23
src/ZoneLoading/Loading/Steps/StepLoadZoneSizes.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "StepLoadZoneSizes.h"
|
||||
|
||||
StepLoadZoneSizes::StepLoadZoneSizes()
|
||||
: m_size(0),
|
||||
m_external_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
void StepLoadZoneSizes::PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream)
|
||||
{
|
||||
stream->Load(&m_size, sizeof(m_size));
|
||||
stream->Load(&m_external_size, sizeof(m_external_size));
|
||||
}
|
||||
|
||||
size_t StepLoadZoneSizes::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
size_t StepLoadZoneSizes::GetExternalSize() const
|
||||
{
|
||||
return m_external_size;
|
||||
}
|
20
src/ZoneLoading/Loading/Steps/StepLoadZoneSizes.h
Normal file
20
src/ZoneLoading/Loading/Steps/StepLoadZoneSizes.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Loading/ILoadingStep.h"
|
||||
|
||||
class StepLoadZoneSizes final : public ILoadingStep
|
||||
{
|
||||
size_t m_size;
|
||||
size_t m_external_size;
|
||||
|
||||
public:
|
||||
StepLoadZoneSizes();
|
||||
|
||||
void PerformStep(ZoneLoader* zoneLoader, ILoadingStream* stream) override;
|
||||
|
||||
_NODISCARD size_t GetSize() const;
|
||||
_NODISCARD size_t GetExternalSize() const;
|
||||
};
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "Crypto.h"
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Loading/ICapturedDataProvider.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
#include "Loading/IHashProvider.h"
|
||||
|
||||
class StepVerifyHash final : public ILoadingStep
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "Loading/ILoadingStep.h"
|
||||
#include "Crypto.h"
|
||||
#include "Loading/ISignatureProvider.h"
|
||||
#include "Loading/ICapturedDataProvider.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
|
||||
class StepVerifySignature final : public ILoadingStep
|
||||
{
|
||||
|
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;
|
||||
};
|
||||
}
|
0
src/ZoneWriting/Writing/AssetWriter.cpp
Normal file
0
src/ZoneWriting/Writing/AssetWriter.cpp
Normal file
6
src/ZoneWriting/Writing/AssetWriter.h
Normal file
6
src/ZoneWriting/Writing/AssetWriter.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
class AssetWriter
|
||||
{
|
||||
|
||||
};
|
0
src/ZoneWriting/Writing/ContentWriterBase.cpp
Normal file
0
src/ZoneWriting/Writing/ContentWriterBase.cpp
Normal file
29
src/ZoneWriting/Writing/ContentWriterBase.h
Normal file
29
src/ZoneWriting/Writing/ContentWriterBase.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/Stream/IZoneOutputStream.h"
|
||||
|
||||
class ContentWriterBase
|
||||
{
|
||||
protected:
|
||||
static constexpr void* PTR_FOLLOWING = reinterpret_cast<void*>(-1);
|
||||
static constexpr void* PTR_INSERT = reinterpret_cast<void*>(-2);
|
||||
|
||||
const char** varXString;
|
||||
|
||||
Zone* m_zone;
|
||||
IZoneOutputStream* m_stream;
|
||||
|
||||
ContentWriterBase();
|
||||
ContentWriterBase(Zone* zone, IZoneOutputStream* stream);
|
||||
|
||||
void WriteXString(bool atStreamStart) const;
|
||||
void WriteXStringArray(bool atStreamStart, size_t count);
|
||||
|
||||
public:
|
||||
virtual ~ContentWriterBase() = default;
|
||||
ContentWriterBase(const ContentWriterBase& other) = default;
|
||||
ContentWriterBase(ContentWriterBase&& other) noexcept = default;
|
||||
ContentWriterBase& operator=(const ContentWriterBase& other) = default;
|
||||
ContentWriterBase& operator=(ContentWriterBase&& other) noexcept = default;
|
||||
};
|
17
src/ZoneWriting/Writing/IContentWritingEntryPoint.h
Normal file
17
src/ZoneWriting/Writing/IContentWritingEntryPoint.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
#include "Zone/Stream/IZoneOutputStream.h"
|
||||
|
||||
class IContentWritingEntryPoint
|
||||
{
|
||||
public:
|
||||
IContentWritingEntryPoint() = default;
|
||||
virtual ~IContentWritingEntryPoint() = default;
|
||||
IContentWritingEntryPoint(const IContentWritingEntryPoint& other) = default;
|
||||
IContentWritingEntryPoint(IContentWritingEntryPoint&& other) noexcept = default;
|
||||
IContentWritingEntryPoint& operator=(const IContentWritingEntryPoint& other) = default;
|
||||
IContentWritingEntryPoint& operator=(IContentWritingEntryPoint&& other) noexcept = default;
|
||||
|
||||
virtual void WriteContent(Zone* zone, IZoneOutputStream* stream) = 0;
|
||||
};
|
19
src/ZoneWriting/Writing/IWritingStep.h
Normal file
19
src/ZoneWriting/Writing/IWritingStep.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "Writing/ZoneWriter.h"
|
||||
#include "IWritingStream.h"
|
||||
|
||||
class ZoneWriter;
|
||||
|
||||
class IWritingStep
|
||||
{
|
||||
public:
|
||||
IWritingStep() = default;
|
||||
virtual ~IWritingStep() = default;
|
||||
IWritingStep(const IWritingStep& other) = default;
|
||||
IWritingStep(IWritingStep&& other) noexcept = default;
|
||||
IWritingStep& operator=(const IWritingStep& other) = default;
|
||||
IWritingStep& operator=(IWritingStep&& other) noexcept = default;
|
||||
|
||||
virtual void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) = 0;
|
||||
};
|
18
src/ZoneWriting/Writing/IWritingStream.h
Normal file
18
src/ZoneWriting/Writing/IWritingStream.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
class IWritingStream
|
||||
{
|
||||
public:
|
||||
IWritingStream() = default;
|
||||
virtual ~IWritingStream() = default;
|
||||
IWritingStream(const IWritingStream& other) = default;
|
||||
IWritingStream(IWritingStream&& other) noexcept = default;
|
||||
IWritingStream& operator=(const IWritingStream& other) = default;
|
||||
IWritingStream& operator=(IWritingStream&& other) noexcept = default;
|
||||
|
||||
virtual void Write(const void* buffer, size_t length) = 0;
|
||||
virtual int64_t Pos() = 0;
|
||||
};
|
19
src/ZoneWriting/Writing/IZoneWriterFactory.h
Normal file
19
src/ZoneWriting/Writing/IZoneWriterFactory.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "ZoneWriter.h"
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
class IZoneWriterFactory
|
||||
{
|
||||
public:
|
||||
IZoneWriterFactory() = default;
|
||||
virtual ~IZoneWriterFactory() = default;
|
||||
IZoneWriterFactory(const IZoneWriterFactory& other) = default;
|
||||
IZoneWriterFactory(IZoneWriterFactory&& other) noexcept = default;
|
||||
IZoneWriterFactory& operator=(const IZoneWriterFactory& other) = default;
|
||||
IZoneWriterFactory& operator=(IZoneWriterFactory&& other) noexcept = default;
|
||||
|
||||
_NODISCARD virtual bool SupportsZone(Zone* zone) const = 0;
|
||||
_NODISCARD virtual std::unique_ptr<ZoneWriter> CreateWriter(Zone* zone) const = 0;
|
||||
};
|
31
src/ZoneWriting/Writing/InMemoryZoneData.cpp
Normal file
31
src/ZoneWriting/Writing/InMemoryZoneData.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "InMemoryZoneData.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
InMemoryZoneData::InMemoryZoneData()
|
||||
: m_total_size(0)
|
||||
{
|
||||
m_buffers.emplace_back(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
InMemoryZoneData::MemoryBuffer::MemoryBuffer(const size_t size)
|
||||
: m_data(std::make_unique<char[]>(size)),
|
||||
m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
void* InMemoryZoneData::GetBufferOfSize(const size_t size)
|
||||
{
|
||||
assert(size <= BUFFER_SIZE);
|
||||
|
||||
if(m_buffers.back().m_size + size > BUFFER_SIZE)
|
||||
{
|
||||
m_buffers.emplace_back(BUFFER_SIZE);
|
||||
}
|
||||
|
||||
auto& backBuffer = m_buffers.back();
|
||||
void* result = &backBuffer.m_data[backBuffer.m_size];
|
||||
backBuffer.m_size += size;
|
||||
m_total_size += size;
|
||||
return result;
|
||||
}
|
25
src/ZoneWriting/Writing/InMemoryZoneData.h
Normal file
25
src/ZoneWriting/Writing/InMemoryZoneData.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
class InMemoryZoneData
|
||||
{
|
||||
static constexpr size_t BUFFER_SIZE = 0x10000;
|
||||
|
||||
public:
|
||||
class MemoryBuffer
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<char[]> m_data;
|
||||
size_t m_size;
|
||||
|
||||
explicit MemoryBuffer(size_t size);
|
||||
};
|
||||
|
||||
int64_t m_total_size;
|
||||
std::vector<MemoryBuffer> m_buffers;
|
||||
|
||||
InMemoryZoneData();
|
||||
void* GetBufferOfSize(size_t size);
|
||||
};
|
11
src/ZoneWriting/Writing/OutputStreamProcessor.cpp
Normal file
11
src/ZoneWriting/Writing/OutputStreamProcessor.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "OutputStreamProcessor.h"
|
||||
|
||||
OutputStreamProcessor::OutputStreamProcessor()
|
||||
{
|
||||
m_base_stream = nullptr;
|
||||
}
|
||||
|
||||
void OutputStreamProcessor::SetBaseStream(IWritingStream* baseStream)
|
||||
{
|
||||
m_base_stream = baseStream;
|
||||
}
|
14
src/ZoneWriting/Writing/OutputStreamProcessor.h
Normal file
14
src/ZoneWriting/Writing/OutputStreamProcessor.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "IWritingStream.h"
|
||||
|
||||
class OutputStreamProcessor : public IWritingStream
|
||||
{
|
||||
protected:
|
||||
IWritingStream* m_base_stream;
|
||||
|
||||
public:
|
||||
OutputStreamProcessor();
|
||||
|
||||
void SetBaseStream(IWritingStream* baseStream);
|
||||
};
|
46
src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp
Normal file
46
src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "OutputProcessorXChunks.h"
|
||||
|
||||
class OutputProcessorXChunks::Impl
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
OutputProcessorXChunks::OutputProcessorXChunks(int numStreams, size_t xChunkSize)
|
||||
{
|
||||
}
|
||||
|
||||
OutputProcessorXChunks::OutputProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
OutputProcessorXChunks::~OutputProcessorXChunks()
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
OutputProcessorXChunks::OutputProcessorXChunks(OutputProcessorXChunks&& other) noexcept
|
||||
: m_impl(other.m_impl)
|
||||
{
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
OutputProcessorXChunks& OutputProcessorXChunks::operator=(OutputProcessorXChunks&& other) noexcept
|
||||
{
|
||||
m_impl = other.m_impl;
|
||||
other.m_impl = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void OutputProcessorXChunks::AddChunkProcessor(std::unique_ptr<IXChunkOutputProcessor> chunkProcessor) const
|
||||
{
|
||||
}
|
||||
|
||||
void OutputProcessorXChunks::Write(const void* buffer, size_t length)
|
||||
{
|
||||
}
|
||||
|
||||
int64_t OutputProcessorXChunks::Pos()
|
||||
{
|
||||
return 0;
|
||||
}
|
26
src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h
Normal file
26
src/ZoneWriting/Writing/Processor/OutputProcessorXChunks.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
#include "Writing/OutputStreamProcessor.h"
|
||||
#include "XChunks/IXChunkOutputProcessor.h"
|
||||
|
||||
class OutputProcessorXChunks final : public OutputStreamProcessor
|
||||
{
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
|
||||
public:
|
||||
OutputProcessorXChunks(int numStreams, size_t xChunkSize);
|
||||
OutputProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize);
|
||||
~OutputProcessorXChunks() override;
|
||||
|
||||
OutputProcessorXChunks(const OutputProcessorXChunks& other) = delete;
|
||||
OutputProcessorXChunks(OutputProcessorXChunks&& other) noexcept;
|
||||
OutputProcessorXChunks& operator=(const OutputProcessorXChunks& other) = delete;
|
||||
OutputProcessorXChunks& operator=(OutputProcessorXChunks&& other) noexcept;
|
||||
|
||||
void AddChunkProcessor(std::unique_ptr<IXChunkOutputProcessor> chunkProcessor) const;
|
||||
|
||||
void Write(const void* buffer, size_t length) override;
|
||||
int64_t Pos() override;
|
||||
};
|
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
class IXChunkOutputProcessor
|
||||
{
|
||||
public:
|
||||
IXChunkOutputProcessor() = default;
|
||||
virtual ~IXChunkOutputProcessor() = default;
|
||||
IXChunkOutputProcessor(const IXChunkOutputProcessor& other) = default;
|
||||
IXChunkOutputProcessor(IXChunkOutputProcessor&& other) noexcept = default;
|
||||
IXChunkOutputProcessor& operator=(const IXChunkOutputProcessor& other) = default;
|
||||
IXChunkOutputProcessor& operator=(IXChunkOutputProcessor&& other) noexcept = default;
|
||||
|
||||
virtual size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) = 0;
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "IXChunkOutputProcessor.h"
|
||||
|
||||
class XChunkOutputProcessorDeflate final : public IXChunkOutputProcessor
|
||||
{
|
||||
public:
|
||||
size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override;
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "IXChunkOutputProcessor.h"
|
||||
#include "Utils/ICapturedDataProvider.h"
|
||||
|
||||
class XChunkOutputProcessorSalsa20 final : public IXChunkOutputProcessor, public ICapturedDataProvider
|
||||
{
|
||||
class Impl;
|
||||
Impl* m_impl;
|
||||
|
||||
public:
|
||||
XChunkOutputProcessorSalsa20(int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize);
|
||||
~XChunkOutputProcessorSalsa20() override;
|
||||
XChunkOutputProcessorSalsa20(const XChunkOutputProcessorSalsa20& other) = delete;
|
||||
XChunkOutputProcessorSalsa20(XChunkOutputProcessorSalsa20&& other) noexcept = default;
|
||||
XChunkOutputProcessorSalsa20& operator=(const XChunkOutputProcessorSalsa20& other) = delete;
|
||||
XChunkOutputProcessorSalsa20& operator=(XChunkOutputProcessorSalsa20&& other) noexcept = default;
|
||||
|
||||
size_t Process(int streamNumber, const uint8_t* input, size_t inputLength, uint8_t* output, size_t outputBufferSize) override;
|
||||
void GetCapturedData(const uint8_t** pCapturedData, size_t* pSize) override;
|
||||
};
|
16
src/ZoneWriting/Writing/Steps/StepAddOutputProcessor.cpp
Normal file
16
src/ZoneWriting/Writing/Steps/StepAddOutputProcessor.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "StepAddOutputProcessor.h"
|
||||
#include <cassert>
|
||||
|
||||
StepAddOutputProcessor::StepAddOutputProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor)
|
||||
: m_stream_processor(std::move(streamProcessor))
|
||||
{
|
||||
}
|
||||
|
||||
void StepAddOutputProcessor::PerformStep(ZoneWriter* zoneLoader, IWritingStream* stream)
|
||||
{
|
||||
assert(zoneLoader != nullptr);
|
||||
assert(m_stream_processor != nullptr);
|
||||
|
||||
zoneLoader->AddStreamProcessor(std::move(m_stream_processor));
|
||||
m_stream_processor = nullptr;
|
||||
}
|
15
src/ZoneWriting/Writing/Steps/StepAddOutputProcessor.h
Normal file
15
src/ZoneWriting/Writing/Steps/StepAddOutputProcessor.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepAddOutputProcessor final : public IWritingStep
|
||||
{
|
||||
std::unique_ptr<OutputStreamProcessor> m_stream_processor;
|
||||
|
||||
public:
|
||||
explicit StepAddOutputProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneLoader, IWritingStream* stream) override;
|
||||
};
|
10
src/ZoneWriting/Writing/Steps/StepWriteXBlockSizes.cpp
Normal file
10
src/ZoneWriting/Writing/Steps/StepWriteXBlockSizes.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "StepWriteXBlockSizes.h"
|
||||
|
||||
StepWriteXBlockSizes::StepWriteXBlockSizes(Zone* zone)
|
||||
: m_zone(zone)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteXBlockSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
}
|
13
src/ZoneWriting/Writing/Steps/StepWriteXBlockSizes.h
Normal file
13
src/ZoneWriting/Writing/Steps/StepWriteXBlockSizes.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "Writing/IWritingStep.h"
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
class StepWriteXBlockSizes final : public IWritingStep
|
||||
{
|
||||
Zone* m_zone;
|
||||
|
||||
public:
|
||||
explicit StepWriteXBlockSizes(Zone* zone);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
};
|
20
src/ZoneWriting/Writing/Steps/StepWriteZero.cpp
Normal file
20
src/ZoneWriting/Writing/Steps/StepWriteZero.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "StepWriteZero.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
StepWriteZero::StepWriteZero(const size_t count)
|
||||
: m_count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteZero::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
const uint64_t num = 0;
|
||||
size_t toWrite;
|
||||
|
||||
for(auto i = 0u; i < m_count; i += toWrite)
|
||||
{
|
||||
toWrite = std::min(sizeof(uint64_t), m_count - i);
|
||||
stream->Write(&num, toWrite);
|
||||
}
|
||||
}
|
12
src/ZoneWriting/Writing/Steps/StepWriteZero.h
Normal file
12
src/ZoneWriting/Writing/Steps/StepWriteZero.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepWriteZero final : public IWritingStep
|
||||
{
|
||||
size_t m_count;
|
||||
|
||||
public:
|
||||
explicit StepWriteZero(size_t count);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
};
|
10
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToFile.cpp
Normal file
10
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToFile.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "StepWriteZoneContentToFile.h"
|
||||
|
||||
StepWriteZoneContentToFile::StepWriteZoneContentToFile(StepWriteZoneContentToMemory* zoneMemory)
|
||||
: m_memory(zoneMemory)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteZoneContentToFile::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
}
|
13
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToFile.h
Normal file
13
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToFile.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "StepWriteZoneContentToMemory.h"
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepWriteZoneContentToFile final : public IWritingStep
|
||||
{
|
||||
StepWriteZoneContentToMemory* m_memory;
|
||||
|
||||
public:
|
||||
explicit StepWriteZoneContentToFile(StepWriteZoneContentToMemory* zoneMemory);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
#include "StepWriteZoneContentToMemory.h"
|
||||
|
||||
#include "Zone/Stream/Impl/InMemoryZoneOutputStream.h"
|
||||
|
||||
StepWriteZoneContentToMemory::StepWriteZoneContentToMemory(std::unique_ptr<IContentWritingEntryPoint> entryPoint, Zone* zone, int offsetBlockBitCount, block_t insertBlock)
|
||||
: m_content_loader(std::move(entryPoint)),
|
||||
m_zone_data(std::make_unique<InMemoryZoneData>()),
|
||||
m_zone(zone),
|
||||
m_offset_block_bit_count(offsetBlockBitCount),
|
||||
m_insert_block(insertBlock)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteZoneContentToMemory::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
std::vector<XBlock*> blocks;
|
||||
for (const auto& block : zoneWriter->m_blocks)
|
||||
blocks.push_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);
|
||||
m_content_loader->WriteContent(m_zone, zoneOutputStream.get());
|
||||
}
|
||||
|
||||
InMemoryZoneData* StepWriteZoneContentToMemory::GetData() const
|
||||
{
|
||||
return m_zone_data.get();
|
||||
}
|
23
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h
Normal file
23
src/ZoneWriting/Writing/Steps/StepWriteZoneContentToMemory.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Writing/IContentWritingEntryPoint.h"
|
||||
#include "Writing/InMemoryZoneData.h"
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepWriteZoneContentToMemory final : public IWritingStep
|
||||
{
|
||||
std::unique_ptr<IContentWritingEntryPoint> m_content_loader;
|
||||
std::unique_ptr<InMemoryZoneData> m_zone_data;
|
||||
Zone* m_zone;
|
||||
int m_offset_block_bit_count;
|
||||
block_t m_insert_block;
|
||||
|
||||
public:
|
||||
StepWriteZoneContentToMemory(std::unique_ptr<IContentWritingEntryPoint> entryPoint, Zone* zone, int offsetBlockBitCount, block_t insertBlock);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
_NODISCARD InMemoryZoneData* GetData() const;
|
||||
};
|
11
src/ZoneWriting/Writing/Steps/StepWriteZoneHeader.cpp
Normal file
11
src/ZoneWriting/Writing/Steps/StepWriteZoneHeader.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "StepWriteZoneHeader.h"
|
||||
|
||||
StepWriteZoneHeader::StepWriteZoneHeader(const ZoneHeader header)
|
||||
: m_header(header)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteZoneHeader::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
stream->Write(&m_header, sizeof(m_header));
|
||||
}
|
12
src/ZoneWriting/Writing/Steps/StepWriteZoneHeader.h
Normal file
12
src/ZoneWriting/Writing/Steps/StepWriteZoneHeader.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepWriteZoneHeader final : public IWritingStep
|
||||
{
|
||||
ZoneHeader m_header;
|
||||
|
||||
public:
|
||||
explicit StepWriteZoneHeader(ZoneHeader header);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
};
|
15
src/ZoneWriting/Writing/Steps/StepWriteZoneSizes.cpp
Normal file
15
src/ZoneWriting/Writing/Steps/StepWriteZoneSizes.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "StepWriteZoneSizes.h"
|
||||
|
||||
StepWriteZoneSizes::StepWriteZoneSizes(StepWriteZoneContentToMemory* memory)
|
||||
: m_memory(memory)
|
||||
{
|
||||
}
|
||||
|
||||
void StepWriteZoneSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||
{
|
||||
auto totalSize = static_cast<size_t>(m_memory->GetData()->m_total_size);
|
||||
size_t externalSize = 0;
|
||||
|
||||
stream->Write(&totalSize, sizeof(totalSize));
|
||||
stream->Write(&externalSize, sizeof(externalSize));
|
||||
}
|
13
src/ZoneWriting/Writing/Steps/StepWriteZoneSizes.h
Normal file
13
src/ZoneWriting/Writing/Steps/StepWriteZoneSizes.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "StepWriteZoneContentToMemory.h"
|
||||
#include "Writing/IWritingStep.h"
|
||||
|
||||
class StepWriteZoneSizes final : public IWritingStep
|
||||
{
|
||||
StepWriteZoneContentToMemory* m_memory;
|
||||
|
||||
public:
|
||||
explicit StepWriteZoneSizes(StepWriteZoneContentToMemory* memory);
|
||||
|
||||
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||
};
|
16
src/ZoneWriting/Writing/WritingException.cpp
Normal file
16
src/ZoneWriting/Writing/WritingException.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "WritingException.h"
|
||||
|
||||
WritingException::WritingException(std::string message)
|
||||
: m_error_message(std::move(message))
|
||||
{
|
||||
}
|
||||
|
||||
char const* WritingException::what() const
|
||||
{
|
||||
return m_error_message.c_str();
|
||||
}
|
||||
|
||||
const std::string& WritingException::Message() const
|
||||
{
|
||||
return m_error_message;
|
||||
}
|
16
src/ZoneWriting/Writing/WritingException.h
Normal file
16
src/ZoneWriting/Writing/WritingException.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
class WritingException final : public std::exception
|
||||
{
|
||||
std::string m_error_message;
|
||||
|
||||
public:
|
||||
explicit WritingException(std::string message);
|
||||
|
||||
_NODISCARD char const* what() const override;
|
||||
_NODISCARD const std::string& Message() const;
|
||||
};
|
16
src/ZoneWriting/Writing/WritingFileStream.cpp
Normal file
16
src/ZoneWriting/Writing/WritingFileStream.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "WritingFileStream.h"
|
||||
|
||||
WritingFileStream::WritingFileStream(std::ostream& stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
void WritingFileStream::Write(const void* buffer, const size_t length)
|
||||
{
|
||||
m_stream.write(static_cast<const char*>(buffer), length);
|
||||
}
|
||||
|
||||
int64_t WritingFileStream::Pos()
|
||||
{
|
||||
return m_stream.tellp();
|
||||
}
|
15
src/ZoneWriting/Writing/WritingFileStream.h
Normal file
15
src/ZoneWriting/Writing/WritingFileStream.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <ostream>
|
||||
|
||||
#include "IWritingStream.h"
|
||||
|
||||
class WritingFileStream final : public IWritingStream
|
||||
{
|
||||
std::ostream& m_stream;
|
||||
|
||||
public:
|
||||
explicit WritingFileStream(std::ostream& stream);
|
||||
|
||||
void Write(const void* buffer, size_t length) override;
|
||||
int64_t Pos() override;
|
||||
};
|
79
src/ZoneWriting/Writing/ZoneWriter.cpp
Normal file
79
src/ZoneWriting/Writing/ZoneWriter.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include "ZoneWriter.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "WritingException.h"
|
||||
#include "WritingFileStream.h"
|
||||
|
||||
ZoneWriter::ZoneWriter()
|
||||
: m_processor_chain_dirty(false)
|
||||
{
|
||||
}
|
||||
|
||||
IWritingStream* ZoneWriter::BuildWritingChain(IWritingStream* rootStream)
|
||||
{
|
||||
auto* currentStream = rootStream;
|
||||
|
||||
for (const auto& processor : m_processors)
|
||||
{
|
||||
processor->SetBaseStream(currentStream);
|
||||
|
||||
currentStream = processor.get();
|
||||
}
|
||||
|
||||
m_processor_chain_dirty = false;
|
||||
return currentStream;
|
||||
}
|
||||
|
||||
void ZoneWriter::AddXBlock(std::unique_ptr<XBlock> block)
|
||||
{
|
||||
m_blocks.emplace_back(std::move(block));
|
||||
}
|
||||
|
||||
void ZoneWriter::AddWritingStep(std::unique_ptr<IWritingStep> step)
|
||||
{
|
||||
m_steps.emplace_back(std::move(step));
|
||||
}
|
||||
|
||||
void ZoneWriter::AddStreamProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor)
|
||||
{
|
||||
m_processors.push_back(std::move(streamProcessor));
|
||||
m_processor_chain_dirty = true;
|
||||
}
|
||||
|
||||
void ZoneWriter::RemoveStreamProcessor(OutputStreamProcessor* streamProcessor)
|
||||
{
|
||||
for (auto i = m_processors.begin(); i < m_processors.end(); ++i)
|
||||
{
|
||||
if (i->get() == streamProcessor)
|
||||
{
|
||||
m_processors.erase(i);
|
||||
m_processor_chain_dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ZoneWriter::WriteZone(std::ostream& stream)
|
||||
{
|
||||
WritingFileStream fileStream(stream);
|
||||
auto* endStream = BuildWritingChain(&fileStream);
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& step : m_steps)
|
||||
{
|
||||
step->PerformStep(this, endStream);
|
||||
|
||||
if (m_processor_chain_dirty)
|
||||
endStream = BuildWritingChain(&fileStream);
|
||||
}
|
||||
}
|
||||
catch (WritingException& e)
|
||||
{
|
||||
std::cout << "Writing fastfile failed: " << e.Message() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
33
src/ZoneWriting/Writing/ZoneWriter.h
Normal file
33
src/ZoneWriting/Writing/ZoneWriter.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "IWritingStep.h"
|
||||
#include "OutputStreamProcessor.h"
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
class IWritingStep;
|
||||
|
||||
class ZoneWriter
|
||||
{
|
||||
std::vector<std::unique_ptr<IWritingStep>> m_steps;
|
||||
std::vector<std::unique_ptr<OutputStreamProcessor>> m_processors;
|
||||
|
||||
bool m_processor_chain_dirty;
|
||||
|
||||
IWritingStream* BuildWritingChain(IWritingStream* rootStream);
|
||||
|
||||
public:
|
||||
std::vector<std::unique_ptr<XBlock>> m_blocks;
|
||||
|
||||
ZoneWriter();
|
||||
|
||||
void AddXBlock(std::unique_ptr<XBlock> block);
|
||||
void AddWritingStep(std::unique_ptr<IWritingStep> step);
|
||||
void AddStreamProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor);
|
||||
|
||||
void RemoveStreamProcessor(OutputStreamProcessor* streamProcessor);
|
||||
|
||||
bool WriteZone(std::ostream& stream);
|
||||
};
|
@ -1,7 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
class IZoneOutputStream
|
||||
#include <cstddef>
|
||||
#include <typeindex>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "Zone/Stream/IZoneStream.h"
|
||||
|
||||
class IZoneOutputStream : public IZoneStream
|
||||
{
|
||||
public:
|
||||
virtual void Align(int alignTo) = 0;
|
||||
|
||||
virtual void* WriteDataRaw(void* dst, size_t size) = 0;
|
||||
virtual void* WriteDataInBlock(void* dst, size_t size) = 0;
|
||||
virtual void IncBlockPos(size_t size) = 0;
|
||||
virtual void WriteNullTerminated(void* dst) = 0;
|
||||
|
||||
virtual bool ReusableShouldWrite(void** pPtr, size_t size, size_t count, std::type_index type) = 0;
|
||||
|
||||
template<typename T>
|
||||
bool ReusableShouldWrite(T** pPtr)
|
||||
{
|
||||
return ReusableShouldWrite(pPtr, sizeof(T), 1, std::type_index(typeid(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ReusableShouldWrite(T** pPtr, size_t count)
|
||||
{
|
||||
return ReusableShouldWrite(pPtr, sizeof(T), count, std::type_index(typeid(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Write(T* dst)
|
||||
{
|
||||
return static_cast<T*>(WriteDataInBlock(const_cast<void*>(reinterpret_cast<const void*>(dst)), sizeof(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Write(T* dst, const uint32_t count)
|
||||
{
|
||||
return static_cast<T*>(WriteDataInBlock(const_cast<void*>(reinterpret_cast<const void*>(dst)), count * sizeof(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* WritePartial(T* dst, const size_t size)
|
||||
{
|
||||
return static_cast<T*>(WriteDataInBlock(const_cast<void*>(reinterpret_cast<const void*>(dst)), size));
|
||||
}
|
||||
};
|
196
src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp
Normal file
196
src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "InMemoryZoneOutputStream.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
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 == XBlock::Type::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 == XBlock::Type::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 > 0)
|
||||
{
|
||||
auto* block = m_block_stack.top();
|
||||
|
||||
if (block->m_type == XBlock::Type::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(void* src, const size_t size)
|
||||
{
|
||||
auto* result = m_zone_data->GetBufferOfSize(size);
|
||||
memcpy(result, src, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
void* InMemoryZoneOutputStream::WriteDataInBlock(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 XBlock::Type::BLOCK_TYPE_TEMP:
|
||||
case XBlock::Type::BLOCK_TYPE_NORMAL:
|
||||
result = m_zone_data->GetBufferOfSize(size);
|
||||
memcpy(result, src, size);
|
||||
break;
|
||||
|
||||
case XBlock::Type::BLOCK_TYPE_RUNTIME:
|
||||
break;
|
||||
|
||||
case XBlock::Type::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 == XBlock::Type::BLOCK_TYPE_TEMP)
|
||||
{
|
||||
m_temp_sizes.top() += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
block->m_buffer_size += size;
|
||||
}
|
||||
}
|
||||
|
||||
void InMemoryZoneOutputStream::WriteNullTerminated(void* src)
|
||||
{
|
||||
const auto len = strlen(static_cast<char*>(src));
|
||||
WriteDataInBlock(src, len + 1);
|
||||
}
|
||||
|
||||
uintptr_t InMemoryZoneOutputStream::GetCurrentZonePointer()
|
||||
{
|
||||
assert(!m_block_stack.empty());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool InMemoryZoneOutputStream::ReusableShouldWrite(void** pPtr, const size_t entrySize, const size_t entryCount, std::type_index type)
|
||||
{
|
||||
assert(!m_block_stack.empty());
|
||||
|
||||
const auto inTemp = m_block_stack.top()->m_type == XBlock::Type::BLOCK_TYPE_TEMP;
|
||||
const auto foundEntriesForType = m_reusable_entries.find(type);
|
||||
if (foundEntriesForType == m_reusable_entries.end())
|
||||
{
|
||||
std::vector<ReusableEntry> entries;
|
||||
auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer();
|
||||
entries.emplace_back(*pPtr, entrySize, entryCount, zoneOffset);
|
||||
m_reusable_entries.emplace(std::make_pair(type, std::move(entries)));
|
||||
|
||||
*pPtr = inTemp ? PTR_INSERT : PTR_FOLLOWING;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
auto zoneOffset = inTemp ? InsertPointer() : GetCurrentZonePointer();
|
||||
foundEntriesForType->second.emplace_back(*pPtr, entrySize, entryCount, zoneOffset);
|
||||
|
||||
*pPtr = inTemp ? PTR_INSERT : PTR_FOLLOWING;
|
||||
return true;
|
||||
}
|
52
src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h
Normal file
52
src/ZoneWriting/Zone/Stream/Impl/InMemoryZoneOutputStream.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Writing/InMemoryZoneData.h"
|
||||
#include "Zone/XBlock.h"
|
||||
#include "Zone/Stream/IZoneOutputStream.h"
|
||||
|
||||
class InMemoryZoneOutputStream final : public IZoneOutputStream
|
||||
{
|
||||
static constexpr void* PTR_FOLLOWING = reinterpret_cast<void*>(-1);
|
||||
static constexpr void* PTR_INSERT = reinterpret_cast<void*>(-2);
|
||||
|
||||
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(void* src, size_t size) override;
|
||||
void* WriteDataInBlock(void* src, size_t size) override;
|
||||
void IncBlockPos(size_t size) override;
|
||||
void WriteNullTerminated(void* src) override;
|
||||
bool ReusableShouldWrite(void** pPtr, size_t entrySize, size_t entryCount, std::type_index type) override;
|
||||
};
|
@ -1,6 +1,16 @@
|
||||
#include "ZoneWriting.h"
|
||||
|
||||
bool ZoneWriting::WriteZone(Zone* zone)
|
||||
#include "Game/IW4/ZoneWriterFactoryIW4.h"
|
||||
#include "Game/T6/ZoneWriterFactoryT6.h"
|
||||
#include "Writing/IZoneWriterFactory.h"
|
||||
|
||||
IZoneWriterFactory* ZoneWriterFactories[]
|
||||
{
|
||||
new IW4::ZoneWriterFactory(),
|
||||
new T6::ZoneWriterFactory()
|
||||
};
|
||||
|
||||
bool ZoneWriting::WriteZone(std::ostream& stream, Zone* zone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
#include "Zone/Zone.h"
|
||||
|
||||
class ZoneWriting
|
||||
{
|
||||
public:
|
||||
static bool WriteZone(Zone* zone);
|
||||
static bool WriteZone(std::ostream& stream, Zone* zone);
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user