Mercurial > hg > openttd
changeset 17782:043b87d0dbec draft
(svn r22567) -Codechange: Store persistent storages inside a pool.
author | terkhen <terkhen@openttd.org> |
---|---|
date | Sun, 12 Jun 2011 20:47:45 +0000 |
parents | dceca5355f39 |
children | 1719e5568a82 |
files | projects/openttd_vs100.vcxproj projects/openttd_vs100.vcxproj.filters projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/industry.h src/industry_cmd.cpp src/newgrf_airport.cpp src/newgrf_debug_gui.cpp src/newgrf_industries.cpp src/newgrf_industrytiles.cpp src/newgrf_storage.cpp src/newgrf_storage.h src/saveload/afterload.cpp src/saveload/industry_sl.cpp src/saveload/saveload.cpp src/saveload/saveload.h src/saveload/station_sl.cpp src/saveload/storage_sl.cpp src/station.cpp src/station_base.h src/station_cmd.cpp src/table/newgrf_debug_data.h |
diffstat | 23 files changed, 257 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -740,6 +740,7 @@ <ClInclude Include="..\src\saveload\saveload_internal.h" /> <ClCompile Include="..\src\saveload\signs_sl.cpp" /> <ClCompile Include="..\src\saveload\station_sl.cpp" /> + <ClCompile Include="..\src\saveload\storage_sl.cpp" /> <ClCompile Include="..\src\saveload\strings_sl.cpp" /> <ClCompile Include="..\src\saveload\subsidy_sl.cpp" /> <ClCompile Include="..\src\saveload\town_sl.cpp" />
--- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -1440,6 +1440,9 @@ <ClCompile Include="..\src\saveload\station_sl.cpp"> <Filter>Save/Load handlers</Filter> </ClCompile> + <ClCompile Include="..\src\saveload\storage_sl.cpp"> + <Filter>Save/Load handlers</Filter> + </ClCompile> <ClCompile Include="..\src\saveload\strings_sl.cpp"> <Filter>Save/Load handlers</Filter> </ClCompile>
--- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -2255,6 +2255,10 @@ > </File> <File + RelativePath=".\..\src\saveload\storage_sl.cpp" + > + </File> + <File RelativePath=".\..\src\saveload\strings_sl.cpp" > </File>
--- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -2252,6 +2252,10 @@ > </File> <File + RelativePath=".\..\src\saveload\storage_sl.cpp" + > + </File> + <File RelativePath=".\..\src\saveload\strings_sl.cpp" > </File>
--- a/source.list +++ b/source.list @@ -498,6 +498,7 @@ saveload/saveload_internal.h saveload/signs_sl.cpp saveload/station_sl.cpp +saveload/storage_sl.cpp saveload/strings_sl.cpp saveload/subsidy_sl.cpp saveload/town_sl.cpp
--- a/src/industry.h +++ b/src/industry.h @@ -38,8 +38,6 @@ * Defines the internal data of a functional industry. */ struct Industry : IndustryPool::PoolItem<&_industry_pool> { - typedef PersistentStorageArray<int32, 16> PersistentStorage; - TileArea location; ///< Location of the industry Town *town; ///< Nearest town CargoID produced_cargo[2]; ///< 2 production cargo slots @@ -72,7 +70,7 @@ byte random_triggers; ///< Triggers for the random uint16 random; ///< Random value used for randomisation of all kinds of things - PersistentStorage psa; ///< Persistent storage for NewGRF industries. + PersistentStorage *psa; ///< Persistent storage for NewGRF industries. Industry(TileIndex tile = INVALID_TILE) : location(tile, 0, 0) {} ~Industry();
--- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -167,6 +167,9 @@ /* don't let any disaster vehicle target invalid industry */ ReleaseDisastersTargetingIndustry(this->index); + /* Clear the persistent storage. */ + delete this->psa; + DecIndustryTypeCount(this->type); DeleteIndustryNews(this->index);
--- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -149,7 +149,7 @@ switch (variable) { /* Get a variable from the persistent storage */ - case 0x7C: return st->airport.psa.GetValue(parameter); + case 0x7C: return (st->airport.psa != NULL) ? st->airport.psa->GetValue(parameter) : 0; case 0xF0: return st->facilities; case 0xFA: return Clamp(st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); @@ -194,7 +194,17 @@ { Station *st = object->u.airport.st; if (object->scope != VSG_SCOPE_SELF || st == NULL) return; - st->airport.psa.StoreValue(pos, value); + + if (st->airport.psa == NULL) { + /* There is no need to create a storage if the value is zero. */ + if (value == 0) return; + + /* Create storage on first modification. */ + uint32 grfid = (object->grffile != NULL) ? object->grffile->grfid : 0; + assert(PersistentStorage::CanAllocateItem()); + st->airport.psa = new PersistentStorage(grfid); + } + st->airport.psa->StoreValue(pos, value); } static void NewAirportResolver(ResolverObject *res, TileIndex tile, Station *st, byte airport_id, byte layout)
--- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -158,7 +158,7 @@ /** * Allows to know the size of the persistent storage. - * @param index Unused. + * @param index Index of the item. * @param grfid Unused. * @return Size of the persistent storage in indices. */ @@ -169,7 +169,7 @@ /** * Gets the first position of the array containing the persistent storage. - * @param index Unused. + * @param index Index of the item. * @param grfid Unused. * @return Pointer to the first position of the storage array or NULL if not present. */ @@ -368,11 +368,11 @@ } } - uint psa_size = nih->GetPSASize(0, 0); - if (psa_size != 0) { + uint psa_size = nih->GetPSASize(index, 0); + int32 *psa = nih->GetPSAFirstPosition(index, 0); + if (psa_size != 0 && psa != NULL) { this->DrawString(r, i++, "Persistent storage:"); assert(psa_size % 4 == 0); - int32 *psa = nih->GetPSAFirstPosition(0, 0); for (uint j = 0; j < psa_size; j += 4, psa += 4) { this->DrawString(r, i++, " %i: %i %i %i %i", j, psa[0], psa[1], psa[2], psa[3]); }
--- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -283,7 +283,7 @@ } /* Get a variable from the persistent storage */ - case 0x7C: return industry->psa.GetValue(parameter); + case 0x7C: return (industry->psa != NULL) ? industry->psa->GetValue(parameter) : 0; /* Industry structure access*/ case 0x80: return industry->location.tile; @@ -386,7 +386,19 @@ { Industry *ind = object->u.industry.ind; if (object->scope != VSG_SCOPE_SELF || ind->index == INVALID_INDUSTRY) return; - ind->psa.StoreValue(pos, value); + + if (ind->psa == NULL) { + /* There is no need to create a storage if the value is zero. */ + if (value == 0) return; + + /* Create storage on first modification. */ + const IndustrySpec *indsp = GetIndustrySpec(ind->type); + uint32 grfid = (indsp->grf_prop.grffile != NULL) ? indsp->grf_prop.grffile->grfid : 0; + assert(PersistentStorage::CanAllocateItem()); + ind->psa = new PersistentStorage(grfid); + } + + ind->psa->StoreValue(pos, value); } static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type)
--- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -158,7 +158,19 @@ { Industry *ind = object->u.industry.ind; if (object->scope != VSG_SCOPE_PARENT || ind->index == INVALID_INDUSTRY) return; - ind->psa.StoreValue(pos, value); + + if (ind->psa == NULL) { + /* There is no need to create a storage if the value is zero. */ + if (value == 0) return; + + /* Create storage on first modification. */ + const IndustrySpec *indsp = GetIndustrySpec(ind->type); + uint32 grfid = (indsp->grf_prop.grffile != NULL) ? indsp->grf_prop.grffile->grfid : 0; + assert(PersistentStorage::CanAllocateItem()); + ind->psa = new PersistentStorage(grfid); + } + + ind->psa->StoreValue(pos, value); } static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIndex tile, Industry *indus)
--- a/src/newgrf_storage.cpp +++ b/src/newgrf_storage.cpp @@ -11,8 +11,12 @@ #include "stdafx.h" #include "newgrf_storage.h" +#include "core/pool_func.hpp" #include <set> +PersistentStoragePool _persistent_storage_pool("PersistentStorage"); +INSTANTIATE_POOL_METHODS(PersistentStorage) + /** The changed storage arrays */ static std::set<BaseStorageArray*> _changed_storage_arrays;
--- a/src/newgrf_storage.h +++ b/src/newgrf_storage.h @@ -13,6 +13,7 @@ #define NEWGRF_STORAGE_H #include "core/alloc_func.hpp" +#include "core/pool_type.hpp" /** * Base class for all NewGRF storage arrays. Nothing fancy, only here @@ -178,4 +179,40 @@ void AddChangedStorage(BaseStorageArray *storage); void ClearStorageChanges(bool keep_changes); + +typedef PersistentStorageArray<int32, 16> OldPersistentStorage; + +typedef uint32 PersistentStorageID; + +struct PersistentStorage; +typedef Pool<PersistentStorage, PersistentStorageID, 1, 0xFF000> PersistentStoragePool; + +extern PersistentStoragePool _persistent_storage_pool; + +/** + * Class for pooled persistent storage of data. + * On ClearChanges that data is always zero-ed. + */ +struct PersistentStorage : PersistentStorageArray<int32, 16>, PersistentStoragePool::PoolItem<&_persistent_storage_pool> { + uint32 grfid; ///< GRFID associated to this persistent storage. A value of zero means "default". + + /** We don't want GCC to zero our struct! It already is zeroed and has an index! */ + PersistentStorage(const uint32 new_grfid) : grfid(new_grfid) + { + this->prev_storage = NULL; + memset(this->storage, 0, sizeof(this->storage)); + } + + /** Free the memory used by the persistent storage. */ + ~PersistentStorage() + { + free(this->prev_storage); + } +}; + +assert_compile(cpp_lengthof(OldPersistentStorage, storage) == cpp_lengthof(PersistentStorage, storage)); + +#define FOR_ALL_STORAGES_FROM(var, start) FOR_ALL_ITEMS_FROM(PersistentStorage, storage_index, var, start) +#define FOR_ALL_STORAGES(var) FOR_ALL_STORAGES_FROM(var, 0) + #endif /* NEWGRF_STORAGE_H */
--- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -2595,6 +2595,58 @@ } } + if (IsSavegameVersionBefore(161)) { + /* Before savegame version 161, persistent storages were not stored in a pool. */ + + if (!IsSavegameVersionBefore(76)) { + Industry *ind; + FOR_ALL_INDUSTRIES(ind) { + assert(ind->psa != NULL); + + /* Check if the old storage was empty. */ + bool is_empty = true; + for (uint i = 0; i < sizeof(ind->psa->storage); i++) { + if (ind->psa->GetValue(i) != 0) { + is_empty = false; + break; + } + } + + if (!is_empty) { + ind->psa->grfid = _industry_mngr.GetGRFID(ind->type); + } else { + delete ind->psa; + ind->psa = NULL; + } + } + } + + if (!IsSavegameVersionBefore(145)) { + Station *st; + FOR_ALL_STATIONS(st) { + if (!st->facilities & FACIL_AIRPORT) continue; + assert(st->airport.psa != NULL); + + /* Check if the old storage was empty. */ + bool is_empty = true; + for (uint i = 0; i < sizeof(st->airport.psa->storage); i++) { + if (st->airport.psa->GetValue(i) != 0) { + is_empty = false; + break; + } + } + + if (!is_empty) { + st->airport.psa->grfid = _airport_mngr.GetGRFID(st->airport.type); + } else { + delete st->airport.psa; + st->airport.psa = NULL; + + } + } + } + } + /* Road stops is 'only' updating some caches */ AfterLoadRoadStops(); AfterLoadLabelMaps();
--- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -11,10 +11,13 @@ #include "../stdafx.h" #include "../industry.h" +#include "../newgrf.h" #include "saveload.h" #include "newgrf_sl.h" +static OldPersistentStorage _old_ind_persistent_storage; + static const SaveLoad _industry_desc[] = { SLE_CONDVAR(Industry, location.tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5), SLE_CONDVAR(Industry, location.tile, SLE_UINT32, 6, SL_MAX_VERSION), @@ -50,7 +53,8 @@ SLE_CONDVAR(Industry, last_cargo_accepted_at, SLE_INT32, 70, SL_MAX_VERSION), SLE_CONDVAR(Industry, selected_layout, SLE_UINT8, 73, SL_MAX_VERSION), - SLE_CONDARR(Industry, psa.storage, SLE_UINT32, 16, 76, SL_MAX_VERSION), + SLEG_CONDARR(_old_ind_persistent_storage.storage, SLE_UINT32, 16, 76, 160), + SLE_CONDREF(Industry, psa, REF_STORAGE, 161, SL_MAX_VERSION), SLE_CONDVAR(Industry, random_triggers, SLE_UINT8, 82, SL_MAX_VERSION), SLE_CONDVAR(Industry, random, SLE_UINT16, 82, SL_MAX_VERSION), @@ -90,6 +94,14 @@ while ((index = SlIterateArray()) != -1) { Industry *i = new (index) Industry(); SlObject(i, _industry_desc); + + /* Before savegame version 161, persistent storages were not stored in a pool. */ + if (IsSavegameVersionBefore(161) && !IsSavegameVersionBefore(76)) { + /* Store the old persistent storage. The GRFID will be added later. */ + assert(PersistentStorage::CanAllocateItem()); + i->psa = new PersistentStorage(0); + memcpy(i->psa->storage, _old_ind_persistent_storage.storage, sizeof(i->psa->storage)); + } Industry::IncIndustryTypeCount(i->type); } }
--- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -225,8 +225,9 @@ * 158 21933 * 159 21962 * 160 21974 + * 161 22567 */ -extern const uint16 SAVEGAME_VERSION = 160; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 161; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading @@ -404,6 +405,7 @@ extern const ChunkHandler _labelmaps_chunk_handlers[]; extern const ChunkHandler _airport_chunk_handlers[]; extern const ChunkHandler _object_chunk_handlers[]; +extern const ChunkHandler _persistent_storage_chunk_handlers[]; /** Array of all chunks in a savegame, \c NULL terminated. */ static const ChunkHandler * const _chunk_handlers[] = { @@ -434,6 +436,7 @@ _labelmaps_chunk_handlers, _airport_chunk_handlers, _object_chunk_handlers, + _persistent_storage_chunk_handlers, NULL, }; @@ -1173,9 +1176,10 @@ case REF_TOWN: return ((const Town*)obj)->index + 1; case REF_ORDER: return ((const Order*)obj)->index + 1; case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1; - case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1; - case REF_CARGO_PACKET: return ((const CargoPacket*)obj)->index + 1; - case REF_ORDERLIST: return ((const OrderList*)obj)->index + 1; + case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1; + case REF_CARGO_PACKET: return ((const CargoPacket*)obj)->index + 1; + case REF_ORDERLIST: return ((const OrderList*)obj)->index + 1; + case REF_STORAGE: return ((const PersistentStorage*)obj)->index + 1; default: NOT_REACHED(); } } @@ -1245,6 +1249,10 @@ if (CargoPacket::IsValidID(index)) return CargoPacket::Get(index); SlErrorCorrupt("Referencing invalid CargoPacket"); + case REF_STORAGE: + if (PersistentStorage::IsValidID(index)) return PersistentStorage::Get(index); + SlErrorCorrupt("Referencing invalid PersistentStorage"); + default: NOT_REACHED(); } }
--- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -88,6 +88,7 @@ REF_ENGINE_RENEWS = 6, ///< Load/save a reference to an engine renewal (autoreplace). REF_CARGO_PACKET = 7, ///< Load/save a reference to a cargo packet. REF_ORDERLIST = 8, ///< Load/save a reference to an orderlist. + REF_STORAGE = 9, ///< Load/save a reference to a persistent storage. }; /** Highest possible savegame version. */
--- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -15,6 +15,7 @@ #include "../roadstop_base.h" #include "../vehicle_base.h" #include "../newgrf_station.h" +#include "../newgrf.h" #include "saveload.h" #include "table/strings.h" @@ -344,6 +345,8 @@ SLE_END() }; +static OldPersistentStorage _old_st_persistent_storage; + static const SaveLoad _station_desc[] = { SLE_WRITEBYTE(Station, facilities, FACIL_NONE), SLE_ST_INCLUDE(), @@ -362,7 +365,8 @@ SLE_CONDVAR(Station, airport.layout, SLE_UINT8, 145, SL_MAX_VERSION), SLE_VAR(Station, airport.flags, SLE_UINT64), SLE_CONDVAR(Station, airport.rotation, SLE_UINT8, 145, SL_MAX_VERSION), - SLE_CONDARR(Station, airport.psa.storage, SLE_UINT32, 16, 145, SL_MAX_VERSION), + SLEG_CONDARR(_old_st_persistent_storage.storage, SLE_UINT32, 16, 145, 160), + SLE_CONDREF(Station, airport.psa, REF_STORAGE, 161, SL_MAX_VERSION), SLE_VAR(Station, indtype, SLE_UINT8), @@ -437,6 +441,15 @@ if (!waypoint) { Station *st = Station::From(bst); + + /* Before savegame version 161, persistent storages were not stored in a pool. */ + if (IsSavegameVersionBefore(161) && !IsSavegameVersionBefore(145) && st->facilities & FACIL_AIRPORT) { + /* Store the old persistent storage. The GRFID will be added later. */ + assert(PersistentStorage::CanAllocateItem()); + st->airport.psa = new PersistentStorage(0); + memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage)); + } + for (CargoID i = 0; i < NUM_CARGO; i++) { SlObject(&st->goods[i], GetGoodsDesc()); }
new file mode 100644 --- /dev/null +++ b/src/saveload/storage_sl.cpp @@ -0,0 +1,50 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file persistent_storage_sl.cpp Code handling saving and loading of persistent storages. */ + +#include "../stdafx.h" +#include "../newgrf_storage.h" +#include "saveload.h" + +/** Description of the data to save and load in #PersistentStorage. */ +static const SaveLoad _storage_desc[] = { + SLE_CONDVAR(PersistentStorage, grfid, SLE_UINT32, 6, SL_MAX_VERSION), + SLE_CONDARR(PersistentStorage, storage, SLE_UINT32, 16, 161, SL_MAX_VERSION), + SLE_END() +}; + +/** Load persistent storage data. */ +static void Load_PSAC() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + assert(PersistentStorage::CanAllocateItem()); + PersistentStorage *ps = new (index) PersistentStorage(0); + SlObject(ps, _storage_desc); + } +} + +/** Save persistent storage data. */ +static void Save_PSAC() +{ + PersistentStorage *ps; + + /* Write the industries */ + FOR_ALL_STORAGES(ps) { + SlSetArrayIndex(ps->index); + SlObject(ps, _storage_desc); + } +} + +/** Chunk handler for persistent storages. */ +extern const ChunkHandler _persistent_storage_chunk_handlers[] = { + { 'PSAC', Save_PSAC, Load_PSAC, NULL, NULL, CH_ARRAY | CH_LAST}, +};
--- a/src/station.cpp +++ b/src/station.cpp @@ -96,6 +96,10 @@ } } + /* Clear the persistent storage. */ + delete this->airport.psa; + + InvalidateWindowData(WC_STATION_LIST, this->owner, 0); DeleteWindowById(WC_STATION_VIEW, index);
--- a/src/station_base.h +++ b/src/station_base.h @@ -56,15 +56,14 @@ /** All airport-related information. Only valid if tile != INVALID_TILE. */ struct Airport : public TileArea { - typedef PersistentStorageArray<int32, 16> PersistentStorage; - Airport() : TileArea(INVALID_TILE, 0, 0) {} uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32 byte type; ///< Type of this airport, @see AirportTypes. byte layout; ///< Airport layout number. Direction rotation; ///< How this airport is rotated. - PersistentStorage psa; ///< Persistent storage for NewGRF airports + + PersistentStorage *psa; ///< Persistent storage for NewGRF airports. /** * Get the AirportSpec that from the airport type of this airport. If there
--- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2191,7 +2191,6 @@ st->airport.layout = layout; st->airport.flags = 0; st->airport.rotation = rotation; - st->airport.psa.ResetToZero(); st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY); @@ -2271,6 +2270,9 @@ } if (flags & DC_EXEC) { + /* Clear the persistent storage. */ + delete st->airport.psa; + const AirportSpec *as = st->airport.GetSpec(); for (uint i = 0; i < st->airport.GetNumHangars(); ++i) { DeleteWindowById( @@ -2288,7 +2290,6 @@ st->airport.Clear(); st->facilities &= ~FACIL_AIRPORT; - st->airport.psa.ResetToZero(); SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
--- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -291,12 +291,13 @@ const void *GetSpec(uint index) const { return GetIndustrySpec(Industry::Get(index)->type); } void SetStringParameters(uint index) const { this->SetSimpleStringParameters(STR_INDUSTRY_NAME, index); } void Resolve(ResolverObject *ro, uint32 index) const { extern void GetIndustryResolver(ResolverObject *ro, uint index); GetIndustryResolver(ro, index); } - uint GetPSASize(uint index, uint32 grfid) const { return cpp_lengthof(Industry, psa.storage); } + uint GetPSASize(uint index, uint32 grfid) const { return cpp_lengthof(PersistentStorage, storage); } int32 *GetPSAFirstPosition(uint index, uint32 grfid) const { - const void *base = this->GetInstance(index); - return (int32*)((byte*)base + cpp_offsetof(Industry, psa.storage)); + Industry *i = (Industry *)this->GetInstance(index); + if (i->psa == NULL) return NULL; + return (int32 *)(&i->psa->storage); } };