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>();
|
||||
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");
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user