diff --git a/src/cargomonitor.h b/src/cargomonitor.h index b71a355d7e..30a87ea320 100644 --- a/src/cargomonitor.h +++ b/src/cargomonitor.h @@ -12,6 +12,7 @@ #include "cargo_type.h" #include "company_func.h" +#include "company_type.h" #include "industry.h" #include "town.h" #include "core/overflowsafe_type.hpp" @@ -24,12 +25,12 @@ struct Station; * - bits 0-15 town or industry number * - bit 16 is set if it is an industry number (else it is a town number). * - bits 19-23 Cargo type. - * - bits 24-31 %Company number. + * - bits 24-COMPANY_BIT_SIZE %Company number. */ -typedef uint32_t CargoMonitorID; ///< Type of the cargo monitor number. +typedef uint64_t CargoMonitorID; ///< Type of the cargo monitor number. /** Map type for storing and updating active cargo monitor numbers and their amounts. */ -typedef std::map CargoMonitorMap; +typedef std::map CargoMonitorMap; extern CargoMonitorMap _cargo_pickups; extern CargoMonitorMap _cargo_deliveries; @@ -44,9 +45,11 @@ enum CargoCompanyBits { CCB_CARGO_TYPE_START = 19, ///< Start bit of the cargo type 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 = 8, ///< Number of bits of the company field. + CCB_COMPANY_LENGTH = COMPANY_SIZE_BITS, ///< Number of bits of the company field. }; + +static_assert(CCB_COMPANY_LENGTH <= (1 << 30)); // This should never be a limiting factor static_assert(NUM_CARGO <= (1 << CCB_CARGO_TYPE_LENGTH)); static_assert(MAX_COMPANIES <= (1 << CCB_COMPANY_LENGTH)); @@ -63,7 +66,7 @@ inline CargoMonitorID EncodeCargoIndustryMonitor(CompanyID company, CargoID ctyp assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); assert(company < (1 << CCB_COMPANY_LENGTH)); - uint32_t ret = 0; + uint64_t ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, ind); SetBit(ret, CCB_IS_INDUSTRY_BIT); SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype); @@ -83,7 +86,7 @@ inline CargoMonitorID EncodeCargoTownMonitor(CompanyID company, CargoID ctype, T assert(ctype < (1 << CCB_CARGO_TYPE_LENGTH)); assert(company < (1 << CCB_COMPANY_LENGTH)); - uint32_t ret = 0; + uint64_t ret = 0; SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, town); SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype); SB(ret, CCB_COMPANY_START, CCB_COMPANY_LENGTH, company); diff --git a/src/clear_map.h b/src/clear_map.h index 64eb640d12..b24753c5f2 100644 --- a/src/clear_map.h +++ b/src/clear_map.h @@ -260,7 +260,6 @@ inline void MakeClear(Tile t, ClearGround g, uint density) { SetTileType(t, MP_CLEAR); t.m1() = 0; - SetTileOwner(t, OWNER_NONE); t.m2() = 0; t.m3() = 0; t.m4() = 0 << 5 | 0 << 2; @@ -268,6 +267,8 @@ inline void MakeClear(Tile t, ClearGround g, uint density) t.m6() = 0; t.m7() = 0; t.m8() = 0; + t.m9() = 0; + SetTileOwner(t, OWNER_NONE); } @@ -281,7 +282,6 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry) { SetTileType(t, MP_CLEAR); t.m1() = 0; - SetTileOwner(t, OWNER_NONE); t.m2() = industry; t.m3() = field_type; t.m4() = 0 << 5 | 0 << 2; @@ -289,6 +289,8 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry) SB(t.m6(), 2, 4, 0); t.m7() = 0; t.m8() = 0; + t.m9() = 0; + SetTileOwner(t, OWNER_NONE); } /** diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 675bb7f350..ecc8bb2f52 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -7,6 +7,7 @@ /** @file company_cmd.cpp Handling of companies. */ +#include "company_type.h" #include "gfx_type.h" #include "stdafx.h" #include "company_base.h" diff --git a/src/company_type.h b/src/company_type.h index 7c4691048c..b283f4b565 100644 --- a/src/company_type.h +++ b/src/company_type.h @@ -11,6 +11,7 @@ #define COMPANY_TYPE_H #include "core/enum_type.hpp" +#include /** * Enum for all companies/owners. @@ -40,6 +41,15 @@ enum Owner : uint8_t { COMPANY_NEW_COMPANY = 0xF8, ///< The client wants a new company COMPANY_SPECTATOR = 0xF9, ///< The client is spectating }; +const uint8_t COMPANY_SIZE_BITS = 8; /// Size of the company id in bits + +static_assert(COMPANY_SIZE_BITS <= 10); /// 32bit m9 can only fit 3 owners of size 10 + +static_assert(MAX_COMPANIES <= (1U << COMPANY_SIZE_BITS) - 1); /// Checking that MAX_COMPANIES is in bounds +static_assert(OWNER_END <= (1U << COMPANY_SIZE_BITS) - 1); +static_assert(INVALID_OWNER <= (1U << COMPANY_SIZE_BITS) - 1); +static_assert(INVALID_COMPANY <= (1U << COMPANY_SIZE_BITS) - 1); + DECLARE_POSTFIX_INCREMENT(Owner) DECLARE_ENUM_AS_ADDABLE(Owner) @@ -53,7 +63,7 @@ static const uint MAX_COMPETITORS_INTERVAL = 500; ///< The maximum interval (in typedef Owner CompanyID; -typedef uint16_t CompanyMask; +typedef std::bitset CompanyMask; struct Company; typedef uint32_t CompanyManagerFace; ///< Company manager face bits, info see in company_manager_face.h diff --git a/src/engine.cpp b/src/engine.cpp index 979c6a7e31..74f2928636 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -940,7 +940,7 @@ static IntervalTimer _calendar_engines_daily({TimerGameCalend CloseWindowById(WC_ENGINE_PREVIEW, i); e->preview_company = INVALID_COMPANY; } - } else if (CountBits(e->preview_asked) < MAX_COMPANIES) { + } else if (e->preview_asked.count() < MAX_COMPANIES) { e->preview_company = GetPreviewCompany(e); if (e->preview_company == INVALID_COMPANY) { @@ -969,7 +969,7 @@ static IntervalTimer _calendar_engines_daily({TimerGameCalend void ClearEnginesHiddenFlagOfCompany(CompanyID cid) { for (Engine *e : Engine::Iterate()) { - SB(e->company_hidden, cid, 1, 0); + e->company_hidden.reset(cid); } } @@ -987,7 +987,7 @@ CommandCost CmdSetVehicleVisibility(DoCommandFlag flags, EngineID engine_id, boo if (!IsEngineBuildable(e->index, e->type, _current_company)) return CMD_ERROR; if ((flags & DC_EXEC) != 0) { - SB(e->company_hidden, _current_company, 1, hide ? 1 : 0); + e->company_hidden.set(_current_company, hide ? 1 : 0); AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); } diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 9c8f97b7ff..1b39376367 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -7,6 +7,7 @@ /** @file graph_gui.cpp GUI that shows performance graphs. */ +#include "company_type.h" #include "stdafx.h" #include "graph_gui.h" #include "window_gui.h" @@ -182,7 +183,7 @@ protected: static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw. static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines. - uint64_t excluded_data; ///< bitmask of the datasets that shouldn't be displayed. + CompanyMask excluded_data; ///< bitmask of the datasets that shouldn't be displayed. uint8_t num_dataset; uint8_t num_on_x_axis; uint8_t num_vert_lines; diff --git a/src/map_func.h b/src/map_func.h index 7d3e11cd80..c85ac32795 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -10,6 +10,8 @@ #ifndef MAP_FUNC_H #define MAP_FUNC_H +#include "company_type.h" +#include "core/bitmath_func.hpp" #include "core/math_func.hpp" #include "tile_type.h" #include "map_type.h" @@ -33,7 +35,7 @@ private: uint8_t type; ///< The type (bits 4..7), bridges (2..3), rainforest/desert (0..1) uint8_t height; ///< The height of the northern corner. uint16_t m2; ///< Primarily used for indices to towns, industries and stations - uint8_t m1; ///< Primarily used for ownership information + uint8_t m1; ///< Primarily used for ownership information (In old versions) uint8_t m3; ///< General purpose uint8_t m4; ///< General purpose uint8_t m5; ///< General purpose @@ -49,6 +51,7 @@ private: uint8_t m6; ///< General purpose uint8_t m7; ///< Primarily used for newgrf support uint16_t m8; ///< General purpose + uint32_t m9; ///< Stores the actuall ownership information }; static TileBase *base_tiles; ///< Pointer to the tile-array. @@ -198,6 +201,18 @@ public: { return extended_tiles[tile.base()].m8; } + + /** + * Primarily used for ownership information + * TODO: Add more docs + * Look at docs/landscape.html for the exact meaning of the data. + * @param tile The tile to get the data for. + * @return reference to the byte holding the data. + */ + debug_inline uint32_t &m9() + { + return extended_tiles[tile.base()].m9; + } }; /** diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 7ed51cac1d..549a2599f7 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -129,6 +129,7 @@ public: Debug(misc, LANDINFOD_LEVEL, "m6 = 0x{:x}", tile.m6()); Debug(misc, LANDINFOD_LEVEL, "m7 = 0x{:x}", tile.m7()); Debug(misc, LANDINFOD_LEVEL, "m8 = 0x{:x}", tile.m8()); + Debug(misc, LANDINFOD_LEVEL, "m9 = 0x{:x}", tile.m9()); PrintWaterRegionDebugInfo(tile); #undef LANDINFOD_LEVEL diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index d144d56561..75227b788c 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -83,8 +83,9 @@ case 0xAB: return GB(this->t->ratings[6], 8, 8); case 0xAC: return this->t->ratings[7]; case 0xAD: return GB(this->t->ratings[7], 8, 8); - case 0xAE: return this->t->have_ratings; - case 0xB2: return this->t->statues; + // MYTODO: Fix this crap later + //case 0xAE: return this->t->have_ratings; + //case 0xB2: return this->t->statues; case 0xB6: return ClampTo(this->t->cache.num_houses); case 0xB9: return this->t->growth_rate / Ticks::TOWN_GROWTH_TICKS; case 0xBA: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo(this->t->supplied[cid].new_max) : 0; diff --git a/src/rail_map.h b/src/rail_map.h index 5ff2fb9ec3..f31bb0b5ce 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -528,6 +528,7 @@ inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r) SB(t.m6(), 2, 4, 0); t.m7() = 0; t.m8() = r; + t.m9() = 0; } /** @@ -561,6 +562,7 @@ inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirectio SB(tile.m6(), 2, 4, 0); tile.m7() = 0; tile.m8() = rail_type; + tile.m9() = 0; } #endif /* RAIL_MAP_H */ diff --git a/src/road_map.h b/src/road_map.h index 9179579b4c..d979f65b78 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -10,6 +10,7 @@ #ifndef ROAD_MAP_H #define ROAD_MAP_H +#include "company_type.h" #include "track_func.h" #include "depot_type.h" #include "rail_type.h" @@ -231,7 +232,7 @@ inline bool HasTileAnyRoadType(Tile t, RoadTypes rts) * @param rtt RoadTramType. * @return Owner of the given road type. */ -inline Owner GetRoadOwner(Tile t, RoadTramType rtt) +inline Owner OldGetRoadOwner(Tile t, RoadTramType rtt) { assert(MayHaveRoad(t)); if (rtt == RTT_ROAD) return (Owner)GB(IsNormalRoadTile(t) ? t.m1() : t.m7(), 0, 5); @@ -242,6 +243,21 @@ inline Owner GetRoadOwner(Tile t, RoadTramType rtt) return o == OWNER_TOWN ? OWNER_NONE : o; } +/** + * Get the owner of a specific road type. + * @param t The tile to query. + * @param rtt RoadTramType. + * @return Owner of the given road type. + */ +inline Owner GetRoadOwner(Tile t, RoadTramType rtt) +{ + assert(MayHaveRoad(t)); + if (rtt == RTT_ROAD) return (Owner)GB(t.m9(), IsNormalRoadTile(t) ? 0 : COMPANY_SIZE_BITS * 2, COMPANY_SIZE_BITS); + + Owner o = (Owner)GB(t.m9(), COMPANY_SIZE_BITS, COMPANY_SIZE_BITS); + return o == OWNER_TOWN ? OWNER_NONE : o; +} + /** * Set the owner of a specific road type. * @param t The tile to change. @@ -249,6 +265,21 @@ inline Owner GetRoadOwner(Tile t, RoadTramType rtt) * @param o New owner of the given road type. */ inline void SetRoadOwner(Tile t, RoadTramType rtt, Owner o) +{ + if (rtt == RTT_ROAD) { + SB(t.m9(), IsNormalRoadTile(t) ? 0 : COMPANY_SIZE_BITS * 2, COMPANY_SIZE_BITS, o); + } else { + SB(t.m9(), COMPANY_SIZE_BITS, COMPANY_SIZE_BITS, o==OWNER_NONE ? OWNER_TOWN : o); + } +} + +/** + * Set the owner of a specific road type. + * @param t The tile to change. + * @param rtt RoadTramType. + * @param o New owner of the given road type. + */ +inline void OldSetRoadOwner(Tile t, RoadTramType rtt, Owner o) { if (rtt == RTT_ROAD) { SB(IsNormalRoadTile(t) ? t.m1() : t.m7(), 0, 5, o); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index b8ddf0258d..e092960f66 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -451,7 +451,7 @@ static void FixOwnerOfRailTrack(Tile t) if (IsLevelCrossingTile(t)) { /* else change the crossing to normal road (road vehicles won't care) */ - Owner road = GetRoadOwner(t, RTT_ROAD); + Owner road = GetRoadOwner(t, RTT_ROAD); // TODO: m9 Owner tram = GetRoadOwner(t, RTT_TRAM); RoadBits bits = GetCrossingRoadBits(t); bool hasroad = HasBit(t.m7(), 6); diff --git a/src/saveload/cargomonitor_sl.cpp b/src/saveload/cargomonitor_sl.cpp index c932ea18d7..cdd166779b 100644 --- a/src/saveload/cargomonitor_sl.cpp +++ b/src/saveload/cargomonitor_sl.cpp @@ -24,7 +24,7 @@ struct TempStorage { /** Description of the #TempStorage structure for the purpose of load and save. */ static const SaveLoad _cargomonitor_pair_desc[] = { - SLE_VAR(TempStorage, number, SLE_UINT32), + SLE_VAR(TempStorage, number, SLE_UINT64), SLE_VAR(TempStorage, amount, SLE_UINT32), }; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 651daa1bcb..a4e5a35e7b 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -476,8 +476,8 @@ static const SaveLoad _company_desc[] = { SLE_CONDVAR(CompanyProperties, num_valid_stat_ent, SLE_UINT8, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH), SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8), - SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_UINT16, SLV_104, SL_MAX_VERSION), + // MYTODO: Fix all the compat issues + SLE_CONDCOMPMASK(CompanyProperties, bankrupt_asked, SLE_UINT8, COMPANY_SIZE_BITS, SLV_179, SL_MAX_VERSION), SLE_VAR(CompanyProperties, bankrupt_timeout, SLE_INT16), SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_VAR_I64 | SLE_FILE_I32, SL_MIN_VERSION, SLV_65), SLE_CONDVAR(CompanyProperties, bankrupt_value, SLE_INT64, SLV_65, SL_MAX_VERSION), diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index ab62d756a8..599803f74d 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" +#include "company_type.h" #include "saveload.h" #include "compat/engine_sl_compat.h" @@ -32,12 +33,11 @@ static const SaveLoad _engine_desc[] = { SLE_VAR(Engine, duration_phase_2, SLE_UINT16), SLE_VAR(Engine, duration_phase_3, SLE_UINT16), SLE_VAR(Engine, flags, SLE_UINT8), - SLE_CONDVAR(Engine, preview_asked, SLE_UINT16, SLV_179, SL_MAX_VERSION), + SLE_CONDCOMPMASK(Engine, preview_asked, SLE_UINT8, COMPANY_SIZE_BITS, SLV_179, SL_MAX_VERSION), SLE_CONDVAR(Engine, preview_company, SLE_UINT8, SLV_179, SL_MAX_VERSION), - SLE_VAR(Engine, preview_wait, SLE_UINT8), - SLE_CONDVAR(Engine, company_avail, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Engine, company_avail, SLE_UINT16, SLV_104, SL_MAX_VERSION), - SLE_CONDVAR(Engine, company_hidden, SLE_UINT16, SLV_193, SL_MAX_VERSION), + SLE_VAR(Engine, preview_wait, SLE_UINT8), +// MYTODO: Fix all the compatibility here + SLE_CONDCOMPMASK(Engine, company_avail, SLE_UINT8, COMPANY_SIZE_BITS, SLV_179, SL_MAX_VERSION), SLE_CONDSSTR(Engine, name, SLE_STR, SLV_84, SL_MAX_VERSION), }; diff --git a/src/saveload/map_sl.cpp b/src/saveload/map_sl.cpp index 3ce23a42b2..8054753908 100644 --- a/src/saveload/map_sl.cpp +++ b/src/saveload/map_sl.cpp @@ -352,6 +352,33 @@ struct MAP8ChunkHandler : ChunkHandler { } }; +struct MAP9ChunkHandler : ChunkHandler { + MAP9ChunkHandler() : ChunkHandler('MAP9', CH_RIFF) {} + + void Load() const override + { + std::array buf; + uint size = Map::Size(); + + for (TileIndex i = 0; i != size;) { + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT32); + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) Tile(i++).m8() = buf[j]; + } + } + + void Save() const override + { + std::array buf; + uint size = Map::Size(); + + SlSetLength(static_cast(size) * sizeof(uint32_t)); + for (TileIndex i = 0; i != size;) { + for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = Tile(i++).m8(); + SlCopy(buf.data(), MAP_SL_BUF_SIZE, SLE_UINT32); + } + } +}; + static const MAPSChunkHandler MAPS; static const MAPTChunkHandler MAPT; static const MAPHChunkHandler MAPH; @@ -363,6 +390,7 @@ static const MAP5ChunkHandler MAP5; static const MAPEChunkHandler MAPE; static const MAP7ChunkHandler MAP7; static const MAP8ChunkHandler MAP8; +static const MAP8ChunkHandler MAP9; static const ChunkHandlerRef map_chunk_handlers[] = { MAPS, MAPT, @@ -375,6 +403,7 @@ static const ChunkHandlerRef map_chunk_handlers[] = { MAPE, MAP7, MAP8, + MAP9, }; extern const ChunkHandlerTable _map_chunk_handlers(map_chunk_handlers); diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 538c1336c3..9985bccb57 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -253,6 +253,7 @@ static bool FixTTOMapArray() break; case 1: // ROAD_TILE_CROSSING (there aren't monorail crossings in TTO) tile.m3() = tile.m1(); // set owner of road = owner of rail + // TODO: Fix this break; case 2: // ROAD_TILE_DEPOT break; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index ded1a83467..f00380b83f 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -20,6 +20,7 @@ * */ +#include "saveload/saveload.h" #include "../stdafx.h" #include "../debug.h" #include "../station_base.h" @@ -42,7 +43,11 @@ #include "../string_func.h" #include "../fios.h" #include "../error.h" +#include "company_type.h" #include +#include +#include +#include #ifdef __EMSCRIPTEN__ # include #endif @@ -1105,6 +1110,76 @@ static void SlArray(void *array, size_t length, VarType conv) } } + + +// MYTODO: Put this somewhere it belongs +std::vector bitset_to_bytes(const CompanyMask& bs) +{ + int N = COMPANY_SIZE_BITS; + std::vector result((N + 7) >> 3); + for (int j=0; j>3] |= (bs[j] << (j & 7)); + return result; +} + +CompanyMask bitset_from_bytes(const std::vector& buf) +{ + size_t N = COMPANY_SIZE_BITS; + assert(buf.size() == ((N + 7) >> 3)); + CompanyMask result; + for (int j=0; j>3] >> (j & 7)) & 1); + return result; +} + + + +/** + * Save/Load the length of the bitset followed by the array of SL_VAR bits. + * @param array The array being manipulated + * @param length The length of the bitset in bytes, + */ +static void SlCompanyMask(void *array, size_t length, VarType conv) +{ + switch (_sl.action) { + case SLA_SAVE: { + CompanyMask *bs = static_cast(array); + // We don't save the number of bits in the company mask, + // because it's incompatible with other versions anyway + std::vector bytes = bitset_to_bytes(*bs); + uint8_t *bytes_arr = &bytes[0]; + + SlWriteArrayLength(bytes.size()); + SlArray(bytes_arr, bytes.size(), conv); + + return; + } + + case SLA_LOAD_CHECK: + case SLA_LOAD: { + + std::vector buff(length); + + SlArray(&buff[0], length, conv); + + CompanyMask res = bitset_from_bytes(buff); + CompanyMask *bs = static_cast(array); + for (int i = 0; i < COMPANY_SIZE_BITS; i++) { + (*bs)[i] = res[i]; + } + + return; + } + + case SLA_PTRS: + case SLA_NULL: + return; + + default: + NOT_REACHED(); + } +} + /** * Pointers cannot be saved to a savegame, so this functions gets * the index of the item, and if not available, it hussles with @@ -1513,6 +1588,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad &sld) case SL_VAR: return SlCalcConvFileLen(sld.conv); case SL_REF: return SlCalcRefLen(); case SL_ARR: return SlCalcArrayLen(sld.length, sld.conv); + case SL_COMPANY_MASK: return SlCalcArrayLen(sld.length, sld.conv); case SL_REFLIST: return SlCalcRefListLen(GetVariableAddress(object, sld), sld.conv); case SL_DEQUE: return SlCalcDequeLen(GetVariableAddress(object, sld), sld.conv); case SL_VECTOR: return SlCalcVectorLen(GetVariableAddress(object, sld), sld.conv); @@ -1568,6 +1644,7 @@ static bool SlObjectMember(void *object, const SaveLoad &sld) case SL_VAR: SlSaveLoadConv(ptr, conv); break; case SL_REF: SlSaveLoadRef(ptr, conv); break; case SL_ARR: SlArray(ptr, sld.length, conv); break; + case SL_COMPANY_MASK: SlCompanyMask(ptr, sld.length, conv); break; case SL_REFLIST: SlRefList(ptr, conv); break; case SL_DEQUE: SlDeque(ptr, conv); break; case SL_VECTOR: SlVector(ptr, conv); break; diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 99f74777bf..f9b8b06905 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -690,9 +690,10 @@ enum SaveLoadType : uint8_t { SL_VECTOR = 7, ///< Save/load a vector of #SL_VAR elements. SL_REFLIST = 8, ///< Save/load a list of #SL_REF elements. SL_STRUCTLIST = 9, ///< Save/load a list of structs. + SL_COMPANY_MASK = 10, ///< Save/load a fixed-size bitset of #SL_VAR bits. - SL_SAVEBYTE = 10, ///< Save (but not load) a byte. - SL_NULL = 11, ///< Save null-bytes and load to nowhere. + SL_SAVEBYTE = 11, ///< Save (but not load) a byte. + SL_NULL = 12, ///< Save null-bytes and load to nowhere. }; typedef void *SaveLoadAddrProc(void *base, size_t extra); @@ -799,6 +800,7 @@ inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t leng case SL_REF: return sizeof(void *) == size; case SL_STDSTR: return SlVarSize(type) == size; case SL_ARR: return SlVarSize(type) * length <= size; // Partial load of array is permitted. + case SL_COMPANY_MASK: return SlVarSize(type) * length <= size; // Partial load of array is permitted. case SL_DEQUE: return sizeof(std::deque) == size; case SL_VECTOR: return sizeof(std::vector) == size; case SL_REFLIST: return sizeof(std::list) == size; @@ -1001,6 +1003,17 @@ inline constexpr bool SlCheckVarSize(SaveLoadType cmd, VarType type, size_t leng */ #define SLE_ARRNAME(base, variable, name, type, length) SLE_CONDARRNAME(base, variable, name, type, length, SL_MIN_VERSION, SL_MAX_VERSION) +/** + * Storage of a fixed-size array of #SL_VAR elements in some savegame versions. + * @param base Name of the class or struct containing the array. + * @param variable Name of the variable in the class or struct referenced by \a base. + * @param type Storage of the data in memory and in the savegame. + * @param length Number of elements in the array. + * @param from First savegame version that has the array. + * @param to Last savegame version that has the array. + */ +#define SLE_CONDCOMPMASK(base, variable, type, length, from, to) SLE_GENERAL(SL_COMPANY_MASK, base, variable, type, length, from, to, 0) + /** * Storage of a \c std::string in every savegame version. * @param base Name of the class or struct containing the string. diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index e09bf9d444..2dc3c1162c 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -215,11 +215,11 @@ static const SaveLoad _town_desc[] = { SLE_CONDSSTR(Town, name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION), SLE_VAR(Town, flags, SLE_UINT8), - SLE_CONDVAR(Town, statues, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Town, statues, SLE_UINT16, SLV_104, SL_MAX_VERSION), + // MYTODO: Fix all the compat +SLE_CONDCOMPMASK(Town, statues, SLE_UINT8, COMPANY_SIZE_BITS, SLV_179, SL_MAX_VERSION), - SLE_CONDVAR(Town, have_ratings, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104), - SLE_CONDVAR(Town, have_ratings, SLE_UINT16, SLV_104, SL_MAX_VERSION), + // MYTODO: Fix all the compat +SLE_CONDCOMPMASK(Town, have_ratings, SLE_UINT8, COMPANY_SIZE_BITS, SLV_179, SL_MAX_VERSION), SLE_CONDARR(Town, ratings, SLE_INT16, 8, SL_MIN_VERSION, SLV_104), SLE_CONDARR(Town, ratings, SLE_INT16, MAX_COMPANIES, SLV_104, SL_MAX_VERSION), SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104), diff --git a/src/tile_map.h b/src/tile_map.h index 6fbb3a53fa..032d75f6d7 100644 --- a/src/tile_map.h +++ b/src/tile_map.h @@ -10,6 +10,7 @@ #ifndef TILE_MAP_H #define TILE_MAP_H +#include "company_type.h" #include "slope_type.h" #include "map_func.h" #include "core/bitmath_func.hpp" @@ -181,6 +182,27 @@ inline Owner GetTileOwner(Tile tile) assert(!IsTileType(tile, MP_HOUSE)); assert(!IsTileType(tile, MP_INDUSTRY)); + return (Owner)GB(tile.m9(), 0, COMPANY_SIZE_BITS); +} + +/** + * Returns the owner of a tile. Only used for legacy code + * + * This function returns the owner of a tile. This cannot used + * for tiles which type is one of MP_HOUSE, MP_VOID and MP_INDUSTRY + * as no company owned any of these buildings. + * + * @param tile The tile to check + * @return The owner of the tile + * @pre IsValidTile(tile) + * @pre The type of the tile must not be MP_HOUSE and MP_INDUSTRY + */ +inline Owner OldGetTileOwner(Tile tile) +{ + assert(IsValidTile(tile)); + assert(!IsTileType(tile, MP_HOUSE)); + assert(!IsTileType(tile, MP_INDUSTRY)); + return (Owner)GB(tile.m1(), 0, 5); } @@ -201,9 +223,30 @@ inline void SetTileOwner(Tile tile, Owner owner) assert(!IsTileType(tile, MP_HOUSE)); assert(!IsTileType(tile, MP_INDUSTRY)); + SB(tile.m9(), 0, COMPANY_SIZE_BITS, owner); +} + +/** + * Sets the owner of a tile (Only for old formats) + * + * This function sets the owner status of a tile. Note that you cannot + * set a owner for tiles of type MP_HOUSE, MP_VOID and MP_INDUSTRY. + * + * @param tile The tile to change the owner status. + * @param owner The new owner. + * @pre IsValidTile(tile) + * @pre The type of the tile must not be MP_HOUSE and MP_INDUSTRY + */ +inline void OldSetTileOwner(Tile tile, Owner owner) +{ + assert(IsValidTile(tile)); + assert(!IsTileType(tile, MP_HOUSE)); + assert(!IsTileType(tile, MP_INDUSTRY)); + SB(tile.m1(), 0, 5, owner); } + /** * Checks if a tile belongs to the given owner * diff --git a/src/void_map.h b/src/void_map.h index e8e031be79..ede9f19d77 100644 --- a/src/void_map.h +++ b/src/void_map.h @@ -27,6 +27,8 @@ inline void MakeVoid(Tile t) t.m5() = 0; t.m6() = 0; t.m7() = 0; + t.m8() = 0; + t.m9() = 0; } #endif /* VOID_MAP_H */