diff --git a/src/newgrf.cpp b/src/newgrf.cpp index e837ba0786..0b89b81e0a 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1222,19 +1222,16 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte case 0x09: // Define sprite layout statspec->tiles = buf->ReadExtendedByte(); - statspec->renderdata = CallocT(statspec->tiles); + statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles]; for (uint t = 0; t < statspec->tiles; t++) { - DrawTileSprites *dts = &statspec->renderdata[t]; - uint seq_count = 0; + NewGRFSpriteLayout *dts = &statspec->renderdata[t]; - dts->seq = NULL; dts->ground.sprite = buf->ReadWord(); dts->ground.pal = buf->ReadWord(); if (dts->ground.sprite == 0 && dts->ground.pal == 0) { extern const DrawTileSprites _station_display_datas_rail[8]; - dts->ground = _station_display_datas_rail[t % 8].ground; - dts->seq = CopyDrawTileSeqStruct(_station_display_datas_rail[t % 8].seq); + dts->Clone(&_station_display_datas_rail[t % 8]); continue; } if (HasBit(dts->ground.pal, 15)) { @@ -1245,10 +1242,12 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte MapSpriteMappingRecolour(&dts->ground); + static SmallVector tmp_layout; + tmp_layout.Clear(); for (;;) { /* no relative bounding box support */ - dts->seq = ReallocT(const_cast(dts->seq), ++seq_count); - DrawTileSeqStruct *dtss = const_cast(&dts->seq[seq_count - 1]); + DrawTileSeqStruct *dtss = tmp_layout.Append(); + MemSetT(dtss, 0); dtss->delta_x = buf->ReadByte(); if (dtss->IsTerminator()) break; @@ -1269,6 +1268,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte MapSpriteMappingRecolour(&dtss->image); } + dts->Clone(tmp_layout.Begin()); } break; @@ -1282,10 +1282,9 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte } statspec->tiles = srcstatspec->tiles; - statspec->renderdata = MallocT(statspec->tiles); + statspec->renderdata = new NewGRFSpriteLayout[statspec->tiles]; for (uint t = 0; t < statspec->tiles; t++) { - statspec->renderdata[t].ground = srcstatspec->renderdata[t].ground; - statspec->renderdata[t].seq = CopyDrawTileSeqStruct(srcstatspec->renderdata[t].seq); + statspec->renderdata[t].Clone(&srcstatspec->renderdata[t]); } break; } @@ -3947,7 +3946,7 @@ static void NewSpriteGroup(ByteReader *buf) act_group = group; /* num_building_stages should be 1, if we are only using non-custom sprites */ group->num_building_stages = max((uint8)1, num_spriteset_ents); - group->dts = CallocT(1); + group->dts = new NewGRFSpriteLayout(); /* Groundsprite */ group->dts->ground.sprite = buf->ReadWord(); @@ -3972,8 +3971,7 @@ static void NewSpriteGroup(ByteReader *buf) } } - group->dts->seq = CallocT(num_building_sprites + 1); - + group->dts->Allocate(num_building_sprites); for (i = 0; i < num_building_sprites; i++) { DrawTileSeqStruct *seq = const_cast(&group->dts->seq[i]); @@ -4009,10 +4007,6 @@ static void NewSpriteGroup(ByteReader *buf) seq->size_y = buf->ReadByte(); seq->size_z = buf->ReadByte(); } - - /* Set the terminator value. */ - const_cast(group->dts->seq)[i].MakeTerminator(); - break; } @@ -7063,10 +7057,7 @@ static void ResetCustomStations() if (stations[i] == NULL) continue; StationSpec *statspec = stations[i]; - for (uint t = 0; t < statspec->tiles; t++) { - free((void*)statspec->renderdata[t].seq); - } - free(statspec->renderdata); + delete[] statspec->renderdata; /* Release platforms and layouts */ if (!statspec->copied_layouts) { diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index edb3212bfe..ce4a6807a6 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -434,3 +434,34 @@ uint32 GetNearbyTileInformation(TileIndex tile) byte terrain_type = GetTerrainType(tile) << 2 | (tile_type == MP_WATER ? 1 : 0) << 1; return tile_type << 24 | z << 16 | terrain_type << 8 | tileh; } + +/** + * Clone the building sprites of a spritelayout. + * @param source The building sprites to copy. + */ +void NewGRFSpriteLayout::Clone(const DrawTileSeqStruct *source) +{ + assert(this->seq == NULL); + assert(source != NULL); + + size_t count = 1; // 1 for the terminator + const DrawTileSeqStruct *element; + foreach_draw_tile_seq(element, source) count++; + + DrawTileSeqStruct *sprites = MallocT(count); + MemCpyT(sprites, source, count); + this->seq = sprites; +} + +/** + * Allocate a spritelayout for \a num_sprites building sprites. + * @param num_sprites Number of building sprites to allocate memory for. (not counting the terminator) + */ +void NewGRFSpriteLayout::Allocate(uint num_sprites) +{ + assert(this->seq == NULL); + + DrawTileSeqStruct *sprites = CallocT(num_sprites + 1); + sprites[num_sprites].MakeTerminator(); + this->seq = sprites; +} diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index 171ccf7597..1ddfdc1818 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -16,14 +16,42 @@ #define NEWGRF_COMMONS_H #include "tile_type.h" +#include "sprite.h" +#include "core/alloc_type.hpp" -/** Contextx for tile accesses */ +/** Context for tile accesses */ enum TileContext { TCX_NORMAL, ///< Nothing special. TCX_UPPER_HALFTILE, ///< Querying information about the upper part of a tile with halftile foundation. TCX_ON_BRIDGE, ///< Querying information about stuff on the bridge (via some bridgehead). }; +/** + * NewGRF supplied spritelayout. + * In contrast to #DrawTileSprites this struct is for allocated + * layouts on the heap. It allocates data and frees them on destruction. + */ +struct NewGRFSpriteLayout : ZeroedMemoryAllocator, DrawTileSprites { + void Allocate(uint num_sprites); + void Clone(const DrawTileSeqStruct *source); + + /** + * Clone a spritelayout. + * @param source The spritelayout to copy. + */ + void Clone(const DrawTileSprites *source) + { + assert(source != NULL && this != source); + this->ground = source->ground; + this->Clone(source->seq); + } + + virtual ~NewGRFSpriteLayout() + { + free(const_cast(this->seq)); + } +}; + /** * Maps an entity id stored on the map to a GRF file. * Entities are objects used ingame (houses, industries, industry tiles) for diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 5edf44b28b..6b041f0e6c 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -37,8 +37,7 @@ RandomizedSpriteGroup::~RandomizedSpriteGroup() TileLayoutSpriteGroup::~TileLayoutSpriteGroup() { - free((void*)this->dts->seq); - free(this->dts); + delete this->dts; } TemporaryStorageArray _temp_store; diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 2541195d90..3d4134af3f 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -283,7 +283,7 @@ struct TileLayoutSpriteGroup : SpriteGroup { ~TileLayoutSpriteGroup(); byte num_building_stages; ///< Number of building stages to show for this house/industry tile - struct DrawTileSprites *dts; + NewGRFSpriteLayout *dts; }; struct IndustryProductionSpriteGroup : SpriteGroup { diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 7363c9e562..e82747bf72 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -77,7 +77,7 @@ struct StationSpec { * 6-7 = platform with roof, right side */ uint tiles; - DrawTileSprites *renderdata; ///< Array of tile layouts. + NewGRFSpriteLayout *renderdata; ///< Array of tile layouts. /** * Cargo threshold for choosing between little and lots of cargo diff --git a/src/sprite.cpp b/src/sprite.cpp index 4e41be4f1e..e9a83052cb 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -110,17 +110,3 @@ void DrawCommonTileSeqInGUI(int x, int y, const DrawTileSprites *dts, int32 orig } } } - -/** Create a copy of an existing DrawTileSeqStruct array. */ -const DrawTileSeqStruct *CopyDrawTileSeqStruct(const DrawTileSeqStruct *dtss) -{ - const DrawTileSeqStruct *element; - - size_t count = 1; // 1 for the terminator - foreach_draw_tile_seq(element, dtss) count++; - - DrawTileSeqStruct *copy = MallocT(count); - MemCpyT(copy, dtss, count); - - return copy; -} diff --git a/src/sprite.h b/src/sprite.h index 9321ba5347..acb19ed4e8 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -52,9 +52,11 @@ struct DrawTileSeqStruct { } }; -const DrawTileSeqStruct *CopyDrawTileSeqStruct(const DrawTileSeqStruct *dtss); - -/** Ground palette sprite of a tile, together with its child sprites */ +/** + * Ground palette sprite of a tile, together with its sprite layout. + * This struct is used for static sprite layouts in the code. + * For allocated ones from NewGRF see #NewGRFSpriteLayout. + */ struct DrawTileSprites { PalSpriteID ground; ///< Palette and sprite for the ground const DrawTileSeqStruct *seq; ///< Array of child sprites. Terminated with a terminator entry