diff --git a/src/base_station_base.h b/src/base_station_base.h index 4fd319d6c9..3541589d47 100644 --- a/src/base_station_base.h +++ b/src/base_station_base.h @@ -24,7 +24,7 @@ extern StationPool _station_pool; struct StationSpecList { const StationSpec *spec; uint32 grfid; ///< GRF ID of this custom station - uint8 localidx; ///< Station ID within GRF of station + uint16 localidx; ///< Station ID within GRF of station }; struct RoadStopSpecList { diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 63e095b2ad..a0da21d2d7 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -215,7 +215,8 @@ public: typedef void (*SpecialSpriteHandler)(ByteReader *buf); -static const uint NUM_STATIONS_PER_GRF = 255; ///< Number of StationSpecs per NewGRF; limited to 255 to allow extending Action3 with an extended byte later on. +/** The maximum amount of stations a single GRF is allowed to add */ +static const uint NUM_STATIONS_PER_GRF = UINT16_MAX - 1; /** Temporary engine data used when loading only */ struct GRFTempEngineData { @@ -1940,7 +1941,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons } case 0x0A: { // Copy sprite layout - byte srcid = buf->ReadByte(); + uint16 srcid = buf->ReadExtendedByte(); const StationSpec *srcstatspec = srcid >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[srcid].get(); if (srcstatspec == nullptr) { @@ -1994,7 +1995,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons break; case 0x0F: { // Copy custom layout - byte srcid = buf->ReadByte(); + uint16 srcid = buf->ReadExtendedByte(); const StationSpec *srcstatspec = srcid >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[srcid].get(); if (srcstatspec == nullptr) { @@ -2047,6 +2048,8 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons statspec->animation.triggers = buf->ReadWord(); break; + /* 0x19 road routing (not implemented) */ + case 0x1A: { // Advanced sprite layout uint16 tiles = buf->ReadExtendedByte(); statspec->renderdata.clear(); // delete earlier loaded stuff @@ -2085,6 +2088,14 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons } break; + case 0x1C: // Station Name + AddStringForMapping(buf->ReadWord(), &statspec->name); + break; + + case 0x1D: // Station Class name + AddStringForMapping(buf->ReadWord(), &StationClass::Get(statspec->cls_id)->name); + break; + default: ret = HandleAction0PropertyDefault(buf, prop); break; @@ -6439,9 +6450,9 @@ static void VehicleMapSpriteGroup(ByteReader *buf, byte feature, uint8 idcount) static void CanalMapSpriteGroup(ByteReader *buf, uint8 idcount) { - CanalFeature *cfs = AllocaM(CanalFeature, idcount); + uint16 *cfs = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - cfs[i] = (CanalFeature)buf->ReadByte(); + cfs[i] = buf->ReadExtendedByte(); } uint8 cidcount = buf->ReadByte(); @@ -6451,7 +6462,7 @@ static void CanalMapSpriteGroup(ByteReader *buf, uint8 idcount) if (!IsValidGroupID(groupid, "CanalMapSpriteGroup")) return; for (uint i = 0; i < idcount; i++) { - CanalFeature cf = cfs[i]; + uint16 cf = cfs[i]; if (cf >= CF_END) { grfmsg(1, "CanalMapSpriteGroup: Canal subset %d out of range, skipping", cf); @@ -6471,9 +6482,9 @@ static void StationMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *stations = AllocaM(uint8, idcount); + uint16 *stations = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - stations[i] = buf->ReadByte(); + stations[i] = buf->ReadExtendedByte(); } uint8 cidcount = buf->ReadByte(); @@ -6489,7 +6500,7 @@ static void StationMapSpriteGroup(ByteReader *buf, uint8 idcount) StationSpec *statspec = stations[i] >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[stations[i]].get(); if (statspec == nullptr) { - grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]); + grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%X undefined, skipping", stations[i]); continue; } @@ -6504,12 +6515,12 @@ static void StationMapSpriteGroup(ByteReader *buf, uint8 idcount) StationSpec *statspec = stations[i] >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[stations[i]].get(); if (statspec == nullptr) { - grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]); + grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%X undefined, skipping", stations[i]); continue; } if (statspec->grf_prop.grffile != nullptr) { - grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X mapped multiple times, skipping", stations[i]); + grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%X mapped multiple times, skipping", stations[i]); continue; } @@ -6528,9 +6539,9 @@ static void TownHouseMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *houses = AllocaM(uint8, idcount); + uint16 *houses = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - houses[i] = buf->ReadByte(); + houses[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6559,9 +6570,9 @@ static void IndustryMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *industries = AllocaM(uint8, idcount); + uint16 *industries = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - industries[i] = buf->ReadByte(); + industries[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6590,9 +6601,9 @@ static void IndustrytileMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *indtiles = AllocaM(uint8, idcount); + uint16 *indtiles = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - indtiles[i] = buf->ReadByte(); + indtiles[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6616,9 +6627,9 @@ static void IndustrytileMapSpriteGroup(ByteReader *buf, uint8 idcount) static void CargoMapSpriteGroup(ByteReader *buf, uint8 idcount) { - CargoID *cargoes = AllocaM(CargoID, idcount); + uint16 *cargoes = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - cargoes[i] = buf->ReadByte(); + cargoes[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6629,7 +6640,7 @@ static void CargoMapSpriteGroup(ByteReader *buf, uint8 idcount) if (!IsValidGroupID(groupid, "CargoMapSpriteGroup")) return; for (uint i = 0; i < idcount; i++) { - CargoID cid = cargoes[i]; + uint16 cid = cargoes[i]; if (cid >= NUM_CARGO) { grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping", cid); @@ -6644,9 +6655,9 @@ static void CargoMapSpriteGroup(ByteReader *buf, uint8 idcount) static void SignalsMapSpriteGroup(ByteReader *buf, uint8 idcount) { - uint8 *ids = AllocaM(uint8, idcount); + uint16 *ids = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - ids[i] = buf->ReadByte(); + ids[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6657,7 +6668,7 @@ static void SignalsMapSpriteGroup(ByteReader *buf, uint8 idcount) if (!IsValidGroupID(groupid, "SignalsMapSpriteGroup")) return; for (uint i = 0; i < idcount; i++) { - uint8 id = ids[i]; + uint16 id = ids[i]; switch (id) { case NSA3ID_CUSTOM_SIGNALS: @@ -6684,7 +6695,7 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount) uint16 *objects = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - objects[i] = HasBit(_cur.grffile->observed_feature_tests, GFTOF_MORE_OBJECTS_PER_GRF) ? buf->ReadExtendedByte() : buf->ReadByte(); + objects[i] = buf->ReadExtendedByte(); } uint8 cidcount = buf->ReadByte(); @@ -6700,7 +6711,7 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount) ObjectSpec *spec = (objects[i] >= _cur.grffile->objectspec.size()) ? nullptr : _cur.grffile->objectspec[objects[i]].get(); if (spec == nullptr) { - grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X undefined, skipping", objects[i]); + grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%X undefined, skipping", objects[i]); continue; } @@ -6715,12 +6726,12 @@ static void ObjectMapSpriteGroup(ByteReader *buf, uint8 idcount) ObjectSpec *spec = (objects[i] >= _cur.grffile->objectspec.size()) ? nullptr : _cur.grffile->objectspec[objects[i]].get(); if (spec == nullptr) { - grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X undefined, skipping", objects[i]); + grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%X undefined, skipping", objects[i]); continue; } if (spec->grf_prop.grffile != nullptr) { - grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%02X mapped multiple times, skipping", objects[i]); + grfmsg(1, "ObjectMapSpriteGroup: Object with ID 0x%X mapped multiple times, skipping", objects[i]); continue; } @@ -6734,7 +6745,7 @@ static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount) { uint8 *railtypes = AllocaM(uint8, idcount); for (uint i = 0; i < idcount; i++) { - uint8 id = buf->ReadByte(); + uint16 id = buf->ReadExtendedByte(); railtypes[i] = id < RAILTYPE_END ? _cur.grffile->railtype_map[id] : INVALID_RAILTYPE; } @@ -6767,7 +6778,7 @@ static void RoadTypeMapSpriteGroup(ByteReader *buf, uint8 idcount, RoadTramType uint8 *roadtypes = AllocaM(uint8, idcount); for (uint i = 0; i < idcount; i++) { - uint8 id = buf->ReadByte(); + uint16 id = buf->ReadExtendedByte(); roadtypes[i] = id < ROADTYPE_END ? type_map[id] : INVALID_ROADTYPE; } @@ -6801,9 +6812,9 @@ static void AirportMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *airports = AllocaM(uint8, idcount); + uint16 *airports = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - airports[i] = buf->ReadByte(); + airports[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6832,9 +6843,9 @@ static void AirportTileMapSpriteGroup(ByteReader *buf, uint8 idcount) return; } - uint8 *airptiles = AllocaM(uint8, idcount); + uint16 *airptiles = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - airptiles[i] = buf->ReadByte(); + airptiles[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6876,7 +6887,7 @@ static void RoadStopMapSpriteGroup(ByteReader *buf, uint8 idcount) RoadStopSpec *roadstopspec = (roadstops[i] >= _cur.grffile->roadstops.size()) ? nullptr : _cur.grffile->roadstops[roadstops[i]].get(); if (roadstopspec == nullptr) { - grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%02X does not exist, skipping", roadstops[i]); + grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%X does not exist, skipping", roadstops[i]); continue; } @@ -6896,12 +6907,12 @@ static void RoadStopMapSpriteGroup(ByteReader *buf, uint8 idcount) RoadStopSpec *roadstopspec = (roadstops[i] >= _cur.grffile->roadstops.size()) ? nullptr : _cur.grffile->roadstops[roadstops[i]].get(); if (roadstopspec == nullptr) { - grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%02X does not exist, skipping.", roadstops[i]); + grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%X does not exist, skipping.", roadstops[i]); continue; } if (roadstopspec->grf_prop.grffile != nullptr) { - grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%02X mapped multiple times, skipping", roadstops[i]); + grfmsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x%X mapped multiple times, skipping", roadstops[i]); continue; } @@ -6914,9 +6925,9 @@ static void RoadStopMapSpriteGroup(ByteReader *buf, uint8 idcount) static void NewLandscapeMapSpriteGroup(ByteReader *buf, uint8 idcount) { - uint8 *ids = AllocaM(uint8, idcount); + uint16 *ids = AllocaM(uint16, idcount); for (uint i = 0; i < idcount; i++) { - ids[i] = buf->ReadByte(); + ids[i] = buf->ReadExtendedByte(); } /* Skip the cargo type section, we only care about the default group */ @@ -6927,7 +6938,7 @@ static void NewLandscapeMapSpriteGroup(ByteReader *buf, uint8 idcount) if (!IsValidGroupID(groupid, "NewLandscapeMapSpriteGroup")) return; for (uint i = 0; i < idcount; i++) { - uint8 id = ids[i]; + uint16 id = ids[i]; switch (id) { case NLA3ID_CUSTOM_ROCKS: @@ -6955,7 +6966,7 @@ static void FeatureMapSpriteGroup(ByteReader *buf) * B feature see action 0 * B n-id bits 0-6: how many IDs this definition applies to * bit 7: if set, this is a wagon override definition (see below) - * B ids the IDs for which this definition applies + * E ids the IDs for which this definition applies * B num-cid number of cargo IDs (sprite group IDs) in this definition * can be zero, in that case the def-cid is used always * B cargo-type type of this cargo type (e.g. mail=2, wood=7, see below) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 191efe2b05..3d290ba207 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -1376,7 +1376,7 @@ int GetEngineProperty(EngineID engine, PropertyID property, int orig_value, cons } -static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, uint16_t base_random_bits, bool first) +static void DoTriggerVehicle(Vehicle *v, VehicleTrigger trigger, uint16 base_random_bits, bool first) { /* We can't trigger a non-existent vehicle... */ assert(v != nullptr); diff --git a/src/newgrf_extension.cpp b/src/newgrf_extension.cpp index 4f1c10a742..c6cda5ff9b 100644 --- a/src/newgrf_extension.cpp +++ b/src/newgrf_extension.cpp @@ -64,7 +64,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = { GRFFeatureInfo("action0_object_viewport_map_tile_type", 1), GRFFeatureInfo("road_stops", 9, GFTOF_ROAD_STOPS), GRFFeatureInfo("new_landscape", 2), - GRFFeatureInfo("more_objects_per_grf", 1, GFTOF_MORE_OBJECTS_PER_GRF), + GRFFeatureInfo("more_objects_per_grf", 1), GRFFeatureInfo("more_action2_ids", 1, GFTOF_MORE_ACTION2_IDS), GRFFeatureInfo("town_feature", 1), GRFFeatureInfo("town_uncapped_variables", 1), diff --git a/src/newgrf_extension.h b/src/newgrf_extension.h index 6764de01f7..a63ca2da57 100644 --- a/src/newgrf_extension.h +++ b/src/newgrf_extension.h @@ -103,8 +103,7 @@ enum Action2VariableRemapIds { }; enum GRFFeatureTestObservationFlag : uint8 { - GFTOF_MORE_OBJECTS_PER_GRF = 0, - GFTOF_MORE_ACTION2_IDS, + GFTOF_MORE_ACTION2_IDS = 0, GFTOF_TOWN_ZONE_CALLBACK, GFTOF_MORE_VARACTION2_TYPES, GFTOF_MULTI_PART_SHIPS, diff --git a/src/object_type.h b/src/object_type.h index e7f9b53076..602b795a02 100644 --- a/src/object_type.h +++ b/src/object_type.h @@ -21,6 +21,7 @@ static const ObjectType OBJECT_HQ = 4; ///< HeadQuarter of a play static const ObjectType NEW_OBJECT_OFFSET = 5; ///< Offset for new objects static const ObjectType NUM_OBJECTS = 64000; ///< Number of supported objects overall +static const ObjectType NUM_OBJECTS_PER_GRF = NUM_OBJECTS; ///< Number of supported objects per NewGRF static const ObjectType INVALID_OBJECT_TYPE = 0xFFFF; ///< An invalid object /** Unique identifier for an object. */ diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index b2a3e4fa4b..1f67823d79 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -183,7 +183,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_TOWN_SETTING_OVERRIDE, XSCF_NULL, 1, 1, "town_setting_override", nullptr, nullptr, nullptr }, { XSLFI_LINKGRAPH_SPARSE_EDGES, XSCF_NULL, 1, 1, "linkgraph_sparse_edges", nullptr, nullptr, nullptr }, { XSLFI_AUX_TILE_LOOP, XSCF_NULL, 1, 1, "aux_tile_loop", nullptr, nullptr, nullptr }, - { XSLFI_NEWGRF_ENTITY_EXTRA, XSCF_NULL, 1, 1, "newgrf_entity_extra", nullptr, nullptr, nullptr }, + { XSLFI_NEWGRF_ENTITY_EXTRA, XSCF_NULL, 2, 2, "newgrf_entity_extra", nullptr, nullptr, nullptr }, { XSLFI_TNNC_CHUNK, XSCF_IGNORABLE_ALL, 0, 1, "tnnc_chunk", nullptr, nullptr, "TNNC" }, { XSLFI_MULTI_CARGO_SHIPS, XSCF_NULL, 1, 1, "multi_cargo_ships", nullptr, nullptr, nullptr }, { XSLFI_REMAIN_NEXT_ORDER_STATION, XSCF_IGNORABLE_UNKNOWN, 1, 1, "remain_next_order_station", nullptr, nullptr, nullptr }, diff --git a/src/saveload/saveload_common.h b/src/saveload/saveload_common.h index 384a73426b..489abb165a 100644 --- a/src/saveload/saveload_common.h +++ b/src/saveload/saveload_common.h @@ -363,6 +363,7 @@ enum SaveLoadVersion : uint16 { SLV_AI_START_DATE, ///< 309 PR#10653 Removal of individual AI start dates and added a generic one. SLV_EXTEND_VEHICLE_RANDOM, ///< 310 PR#10701 Extend vehicle random bits. + SLV_EXTEND_ENTITY_MAPPING, ///< 311 PR#10672 Extend entity mapping range. SL_MAX_VERSION, ///< Highest possible saveload version diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 9b40bb336c..d802077f00 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -240,7 +240,8 @@ static Money _cargo_feeder_share; static const SaveLoad _station_speclist_desc[] = { SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, SLV_27, SL_MAX_VERSION), - SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8, SLV_27, SL_MAX_VERSION), + SLE_CONDVAR_X(StationSpecList, localidx, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_NEWGRF_ENTITY_EXTRA, 0, 1)), + SLE_CONDVAR_X(StationSpecList, localidx, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_NEWGRF_ENTITY_EXTRA, 2)), }; static const SaveLoad _roadstop_speclist_desc[] = { diff --git a/src/saveload/upstream/station_sl.cpp b/src/saveload/upstream/station_sl.cpp index 52966be04e..aa79c11941 100644 --- a/src/saveload/upstream/station_sl.cpp +++ b/src/saveload/upstream/station_sl.cpp @@ -79,8 +79,9 @@ static void SwapPackets(GoodsEntry *ge) class SlStationSpecList : public DefaultSaveLoadHandler { public: inline static const SaveLoad description[] = { - SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, SLV_27, SL_MAX_VERSION), - SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8, SLV_27, SL_MAX_VERSION), + SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, SLV_27, SL_MAX_VERSION), + SLE_CONDVAR(StationSpecList, localidx, SLE_FILE_U8 | SLE_VAR_U16, SLV_27, SLV_EXTEND_ENTITY_MAPPING), + SLE_CONDVAR(StationSpecList, localidx, SLE_UINT16, SLV_EXTEND_ENTITY_MAPPING, SL_MAX_VERSION), }; inline const static SaveLoadCompatTable compat_description = _station_spec_list_sl_compat; @@ -106,8 +107,9 @@ public: class SlRoadStopSpecList : public DefaultSaveLoadHandler { public: inline static const SaveLoad description[] = { - SLE_VAR(RoadStopSpecList, grfid, SLE_UINT32), - SLE_VAR(RoadStopSpecList, localidx, SLE_FILE_U8 | SLE_VAR_U16), + SLE_CONDVAR(StationSpecList, grfid, SLE_UINT32, SLV_27, SL_MAX_VERSION), + SLE_CONDVAR(StationSpecList, localidx, SLE_FILE_U8 | SLE_VAR_U16, SLV_27, SLV_EXTEND_ENTITY_MAPPING), + SLE_CONDVAR(StationSpecList, localidx, SLE_UINT16, SLV_EXTEND_ENTITY_MAPPING, SL_MAX_VERSION), }; inline const static SaveLoadCompatTable compat_description = _station_road_stop_spec_list_sl_compat;