From 9d1643d3ce1e4ec14ebb48ef987e869bbd104dcd Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sun, 7 Mar 2021 00:08:51 +0100 Subject: [PATCH] Fix #14217: Crash in large_scenery_paint() --- src/openrct2/object/LargeSceneryObject.cpp | 8 ++++++++ src/openrct2/object/LargeSceneryObject.h | 1 + .../paint/tile_element/Paint.LargeScenery.cpp | 14 +++++++++++--- src/openrct2/world/LargeScenery.cpp | 6 ++++++ src/openrct2/world/TileElement.h | 2 ++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 47d3a3cc52..1cb0738bc7 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -274,3 +274,11 @@ std::vector LargeSceneryObject::ReadJsonGlyphs(jso } return glyphs; } + +const rct_large_scenery_tile* LargeSceneryObject::GetTileForSequence(uint8_t SequenceIndex) const +{ + if (SequenceIndex >= _tiles.size()) + return nullptr; + + return &_tiles[SequenceIndex]; +} diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index 36ffd7b5c1..00e33a4670 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -40,6 +40,7 @@ public: void Unload() override; void DrawPreview(rct_drawpixelinfo* dpi, int32_t width, int32_t height) const override; + const rct_large_scenery_tile* GetTileForSequence(uint8_t SequenceIndex) const; private: static std::vector ReadTiles(OpenRCT2::IStream* stream); diff --git a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp index fedcc4adb2..b0d072d05b 100644 --- a/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp +++ b/src/openrct2/paint/tile_element/Paint.LargeScenery.cpp @@ -11,6 +11,7 @@ #include "../../config/Config.h" #include "../../interface/Viewport.h" #include "../../localisation/Localisation.h" +#include "../../object/LargeSceneryObject.h" #include "../../ride/Ride.h" #include "../../ride/TrackDesign.h" #include "../../util/Util.h" @@ -27,7 +28,7 @@ // 6B8172: static void large_scenery_paint_supports( paint_session* session, uint8_t direction, uint16_t height, const TileElement* tileElement, uint32_t dword_F4387C, - rct_large_scenery_tile* tile) + const rct_large_scenery_tile* tile) { if (tile->flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS) { @@ -227,12 +228,19 @@ void large_scenery_paint(paint_session* session, uint8_t direction, uint16_t hei } session->InteractionType = ViewportInteractionItem::LargeScenery; uint32_t sequenceNum = tileElement->AsLargeScenery()->GetSequenceIndex(); - rct_scenery_entry* entry = tileElement->AsLargeScenery()->GetEntry(); + const LargeSceneryObject* object = tileElement->AsLargeScenery()->GetObject(); + if (object == nullptr) + return; + + const rct_scenery_entry* entry = tileElement->AsLargeScenery()->GetEntry(); if (entry == nullptr) return; uint32_t image_id = (sequenceNum << 2) + entry->image + 4 + direction; - rct_large_scenery_tile* tile = &entry->large_scenery.tiles[sequenceNum]; + const rct_large_scenery_tile* tile = object->GetTileForSequence(sequenceNum); + if (tile == nullptr) + return; + uint32_t dword_F4387C = 0; image_id |= SPRITE_ID_PALETTE_COLOUR_2( tileElement->AsLargeScenery()->GetPrimaryColour(), tileElement->AsLargeScenery()->GetSecondaryColour()); diff --git a/src/openrct2/world/LargeScenery.cpp b/src/openrct2/world/LargeScenery.cpp index 32e5c510d8..8435f129ad 100644 --- a/src/openrct2/world/LargeScenery.cpp +++ b/src/openrct2/world/LargeScenery.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../common.h" +#include "../object/LargeSceneryObject.h" #include "../object/ObjectManager.h" #include "../world/Banner.h" #include "TileElement.h" @@ -79,6 +80,11 @@ rct_scenery_entry* LargeSceneryElement::GetEntry() const return get_large_scenery_entry(GetEntryIndex()); } +const LargeSceneryObject* LargeSceneryElement::GetObject() const +{ + return static_cast(object_entry_get_object(ObjectType::LargeScenery, GetEntryIndex())); +} + uint8_t LargeSceneryElement::GetSequenceIndex() const { return SequenceIndex; diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index d9d6c7186a..46342baaba 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -19,6 +19,7 @@ struct Banner; struct CoordsXY; struct rct_scenery_entry; struct rct_footpath_entry; +class LargeSceneryObject; class TerrainSurfaceObject; class TerrainEdgeObject; using track_type_t = uint16_t; @@ -492,6 +493,7 @@ public: ObjectEntryIndex GetEntryIndex() const; void SetEntryIndex(ObjectEntryIndex newIndex); rct_scenery_entry* GetEntry() const; + const LargeSceneryObject* GetObject() const; uint8_t GetSequenceIndex() const; void SetSequenceIndex(uint8_t newIndex);