1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-22 06:23:04 +01:00

Reduce duplication of gx readers (#16882)

* Reduce duplication of gx readers

* Readd nographics return
This commit is contained in:
Duncan
2022-03-28 09:32:33 +01:00
committed by GitHub
parent 660b03f00b
commit 2b371db8e3
3 changed files with 21 additions and 61 deletions

View File

@@ -16,6 +16,7 @@
#include "../core/FileScanner.h"
#include "../core/IStream.hpp"
#include "../core/Json.hpp"
#include "../core/MemoryStream.h"
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../drawing/ImageImporter.h"
@@ -240,7 +241,8 @@ std::vector<std::unique_ptr<ImageTable::RequiredImage>> ImageTable::LoadImageArc
{
std::vector<std::unique_ptr<RequiredImage>> result;
auto gxRaw = context->GetData(path);
std::optional<rct_gx> gxData = GfxLoadGx(gxRaw);
OpenRCT2::MemoryStream stream(gxRaw.data(), gxRaw.size());
std::optional<rct_gx> gxData = GfxLoadGx(&stream);
if (gxData.has_value())
{
// Fix entry data offsets
@@ -428,63 +430,19 @@ void ImageTable::Read(IReadObjectContext* context, OpenRCT2::IStream* stream)
{
return;
}
auto gxData = GfxLoadGx(stream);
try
if (gxData.has_value())
{
uint32_t numImages = stream->ReadValue<uint32_t>();
uint32_t imageDataSize = stream->ReadValue<uint32_t>();
uint64_t headerTableSize = numImages * 16;
uint64_t remainingBytes = stream->GetLength() - stream->GetPosition() - headerTableSize;
if (remainingBytes > imageDataSize)
_data = std::move(gxData->data);
// Fix entry data offsets
for (auto& entry : gxData->elements)
{
context->LogVerbose(ObjectError::BadImageTable, "Image table size longer than expected.");
imageDataSize = static_cast<uint32_t>(remainingBytes);
entry.offset += reinterpret_cast<uintptr_t>(_data.get());
}
auto dataSize = static_cast<size_t>(imageDataSize);
auto data = std::make_unique<uint8_t[]>(dataSize);
if (data == nullptr)
{
context->LogError(ObjectError::BadImageTable, "Image table too large.");
throw std::runtime_error("Image table too large.");
}
// Read g1 element headers
uintptr_t imageDataBase = reinterpret_cast<uintptr_t>(data.get());
std::vector<rct_g1_element> newEntries;
for (uint32_t i = 0; i < numImages; i++)
{
rct_g1_element g1Element{};
uintptr_t imageDataOffset = static_cast<uintptr_t>(stream->ReadValue<uint32_t>());
g1Element.offset = reinterpret_cast<uint8_t*>(imageDataBase + imageDataOffset);
g1Element.width = stream->ReadValue<int16_t>();
g1Element.height = stream->ReadValue<int16_t>();
g1Element.x_offset = stream->ReadValue<int16_t>();
g1Element.y_offset = stream->ReadValue<int16_t>();
g1Element.flags = stream->ReadValue<uint16_t>();
g1Element.zoomed_offset = stream->ReadValue<uint16_t>();
newEntries.push_back(std::move(g1Element));
}
// Read g1 element data
size_t readBytes = static_cast<size_t>(stream->TryRead(data.get(), dataSize));
// If data is shorter than expected (some custom objects are unfortunately like that)
size_t unreadBytes = dataSize - readBytes;
if (unreadBytes > 0)
{
std::fill_n(data.get() + readBytes, unreadBytes, 0);
context->LogWarning(ObjectError::BadImageTable, "Image table size shorter than expected.");
}
_data = std::move(data);
_entries.insert(_entries.end(), newEntries.begin(), newEntries.end());
_entries.insert(_entries.end(), gxData->elements.begin(), gxData->elements.end());
}
catch (const std::exception&)
else
{
context->LogError(ObjectError::BadImageTable, "Bad image table.");
throw;