# HG changeset patch # User Peter Nelson # Date 2019-02-03 23:50:50 # Node ID d6e94d4e839d3475fa0027551da1fe302f61f81f # Parent 5df09db4235a2e9596e503e94b7a507ccf3ca33d Fix #6803: CargoMonitorID bit packing updated to handle 64 cargo types. This requires a saveload bump to change the bitpacking on loading older saves. diff --git a/src/cargomonitor.h b/src/cargomonitor.h --- a/src/cargomonitor.h +++ b/src/cargomonitor.h @@ -45,11 +45,14 @@ enum CargoCompanyBits { CCB_IS_INDUSTRY_BIT = 16, ///< Bit indicating the town/industry number is an industry. CCB_IS_INDUSTRY_BIT_VALUE = 1ul << CCB_IS_INDUSTRY_BIT, ///< Value of the #CCB_IS_INDUSTRY_BIT bit. CCB_CARGO_TYPE_START = 19, ///< Start bit of the cargo type field. - CCB_CARGO_TYPE_LENGTH = 5, ///< Number of bits of the cargo type field. - CCB_COMPANY_START = 24, ///< Start bit of the company field. - CCB_COMPANY_LENGTH = 8, ///< Number of bits of the company field. + CCB_CARGO_TYPE_LENGTH = 6, ///< Number of bits of the cargo type field. + CCB_COMPANY_START = 25, ///< Start bit of the company field. + CCB_COMPANY_LENGTH = 4, ///< Number of bits of the company field. }; +assert_compile(NUM_CARGO <= (1 << CCB_CARGO_TYPE_LENGTH)); +assert_compile(MAX_COMPANIES <= (1 << CCB_COMPANY_LENGTH)); + /** * Encode a cargo monitor for pickup or delivery at an industry. @@ -61,6 +64,7 @@ enum CargoCompanyBits { static inline CargoMonitorID EncodeCargoIndustryMonitor(CompanyID company, CargoID ctype, IndustryID ind) { assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); + assert(company < (1 << CCB_COMPANY_LENGTH)); uint32 ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, ind); @@ -80,6 +84,7 @@ static inline CargoMonitorID EncodeCargo static inline CargoMonitorID EncodeCargoTownMonitor(CompanyID company, CargoID ctype, TownID town) { assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); + assert(company < (1 << CCB_COMPANY_LENGTH)); uint32 ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, town); diff --git a/src/saveload/cargomonitor_sl.cpp b/src/saveload/cargomonitor_sl.cpp --- a/src/saveload/cargomonitor_sl.cpp +++ b/src/saveload/cargomonitor_sl.cpp @@ -29,6 +29,21 @@ static const SaveLoad _cargomonitor_pair SLE_END() }; +static CargoMonitorID FixupCargoMonitor(CargoMonitorID number) +{ + /* Between SLV_EXTEND_CARGOTYPES and SLV_FIX_CARGO_MONITOR, the + * CargoMonitorID structure had insufficient packing for more + * than 32 cargo types. Here we have to shuffle bits to account + * for the change. + * Company moved from bits 24-31 to 25-28. + * Cargo type increased from bits 19-23 to 19-24. + */ + SB(number, 25, 4, GB(number, 24, 4)); + SB(number, 29, 3, 0); + ClrBit(number, 24); + return number; +} + /** Save the #_cargo_deliveries monitoring map. */ static void SaveDelivery() { @@ -52,12 +67,15 @@ static void SaveDelivery() static void LoadDelivery() { TempStorage storage; + bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); ClearCargoDeliveryMonitoring(); for (;;) { if (SlIterateArray() < 0) break; SlObject(&storage, _cargomonitor_pair_desc); + if (fix) storage.number = FixupCargoMonitor(storage.number); + std::pair p(storage.number, storage.amount); _cargo_deliveries.insert(p); } @@ -87,12 +105,15 @@ static void SavePickup() static void LoadPickup() { TempStorage storage; + bool fix = IsSavegameVersionBefore(SLV_FIX_CARGO_MONITOR); ClearCargoPickupMonitoring(); for (;;) { if (SlIterateArray() < 0) break; SlObject(&storage, _cargomonitor_pair_desc); + if (fix) storage.number = FixupCargoMonitor(storage.number); + std::pair p(storage.number, storage.amount); _cargo_pickups.insert(p); } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -290,6 +290,7 @@ enum SaveLoadVersion : uint16 { SLV_GROUP_LIVERIES, ///< 205 PR#7108 Livery storage change and group liveries. SLV_SHIPS_STOP_IN_LOCKS, ///< 206 PR#7150 Ship/lock movement changes. + SLV_FIX_CARGO_MONITOR, ///< 207 PR#7175 Cargo monitor data packing fix to support 64 cargotypes. SL_MAX_VERSION, ///< Highest possible saveload version };