mirror of https://github.com/OpenRCT2/OpenRCT2.git
Revert "Reduce duplication of gx readers (#16882)"
This reverts commit 2b371db8e3
.
This commit is contained in:
parent
f5507c42e0
commit
bd7ac0bace
|
@ -14,6 +14,7 @@
|
||||||
#include "../PlatformEnvironment.h"
|
#include "../PlatformEnvironment.h"
|
||||||
#include "../config/Config.h"
|
#include "../config/Config.h"
|
||||||
#include "../core/FileStream.h"
|
#include "../core/FileStream.h"
|
||||||
|
#include "../core/MemoryStream.h"
|
||||||
#include "../core/Path.hpp"
|
#include "../core/Path.hpp"
|
||||||
#include "../platform/Platform.h"
|
#include "../platform/Platform.h"
|
||||||
#include "../sprites.h"
|
#include "../sprites.h"
|
||||||
|
@ -361,25 +362,22 @@ bool gfx_load_csg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<rct_gx> GfxLoadGx(OpenRCT2::IStream* stream)
|
std::optional<rct_gx> GfxLoadGx(const std::vector<uint8_t>& buffer)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
OpenRCT2::MemoryStream istream(buffer.data(), buffer.size());
|
||||||
rct_gx gx;
|
rct_gx gx;
|
||||||
|
|
||||||
gx.header = stream->ReadValue<rct_g1_header>();
|
gx.header = istream.ReadValue<rct_g1_header>();
|
||||||
|
|
||||||
// Read element headers
|
// Read element headers
|
||||||
gx.elements.resize(gx.header.num_entries);
|
gx.elements.resize(gx.header.num_entries);
|
||||||
read_and_convert_gxdat(stream, gx.header.num_entries, false, gx.elements.data());
|
read_and_convert_gxdat(&istream, gx.header.num_entries, false, gx.elements.data());
|
||||||
|
|
||||||
// Read element data
|
// Read element data
|
||||||
gx.data = std::make_unique<uint8_t[]>(gx.header.total_size);
|
gx.data = istream.ReadArray<uint8_t>(gx.header.total_size);
|
||||||
const auto readBytes = stream->TryRead(gx.data.get(), gx.header.total_size);
|
|
||||||
if (readBytes != gx.header.total_size)
|
|
||||||
{
|
|
||||||
log_verbose("GXdata size shorter than expected.");
|
|
||||||
}
|
|
||||||
return std::make_optional(std::move(gx));
|
return std::make_optional(std::move(gx));
|
||||||
}
|
}
|
||||||
catch (const std::exception&)
|
catch (const std::exception&)
|
||||||
|
|
|
@ -526,7 +526,7 @@ void gfx_unload_csg();
|
||||||
const rct_g1_element* gfx_get_g1_element(ImageId imageId);
|
const rct_g1_element* gfx_get_g1_element(ImageId imageId);
|
||||||
const rct_g1_element* gfx_get_g1_element(ImageIndex image_id);
|
const rct_g1_element* gfx_get_g1_element(ImageIndex image_id);
|
||||||
void gfx_set_g1_element(ImageIndex imageId, const rct_g1_element* g1);
|
void gfx_set_g1_element(ImageIndex imageId, const rct_g1_element* g1);
|
||||||
std::optional<rct_gx> GfxLoadGx(OpenRCT2::IStream* stream);
|
std::optional<rct_gx> GfxLoadGx(const std::vector<uint8_t>& buffer);
|
||||||
bool is_csg_loaded();
|
bool is_csg_loaded();
|
||||||
void FASTCALL gfx_sprite_to_buffer(rct_drawpixelinfo& dpi, const DrawSpriteArgs& args);
|
void FASTCALL gfx_sprite_to_buffer(rct_drawpixelinfo& dpi, const DrawSpriteArgs& args);
|
||||||
void FASTCALL gfx_bmp_sprite_to_buffer(rct_drawpixelinfo& dpi, const DrawSpriteArgs& args);
|
void FASTCALL gfx_bmp_sprite_to_buffer(rct_drawpixelinfo& dpi, const DrawSpriteArgs& args);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include "../core/FileScanner.h"
|
#include "../core/FileScanner.h"
|
||||||
#include "../core/IStream.hpp"
|
#include "../core/IStream.hpp"
|
||||||
#include "../core/Json.hpp"
|
#include "../core/Json.hpp"
|
||||||
#include "../core/MemoryStream.h"
|
|
||||||
#include "../core/Path.hpp"
|
#include "../core/Path.hpp"
|
||||||
#include "../core/String.hpp"
|
#include "../core/String.hpp"
|
||||||
#include "../drawing/ImageImporter.h"
|
#include "../drawing/ImageImporter.h"
|
||||||
|
@ -241,8 +240,7 @@ std::vector<std::unique_ptr<ImageTable::RequiredImage>> ImageTable::LoadImageArc
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<RequiredImage>> result;
|
std::vector<std::unique_ptr<RequiredImage>> result;
|
||||||
auto gxRaw = context->GetData(path);
|
auto gxRaw = context->GetData(path);
|
||||||
OpenRCT2::MemoryStream stream(gxRaw.data(), gxRaw.size());
|
std::optional<rct_gx> gxData = GfxLoadGx(gxRaw);
|
||||||
std::optional<rct_gx> gxData = GfxLoadGx(&stream);
|
|
||||||
if (gxData.has_value())
|
if (gxData.has_value())
|
||||||
{
|
{
|
||||||
// Fix entry data offsets
|
// Fix entry data offsets
|
||||||
|
@ -430,19 +428,63 @@ void ImageTable::Read(IReadObjectContext* context, OpenRCT2::IStream* stream)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto gxData = GfxLoadGx(stream);
|
|
||||||
|
|
||||||
if (gxData.has_value())
|
try
|
||||||
{
|
{
|
||||||
_data = std::move(gxData->data);
|
uint32_t numImages = stream->ReadValue<uint32_t>();
|
||||||
// Fix entry data offsets
|
uint32_t imageDataSize = stream->ReadValue<uint32_t>();
|
||||||
for (auto& entry : gxData->elements)
|
|
||||||
|
uint64_t headerTableSize = numImages * 16;
|
||||||
|
uint64_t remainingBytes = stream->GetLength() - stream->GetPosition() - headerTableSize;
|
||||||
|
if (remainingBytes > imageDataSize)
|
||||||
{
|
{
|
||||||
entry.offset += reinterpret_cast<uintptr_t>(_data.get());
|
context->LogVerbose(ObjectError::BadImageTable, "Image table size longer than expected.");
|
||||||
|
imageDataSize = static_cast<uint32_t>(remainingBytes);
|
||||||
}
|
}
|
||||||
_entries.insert(_entries.end(), gxData->elements.begin(), gxData->elements.end());
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
else
|
catch (const std::exception&)
|
||||||
{
|
{
|
||||||
context->LogError(ObjectError::BadImageTable, "Bad image table.");
|
context->LogError(ObjectError::BadImageTable, "Bad image table.");
|
||||||
throw;
|
throw;
|
||||||
|
|
Loading…
Reference in New Issue