From 51c0b222cc4274a6fb3901a5125df75d452f3383 Mon Sep 17 00:00:00 2001 From: reldred Date: Sat, 10 Apr 2021 21:16:09 +0930 Subject: [PATCH 1/2] Extra House ID's Use an extra unused bit in m3 to boost the max number of house types from 512 to 1024. So-far everything works, construction stages and animations appear unaffacted by my hubris. --- src/house.h | 2 +- src/town_map.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/house.h b/src/house.h index 8745fbb693..21d28b0a2a 100644 --- a/src/house.h +++ b/src/house.h @@ -26,7 +26,7 @@ static const HouseID NUM_HOUSES_PER_GRF = 255; ///< Number of supported house static const uint HOUSE_NO_CLASS = 0; static const HouseID NEW_HOUSE_OFFSET = 110; ///< Offset for new houses. -static const HouseID NUM_HOUSES = 512; ///< Total number of houses. +static const HouseID NUM_HOUSES = 1024; ///< Total number of houses. static const HouseID INVALID_HOUSE_ID = 0xFFFF; static const uint HOUSE_NUM_ACCEPTS = 16; ///< Max number of cargoes accepted by a tile diff --git a/src/town_map.h b/src/town_map.h index 9d11699b70..ff968f0ae1 100644 --- a/src/town_map.h +++ b/src/town_map.h @@ -47,7 +47,7 @@ static inline void SetTownIndex(TileIndex t, TownID index) static inline HouseID GetCleanHouseType(TileIndex t) { assert_tile(IsTileType(t, MP_HOUSE), t); - return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8); + return _m[t].m4 | (GB(_m[t].m3, 5, 2) << 8); } /** @@ -71,7 +71,7 @@ static inline void SetHouseType(TileIndex t, HouseID house_id) { assert_tile(IsTileType(t, MP_HOUSE), t); _m[t].m4 = GB(house_id, 0, 8); - SB(_m[t].m3, 6, 1, GB(house_id, 8, 1)); + SB(_m[t].m3, 5, 2, GB(house_id, 8, 2)); } /** From 4c2e42fae06e776cc8ab4f9ea6f2a7e21dab2b74 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 11 Apr 2021 12:32:13 +0100 Subject: [PATCH 2/2] Add savegame conversion and version bump for more house IDs --- src/saveload/afterload.cpp | 13 +++++++++++-- src/saveload/extended_ver_sl.cpp | 1 + src/saveload/extended_ver_sl.h | 1 + src/saveload/saveload_internal.h | 2 +- src/saveload/town_sl.cpp | 32 ++++++++++++++++++++++---------- 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 660ad144e4..813f960c45 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1803,7 +1803,7 @@ bool AfterLoadGame() } /* Check and update house and town values */ - UpdateHousesAndTowns(gcf_res != GLC_ALL_GOOD); + UpdateHousesAndTowns(gcf_res != GLC_ALL_GOOD, true); if (IsSavegameVersionBefore(SLV_43)) { for (TileIndex t = 0; t < map_size; t++) { @@ -3878,6 +3878,15 @@ bool AfterLoadGame() _settings_game.economy.inflation_fixed_dates = !IsSavegameVersionBefore(SLV_GS_INDUSTRY_CONTROL); } + if (SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) { + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_HOUSE)) { + /* Move upper bit of house ID from bit 6 of m3 to bits 6..5 of m3. */ + SB(_m[t].m3, 5, 2, GB(_m[t].m3, 6, 1)); + } + } + } + InitializeRoadGUI(); /* This needs to be done after conversion. */ @@ -3988,7 +3997,7 @@ void ReloadNewGRFData() /* Update company statistics. */ AfterLoadCompanyStats(); /* Check and update house and town values */ - UpdateHousesAndTowns(true); + UpdateHousesAndTowns(true, false); /* Delete news referring to no longer existing entities */ DeleteInvalidEngineNews(); /* Update livery selection windows */ diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 142de3bfe7..3796151744 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -147,6 +147,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 1, 1, "realistic_train_braking", nullptr, nullptr, "VLKA" }, { XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr }, { XSLFI_WATER_FLOODING, XSCF_NULL, 1, 1, "water_flooding", nullptr, nullptr, nullptr }, + { XSLFI_MORE_HOUSES, XSCF_NULL, 1, 1, "more_houses", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 2b7e84be11..8e7ec2e39c 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -101,6 +101,7 @@ enum SlXvFeatureIndex { XSLFI_REALISTIC_TRAIN_BRAKING, ///< Realistic train braking XSLFI_INFLATION_FIXED_DATES, ///< Inflation is applied between fixed dates XSLFI_WATER_FLOODING, ///< Water flooding map bit + XSLFI_MORE_HOUSES, ///< More house types XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h index e49e7d6d42..1f7b2e7511 100644 --- a/src/saveload/saveload_internal.h +++ b/src/saveload/saveload_internal.h @@ -36,7 +36,7 @@ void AfterLoadStoryBook(); void AfterLoadLinkGraphs(); void AfterLoadCompanyStats(); void AfterLoadTraceRestrict(); -void UpdateHousesAndTowns(bool cargo_update_required); +void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position); void UpdateOldAircraft(); diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 5050996ffd..2811b9f7b4 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -59,17 +59,29 @@ void RebuildTownCaches(bool cargo_update_required) * town, the town radius and the max passengers * of the town. */ -void UpdateHousesAndTowns(bool cargo_update_required) +void UpdateHousesAndTowns(bool cargo_update_required, bool old_map_position) { + auto get_house_type = [&](TileIndex t) -> HouseID { + if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) { + return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8); + } else { + return GetCleanHouseType(t); + } + }; for (TileIndex t = 0; t < MapSize(); t++) { if (!IsTileType(t, MP_HOUSE)) continue; - HouseID house_id = GetCleanHouseType(t); + HouseID house_id = get_house_type(t); if (!HouseSpec::Get(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) { /* The specs for this type of house are not available any more, so * replace it with the substitute original house type. */ house_id = _house_mngr.GetSubstituteID(house_id); - SetHouseType(t, house_id); + if (old_map_position && SlXvIsFeatureMissing(XSLFI_MORE_HOUSES)) { + _m[t].m4 = GB(house_id, 0, 8); + SB(_m[t].m3, 6, 1, GB(house_id, 8, 1)); + } else { + SetHouseType(t, house_id); + } cargo_update_required = true; } } @@ -78,24 +90,24 @@ void UpdateHousesAndTowns(bool cargo_update_required) for (TileIndex t = 0; t < MapSize(); t++) { if (!IsTileType(t, MP_HOUSE)) continue; - HouseID house_type = GetCleanHouseType(t); + HouseID house_type = get_house_type(t); TileIndex north_tile = t + GetHouseNorthPart(house_type); // modifies 'house_type'! if (t == north_tile) { const HouseSpec *hs = HouseSpec::Get(house_type); bool valid_house = true; if (hs->building_flags & TILE_SIZE_2x1) { TileIndex tile = t + TileDiffXY(1, 0); - if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false; + if (!IsTileType(tile, MP_HOUSE) || get_house_type(tile) != house_type + 1) valid_house = false; } else if (hs->building_flags & TILE_SIZE_1x2) { TileIndex tile = t + TileDiffXY(0, 1); - if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false; + if (!IsTileType(tile, MP_HOUSE) || get_house_type(tile) != house_type + 1) valid_house = false; } else if (hs->building_flags & TILE_SIZE_2x2) { TileIndex tile = t + TileDiffXY(0, 1); - if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 1) valid_house = false; + if (!IsTileType(tile, MP_HOUSE) || get_house_type(tile) != house_type + 1) valid_house = false; tile = t + TileDiffXY(1, 0); - if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 2) valid_house = false; + if (!IsTileType(tile, MP_HOUSE) || get_house_type(tile) != house_type + 2) valid_house = false; tile = t + TileDiffXY(1, 1); - if (!IsTileType(tile, MP_HOUSE) || GetCleanHouseType(tile) != house_type + 3) valid_house = false; + if (!IsTileType(tile, MP_HOUSE) || get_house_type(tile) != house_type + 3) valid_house = false; } /* If not all tiles of this house are present remove the house. * The other tiles will get removed later in this loop because @@ -104,7 +116,7 @@ void UpdateHousesAndTowns(bool cargo_update_required) DoClearSquare(t); cargo_update_required = true; } - } else if (!IsTileType(north_tile, MP_HOUSE) || GetCleanHouseType(north_tile) != house_type) { + } else if (!IsTileType(north_tile, MP_HOUSE) || get_house_type(north_tile) != house_type) { /* This tile should be part of a multi-tile building but the * north tile of this house isn't on the map. */ DoClearSquare(t);