mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
Write XChunks in fastfiles
This commit is contained in:
parent
f22012d282
commit
724e221ba4
@ -443,7 +443,7 @@ class Linker::Impl
|
|||||||
|
|
||||||
fs::create_directories(zoneFolderPath);
|
fs::create_directories(zoneFolderPath);
|
||||||
|
|
||||||
std::ofstream stream(zoneFilePath);
|
std::ofstream stream(zoneFilePath, std::fstream::out | std::fstream::binary);
|
||||||
if (!stream.is_open())
|
if (!stream.is_open())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "XChunkProcessorDeflate.h"
|
#include "XChunkProcessorDeflate.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <zutil.h>
|
#include <zutil.h>
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ size_t XChunkProcessorDeflate::Process(int streamNumber, const uint8_t* input, c
|
|||||||
|
|
||||||
ret = deflate(&stream, Z_FINISH);
|
ret = deflate(&stream, Z_FINISH);
|
||||||
if (ret != Z_STREAM_END)
|
if (ret != Z_STREAM_END)
|
||||||
throw XChunkException("Zone has invalid or unsupported compression. Deflate failed");
|
throw XChunkException("Failed to deflate memory of zone.");
|
||||||
|
|
||||||
const size_t outputSize = stream.total_out;
|
const size_t outputSize = stream.total_out;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "AbstractSalsa20Processor.h"
|
#include "AbstractSalsa20Processor.h"
|
||||||
|
|
||||||
XChunkProcessorSalsa20Decryption::XChunkProcessorSalsa20Decryption(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, size_t keySize)
|
XChunkProcessorSalsa20Decryption::XChunkProcessorSalsa20Decryption(const int streamCount, std::string& zoneName, const uint8_t* salsa20Key, const size_t keySize)
|
||||||
: AbstractSalsa20Processor(streamCount, zoneName, salsa20Key, keySize)
|
: AbstractSalsa20Processor(streamCount, zoneName, salsa20Key, keySize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#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"
|
||||||
|
#include "Writing/Steps/StepWriteZoneSizes.h"
|
||||||
|
|
||||||
using namespace T6;
|
using namespace T6;
|
||||||
|
|
||||||
@ -74,6 +75,9 @@ public:
|
|||||||
ICapturedDataProvider* result = nullptr;
|
ICapturedDataProvider* result = nullptr;
|
||||||
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
auto xChunkProcessor = std::make_unique<OutputProcessorXChunks>(ZoneConstants::STREAM_COUNT, ZoneConstants::XCHUNK_SIZE, ZoneConstants::VANILLA_BUFFER_SIZE);
|
||||||
|
|
||||||
|
// Decompress the chunks using zlib
|
||||||
|
xChunkProcessor->AddChunkProcessor(std::make_unique<XChunkProcessorDeflate>());
|
||||||
|
|
||||||
if (isEncrypted)
|
if (isEncrypted)
|
||||||
{
|
{
|
||||||
// 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.
|
||||||
@ -83,8 +87,6 @@ public:
|
|||||||
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
xChunkProcessor->AddChunkProcessor(std::move(chunkProcessorSalsa20));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompress the chunks using zlib
|
|
||||||
xChunkProcessor->AddChunkProcessor(std::make_unique<XChunkProcessorDeflate>());
|
|
||||||
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
|
// If there is encryption, the signed data of the zone is the final hash blocks provided by the Salsa20 IV adaption algorithm
|
||||||
@ -111,6 +113,7 @@ public:
|
|||||||
|
|
||||||
// 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
|
||||||
|
m_writer->AddWritingStep(std::make_unique<StepWriteZoneSizes>(contentInMemoryPtr));
|
||||||
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
m_writer->AddWritingStep(std::make_unique<StepWriteXBlockSizes>(m_zone));
|
||||||
|
|
||||||
// Start of the zone content
|
// Start of the zone content
|
||||||
|
@ -14,5 +14,6 @@ public:
|
|||||||
IWritingStream& operator=(IWritingStream&& other) noexcept = default;
|
IWritingStream& operator=(IWritingStream&& other) noexcept = default;
|
||||||
|
|
||||||
virtual void Write(const void* buffer, size_t length) = 0;
|
virtual void Write(const void* buffer, size_t length) = 0;
|
||||||
|
virtual void Flush() = 0;
|
||||||
virtual int64_t Pos() = 0;
|
virtual int64_t Pos() = 0;
|
||||||
};
|
};
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
class InMemoryZoneData
|
class InMemoryZoneData
|
||||||
{
|
{
|
||||||
static constexpr size_t BUFFER_SIZE = 0x10000;
|
static constexpr size_t BUFFER_SIZE = 0x400000;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class MemoryBuffer
|
class MemoryBuffer
|
||||||
|
@ -1,46 +1,123 @@
|
|||||||
#include "OutputProcessorXChunks.h"
|
#include "OutputProcessorXChunks.h"
|
||||||
|
|
||||||
class OutputProcessorXChunks::Impl
|
#include <cassert>
|
||||||
{
|
|
||||||
|
|
||||||
};
|
#include "Writing/WritingException.h"
|
||||||
|
#include "Zone/ZoneTypes.h"
|
||||||
|
#include "Zone/XChunk/XChunkException.h"
|
||||||
|
|
||||||
OutputProcessorXChunks::OutputProcessorXChunks(int numStreams, size_t xChunkSize)
|
void OutputProcessorXChunks::Init()
|
||||||
{
|
{
|
||||||
|
if (m_vanilla_buffer_size > 0)
|
||||||
|
m_vanilla_buffer_offset = static_cast<size_t>(m_base_stream->Pos()) % m_vanilla_buffer_size;
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputProcessorXChunks::OutputProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize)
|
void OutputProcessorXChunks::WriteChunk()
|
||||||
{
|
{
|
||||||
|
if (m_vanilla_buffer_size > 0)
|
||||||
|
{
|
||||||
|
if (m_vanilla_buffer_offset + sizeof(xchunk_size_t) > m_vanilla_buffer_size)
|
||||||
|
{
|
||||||
|
xchunk_size_t zeroMem = 0;
|
||||||
|
m_base_stream->Write(&zeroMem, m_vanilla_buffer_size - m_vanilla_buffer_offset);
|
||||||
|
m_vanilla_buffer_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (const auto& processor : m_chunk_processors)
|
||||||
|
{
|
||||||
|
m_input_size = processor->Process(m_current_stream, m_input_buffer, m_input_size, m_output_buffer, m_chunk_size);
|
||||||
|
auto* swap = m_input_buffer;
|
||||||
|
m_input_buffer = m_output_buffer;
|
||||||
|
m_output_buffer = swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XChunkException& e)
|
||||||
|
{
|
||||||
|
throw WritingException(e.Message());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto chunkSize = static_cast<xchunk_size_t>(m_input_size);
|
||||||
|
m_base_stream->Write(&chunkSize, sizeof(chunkSize));
|
||||||
|
m_base_stream->Write(m_input_buffer, m_input_size);
|
||||||
|
|
||||||
|
if (m_vanilla_buffer_size > 0)
|
||||||
|
{
|
||||||
|
m_vanilla_buffer_offset += sizeof(chunkSize) + m_input_size;
|
||||||
|
m_vanilla_buffer_offset %= m_vanilla_buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_current_stream = (m_current_stream + 1) % m_stream_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputProcessorXChunks::~OutputProcessorXChunks()
|
OutputProcessorXChunks::OutputProcessorXChunks(const int numStreams, const size_t xChunkSize)
|
||||||
|
: m_stream_count(numStreams),
|
||||||
|
m_chunk_size(xChunkSize),
|
||||||
|
m_vanilla_buffer_size(0),
|
||||||
|
m_initialized(false),
|
||||||
|
m_current_stream(0),
|
||||||
|
m_vanilla_buffer_offset(0),
|
||||||
|
m_input_buffer(nullptr),
|
||||||
|
m_output_buffer(nullptr),
|
||||||
|
m_input_size(0)
|
||||||
{
|
{
|
||||||
delete m_impl;
|
assert(numStreams > 0);
|
||||||
m_impl = nullptr;
|
assert(xChunkSize > 0);
|
||||||
|
|
||||||
|
for (auto i = 0u; i < 2u; i++)
|
||||||
|
m_buffers.emplace_back(std::make_unique<uint8_t[]>(xChunkSize));
|
||||||
|
|
||||||
|
m_input_buffer = m_buffers[0].get();
|
||||||
|
m_output_buffer = m_buffers[1].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputProcessorXChunks::OutputProcessorXChunks(OutputProcessorXChunks&& other) noexcept
|
OutputProcessorXChunks::OutputProcessorXChunks(const int numStreams, const size_t xChunkSize, const size_t vanillaBufferSize)
|
||||||
: m_impl(other.m_impl)
|
: OutputProcessorXChunks(numStreams, xChunkSize)
|
||||||
{
|
{
|
||||||
other.m_impl = nullptr;
|
m_vanilla_buffer_size = vanillaBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputProcessorXChunks& OutputProcessorXChunks::operator=(OutputProcessorXChunks&& other) noexcept
|
void OutputProcessorXChunks::AddChunkProcessor(std::unique_ptr<IXChunkProcessor> chunkProcessor)
|
||||||
{
|
{
|
||||||
m_impl = other.m_impl;
|
assert(chunkProcessor != nullptr);
|
||||||
other.m_impl = nullptr;
|
|
||||||
return *this;
|
m_chunk_processors.emplace_back(std::move(chunkProcessor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputProcessorXChunks::AddChunkProcessor(std::unique_ptr<IXChunkProcessor> chunkProcessor) const
|
void OutputProcessorXChunks::Write(const void* buffer, const size_t length)
|
||||||
{
|
{
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
|
||||||
|
if (!m_initialized)
|
||||||
|
Init();
|
||||||
|
|
||||||
|
auto sizeRemaining = length;
|
||||||
|
while (sizeRemaining > 0)
|
||||||
|
{
|
||||||
|
const auto toWrite = std::min(m_chunk_size - m_input_size, sizeRemaining);
|
||||||
|
|
||||||
|
memcpy(&m_input_buffer[m_input_size], &static_cast<const char*>(buffer)[length - sizeRemaining], toWrite);
|
||||||
|
m_input_size += toWrite;
|
||||||
|
if (m_input_size >= m_chunk_size)
|
||||||
|
WriteChunk();
|
||||||
|
|
||||||
|
sizeRemaining -= toWrite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputProcessorXChunks::Write(const void* buffer, size_t length)
|
void OutputProcessorXChunks::Flush()
|
||||||
{
|
{
|
||||||
|
if (m_input_size)
|
||||||
|
WriteChunk();
|
||||||
|
|
||||||
|
m_base_stream->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t OutputProcessorXChunks::Pos()
|
int64_t OutputProcessorXChunks::Pos()
|
||||||
{
|
{
|
||||||
return 0;
|
return m_base_stream->Pos();
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,45 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "Writing/OutputStreamProcessor.h"
|
#include "Writing/OutputStreamProcessor.h"
|
||||||
#include "Zone/XChunk/IXChunkProcessor.h"
|
#include "Zone/XChunk/IXChunkProcessor.h"
|
||||||
|
|
||||||
class OutputProcessorXChunks final : public OutputStreamProcessor
|
class OutputProcessorXChunks final : public OutputStreamProcessor
|
||||||
{
|
{
|
||||||
class Impl;
|
std::vector<std::unique_ptr<IXChunkProcessor>> m_chunk_processors;
|
||||||
Impl* m_impl;
|
|
||||||
|
int m_stream_count;
|
||||||
|
size_t m_chunk_size;
|
||||||
|
size_t m_vanilla_buffer_size;
|
||||||
|
|
||||||
|
bool m_initialized;
|
||||||
|
int m_current_stream;
|
||||||
|
size_t m_vanilla_buffer_offset;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<uint8_t[]>> m_buffers;
|
||||||
|
uint8_t* m_input_buffer;
|
||||||
|
uint8_t* m_output_buffer;
|
||||||
|
size_t m_input_size;
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void WriteChunk();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OutputProcessorXChunks(int numStreams, size_t xChunkSize);
|
OutputProcessorXChunks(int numStreams, size_t xChunkSize);
|
||||||
OutputProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize);
|
OutputProcessorXChunks(int numStreams, size_t xChunkSize, size_t vanillaBufferSize);
|
||||||
~OutputProcessorXChunks() override;
|
~OutputProcessorXChunks() override = default;
|
||||||
|
|
||||||
OutputProcessorXChunks(const OutputProcessorXChunks& other) = delete;
|
OutputProcessorXChunks(const OutputProcessorXChunks& other) = delete;
|
||||||
OutputProcessorXChunks(OutputProcessorXChunks&& other) noexcept;
|
OutputProcessorXChunks(OutputProcessorXChunks&& other) noexcept = default;
|
||||||
OutputProcessorXChunks& operator=(const OutputProcessorXChunks& other) = delete;
|
OutputProcessorXChunks& operator=(const OutputProcessorXChunks& other) = delete;
|
||||||
OutputProcessorXChunks& operator=(OutputProcessorXChunks&& other) noexcept;
|
OutputProcessorXChunks& operator=(OutputProcessorXChunks&& other) noexcept = default;
|
||||||
|
|
||||||
void AddChunkProcessor(std::unique_ptr<IXChunkProcessor> chunkProcessor) const;
|
void AddChunkProcessor(std::unique_ptr<IXChunkProcessor> chunkProcessor);
|
||||||
|
|
||||||
void Write(const void* buffer, size_t length) override;
|
void Write(const void* buffer, size_t length) override;
|
||||||
|
void Flush() override;
|
||||||
int64_t Pos() override;
|
int64_t Pos() override;
|
||||||
};
|
};
|
||||||
|
@ -7,4 +7,9 @@ StepWriteXBlockSizes::StepWriteXBlockSizes(Zone* zone)
|
|||||||
|
|
||||||
void StepWriteXBlockSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
void StepWriteXBlockSizes::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||||
{
|
{
|
||||||
|
for(const auto& block : zoneWriter->m_blocks)
|
||||||
|
{
|
||||||
|
auto blockSize = static_cast<xblock_size_t>(block->m_buffer_size);
|
||||||
|
stream->Write(&blockSize, sizeof(blockSize));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,8 @@ StepWriteZoneContentToFile::StepWriteZoneContentToFile(StepWriteZoneContentToMem
|
|||||||
|
|
||||||
void StepWriteZoneContentToFile::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
void StepWriteZoneContentToFile::PerformStep(ZoneWriter* zoneWriter, IWritingStream* stream)
|
||||||
{
|
{
|
||||||
|
for(const auto& dataBuffer : m_memory->GetData()->m_buffers)
|
||||||
|
{
|
||||||
|
stream->Write(dataBuffer.m_data.get(), dataBuffer.m_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,11 @@ void WritingFileStream::Write(const void* buffer, const size_t length)
|
|||||||
m_stream.write(static_cast<const char*>(buffer), length);
|
m_stream.write(static_cast<const char*>(buffer), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WritingFileStream::Flush()
|
||||||
|
{
|
||||||
|
m_stream.flush();
|
||||||
|
}
|
||||||
|
|
||||||
int64_t WritingFileStream::Pos()
|
int64_t WritingFileStream::Pos()
|
||||||
{
|
{
|
||||||
return m_stream.tellp();
|
return m_stream.tellp();
|
||||||
|
@ -11,5 +11,6 @@ public:
|
|||||||
explicit WritingFileStream(std::ostream& stream);
|
explicit WritingFileStream(std::ostream& stream);
|
||||||
|
|
||||||
void Write(const void* buffer, size_t length) override;
|
void Write(const void* buffer, size_t length) override;
|
||||||
|
void Flush() override;
|
||||||
int64_t Pos() override;
|
int64_t Pos() override;
|
||||||
};
|
};
|
||||||
|
@ -75,5 +75,7 @@ bool ZoneWriter::WriteZone(std::ostream& stream)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endStream->Flush();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user