mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
Write null memory at end of t6 fastfiles like the original linker does because the game's reader needs it for some reason
This commit is contained in:
parent
d99eb0ab24
commit
1058ee7881
@ -30,6 +30,9 @@ namespace T6
|
|||||||
static constexpr int OFFSET_BLOCK_BIT_COUNT = 3;
|
static constexpr int OFFSET_BLOCK_BIT_COUNT = 3;
|
||||||
static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL;
|
static constexpr block_t INSERT_BLOCK = XFILE_BLOCK_VIRTUAL;
|
||||||
|
|
||||||
|
static constexpr size_t FILE_SUFFIX_ZERO_MIN_SIZE = 0x40;
|
||||||
|
static constexpr size_t FILE_SUFFIX_ZERO_ALIGN = 0x40;
|
||||||
|
|
||||||
static constexpr const char* MAGIC_AUTH_HEADER = "PHEEBs71";
|
static constexpr const char* MAGIC_AUTH_HEADER = "PHEEBs71";
|
||||||
inline static const uint8_t SALSA20_KEY_TREYARCH[]
|
inline static const uint8_t SALSA20_KEY_TREYARCH[]
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,10 @@
|
|||||||
#include "Zone/XChunk/XChunkProcessorDeflate.h"
|
#include "Zone/XChunk/XChunkProcessorDeflate.h"
|
||||||
#include "Zone/XChunk/XChunkProcessorSalsa20Encryption.h"
|
#include "Zone/XChunk/XChunkProcessorSalsa20Encryption.h"
|
||||||
#include "Writing/Steps/StepAddOutputProcessor.h"
|
#include "Writing/Steps/StepAddOutputProcessor.h"
|
||||||
|
#include "Writing/Steps/StepAlign.h"
|
||||||
|
#include "Writing/Steps/StepRemoveOutputProcessor.h"
|
||||||
#include "Writing/Steps/StepWriteXBlockSizes.h"
|
#include "Writing/Steps/StepWriteXBlockSizes.h"
|
||||||
|
#include "Writing/Steps/StepWriteZero.h"
|
||||||
#include "Writing/Steps/StepWriteZoneContentToFile.h"
|
#include "Writing/Steps/StepWriteZoneContentToFile.h"
|
||||||
#include "Writing/Steps/StepWriteZoneContentToMemory.h"
|
#include "Writing/Steps/StepWriteZoneContentToMemory.h"
|
||||||
#include "Writing/Steps/StepWriteZoneHeader.h"
|
#include "Writing/Steps/StepWriteZoneHeader.h"
|
||||||
@ -71,10 +74,11 @@ public:
|
|||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICapturedDataProvider* AddXChunkProcessor(const bool isEncrypted)
|
void AddXChunkProcessor(const bool isEncrypted, ICapturedDataProvider** dataToSignProviderPtr, OutputProcessorXChunks** xChunkProcessorPtr) const
|
||||||
{
|
{
|
||||||
ICapturedDataProvider* result = nullptr;
|
|
||||||
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::XCHUNK_MAX_WRITE_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::XCHUNK_MAX_WRITE_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
||||||
|
if (xChunkProcessorPtr)
|
||||||
|
*xChunkProcessorPtr = xChunkProcessor.get();
|
||||||
|
|
||||||
// Decompress the chunks using zlib
|
// Decompress the chunks using zlib
|
||||||
xChunkProcessor->AddChunkProcessor(std::make_unique<XChunkProcessorDeflate>());
|
xChunkProcessor->AddChunkProcessor(std::make_unique<XChunkProcessorDeflate>());
|
||||||
@ -84,14 +88,16 @@ public:
|
|||||||
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
// If zone is encrypted, the decryption is applied before the decompression. T6 Zones always use Salsa20.
|
||||||
auto chunkProcessorSalsa20 = std::make_unique<XChunkProcessorSalsa20Encryption>(ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH,
|
auto chunkProcessorSalsa20 = std::make_unique<XChunkProcessorSalsa20Encryption>(ZoneConstants::STREAM_COUNT, m_zone->m_name, ZoneConstants::SALSA20_KEY_TREYARCH,
|
||||||
sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
sizeof(ZoneConstants::SALSA20_KEY_TREYARCH));
|
||||||
result = chunkProcessorSalsa20.get();
|
|
||||||
|
// If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm
|
||||||
|
if (dataToSignProviderPtr)
|
||||||
|
*dataToSignProviderPtr = chunkProcessorSalsa20.get();
|
||||||
|
|
||||||
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_writer->AddWritingStep(std::make_unique<StepAddOutputProcessor>(std::move(xChunkProcessor)));
|
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()
|
std::unique_ptr<ZoneWriter> CreateWriter()
|
||||||
@ -110,7 +116,9 @@ public:
|
|||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false, isEncrypted)));
|
m_writer->AddWritingStep(std::make_unique<StepWriteZoneHeader>(CreateHeaderForParams(isSecure, false, isEncrypted)));
|
||||||
|
|
||||||
// Setup loading XChunks from the zone from this point on.
|
// Setup loading XChunks from the zone from this point on.
|
||||||
auto* signatureDataProvider = AddXChunkProcessor(isEncrypted);
|
ICapturedDataProvider* dataToSignProvider;
|
||||||
|
OutputProcessorXChunks* xChunksProcessor;
|
||||||
|
AddXChunkProcessor(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
|
//m_writer->AddWritingStep(std::make_unique<StepSkipBytes>(8)); // Skip size and externalSize fields since they are not interesting for us
|
||||||
@ -120,6 +128,14 @@ public:
|
|||||||
// Start of the zone content
|
// Start of the zone content
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
m_writer->AddWritingStep(std::make_unique<StepWriteZoneContentToFile>(contentInMemoryPtr));
|
||||||
|
|
||||||
|
// Stop writing in XChunks
|
||||||
|
m_writer->AddWritingStep(std::make_unique<StepRemoveOutputProcessor>(xChunksProcessor));
|
||||||
|
|
||||||
|
// Pad ending with zeros like the original linker does it. The game's reader needs it for some reason.
|
||||||
|
// From my observations this is most likely the logic behind the amount of bytes: At least 0x40 bytes and aligned to the next 0x40
|
||||||
|
m_writer->AddWritingStep(std::make_unique<StepWriteZero>(ZoneConstants::FILE_SUFFIX_ZERO_MIN_SIZE));
|
||||||
|
m_writer->AddWritingStep(std::make_unique<StepAlign>(ZoneConstants::FILE_SUFFIX_ZERO_ALIGN, '\0'));
|
||||||
|
|
||||||
// Return the fully setup zoneloader
|
// Return the fully setup zoneloader
|
||||||
return std::move(m_writer);
|
return std::move(m_writer);
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,12 @@ StepAddOutputProcessor::StepAddOutputProcessor(std::unique_ptr<OutputStreamProce
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void StepAddOutputProcessor::PerformStep(ZoneWriter* zoneLoader, IWritingStream* stream)
|
void StepAddOutputProcessor::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||||
{
|
{
|
||||||
assert(zoneLoader != nullptr);
|
assert(zoneWriter != nullptr);
|
||||||
assert(m_stream_processor != nullptr);
|
assert(m_stream_processor != nullptr);
|
||||||
|
|
||||||
zoneLoader->AddStreamProcessor(std::move(m_stream_processor));
|
stream->Flush();
|
||||||
|
zoneWriter->AddStreamProcessor(std::move(m_stream_processor));
|
||||||
m_stream_processor = nullptr;
|
m_stream_processor = nullptr;
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Writing/OutputStreamProcessor.h"
|
||||||
#include "Writing/IWritingStep.h"
|
#include "Writing/IWritingStep.h"
|
||||||
|
|
||||||
class StepAddOutputProcessor final : public IWritingStep
|
class StepAddOutputProcessor final : public IWritingStep
|
||||||
@ -11,5 +12,5 @@ class StepAddOutputProcessor final : public IWritingStep
|
|||||||
public:
|
public:
|
||||||
explicit StepAddOutputProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor);
|
explicit StepAddOutputProcessor(std::unique_ptr<OutputStreamProcessor> streamProcessor);
|
||||||
|
|
||||||
void PerformStep(ZoneWriter* zoneLoader, IWritingStream* stream) override;
|
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||||
};
|
};
|
||||||
|
17
src/ZoneWriting/Writing/Steps/StepAlign.cpp
Normal file
17
src/ZoneWriting/Writing/Steps/StepAlign.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "StepAlign.h"
|
||||||
|
|
||||||
|
StepAlign::StepAlign(const size_t alignTo, const uint8_t alignValue)
|
||||||
|
: m_align_to(alignTo),
|
||||||
|
m_align_value(alignValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StepAlign::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||||
|
{
|
||||||
|
const auto pos = stream->Pos();
|
||||||
|
const auto targetPos = (pos + m_align_to - 1) / m_align_to * m_align_to;
|
||||||
|
const auto valueCount = static_cast<size_t>(targetPos - pos);
|
||||||
|
|
||||||
|
for(auto i = 0u; i < valueCount; i++)
|
||||||
|
stream->Write(&m_align_value, sizeof(m_align_value));
|
||||||
|
}
|
17
src/ZoneWriting/Writing/Steps/StepAlign.h
Normal file
17
src/ZoneWriting/Writing/Steps/StepAlign.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "Writing/IWritingStep.h"
|
||||||
|
|
||||||
|
class StepAlign final : public IWritingStep
|
||||||
|
{
|
||||||
|
size_t m_align_to;
|
||||||
|
uint8_t m_align_value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
StepAlign(size_t alignTo, uint8_t alignValue);
|
||||||
|
|
||||||
|
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||||
|
};
|
12
src/ZoneWriting/Writing/Steps/StepRemoveOutputProcessor.cpp
Normal file
12
src/ZoneWriting/Writing/Steps/StepRemoveOutputProcessor.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "StepRemoveOutputProcessor.h"
|
||||||
|
|
||||||
|
StepRemoveOutputProcessor::StepRemoveOutputProcessor(OutputStreamProcessor* streamProcessor)
|
||||||
|
: m_stream_processor(streamProcessor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StepRemoveOutputProcessor::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||||
|
{
|
||||||
|
stream->Flush();
|
||||||
|
zoneWriter->RemoveStreamProcessor(m_stream_processor);
|
||||||
|
}
|
14
src/ZoneWriting/Writing/Steps/StepRemoveOutputProcessor.h
Normal file
14
src/ZoneWriting/Writing/Steps/StepRemoveOutputProcessor.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Writing/OutputStreamProcessor.h"
|
||||||
|
#include "Writing/IWritingStep.h"
|
||||||
|
|
||||||
|
class StepRemoveOutputProcessor final : public IWritingStep
|
||||||
|
{
|
||||||
|
OutputStreamProcessor* m_stream_processor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StepRemoveOutputProcessor(OutputStreamProcessor* streamProcessor);
|
||||||
|
|
||||||
|
void PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream) override;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user