1
0
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:
LRFLEW
2025-07-20 19:03:52 -05:00
committed by GitHub
parent 9d5b21cebf
commit c79eb0609b
4 changed files with 58 additions and 39 deletions

View File

@@ -261,7 +261,7 @@ namespace OpenRCT2
auto exporter = std::make_unique<ParkFileExporter>();
exporter->ExportObjectsList = objects;
exporter->Export(gameState, replayData->parkData);
exporter->Export(gameState, replayData->parkData, Compression::kNoCompressionLevel);
replayData->timeRecorded = std::chrono::seconds(std::time(nullptr)).count();
@@ -314,8 +314,7 @@ namespace OpenRCT2
MemoryStream compressed;
stream.SetPosition(0);
bool compressStatus = Compression::zlibCompress(
stream, static_cast<size_t>(stream.GetLength()), compressed, Compression::ZlibHeaderType::zlib,
kReplayCompressionLevel);
stream, stream.GetLength(), compressed, Compression::ZlibHeaderType::zlib, kReplayCompressionLevel);
if (!compressStatus)
throw IOException("Compression Error");
@@ -567,8 +566,8 @@ namespace OpenRCT2
recFile.data.SetPosition(0);
decompressStatus = Compression::zlibDecompress(
recFile.data, static_cast<size_t>(recFile.data.GetLength()), decompressed,
static_cast<size_t>(recFile.uncompressedSize), Compression::ZlibHeaderType::zlib);
recFile.data, recFile.data.GetLength(), decompressed, recFile.uncompressedSize,
Compression::ZlibHeaderType::zlib);
if (!decompressStatus)
throw IOException("Decompression Error");

View File

@@ -73,12 +73,14 @@ namespace OpenRCT2
sfl::small_vector<ChunkEntry, 32> _chunks;
MemoryStream _buffer;
ChunkEntry _currentChunk;
int16_t _compressionLevel;
public:
OrcaStream(IStream& stream, const Mode mode)
OrcaStream(IStream& stream, const Mode mode, int16_t compressionLevel = Compression::kZlibDefaultCompressionLevel)
{
_stream = &stream;
_mode = mode;
_compressionLevel = compressionLevel;
if (mode == Mode::READING)
{
_header = _stream->ReadValue<Header>();
@@ -93,15 +95,14 @@ namespace OpenRCT2
// Uncompress
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;
switch (_header.Compression)
{
case CompressionType::gzip:
decompressStatus = Compression::zlibDecompress(
*_stream, compressedSize, _buffer, uncompressedSize, Compression::ZlibHeaderType::gzip);
*_stream, _header.CompressedSize, _buffer, _header.UncompressedSize,
Compression::ZlibHeaderType::gzip);
break;
default:
throw IOException("Unknown Park Compression Type");
@@ -129,7 +130,8 @@ namespace OpenRCT2
else
{
_header = {};
_header.Compression = CompressionType::gzip;
_header.Compression = _compressionLevel == Compression::kNoCompressionLevel ? CompressionType::none
: CompressionType::gzip;
_buffer = MemoryStream{};
}
}
@@ -145,11 +147,13 @@ namespace OpenRCT2
_header.CompressedSize = _buffer.GetLength();
_header.FNV1a = Crypt::FNV1a(_buffer.GetData(), _buffer.GetLength());
if (_compressionLevel == Compression::kNoCompressionLevel)
_header.Compression = CompressionType::none;
// Compress data
if (_header.Compression != CompressionType::none)
{
MemoryStream compressed;
size_t bufferLength = static_cast<size_t>(_buffer.GetLength());
bool compressStatus = false;
_buffer.SetPosition(0);
@@ -157,7 +161,7 @@ namespace OpenRCT2
{
case CompressionType::gzip:
compressStatus = Compression::zlibCompress(
_buffer, bufferLength, compressed, Compression::ZlibHeaderType::gzip);
_buffer, _buffer.GetLength(), compressed, Compression::ZlibHeaderType::gzip, _compressionLevel);
break;
default:
break;
@@ -199,6 +203,16 @@ namespace OpenRCT2
return _header;
}
int16_t GetCompressionLevel() const
{
return _compressionLevel;
}
void SetCompressionLevel(int16_t compressionLevel)
{
_compressionLevel = compressionLevel;
}
template<typename TFunc>
bool ReadWriteChunk(const uint32_t chunkId, TFunc f)
{

View File

@@ -177,9 +177,9 @@ namespace OpenRCT2
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();
header.Magic = kParkFileMagic;
@@ -206,10 +206,10 @@ namespace OpenRCT2
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);
Save(gameState, fs);
Save(gameState, fs, compressionLevel);
}
ScenarioIndexEntry ReadScenarioChunk()
@@ -2706,20 +2706,20 @@ namespace OpenRCT2
}
});
}
} // namespace OpenRCT2
void ParkFileExporter::Export(GameState_t& gameState, std::string_view path)
void ParkFileExporter::Export(GameState_t& gameState, std::string_view path, int16_t compressionLevel)
{
auto parkFile = std::make_unique<OpenRCT2::ParkFile>();
parkFile->Save(gameState, path);
parkFile->Save(gameState, path, compressionLevel);
}
void ParkFileExporter::Export(GameState_t& gameState, IStream& stream)
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);
parkFile->Save(gameState, stream, compressionLevel);
}
} // namespace OpenRCT2
enum : uint32_t
{
@@ -2766,7 +2766,7 @@ int32_t ScenarioSave(GameState_t& gameState, u8string_view path, int32_t flags)
{
// s6exporter->SaveGame(path);
}
parkFile->Save(gameState, path);
parkFile->Save(gameState, path, Compression::kZlibDefaultCompressionLevel);
result = true;
}
catch (const std::exception& e)

View File

@@ -9,6 +9,8 @@
#pragma once
#include "../core/Compression.h"
#include <cstdint>
#include <string_view>
#include <vector>
@@ -54,13 +56,17 @@ namespace OpenRCT2
constexpr uint16_t kExtendedGoKartsVersion = 54;
constexpr uint16_t kHigherInversionsHolesHelicesStatsVersion = 55;
constexpr uint16_t kFixedObsoleteFootpathsVersion = 56;
} // 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);
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