mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-10 09:32:29 +01:00
Don't Double-Compress Park Chunks in Replay File (#24728)
This commit is contained in:
@@ -261,7 +261,7 @@ namespace OpenRCT2
|
|||||||
|
|
||||||
auto exporter = std::make_unique<ParkFileExporter>();
|
auto exporter = std::make_unique<ParkFileExporter>();
|
||||||
exporter->ExportObjectsList = objects;
|
exporter->ExportObjectsList = objects;
|
||||||
exporter->Export(gameState, replayData->parkData);
|
exporter->Export(gameState, replayData->parkData, Compression::kNoCompressionLevel);
|
||||||
|
|
||||||
replayData->timeRecorded = std::chrono::seconds(std::time(nullptr)).count();
|
replayData->timeRecorded = std::chrono::seconds(std::time(nullptr)).count();
|
||||||
|
|
||||||
@@ -314,8 +314,7 @@ namespace OpenRCT2
|
|||||||
MemoryStream compressed;
|
MemoryStream compressed;
|
||||||
stream.SetPosition(0);
|
stream.SetPosition(0);
|
||||||
bool compressStatus = Compression::zlibCompress(
|
bool compressStatus = Compression::zlibCompress(
|
||||||
stream, static_cast<size_t>(stream.GetLength()), compressed, Compression::ZlibHeaderType::zlib,
|
stream, stream.GetLength(), compressed, Compression::ZlibHeaderType::zlib, kReplayCompressionLevel);
|
||||||
kReplayCompressionLevel);
|
|
||||||
if (!compressStatus)
|
if (!compressStatus)
|
||||||
throw IOException("Compression Error");
|
throw IOException("Compression Error");
|
||||||
|
|
||||||
@@ -567,8 +566,8 @@ namespace OpenRCT2
|
|||||||
|
|
||||||
recFile.data.SetPosition(0);
|
recFile.data.SetPosition(0);
|
||||||
decompressStatus = Compression::zlibDecompress(
|
decompressStatus = Compression::zlibDecompress(
|
||||||
recFile.data, static_cast<size_t>(recFile.data.GetLength()), decompressed,
|
recFile.data, recFile.data.GetLength(), decompressed, recFile.uncompressedSize,
|
||||||
static_cast<size_t>(recFile.uncompressedSize), Compression::ZlibHeaderType::zlib);
|
Compression::ZlibHeaderType::zlib);
|
||||||
|
|
||||||
if (!decompressStatus)
|
if (!decompressStatus)
|
||||||
throw IOException("Decompression Error");
|
throw IOException("Decompression Error");
|
||||||
|
|||||||
@@ -73,12 +73,14 @@ namespace OpenRCT2
|
|||||||
sfl::small_vector<ChunkEntry, 32> _chunks;
|
sfl::small_vector<ChunkEntry, 32> _chunks;
|
||||||
MemoryStream _buffer;
|
MemoryStream _buffer;
|
||||||
ChunkEntry _currentChunk;
|
ChunkEntry _currentChunk;
|
||||||
|
int16_t _compressionLevel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OrcaStream(IStream& stream, const Mode mode)
|
OrcaStream(IStream& stream, const Mode mode, int16_t compressionLevel = Compression::kZlibDefaultCompressionLevel)
|
||||||
{
|
{
|
||||||
_stream = &stream;
|
_stream = &stream;
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
|
_compressionLevel = compressionLevel;
|
||||||
if (mode == Mode::READING)
|
if (mode == Mode::READING)
|
||||||
{
|
{
|
||||||
_header = _stream->ReadValue<Header>();
|
_header = _stream->ReadValue<Header>();
|
||||||
@@ -93,15 +95,14 @@ namespace OpenRCT2
|
|||||||
// Uncompress
|
// Uncompress
|
||||||
if (_header.Compression != CompressionType::none)
|
if (_header.Compression != CompressionType::none)
|
||||||
{
|
{
|
||||||
size_t compressedSize = static_cast<size_t>(_header.CompressedSize);
|
|
||||||
size_t uncompressedSize = static_cast<size_t>(_header.UncompressedSize);
|
|
||||||
bool decompressStatus = false;
|
bool decompressStatus = false;
|
||||||
|
|
||||||
switch (_header.Compression)
|
switch (_header.Compression)
|
||||||
{
|
{
|
||||||
case CompressionType::gzip:
|
case CompressionType::gzip:
|
||||||
decompressStatus = Compression::zlibDecompress(
|
decompressStatus = Compression::zlibDecompress(
|
||||||
*_stream, compressedSize, _buffer, uncompressedSize, Compression::ZlibHeaderType::gzip);
|
*_stream, _header.CompressedSize, _buffer, _header.UncompressedSize,
|
||||||
|
Compression::ZlibHeaderType::gzip);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw IOException("Unknown Park Compression Type");
|
throw IOException("Unknown Park Compression Type");
|
||||||
@@ -129,7 +130,8 @@ namespace OpenRCT2
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
_header = {};
|
_header = {};
|
||||||
_header.Compression = CompressionType::gzip;
|
_header.Compression = _compressionLevel == Compression::kNoCompressionLevel ? CompressionType::none
|
||||||
|
: CompressionType::gzip;
|
||||||
_buffer = MemoryStream{};
|
_buffer = MemoryStream{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,11 +147,13 @@ namespace OpenRCT2
|
|||||||
_header.CompressedSize = _buffer.GetLength();
|
_header.CompressedSize = _buffer.GetLength();
|
||||||
_header.FNV1a = Crypt::FNV1a(_buffer.GetData(), _buffer.GetLength());
|
_header.FNV1a = Crypt::FNV1a(_buffer.GetData(), _buffer.GetLength());
|
||||||
|
|
||||||
|
if (_compressionLevel == Compression::kNoCompressionLevel)
|
||||||
|
_header.Compression = CompressionType::none;
|
||||||
|
|
||||||
// Compress data
|
// Compress data
|
||||||
if (_header.Compression != CompressionType::none)
|
if (_header.Compression != CompressionType::none)
|
||||||
{
|
{
|
||||||
MemoryStream compressed;
|
MemoryStream compressed;
|
||||||
size_t bufferLength = static_cast<size_t>(_buffer.GetLength());
|
|
||||||
bool compressStatus = false;
|
bool compressStatus = false;
|
||||||
|
|
||||||
_buffer.SetPosition(0);
|
_buffer.SetPosition(0);
|
||||||
@@ -157,7 +161,7 @@ namespace OpenRCT2
|
|||||||
{
|
{
|
||||||
case CompressionType::gzip:
|
case CompressionType::gzip:
|
||||||
compressStatus = Compression::zlibCompress(
|
compressStatus = Compression::zlibCompress(
|
||||||
_buffer, bufferLength, compressed, Compression::ZlibHeaderType::gzip);
|
_buffer, _buffer.GetLength(), compressed, Compression::ZlibHeaderType::gzip, _compressionLevel);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -199,6 +203,16 @@ namespace OpenRCT2
|
|||||||
return _header;
|
return _header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t GetCompressionLevel() const
|
||||||
|
{
|
||||||
|
return _compressionLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCompressionLevel(int16_t compressionLevel)
|
||||||
|
{
|
||||||
|
_compressionLevel = compressionLevel;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename TFunc>
|
template<typename TFunc>
|
||||||
bool ReadWriteChunk(const uint32_t chunkId, TFunc f)
|
bool ReadWriteChunk(const uint32_t chunkId, TFunc f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -177,9 +177,9 @@ namespace OpenRCT2
|
|||||||
gameState.initialCash = gameState.cash;
|
gameState.initialCash = gameState.cash;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save(GameState_t& gameState, IStream& stream)
|
void Save(GameState_t& gameState, IStream& stream, int16_t compressionLevel)
|
||||||
{
|
{
|
||||||
OrcaStream os(stream, OrcaStream::Mode::WRITING);
|
OrcaStream os(stream, OrcaStream::Mode::WRITING, compressionLevel);
|
||||||
|
|
||||||
auto& header = os.GetHeader();
|
auto& header = os.GetHeader();
|
||||||
header.Magic = kParkFileMagic;
|
header.Magic = kParkFileMagic;
|
||||||
@@ -206,10 +206,10 @@ namespace OpenRCT2
|
|||||||
ReadWritePackedObjectsChunk(os);
|
ReadWritePackedObjectsChunk(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save(GameState_t& gameState, const std::string_view path)
|
void Save(GameState_t& gameState, const std::string_view path, int16_t compressionLevel)
|
||||||
{
|
{
|
||||||
FileStream fs(path, FileMode::write);
|
FileStream fs(path, FileMode::write);
|
||||||
Save(gameState, fs);
|
Save(gameState, fs, compressionLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScenarioIndexEntry ReadScenarioChunk()
|
ScenarioIndexEntry ReadScenarioChunk()
|
||||||
@@ -2706,21 +2706,21 @@ namespace OpenRCT2
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParkFileExporter::Export(GameState_t& gameState, std::string_view path, int16_t compressionLevel)
|
||||||
|
{
|
||||||
|
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
|
||||||
|
parkFile->Save(gameState, path, compressionLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParkFileExporter::Export(GameState_t& gameState, IStream& stream, int16_t compressionLevel)
|
||||||
|
{
|
||||||
|
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
|
||||||
|
parkFile->ExportObjectsList = ExportObjectsList;
|
||||||
|
parkFile->Save(gameState, stream, compressionLevel);
|
||||||
|
}
|
||||||
} // namespace OpenRCT2
|
} // namespace OpenRCT2
|
||||||
|
|
||||||
void ParkFileExporter::Export(GameState_t& gameState, std::string_view path)
|
|
||||||
{
|
|
||||||
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
|
|
||||||
parkFile->Save(gameState, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParkFileExporter::Export(GameState_t& gameState, IStream& stream)
|
|
||||||
{
|
|
||||||
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
|
|
||||||
parkFile->ExportObjectsList = ExportObjectsList;
|
|
||||||
parkFile->Save(gameState, stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum : uint32_t
|
enum : uint32_t
|
||||||
{
|
{
|
||||||
S6_SAVE_FLAG_EXPORT = 1 << 0,
|
S6_SAVE_FLAG_EXPORT = 1 << 0,
|
||||||
@@ -2766,7 +2766,7 @@ int32_t ScenarioSave(GameState_t& gameState, u8string_view path, int32_t flags)
|
|||||||
{
|
{
|
||||||
// s6exporter->SaveGame(path);
|
// s6exporter->SaveGame(path);
|
||||||
}
|
}
|
||||||
parkFile->Save(gameState, path);
|
parkFile->Save(gameState, path, Compression::kZlibDefaultCompressionLevel);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../core/Compression.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -54,13 +56,17 @@ namespace OpenRCT2
|
|||||||
constexpr uint16_t kExtendedGoKartsVersion = 54;
|
constexpr uint16_t kExtendedGoKartsVersion = 54;
|
||||||
constexpr uint16_t kHigherInversionsHolesHelicesStatsVersion = 55;
|
constexpr uint16_t kHigherInversionsHolesHelicesStatsVersion = 55;
|
||||||
constexpr uint16_t kFixedObsoleteFootpathsVersion = 56;
|
constexpr uint16_t kFixedObsoleteFootpathsVersion = 56;
|
||||||
|
|
||||||
|
class ParkFileExporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<const ObjectRepositoryItem*> ExportObjectsList;
|
||||||
|
|
||||||
|
void Export(
|
||||||
|
OpenRCT2::GameState_t& gameState, std::string_view path,
|
||||||
|
int16_t compressionLevel = Compression::kZlibDefaultCompressionLevel);
|
||||||
|
void Export(
|
||||||
|
OpenRCT2::GameState_t& gameState, OpenRCT2::IStream& stream,
|
||||||
|
int16_t compressionLevel = Compression::kZlibDefaultCompressionLevel);
|
||||||
|
};
|
||||||
} // namespace OpenRCT2
|
} // namespace OpenRCT2
|
||||||
|
|
||||||
class ParkFileExporter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::vector<const ObjectRepositoryItem*> ExportObjectsList;
|
|
||||||
|
|
||||||
void Export(OpenRCT2::GameState_t& gameState, std::string_view path);
|
|
||||||
void Export(OpenRCT2::GameState_t& gameState, OpenRCT2::IStream& stream);
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user