55#include "table/strings.h"
72const std::vector<GRFFile *> &GetAllGRFFiles()
121 this->skip_sprites = 0;
123 for (uint i = 0; i < GSF_END; i++) {
124 this->spritesets[i].clear();
127 memset(this->spritegroups, 0,
sizeof(this->spritegroups));
140 assert(feature < GSF_END);
141 for (uint i = 0; i < numsets; i++) {
142 SpriteSet &set = this->spritesets[feature][first_set + i];
143 set.
sprite = first_sprite + i * numents;
156 assert(feature < GSF_END);
157 return !this->spritesets[feature].empty();
169 assert(feature < GSF_END);
170 return this->spritesets[feature].find(set) != this->spritesets[feature].end();
182 return this->spritesets[feature].find(set)->second.sprite;
194 return this->spritesets[feature].find(set)->second.num_sprites;
207template <VehicleType T>
210 return image_index == 0xFD || IsValidImageIndex<T>(image_index);
222 ByteReader(uint8_t *data, uint8_t *end) : data(data), end(end) { }
224 inline uint8_t *ReadBytes(
size_t size)
226 if (data + size >= end) {
237 inline uint8_t ReadByte()
239 if (data < end)
return *(data)++;
245 uint16_t val = ReadByte();
246 return val | (ReadByte() << 8);
249 uint16_t ReadExtendedByte()
251 uint16_t val = ReadByte();
252 return val == 0xFF ? ReadWord() : val;
257 uint32_t val = ReadWord();
258 return val | (ReadWord() << 16);
264 return this->ReadDWord();
267 uint32_t ReadVarSize(uint8_t size)
270 case 1:
return ReadByte();
271 case 2:
return ReadWord();
272 case 4:
return ReadDWord();
279 std::string_view ReadString()
281 char *
string =
reinterpret_cast<char *
>(data);
282 size_t string_length =
ttd_strnlen(
string, Remaining());
285 Skip(std::min(string_length + 1, Remaining()));
287 return std::string_view(
string, string_length);
290 inline size_t Remaining()
const
295 inline bool HasData(
size_t count = 1)
const
297 return data + count <= end;
300 inline void Skip(
size_t len)
309typedef void (*SpecialSpriteHandler)(
ByteReader &buf);
326 RailTypeLabel railtypelabel;
327 uint8_t roadtramtype;
342 }
else if (this->refittability ==
UNSET) {
343 this->refittability =
EMPTY;
348static std::vector<GRFTempEngineData>
_gted;
363 GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
367 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
372 return this->grfid == other.grfid && this->nfoline == other.nfoline;
376static std::map<GRFLocation, std::pair<SpriteID, uint16_t>> _grm_sprites;
377typedef std::map<GRFLocation, std::vector<uint8_t>> GRFLineToSpriteOverride;
378static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
390void GrfMsgI(
int severity,
const std::string &msg)
403 if (file->grfid == grfid)
return file;
416 if (file->filename == filename)
return file;
436 if (config !=
nullptr) {
447 if (message == STR_NULL)
return nullptr;
449 config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
451 return &config->error.value();
499 static const StringID units_volume[] = {
500 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
501 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
502 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
503 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
504 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
505 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
506 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
507 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
511 assert(!
IsInsideMM(str.base(), 0xD000, 0xD7FF));
513#define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
514 static_assert(stringend - stringid == end - begin); \
515 if (str.base() >= begin && str.base() <= end) return StringID{str.base() + (stringid - begin)}
518 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
519 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
520 if (str.base() >= 0x004E && str.base() <= 0x006D)
return units_volume[str.base() - 0x004E];
521 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
522 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
523 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
528 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
529 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
530 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
533 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
534 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
535 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
536 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
537 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
539 switch (str.base()) {
540 case 0x4830:
return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
541 case 0x4831:
return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
542 case 0x483B:
return STR_ERROR_CAN_ONLY_BE_POSITIONED;
544#undef TEXTID_TO_STRINGID
546 if (str.base() == 0)
return STR_EMPTY;
548 Debug(grf, 0,
"Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
562 if (
IsInsideMM(str.base(), 0xD800, 0x10000)) {
569 }
else if (
IsInsideMM(str.base(), 0xD000, 0xD800)) {
587static std::map<uint32_t, uint32_t> _grf_id_overrides;
596 if (target_grfid == 0) {
597 _grf_id_overrides.erase(source_grfid);
598 GrfMsg(5,
"SetNewGRFOverride: Removed override of 0x{:X}", std::byteswap(source_grfid));
600 _grf_id_overrides[source_grfid] = target_grfid;
601 GrfMsg(5,
"SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}", std::byteswap(source_grfid), std::byteswap(target_grfid));
611 auto found = _grf_id_overrides.find(_cur.
grffile->grfid);
612 if (found != std::end(_grf_id_overrides)) {
614 if (grffile !=
nullptr)
return grffile;
631 uint32_t scope_grfid = INVALID_GRFID;
634 scope_grfid = file->grfid;
635 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
636 scope_grfid = it->second;
638 if (grf_match ==
nullptr) {
639 GrfMsg(5,
"Tried mapping from GRFID {:x} to {:x} but target is not loaded", std::byteswap(file->grfid), std::byteswap(scope_grfid));
641 GrfMsg(5,
"Mapping from GRFID {:x} to {:x}", std::byteswap(file->grfid), std::byteswap(scope_grfid));
646 EngineID engine = _engine_mngr.
GetID(type, internal_id, scope_grfid);
665 GrfMsg(5,
"Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->
index, std::byteswap(file->grfid), type, internal_id);
671 if (static_access)
return nullptr;
674 GrfMsg(0,
"Can't allocate any more engines");
686 _engine_mngr.SetID(type, internal_id, scope_grfid, std::min<uint8_t>(internal_id,
_engine_counts[type]), e->
index);
696 GrfMsg(5,
"Created new engine at index {} for GRFID {:x}, type {}, index {}", e->
index, std::byteswap(file->grfid), type, internal_id);
713 uint32_t scope_grfid = INVALID_GRFID;
715 scope_grfid = file->grfid;
716 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
717 scope_grfid = it->second;
721 return _engine_mngr.
GetID(type, internal_id, scope_grfid);
761 grf_sprite->
sprite = buf.ReadWord();
762 grf_sprite->
pal = buf.ReadWord();
767 bool custom_sprite =
HasBit(grf_sprite->
pal, 15) != invert_action1_flag;
771 uint index =
GB(grf_sprite->
sprite, 0, 14);
773 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {}", index);
774 grf_sprite->
sprite = SPR_IMG_QUERY;
775 grf_sprite->
pal = PAL_NONE;
778 if (max_sprite_offset !=
nullptr) *max_sprite_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
783 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
784 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
790 uint index =
GB(grf_sprite->
pal, 0, 14);
792 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {} for 'palette'", index);
793 grf_sprite->
pal = PAL_NONE;
796 if (max_palette_offset !=
nullptr) *max_palette_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
801 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
802 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
831 regs.delta.
parent[0] = buf.ReadByte();
832 regs.delta.
parent[1] = buf.ReadByte();
843 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
sprite_var10,
TLR_MAX_VAR10);
844 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
852 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
palette_var10,
TLR_MAX_VAR10);
853 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
872 bool has_flags =
HasBit(num_building_sprites, 6);
873 ClrBit(num_building_sprites, 6);
875 if (!allow_var10) valid_flags &= ~TLF_VAR10_FLAGS;
876 dts->
Allocate(num_building_sprites);
878 std::vector<uint16_t> max_sprite_offset(num_building_sprites + 1, 0);
879 std::vector<uint16_t> max_palette_offset(num_building_sprites + 1, 0);
886 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses invalid flag 0x{:X} for ground sprite", flags & ~(valid_flags & ~
TLF_NON_GROUND_FLAGS));
887 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
894 for (uint i = 0; i < num_building_sprites; i++) {
897 flags =
ReadSpriteLayoutSprite(buf, has_flags,
false, use_cur_spritesets, feature, &seq->image, max_sprite_offset.data() + i + 1, max_palette_offset.data() + i + 1);
900 if (flags & ~valid_flags) {
901 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses unknown flag 0x{:X}", flags & ~valid_flags);
902 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
907 seq->delta_y = buf.ReadByte();
909 if (!no_z_position) seq->
delta_z = buf.ReadByte();
912 seq->size_x = buf.ReadByte();
913 seq->size_y = buf.ReadByte();
914 seq->size_z = buf.ReadByte();
922 bool is_consistent =
true;
924 for (uint i = 0; i < num_building_sprites + 1; i++) {
925 if (max_sprite_offset[i] > 0) {
929 is_consistent =
false;
933 if (max_palette_offset[i] > 0) {
937 is_consistent =
false;
946 if (!is_consistent || dts->registers !=
nullptr) {
950 for (uint i = 0; i < num_building_sprites + 1; i++) {
965 CargoTypes result = 0;
983 if (base_pointer == 0) {
984 *index = INVALID_PRICE;
988 static const uint32_t start = 0x4B34;
989 static const uint32_t size = 6;
991 if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
992 GrfMsg(1,
"{}: Unsupported running cost base 0x{:04X}, ignoring", error_location, base_pointer);
996 *index = (
Price)((base_pointer - start) / size);
1025 ei->decay_speed = buf.ReadByte();
1042 ei->load_amount = buf.ReadByte();
1064 for (uint
id = first;
id < last; ++id) {
1073 uint8_t tracktype = buf.ReadByte();
1075 if (tracktype < _cur.grffile->railtype_list.size()) {
1080 switch (tracktype) {
1081 case 0:
_gted[e->
index].railtypelabel = rvi->
engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL;
break;
1082 case 1:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MONO;
break;
1083 case 2:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MAGLEV;
break;
1085 GrfMsg(1,
"RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1098 uint16_t speed = buf.ReadWord();
1099 if (speed == 0xFFFF) speed = 0;
1106 rvi->
power = buf.ReadWord();
1109 if (rvi->
power != 0) {
1127 uint8_t spriteid = buf.ReadByte();
1128 uint8_t orig_spriteid = spriteid;
1132 if (spriteid < 0xFD) spriteid >>= 1;
1134 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1135 rvi->image_index = spriteid;
1137 GrfMsg(1,
"RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1138 rvi->image_index = 0;
1144 uint8_t dual = buf.ReadByte();
1149 rvi->railveh_type = rvi->
power == 0 ?
1161 uint8_t ctype = buf.ReadByte();
1163 if (ctype == 0xFF) {
1165 ei->cargo_type = INVALID_CARGO;
1169 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1176 SB(rvi->
weight, 0, 8, buf.ReadByte());
1184 GrfMsg(2,
"RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1196 uint8_t traction = buf.ReadByte();
1199 if (traction <= 0x07) {
1201 }
else if (traction <= 0x27) {
1203 }
else if (traction <= 0x31) {
1205 }
else if (traction <= 0x37) {
1207 }
else if (traction <= 0x41) {
1233 ei->refit_cost = buf.ReadByte();
1237 uint32_t mask = buf.ReadDWord();
1238 _gted[e->
index].UpdateRefittability(mask != 0);
1246 SB(mask, 0, 8, buf.ReadByte());
1278 uint8_t weight = buf.ReadByte();
1281 GrfMsg(2,
"RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1302 _gted[e->
index].cargo_allowed = buf.ReadWord();
1308 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1313 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1322 uint8_t count = buf.ReadByte();
1323 _gted[e->
index].UpdateRefittability(prop == 0x2C && count != 0);
1325 CargoTypes &ctt = prop == 0x2C ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1348 SB(mask, 8, 8, buf.ReadByte());
1354 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1378 for (uint
id = first;
id < last; ++id) {
1389 _gted[e->
index].roadtramtype = buf.ReadByte() + 1;
1397 rvi->running_cost = buf.ReadByte();
1405 uint8_t spriteid = buf.ReadByte();
1406 uint8_t orig_spriteid = spriteid;
1409 if (spriteid == 0xFF) spriteid = 0xFD;
1411 if (spriteid < 0xFD) spriteid >>= 1;
1413 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1414 rvi->image_index = spriteid;
1416 GrfMsg(1,
"RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1417 rvi->image_index = 0;
1423 rvi->capacity = buf.ReadByte();
1428 uint8_t ctype = buf.ReadByte();
1430 if (ctype == 0xFF) {
1432 ei->cargo_type = INVALID_CARGO;
1436 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1443 rvi->cost_factor = buf.ReadByte();
1451 rvi->
power = buf.ReadByte();
1455 rvi->
weight = buf.ReadByte();
1459 _gted[e->
index].rv_max_speed = buf.ReadByte();
1463 uint32_t mask = buf.ReadDWord();
1464 _gted[e->
index].UpdateRefittability(mask != 0);
1472 SB(mask, 0, 8, buf.ReadByte());
1486 ei->refit_cost = buf.ReadByte();
1499 _gted[e->
index].cargo_allowed = buf.ReadWord();
1505 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1510 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1537 uint8_t count = buf.ReadByte();
1538 _gted[e->
index].UpdateRefittability(prop == 0x24 && count != 0);
1540 CargoTypes &ctt = prop == 0x24 ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1559 SB(mask, 8, 8, buf.ReadByte());
1565 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1589 for (uint
id = first;
id < last; ++id) {
1598 uint8_t spriteid = buf.ReadByte();
1599 uint8_t orig_spriteid = spriteid;
1602 if (spriteid == 0xFF) spriteid = 0xFD;
1604 if (spriteid < 0xFD) spriteid >>= 1;
1606 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1607 svi->image_index = spriteid;
1609 GrfMsg(1,
"ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1610 svi->image_index = 0;
1620 svi->cost_factor = buf.ReadByte();
1629 uint8_t ctype = buf.ReadByte();
1631 if (ctype == 0xFF) {
1633 ei->cargo_type = INVALID_CARGO;
1637 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1644 svi->capacity = buf.ReadWord();
1648 svi->running_cost = buf.ReadByte();
1656 uint32_t mask = buf.ReadDWord();
1657 _gted[e->
index].UpdateRefittability(mask != 0);
1665 SB(mask, 0, 8, buf.ReadByte());
1671 ei->refit_cost = buf.ReadByte();
1692 _gted[e->
index].cargo_allowed = buf.ReadWord();
1698 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1703 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1726 uint8_t count = buf.ReadByte();
1727 _gted[e->
index].UpdateRefittability(prop == 0x1E && count != 0);
1729 CargoTypes &ctt = prop == 0x1E ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1748 SB(mask, 8, 8, buf.ReadByte());
1758 svi->
acceleration = std::max<uint8_t>(1, buf.ReadByte());
1762 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1786 for (uint
id = first;
id < last; ++id) {
1795 uint8_t spriteid = buf.ReadByte();
1796 uint8_t orig_spriteid = spriteid;
1799 if (spriteid == 0xFF) spriteid = 0xFD;
1801 if (spriteid < 0xFD) spriteid >>= 1;
1803 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1804 avi->image_index = spriteid;
1806 GrfMsg(1,
"AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1807 avi->image_index = 0;
1813 if (buf.ReadByte() == 0) {
1825 avi->cost_factor = buf.ReadByte();
1829 avi->
max_speed = (buf.ReadByte() * 128) / 10;
1833 avi->acceleration = buf.ReadByte();
1837 avi->running_cost = buf.ReadByte();
1853 uint32_t mask = buf.ReadDWord();
1854 _gted[e->
index].UpdateRefittability(mask != 0);
1862 SB(mask, 0, 8, buf.ReadByte());
1868 ei->refit_cost = buf.ReadByte();
1881 _gted[e->
index].cargo_allowed = buf.ReadWord();
1887 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1892 ei->
base_intro = TimerGameCalendar::Date(buf.ReadDWord());
1905 uint8_t count = buf.ReadByte();
1906 _gted[e->
index].UpdateRefittability(prop == 0x1D && count != 0);
1908 CargoTypes &ctt = prop == 0x1D ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1931 SB(mask, 8, 8, buf.ReadByte());
1937 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1962 GrfMsg(1,
"StationChangeInfo: Station {} is invalid, max {}, ignoring", last,
NUM_STATIONS_PER_GRF);
1967 if (_cur.
grffile->stations.size() < last) _cur.
grffile->stations.resize(last);
1969 for (uint
id = first;
id < last; ++id) {
1970 auto &statspec = _cur.
grffile->stations[id];
1973 if (statspec ==
nullptr && prop != 0x08) {
1974 GrfMsg(2,
"StationChangeInfo: Attempt to modify undefined station {}, ignoring",
id);
1981 if (statspec ==
nullptr) {
1982 statspec = std::make_unique<StationSpec>();
1986 uint32_t classid = buf.ReadDWord();
1992 uint16_t tiles = buf.ReadExtendedByte();
1993 statspec->renderdata.clear();
1994 statspec->renderdata.reserve(tiles);
1996 for (uint t = 0; t < tiles; t++) {
2000 if (buf.HasData(4) && buf.PeekDWord() == 0) {
2003 dts->
Clone(&_station_display_datas_rail[t % 8]);
2011 static std::vector<DrawTileSeqStruct> tmp_layout;
2018 dtss.
delta_x = buf.ReadByte();
2020 dtss.delta_y = buf.ReadByte();
2021 dtss.
delta_z = buf.ReadByte();
2022 dtss.size_x = buf.ReadByte();
2023 dtss.size_y = buf.ReadByte();
2024 dtss.size_z = buf.ReadByte();
2030 dts->
Clone(tmp_layout.data());
2034 if (statspec->renderdata.size() & 1) {
2035 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item",
id);
2036 statspec->renderdata.pop_back();
2042 uint16_t srcid = buf.ReadExtendedByte();
2043 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2045 if (srcstatspec ==
nullptr) {
2046 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid,
id);
2050 statspec->renderdata.clear();
2051 statspec->renderdata.reserve(srcstatspec->
renderdata.size());
2053 for (
const auto &it : srcstatspec->
renderdata) {
2065 statspec->disallowed_platforms = buf.ReadByte();
2069 statspec->disallowed_lengths = buf.ReadByte();
2073 while (buf.HasData()) {
2074 uint8_t length = buf.ReadByte();
2075 uint8_t number = buf.ReadByte();
2077 if (length == 0 || number == 0)
break;
2079 const uint8_t *buf_layout = buf.ReadBytes(length * number);
2083 layout.assign(buf_layout, buf_layout + length * number);
2086 for (
auto &tile : layout) {
2087 if ((tile & ~1U) != tile) {
2088 GrfMsg(1,
"StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2096 uint16_t srcid = buf.ReadExtendedByte();
2097 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2099 if (srcstatspec ==
nullptr) {
2100 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid,
id);
2104 statspec->layouts = srcstatspec->
layouts;
2109 statspec->cargo_threshold = buf.ReadWord();
2113 uint8_t pylons = buf.ReadByte();
2114 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2115 for (
int j = 0; j < 8; ++j) {
2126 if (_cur.
grffile->grf_version >= 7) {
2129 statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2138 uint8_t wires = buf.ReadByte();
2139 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2140 for (
int j = 0; j < 8; ++j) {
2151 uint8_t blocked = buf.ReadByte();
2152 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2153 for (
int j = 0; j < 8; ++j) {
2154 if (
HasBit(blocked, j)) {
2164 statspec->animation.frames = buf.ReadByte();
2165 statspec->animation.status = buf.ReadByte();
2169 statspec->animation.speed = buf.ReadByte();
2173 statspec->animation.triggers = buf.ReadWord();
2179 uint16_t tiles = buf.ReadExtendedByte();
2180 statspec->renderdata.clear();
2181 statspec->renderdata.reserve(tiles);
2183 for (uint t = 0; t < tiles; t++) {
2185 uint num_building_sprites = buf.ReadByte();
2191 if (statspec->renderdata.size() & 1) {
2192 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item",
id);
2193 statspec->renderdata.pop_back();
2214 uint16_t tiles = buf.ReadExtendedByte();
2216 statspec->tileflags.assign(flags, flags + tiles);
2241 if (last > CF_END) {
2242 GrfMsg(1,
"CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring", last, CF_END);
2246 for (uint
id = first;
id < last; ++id) {
2255 cp->
flags = buf.ReadByte();
2280 GrfMsg(1,
"BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", last,
MAX_BRIDGES);
2284 for (uint
id = first;
id < last; ++id) {
2290 uint8_t year = buf.ReadByte();
2305 bridge->
price = buf.ReadByte();
2309 bridge->
speed = buf.ReadWord();
2310 if (bridge->
speed == 0) bridge->
speed = UINT16_MAX;
2314 uint8_t tableid = buf.ReadByte();
2315 uint8_t numtables = buf.ReadByte();
2319 bridge->
sprite_table = CallocT<PalSpriteID*>(NUM_BRIDGE_PIECES);
2322 for (; numtables-- != 0; tableid++) {
2323 if (tableid >= NUM_BRIDGE_PIECES) {
2324 GrfMsg(1,
"BridgeChangeInfo: Table {} >= {}, skipping", tableid, NUM_BRIDGE_PIECES);
2347 bridge->
flags = buf.ReadByte();
2367 bridge->
price = buf.ReadWord();
2424 for (uint j = 0; j < 4; j++) buf.ReadByte();
2428 uint8_t count = buf.ReadByte();
2429 for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2434 buf.Skip(buf.ReadByte() * 2);
2457 GrfMsg(1,
"TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", last,
NUM_HOUSES_PER_GRF);
2462 if (_cur.
grffile->housespec.size() < last) _cur.
grffile->housespec.resize(last);
2464 for (uint
id = first;
id < last; ++id) {
2465 auto &housespec = _cur.
grffile->housespec[id];
2467 if (prop != 0x08 && housespec ==
nullptr) {
2470 if (cir > ret) ret = cir;
2476 uint8_t subs_id = buf.ReadByte();
2477 if (subs_id == 0xFF) {
2484 GrfMsg(2,
"TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id,
id);
2489 if (housespec ==
nullptr) {
2491 housespec = std::make_unique<HouseSpec>(*
HouseSpec::Get(subs_id));
2493 housespec->enabled =
true;
2494 housespec->grf_prop.local_id = id;
2495 housespec->grf_prop.subst_id = subs_id;
2496 housespec->grf_prop.grfid = _cur.
grffile->grfid;
2497 housespec->grf_prop.grffile = _cur.
grffile;
2499 housespec->random_colour[0] = COLOUR_RED;
2500 housespec->random_colour[1] = COLOUR_BLUE;
2501 housespec->random_colour[2] = COLOUR_ORANGE;
2502 housespec->random_colour[3] = COLOUR_GREEN;
2505 housespec->building_flags.Reset(BuildingFlag::IsChurch).Reset(BuildingFlag::IsStadium);
2511 CargoType cargo_type = housespec->accepts_cargo[2];
2512 if (!
IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(housespec->accepts_cargo_label[2]);
2514 housespec->cargo_acceptance[2] = 0;
2525 uint16_t years = buf.ReadWord();
2532 housespec->population = buf.ReadByte();
2536 housespec->mail_generation = buf.ReadByte();
2541 housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2545 int8_t goods = buf.ReadByte();
2555 housespec->accepts_cargo[2] = cargo_type;
2556 housespec->accepts_cargo_label[2] =
CT_INVALID;
2557 housespec->cargo_acceptance[2] =
abs(goods);
2562 housespec->remove_rating_decrease = buf.ReadWord();
2566 housespec->removal_cost = buf.ReadByte();
2574 housespec->building_availability = (
HouseZones)buf.ReadWord();
2578 auto mask = housespec->callback_mask.base();
2579 SB(mask, 0, 8, buf.ReadByte());
2585 uint8_t
override = buf.ReadByte();
2589 GrfMsg(2,
"TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.",
override,
id);
2593 _house_mngr.
Add(
id, _cur.
grffile->grfid,
override);
2598 housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2602 for (uint j = 0; j < 4; j++) housespec->random_colour[j] =
static_cast<Colours
>(
GB(buf.ReadByte(), 0, 4));
2606 housespec->probability = buf.ReadByte();
2610 housespec->extra_flags =
static_cast<HouseExtraFlags>(buf.ReadByte());
2614 housespec->animation.frames = buf.ReadByte();
2615 housespec->animation.status =
GB(housespec->animation.frames, 7, 1);
2616 SB(housespec->animation.frames, 7, 1, 0);
2620 housespec->animation.speed =
Clamp(buf.ReadByte(), 2, 16);
2624 housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.
grffile->grfid);
2628 auto mask = housespec->callback_mask.base();
2629 SB(mask, 8, 8, buf.ReadByte());
2635 uint32_t cargotypes = buf.ReadDWord();
2638 if (cargotypes == 0xFFFFFFFF)
break;
2642 uint8_t cargo_part =
GB(cargotypes, 8 * j, 8);
2647 housespec->cargo_acceptance[j] = 0;
2649 housespec->accepts_cargo[j] = cargo;
2651 housespec->accepts_cargo_label[j] =
CT_INVALID;
2657 housespec->minimum_life = buf.ReadByte();
2661 uint8_t count = buf.ReadByte();
2662 for (uint8_t j = 0; j < count; j++) {
2679 uint count = buf.ReadByte();
2680 if (count >
lengthof(housespec->accepts_cargo)) {
2688 for (uint i = 0; i <
lengthof(housespec->accepts_cargo); i++) {
2691 housespec->cargo_acceptance[i] = buf.ReadByte();
2693 housespec->accepts_cargo[i] = INVALID_CARGO;
2694 housespec->cargo_acceptance[i] = 0;
2696 if (i < std::size(housespec->accepts_cargo_label)) housespec->accepts_cargo_label[i] =
CT_INVALID;
2720 if (grffile ==
nullptr)
return nullptr;
2723 if (it == std::end(grffile->
language_map))
return nullptr;
2737template <
typename T,
typename TGetTableFunc>
2741 GrfMsg(1,
"LoadTranslationTable: {} translation table must start at zero", name);
2745 std::vector<T> &translation_table = gettable(*_cur.
grffile);
2746 translation_table.clear();
2747 translation_table.reserve(last);
2748 for (uint
id = first;
id < last; ++id) {
2749 translation_table.push_back(T(std::byteswap(buf.ReadDWord())));
2753 if (grf_override !=
nullptr) {
2755 GrfMsg(1,
"LoadTranslationTable: Copying {} translation table to override GRFID '{}'", name, std::byteswap(grf_override->grfid));
2756 std::vector<T> &override_table = gettable(*grf_override);
2757 override_table = translation_table;
2772 for (
int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2789 return LoadTranslationTable<CargoLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
2792 return LoadTranslationTable<RailTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
2795 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
2798 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
2806 for (uint
id = first;
id < last; ++id) {
2809 int factor = buf.ReadByte();
2814 GrfMsg(1,
"GlobalVarChangeInfo: Price {} out of range, ignoring",
id);
2834 uint32_t rate = buf.ReadDWord();
2842 GrfMsg(1,
"GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2849 uint16_t options = buf.ReadWord();
2858 GrfMsg(1,
"GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2870 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2882 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2894 GrfMsg(1,
"GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2901 GrfMsg(1,
"GlobalVarChangeInfo: The snowline can only be set once ({})", last);
2903 GrfMsg(1,
"GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2905 auto snow_line = std::make_unique<SnowLine>();
2909 uint8_t &level = snow_line->table[i][j];
2910 level = buf.ReadByte();
2911 if (_cur.
grffile->grf_version >= 8) {
2922 snow_line->highest_value = std::max(snow_line->highest_value, level);
2923 snow_line->lowest_value = std::min(snow_line->lowest_value, level);
2941 if (lang ==
nullptr) {
2942 GrfMsg(1,
"GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
2947 while (buf.ReadByte() != 0) {
2955 uint plural_form = buf.ReadByte();
2956 if (plural_form >= LANGUAGE_MAX_PLURAL) {
2957 GrfMsg(1,
"GlobalVarChanceInfo: Plural form {} is out of range, ignoring", plural_form);
2964 uint8_t newgrf_id = buf.ReadByte();
2965 while (newgrf_id != 0) {
2966 std::string_view name = buf.ReadString();
2981 GrfMsg(1,
"GlobalVarChangeInfo: Gender name {} is not known, ignoring",
StrMakeValid(name));
2988 GrfMsg(1,
"GlobalVarChangeInfo: Case name {} is not known, ignoring",
StrMakeValid(name));
2993 newgrf_id = buf.ReadByte();
3012 return LoadTranslationTable<CargoLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<CargoLabel> & {
return grf.
cargo_list; },
"Cargo");
3015 return LoadTranslationTable<RailTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RailTypeLabel> & {
return grf.
railtype_list; },
"Rail type");
3018 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
roadtype_list; },
"Road type");
3021 return LoadTranslationTable<RoadTypeLabel>(first, last, buf, [](
GRFFile &grf) -> std::vector<RoadTypeLabel> & {
return grf.
tramtype_list; },
"Tram type");
3030 for (uint
id = first;
id < last; ++id) {
3054 uint32_t s = buf.ReadDWord();
3055 uint32_t t = buf.ReadDWord();
3062 while (buf.ReadByte() != 0) {
3090 GrfMsg(2,
"CargoChangeInfo: Cargo type {} out of range (max {})", last,
NUM_CARGO - 1);
3094 for (uint
id = first;
id < last; ++id) {
3099 cs->
bitnum = buf.ReadByte();
3138 cs->
sprite = buf.ReadWord();
3142 cs->
weight = buf.ReadByte();
3146 cs->transit_periods[0] = buf.ReadByte();
3150 cs->transit_periods[1] = buf.ReadByte();
3158 cs->rating_colour = buf.ReadByte();
3162 cs->legend_colour = buf.ReadByte();
3179 uint8_t substitute_type = buf.ReadByte();
3181 switch (substitute_type) {
3188 GrfMsg(1,
"CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3204 cs->
multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3208 uint8_t substitute_type = buf.ReadByte();
3210 switch (substitute_type) {
3214 GrfMsg(1,
"CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3247 if (_cur.
grffile->sound_offset == 0) {
3248 GrfMsg(1,
"SoundEffectChangeInfo: No effects defined, skipping");
3253 GrfMsg(1,
"SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", last,
ORIGINAL_SAMPLE_COUNT + _cur.
grffile->num_sounds);
3257 for (uint
id = first;
id < last; ++id) {
3262 sound->volume =
Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3266 sound->priority = buf.ReadByte();
3270 SoundID orig_sound = buf.ReadByte();
3273 GrfMsg(1,
"SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound,
ORIGINAL_SAMPLE_COUNT);
3275 SoundEntry *old_sound = GetSound(orig_sound);
3278 *old_sound = *sound;
3320 buf.Skip(buf.ReadByte() * 2);
3343 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTILES_PER_GRF);
3348 if (_cur.
grffile->indtspec.size() < last) _cur.
grffile->indtspec.resize(last);
3350 for (uint
id = first;
id < last; ++id) {
3351 auto &tsp = _cur.
grffile->indtspec[id];
3353 if (prop != 0x08 && tsp ==
nullptr) {
3355 if (cir > ret) ret = cir;
3361 uint8_t subs_id = buf.ReadByte();
3364 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id,
id);
3369 if (tsp ==
nullptr) {
3370 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3372 tsp->enabled =
true;
3380 tsp->grf_prop.local_id = id;
3381 tsp->grf_prop.subst_id = subs_id;
3382 tsp->grf_prop.grfid = _cur.
grffile->grfid;
3383 tsp->grf_prop.grffile = _cur.
grffile;
3390 uint8_t ovrid = buf.ReadByte();
3394 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid,
id);
3398 _industile_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
3405 uint16_t acctp = buf.ReadWord();
3407 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
3408 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
3413 tsp->slopes_refused = (
Slope)buf.ReadByte();
3421 tsp->animation.frames = buf.ReadByte();
3422 tsp->animation.status = buf.ReadByte();
3426 tsp->animation.speed = buf.ReadByte();
3430 tsp->animation.triggers = buf.ReadByte();
3438 uint8_t num_cargoes = buf.ReadByte();
3439 if (num_cargoes > std::size(tsp->acceptance)) {
3444 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3445 if (i < num_cargoes) {
3448 tsp->acceptance[i] = (int8_t)buf.ReadByte();
3450 tsp->accepts_cargo[i] = INVALID_CARGO;
3451 tsp->acceptance[i] = 0;
3453 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
3513 uint8_t num_table = buf.ReadByte();
3514 for (uint8_t j = 0; j < num_table; j++) {
3515 for (uint k = 0;; k++) {
3516 uint8_t x = buf.ReadByte();
3517 if (x == 0xFE && k == 0) {
3523 uint8_t y = buf.ReadByte();
3524 if (x == 0 && y == 0x80)
break;
3526 uint8_t gfx = buf.ReadByte();
3527 if (gfx == 0xFE) buf.ReadWord();
3541 buf.Skip(buf.ReadByte());
3545 int num_inputs = buf.ReadByte();
3546 int num_outputs = buf.ReadByte();
3547 buf.Skip(num_inputs * num_outputs * 2);
3565 const size_t size = layout.size();
3566 if (size == 0)
return false;
3568 for (
size_t i = 0; i < size - 1; i++) {
3569 for (
size_t j = i + 1; j < size; j++) {
3570 if (layout[i].ti.x == layout[j].ti.x &&
3571 layout[i].ti.y == layout[j].ti.y) {
3577 bool have_regular_tile =
false;
3578 for (
const auto &tilelayout : layout) {
3580 have_regular_tile =
true;
3585 return have_regular_tile;
3601 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last,
NUM_INDUSTRYTYPES_PER_GRF);
3606 if (_cur.
grffile->industryspec.size() < last) _cur.
grffile->industryspec.resize(last);
3608 for (uint
id = first;
id < last; ++id) {
3609 auto &indsp = _cur.
grffile->industryspec[id];
3611 if (prop != 0x08 && indsp ==
nullptr) {
3613 if (cir > ret) ret = cir;
3619 uint8_t subs_id = buf.ReadByte();
3620 if (subs_id == 0xFF) {
3623 _industry_specs[id].
enabled =
false;
3627 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id,
id);
3634 if (indsp ==
nullptr) {
3635 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3637 indsp->enabled =
true;
3638 indsp->grf_prop.local_id = id;
3639 indsp->grf_prop.subst_id = subs_id;
3640 indsp->grf_prop.grfid = _cur.
grffile->grfid;
3641 indsp->grf_prop.grffile = _cur.
grffile;
3650 uint8_t ovrid = buf.ReadByte();
3654 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid,
id);
3657 indsp->grf_prop.override = ovrid;
3658 _industry_mngr.
Add(
id, _cur.
grffile->grfid, ovrid);
3663 uint8_t new_num_layouts = buf.ReadByte();
3664 uint32_t definition_size = buf.ReadDWord();
3665 uint32_t bytes_read = 0;
3666 std::vector<IndustryTileLayout> new_layouts;
3669 for (uint8_t j = 0; j < new_num_layouts; j++) {
3671 layout.reserve(new_num_layouts);
3673 for (uint k = 0;; k++) {
3674 if (bytes_read >= definition_size) {
3675 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.",
id);
3677 definition_size = UINT32_MAX;
3682 it.ti.
x = buf.ReadByte();
3685 if (it.ti.
x == 0xFE && k == 0) {
3687 IndustryType type = buf.ReadByte();
3688 uint8_t laynbr = buf.ReadByte();
3691 if (type >=
lengthof(_origin_industry_specs)) {
3692 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}",
id);
3696 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3697 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}",
id);
3701 layout = _origin_industry_specs[type].layouts[laynbr];
3705 it.ti.
y = buf.ReadByte();
3708 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
3714 it.gfx = buf.ReadByte();
3717 if (it.gfx == 0xFE) {
3719 int local_tile_id = buf.ReadWord();
3723 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3726 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id,
id);
3732 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
3733 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
3742 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
3748 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring",
id);
3752 new_layouts.push_back(layout);
3757 indsp->layouts = new_layouts;
3778 indsp->cost_multiplier = buf.ReadByte();
3798 indsp->production_rate[prop - 0x12] = buf.ReadByte();
3802 indsp->minimal_cargo = buf.ReadByte();
3806 uint8_t num_sounds = buf.ReadByte();
3808 std::vector<uint8_t> sounds;
3809 sounds.reserve(num_sounds);
3810 for (uint8_t j = 0; j < num_sounds; ++j) {
3811 sounds.push_back(buf.ReadByte());
3814 indsp->random_sounds = std::move(sounds);
3819 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3831 indsp->map_colour = buf.ReadByte();
3845 uint32_t multiples = buf.ReadDWord();
3846 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
3847 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
3856 indsp->prospecting_chance = buf.ReadDWord();
3861 auto mask = indsp->callback_mask.base();
3862 SB(mask, (prop - 0x21) * 8, 8, buf.ReadByte());
3868 indsp->removal_cost_multiplier = buf.ReadDWord();
3874 indsp->station_name = STR_NULL;
3882 uint8_t num_cargoes = buf.ReadByte();
3883 if (num_cargoes > std::size(indsp->produced_cargo)) {
3888 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3889 if (i < num_cargoes) {
3891 indsp->produced_cargo[i] = cargo;
3893 indsp->produced_cargo[i] = INVALID_CARGO;
3895 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
3901 uint8_t num_cargoes = buf.ReadByte();
3902 if (num_cargoes > std::size(indsp->accepts_cargo)) {
3907 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3908 if (i < num_cargoes) {
3910 indsp->accepts_cargo[i] = cargo;
3912 indsp->accepts_cargo[i] = INVALID_CARGO;
3914 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
3920 uint8_t num_cargoes = buf.ReadByte();
3921 if (num_cargoes >
lengthof(indsp->production_rate)) {
3926 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
3927 if (i < num_cargoes) {
3928 indsp->production_rate[i] = buf.ReadByte();
3930 indsp->production_rate[i] = 0;
3937 uint8_t num_inputs = buf.ReadByte();
3938 uint8_t num_outputs = buf.ReadByte();
3939 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
3944 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3945 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
3947 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
3948 indsp->input_cargo_multiplier[i][j] = mult;
3976 GrfMsg(1,
"AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", last,
NUM_AIRPORTS_PER_GRF);
3981 if (_cur.
grffile->airportspec.size() < last) _cur.
grffile->airportspec.resize(last);
3983 for (uint
id = first;
id < last; ++id) {
3984 auto &as = _cur.
grffile->airportspec[id];
3986 if (as ==
nullptr && prop != 0x08 && prop != 0x09) {
3987 GrfMsg(2,
"AirportChangeInfo: Attempt to modify undefined airport {}, ignoring",
id);
3993 uint8_t subs_id = buf.ReadByte();
3994 if (subs_id == 0xFF) {
4001 GrfMsg(2,
"AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id,
id);
4008 if (as ==
nullptr) {
4012 as->grf_prop.local_id = id;
4013 as->grf_prop.subst_id = subs_id;
4014 as->grf_prop.grfid = _cur.
grffile->grfid;
4015 as->grf_prop.grffile = _cur.
grffile;
4017 _airport_mngr.
Add(
id, _cur.
grffile->grfid, subs_id);
4023 uint8_t num_layouts = buf.ReadByte();
4028 std::vector<AirportTileLayout> layouts;
4029 layouts.reserve(num_layouts);
4031 for (uint8_t j = 0; j != num_layouts; ++j) {
4032 auto &layout = layouts.emplace_back();
4033 layout.rotation =
static_cast<Direction>(buf.ReadByte() & 6);
4036 auto &tile = layout.tiles.emplace_back();
4037 tile.ti.x = buf.ReadByte();
4038 tile.ti.y = buf.ReadByte();
4039 if (tile.ti.x == 0 && tile.ti.y == 0x80) {
4047 tile.gfx = buf.ReadByte();
4049 if (tile.gfx == 0xFE) {
4051 int local_tile_id = buf.ReadWord();
4054 uint16_t tempid = _airporttile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
4057 GrfMsg(2,
"AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id,
id);
4062 }
else if (tile.gfx == 0xFF) {
4063 tile.ti.x =
static_cast<int8_t
>(
GB(tile.ti.x, 0, 8));
4064 tile.ti.y =
static_cast<int8_t
>(
GB(tile.ti.y, 0, 8));
4068 if (layout.rotation ==
DIR_E || layout.rotation ==
DIR_W) {
4069 size_x = std::max<uint8_t>(size_x, tile.ti.y + 1);
4070 size_y = std::max<uint8_t>(size_y, tile.ti.x + 1);
4072 size_x = std::max<uint8_t>(size_x, tile.ti.x + 1);
4073 size_y = std::max<uint8_t>(size_y, tile.ti.y + 1);
4077 as->layouts = std::move(layouts);
4078 as->size_x = size_x;
4079 as->size_y = size_y;
4098 as->noise_level = buf.ReadByte();
4106 as->maintenance_cost = buf.ReadWord();
4176 GrfMsg(1,
"ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.", last,
NUM_OBJECTS_PER_GRF);
4181 if (_cur.
grffile->objectspec.size() < last) _cur.
grffile->objectspec.resize(last);
4183 for (uint
id = first;
id < last; ++id) {
4184 auto &spec = _cur.
grffile->objectspec[id];
4186 if (prop != 0x08 && spec ==
nullptr) {
4189 if (cir > ret) ret = cir;
4196 if (spec ==
nullptr) {
4197 spec = std::make_unique<ObjectSpec>();
4203 uint32_t classid = buf.ReadDWord();
4222 spec->size = buf.ReadByte();
4223 if (
GB(spec->size, 0, 4) == 0 ||
GB(spec->size, 4, 4) == 0) {
4224 GrfMsg(0,
"ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size,
id);
4230 spec->build_cost_multiplier = buf.ReadByte();
4231 spec->clear_cost_multiplier = spec->build_cost_multiplier;
4235 spec->introduction_date = TimerGameCalendar::Date(buf.ReadDWord());
4239 spec->end_of_life_date = TimerGameCalendar::Date(buf.ReadDWord());
4248 spec->animation.frames = buf.ReadByte();
4249 spec->animation.status = buf.ReadByte();
4253 spec->animation.speed = buf.ReadByte();
4257 spec->animation.triggers = buf.ReadWord();
4261 spec->clear_cost_multiplier = buf.ReadByte();
4269 spec->height = buf.ReadByte();
4273 spec->views = buf.ReadByte();
4274 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
4275 GrfMsg(2,
"ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views,
id);
4281 spec->generate_amount = buf.ReadByte();
4308 GrfMsg(1,
"RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring", last,
RAILTYPE_END);
4312 for (uint
id = first;
id < last; ++id) {
4327 if (_cur.
grffile->grf_version < 8) {
4357 int n = buf.ReadByte();
4358 for (
int j = 0; j != n; j++) {
4359 RailTypeLabel label = buf.ReadDWord();
4419 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4438 GrfMsg(1,
"RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring", last,
RAILTYPE_END);
4442 for (uint
id = first;
id < last; ++id) {
4446 RailTypeLabel rtl = buf.ReadDWord();
4455 _cur.
grffile->railtype_map[id] = rt;
4473 int n = buf.ReadByte();
4474 for (
int j = 0; j != n; j++) {
4479 GrfMsg(1,
"RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set",
id);
4486 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4524 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.
grffile->roadtype_map;
4527 GrfMsg(1,
"RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring", last,
ROADTYPE_END);
4531 for (uint
id = first;
id < last; ++id) {
4569 int n = buf.ReadByte();
4570 for (
int j = 0; j != n; j++) {
4571 RoadTypeLabel label = buf.ReadDWord();
4576 if (GetRoadTramType(resolved_rt) == rtt) {
4579 GrfMsg(1,
"RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4624 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4652 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
4655 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring", last,
ROADTYPE_END);
4659 for (uint
id = first;
id < last; ++id) {
4662 RoadTypeLabel rtl = buf.ReadDWord();
4669 }
else if (GetRoadTramType(rt) != rtt) {
4670 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring",
id);
4691 int n = buf.ReadByte();
4692 for (
int j = 0; j != n; j++) {
4693 _roadtypes[type_map[id]].
alternate_labels.push_back(std::byteswap(buf.ReadDWord()));
4697 GrfMsg(1,
"RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set",
id);
4703 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4727 return RoadTypeReserveInfo(first, last, prop, buf, RTT_ROAD);
4732 return RoadTypeReserveInfo(first, last, prop, buf, RTT_TRAM);
4740 GrfMsg(1,
"AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", last,
NUM_AIRPORTTILES_PER_GRF);
4745 if (_cur.
grffile->airtspec.size() < last) _cur.
grffile->airtspec.resize(last);
4747 for (uint
id = first;
id < last; ++id) {
4748 auto &tsp = _cur.
grffile->airtspec[id];
4750 if (prop != 0x08 && tsp ==
nullptr) {
4751 GrfMsg(2,
"AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.",
id);
4757 uint8_t subs_id = buf.ReadByte();
4760 GrfMsg(2,
"AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id,
id);
4765 if (tsp ==
nullptr) {
4768 tsp->enabled =
true;
4772 tsp->grf_prop.local_id = id;
4773 tsp->grf_prop.subst_id = subs_id;
4774 tsp->grf_prop.grfid = _cur.
grffile->grfid;
4775 tsp->grf_prop.grffile = _cur.
grffile;
4782 uint8_t
override = buf.ReadByte();
4786 GrfMsg(2,
"AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.",
override,
id);
4790 _airporttile_mngr.
Add(
id, _cur.
grffile->grfid,
override);
4799 tsp->animation.frames = buf.ReadByte();
4800 tsp->animation.status = buf.ReadByte();
4804 tsp->animation.speed = buf.ReadByte();
4808 tsp->animation.triggers = buf.ReadByte();
4865 GrfMsg(1,
"RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring", last,
NUM_ROADSTOPS_PER_GRF);
4869 if (_cur.
grffile->roadstops.size() < last) _cur.
grffile->roadstops.resize(last);
4871 for (uint
id = first;
id < last; ++id) {
4872 auto &rs = _cur.
grffile->roadstops[id];
4874 if (rs ==
nullptr && prop != 0x08) {
4875 GrfMsg(1,
"RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring",
id);
4877 if (cir > ret) ret = cir;
4883 if (rs ==
nullptr) {
4884 rs = std::make_unique<RoadStopSpec>();
4887 uint32_t classid = buf.ReadDWord();
4913 rs->animation.frames = buf.ReadByte();
4914 rs->animation.status = buf.ReadByte();
4918 rs->animation.speed = buf.ReadByte();
4922 rs->animation.triggers = buf.ReadWord();
4934 rs->build_cost_multiplier = buf.ReadByte();
4935 rs->clear_cost_multiplier = buf.ReadByte();
4947static bool HandleChangeInfoResult(
const char *caller,
ChangeInfoResult cir, uint8_t feature, uint8_t property)
4950 default: NOT_REACHED();
4960 GrfMsg(1,
"{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
4964 GrfMsg(0,
"{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
4977static void FeatureChangeInfo(
ByteReader &buf)
4990 static ChangeInfoHandler *
const handler[] = {
5008 AirportTilesChangeInfo,
5013 static_assert(GSF_END == std::size(handler));
5015 uint8_t feature = buf.ReadByte();
5016 uint8_t numprops = buf.ReadByte();
5017 uint numinfo = buf.ReadByte();
5018 uint engine = buf.ReadExtendedByte();
5020 if (feature >= GSF_END) {
5021 GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
5025 GrfMsg(6,
"FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
5026 feature, numprops, engine, numinfo);
5028 if (handler[feature] ==
nullptr) {
5029 if (feature != GSF_CARGOES) GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
5036 while (numprops-- && buf.HasData()) {
5037 uint8_t prop = buf.ReadByte();
5039 ChangeInfoResult cir = handler[feature](engine, engine + numinfo, prop, buf);
5040 if (HandleChangeInfoResult(
"FeatureChangeInfo", cir, feature, prop))
return;
5047 uint8_t feature = buf.ReadByte();
5048 uint8_t numprops = buf.ReadByte();
5049 uint numinfo = buf.ReadByte();
5050 buf.ReadExtendedByte();
5052 if (feature == GSF_BRIDGES && numprops == 1) {
5053 uint8_t prop = buf.ReadByte();
5056 if (prop == 0x0D)
return;
5057 }
else if (feature == GSF_GLOBALVAR && numprops == 1) {
5058 uint8_t prop = buf.ReadByte();
5061 bool is_safe =
true;
5062 for (uint i = 0; i < numinfo; i++) {
5063 uint32_t s = buf.ReadDWord();
5071 if (is_safe)
return;
5082static void ReserveChangeInfo(
ByteReader &buf)
5084 uint8_t feature = buf.ReadByte();
5086 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES)
return;
5088 uint8_t numprops = buf.ReadByte();
5089 uint8_t numinfo = buf.ReadByte();
5090 uint16_t index = buf.ReadExtendedByte();
5092 while (numprops-- && buf.HasData()) {
5093 uint8_t prop = buf.ReadByte();
5097 default: NOT_REACHED();
5103 cir = GlobalVarReserveInfo(index, index + numinfo, prop, buf);
5107 cir = RailTypeReserveInfo(index, index + numinfo, prop, buf);
5111 cir = RoadTypeReserveInfo(index, index + numinfo, prop, buf);
5115 cir = TramTypeReserveInfo(index, index + numinfo, prop, buf);
5119 if (HandleChangeInfoResult(
"ReserveChangeInfo", cir, feature, prop))
return;
5140 uint8_t feature = buf.ReadByte();
5141 uint16_t num_sets = buf.ReadByte();
5142 uint16_t first_set = 0;
5144 if (num_sets == 0 && buf.HasData(3)) {
5147 first_set = buf.ReadExtendedByte();
5148 num_sets = buf.ReadExtendedByte();
5150 uint16_t num_ents = buf.ReadExtendedByte();
5152 if (feature >= GSF_END) {
5154 GrfMsg(1,
"NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.
skip_sprites);
5160 GrfMsg(7,
"New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
5161 _cur.
spriteid, feature, num_sets, num_ents, num_sets * num_ents
5164 for (
int i = 0; i < num_sets * num_ents; i++) {
5174 uint16_t num_sets = buf.ReadByte();
5176 if (num_sets == 0 && buf.HasData(3)) {
5179 buf.ReadExtendedByte();
5180 num_sets = buf.ReadExtendedByte();
5182 uint16_t num_ents = buf.ReadExtendedByte();
5186 GrfMsg(3,
"SkipAct1: Skipping {} sprites", _cur.
skip_sprites);
5189using CachedCallback = std::pair<uint16_t, SpriteGroupID>;
5192static const SpriteGroup *GetCallbackResultGroup(uint16_t value)
5196 if (_cur.
grffile->grf_version < 8 &&
GB(value, 8, 8) == 0xFF) {
5215static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5217 if (
HasBit(groupid, 15))
return GetCallbackResultGroup(groupid);
5219 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5220 GrfMsg(1,
"GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
5224 return _cur.spritegroups[groupid];
5237 if (
HasBit(spriteid, 15))
return GetCallbackResultGroup(spriteid);
5240 GrfMsg(1,
"CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5245 uint num_sprites = _cur.
GetNumEnts(feature, spriteid);
5248 assert(spriteset_start + num_sprites <= _cur.
spriteid);
5269 uint8_t feature = buf.ReadByte();
5270 if (feature >= GSF_END) {
5271 GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5275 uint8_t setid = buf.ReadByte();
5276 uint8_t type = buf.ReadByte();
5300 switch (
GB(type, 2, 2)) {
5301 default: NOT_REACHED();
5302 case 0: group->size = DSG_SIZE_BYTE; varsize = 1;
break;
5303 case 1: group->size = DSG_SIZE_WORD; varsize = 2;
break;
5304 case 2: group->size = DSG_SIZE_DWORD; varsize = 4;
break;
5314 adjust.variable = buf.ReadByte();
5315 if (adjust.variable == 0x7E) {
5317 adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5322 varadjust = buf.ReadByte();
5323 adjust.shift_num =
GB(varadjust, 0, 5);
5324 adjust.type = (DeterministicSpriteGroupAdjustType)
GB(varadjust, 6, 2);
5325 adjust.and_mask = buf.ReadVarSize(varsize);
5327 if (adjust.type != DSGA_TYPE_NONE) {
5328 adjust.add_val = buf.ReadVarSize(varsize);
5329 adjust.divmod_val = buf.ReadVarSize(varsize);
5330 if (adjust.divmod_val == 0) adjust.divmod_val = 1;
5333 adjust.divmod_val = 0;
5337 }
while (
HasBit(varadjust, 5));
5339 std::vector<DeterministicSpriteGroupRange> ranges;
5340 ranges.resize(buf.ReadByte());
5341 for (
auto &range : ranges) {
5342 range.group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5343 range.low = buf.ReadVarSize(varsize);
5344 range.high = buf.ReadVarSize(varsize);
5347 group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5348 group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5350 group->calculated_result = ranges.empty();
5353 std::vector<uint32_t> bounds;
5354 bounds.reserve(ranges.size());
5355 for (
const auto &range : ranges) {
5356 bounds.push_back(range.low);
5357 if (range.high != UINT32_MAX) bounds.push_back(range.high + 1);
5359 std::sort(bounds.begin(), bounds.end());
5360 bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5362 std::vector<const SpriteGroup *> target;
5363 target.reserve(bounds.size());
5364 for (
const auto &bound : bounds) {
5366 for (
const auto &range : ranges) {
5367 if (range.low <= bound && bound <= range.high) {
5372 target.push_back(t);
5374 assert(target.size() == bounds.size());
5376 for (uint j = 0; j < bounds.size(); ) {
5377 if (target[j] != group->default_group) {
5379 r.group = target[j];
5381 while (j < bounds.size() && target[j] == r.group) {
5384 r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5406 group->count = buf.ReadByte();
5409 uint8_t triggers = buf.ReadByte();
5410 group->triggers =
GB(triggers, 0, 7);
5411 group->
cmp_mode =
HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
5414 uint8_t num_groups = buf.ReadByte();
5416 GrfMsg(1,
"NewSpriteGroup: Random Action 2 nrand should be power of 2");
5419 group->
groups.reserve(num_groups);
5420 for (uint i = 0; i < num_groups; i++) {
5421 group->
groups.push_back(GetGroupFromGroupID(setid, type, buf.ReadWord()));
5432 case GSF_ROADVEHICLES:
5443 uint8_t num_loaded = type;
5444 uint8_t num_loading = buf.ReadByte();
5447 GrfMsg(0,
"NewSpriteGroup: No sprite set to work on! Skipping");
5451 GrfMsg(6,
"NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5452 setid, num_loaded, num_loading);
5454 if (num_loaded + num_loading == 0) {
5455 GrfMsg(1,
"NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5459 if (num_loaded + num_loading == 1) {
5461 uint16_t spriteid = buf.ReadWord();
5463 GrfMsg(8,
"NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5467 std::vector<uint16_t> loaded;
5468 std::vector<uint16_t> loading;
5470 loaded.reserve(num_loaded);
5471 for (uint i = 0; i < num_loaded; i++) {
5472 loaded.push_back(buf.ReadWord());
5473 GrfMsg(8,
"NewSpriteGroup: + rg->loaded[{}] = subset {}", i, loaded[i]);
5476 loading.reserve(num_loading);
5477 for (uint i = 0; i < num_loading; i++) {
5478 loading.push_back(buf.ReadWord());
5479 GrfMsg(8,
"NewSpriteGroup: + rg->loading[{}] = subset {}", i, loading[i]);
5482 bool loaded_same = !loaded.empty() && std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end();
5483 bool loading_same = !loading.empty() && std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end();
5484 if (loaded_same && loading_same && loaded[0] == loading[0]) {
5487 GrfMsg(8,
"NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5496 if (loaded_same && loaded.size() > 1) loaded.resize(1);
5497 group->
loaded.reserve(loaded.size());
5498 for (uint16_t spriteid : loaded) {
5500 group->
loaded.push_back(t);
5503 if (loading_same && loading.size() > 1) loading.resize(1);
5504 group->
loading.reserve(loading.size());
5505 for (uint16_t spriteid : loading) {
5514 case GSF_AIRPORTTILES:
5516 case GSF_INDUSTRYTILES:
5517 case GSF_ROADSTOPS: {
5518 uint8_t num_building_sprites = std::max((uint8_t)1, type);
5526 if (
ReadSpriteLayout(buf, num_building_sprites,
true, feature,
false, type == 0, &group->dts))
return;
5530 case GSF_INDUSTRIES: {
5532 GrfMsg(1,
"NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5550 group->again = buf.ReadByte();
5551 }
else if (type == 1) {
5560 group->again = buf.ReadByte();
5561 }
else if (type == 2) {
5565 error->
data =
"too many inputs (max 16)";
5568 for (uint i = 0; i < group->
num_input; i++) {
5569 uint8_t rawcargo = buf.ReadByte();
5578 error->
data =
"duplicate input cargo";
5587 error->
data =
"too many outputs (max 16)";
5590 for (uint i = 0; i < group->
num_output; i++) {
5591 uint8_t rawcargo = buf.ReadByte();
5598 error->
data =
"duplicate output cargo";
5604 group->again = buf.ReadByte();
5612 default: GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5617 _cur.spritegroups[setid] = act_group;
5637static CargoType TranslateCargo(uint8_t feature, uint8_t ctype)
5646 if (ctype >= cargo_list.size()) {
5647 GrfMsg(1,
"TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (
unsigned int)_cur.
grffile->
cargo_list.size() - 1);
5648 return INVALID_CARGO;
5654 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5655 return INVALID_CARGO;
5658 CargoType cargo_type = GetCargoTypeByLabel(cl);
5660 GrfMsg(5,
"TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' unsupported, skipping.",
GB(cl.base(), 24, 8),
GB(cl.base(), 16, 8),
GB(cl.base(), 8, 8),
GB(cl.base(), 0, 8));
5661 return INVALID_CARGO;
5664 GrfMsg(6,
"TranslateCargo: Cargo '{:c}{:c}{:c}{:c}' mapped to cargo type {}.",
GB(cl.base(), 24, 8),
GB(cl.base(), 16, 8),
GB(cl.base(), 8, 8),
GB(cl.base(), 0, 8), cargo_type);
5669static bool IsValidGroupID(uint16_t groupid,
const char *function)
5671 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5672 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
5679static void VehicleMapSpriteGroup(
ByteReader &buf, uint8_t feature, uint8_t idcount)
5681 static std::vector<EngineID> last_engines;
5682 bool wagover =
false;
5685 if (
HasBit(idcount, 7)) {
5688 idcount =
GB(idcount, 0, 7);
5690 if (last_engines.empty()) {
5691 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5695 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5697 last_engines.resize(idcount);
5700 std::vector<EngineID> engines;
5701 engines.reserve(idcount);
5702 for (uint i = 0; i < idcount; i++) {
5708 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, 0, 0);
5712 engines.push_back(e->
index);
5713 if (!wagover) last_engines[i] = engines[i];
5716 uint8_t cidcount = buf.ReadByte();
5717 for (uint c = 0; c < cidcount; c++) {
5718 uint8_t ctype = buf.ReadByte();
5719 uint16_t groupid = buf.ReadWord();
5720 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
5722 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5724 CargoType cargo_type = TranslateCargo(feature, ctype);
5727 for (uint i = 0; i < idcount; i++) {
5730 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5733 SetWagonOverrideSprites(engine, cargo_type, _cur.spritegroups[groupid], last_engines);
5735 SetCustomEngineSprites(engine, cargo_type, _cur.spritegroups[groupid]);
5740 uint16_t groupid = buf.ReadWord();
5741 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
5743 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
5745 for (uint i = 0; i < idcount; i++) {
5758static void CanalMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5760 std::vector<uint16_t> cfs;
5761 cfs.reserve(idcount);
5762 for (uint i = 0; i < idcount; i++) {
5763 cfs.push_back(buf.ReadExtendedByte());
5766 uint8_t cidcount = buf.ReadByte();
5767 buf.Skip(cidcount * 3);
5769 uint16_t groupid = buf.ReadWord();
5770 if (!IsValidGroupID(groupid,
"CanalMapSpriteGroup"))
return;
5772 for (
auto &cf : cfs) {
5774 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5784static void StationMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5786 if (_cur.
grffile->stations.empty()) {
5787 GrfMsg(1,
"StationMapSpriteGroup: No stations defined, skipping");
5791 std::vector<uint16_t> stations;
5792 stations.reserve(idcount);
5793 for (uint i = 0; i < idcount; i++) {
5794 stations.push_back(buf.ReadExtendedByte());
5797 uint8_t cidcount = buf.ReadByte();
5798 for (uint c = 0; c < cidcount; c++) {
5799 uint8_t ctype = buf.ReadByte();
5800 uint16_t groupid = buf.ReadWord();
5801 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
continue;
5803 ctype = TranslateCargo(GSF_STATIONS, ctype);
5806 for (
auto &station : stations) {
5809 if (statspec ==
nullptr) {
5810 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5818 uint16_t groupid = buf.ReadWord();
5819 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
return;
5821 for (
auto &station : stations) {
5824 if (statspec ==
nullptr) {
5825 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5830 GrfMsg(1,
"StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
5843static void TownHouseMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5845 if (_cur.
grffile->housespec.empty()) {
5846 GrfMsg(1,
"TownHouseMapSpriteGroup: No houses defined, skipping");
5850 std::vector<uint16_t> houses;
5851 houses.reserve(idcount);
5852 for (uint i = 0; i < idcount; i++) {
5853 houses.push_back(buf.ReadExtendedByte());
5857 uint8_t cidcount = buf.ReadByte();
5858 buf.Skip(cidcount * 3);
5860 uint16_t groupid = buf.ReadWord();
5861 if (!IsValidGroupID(groupid,
"TownHouseMapSpriteGroup"))
return;
5863 for (
auto &house : houses) {
5866 if (hs ==
nullptr) {
5867 GrfMsg(1,
"TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
5875static void IndustryMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5877 if (_cur.
grffile->industryspec.empty()) {
5878 GrfMsg(1,
"IndustryMapSpriteGroup: No industries defined, skipping");
5882 std::vector<uint16_t> industries;
5883 industries.reserve(idcount);
5884 for (uint i = 0; i < idcount; i++) {
5885 industries.push_back(buf.ReadExtendedByte());
5889 uint8_t cidcount = buf.ReadByte();
5890 buf.Skip(cidcount * 3);
5892 uint16_t groupid = buf.ReadWord();
5893 if (!IsValidGroupID(groupid,
"IndustryMapSpriteGroup"))
return;
5895 for (
auto &industry : industries) {
5898 if (indsp ==
nullptr) {
5899 GrfMsg(1,
"IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
5907static void IndustrytileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5909 if (_cur.
grffile->indtspec.empty()) {
5910 GrfMsg(1,
"IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
5914 std::vector<uint16_t> indtiles;
5915 indtiles.reserve(idcount);
5916 for (uint i = 0; i < idcount; i++) {
5917 indtiles.push_back(buf.ReadExtendedByte());
5921 uint8_t cidcount = buf.ReadByte();
5922 buf.Skip(cidcount * 3);
5924 uint16_t groupid = buf.ReadWord();
5925 if (!IsValidGroupID(groupid,
"IndustrytileMapSpriteGroup"))
return;
5927 for (
auto &indtile : indtiles) {
5930 if (indtsp ==
nullptr) {
5931 GrfMsg(1,
"IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
5939static void CargoMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5941 std::vector<uint16_t> cargoes;
5942 cargoes.reserve(idcount);
5943 for (uint i = 0; i < idcount; i++) {
5944 cargoes.push_back(buf.ReadExtendedByte());
5948 uint8_t cidcount = buf.ReadByte();
5949 buf.Skip(cidcount * 3);
5951 uint16_t groupid = buf.ReadWord();
5952 if (!IsValidGroupID(groupid,
"CargoMapSpriteGroup"))
return;
5954 for (
auto &cargo_type : cargoes) {
5956 GrfMsg(1,
"CargoMapSpriteGroup: Cargo type {} out of range, skipping", cargo_type);
5962 cs->group = _cur.spritegroups[groupid];
5966static void ObjectMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5968 if (_cur.
grffile->objectspec.empty()) {
5969 GrfMsg(1,
"ObjectMapSpriteGroup: No object tiles defined, skipping");
5973 std::vector<uint16_t> objects;
5974 objects.reserve(idcount);
5975 for (uint i = 0; i < idcount; i++) {
5976 objects.push_back(buf.ReadExtendedByte());
5979 uint8_t cidcount = buf.ReadByte();
5980 for (uint c = 0; c < cidcount; c++) {
5981 uint8_t ctype = buf.ReadByte();
5982 uint16_t groupid = buf.ReadWord();
5983 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
continue;
5986 if (ctype != 0xFF) {
5987 GrfMsg(1,
"ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
5991 for (
auto &
object : objects) {
5994 if (spec ==
nullptr) {
5995 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
6003 uint16_t groupid = buf.ReadWord();
6004 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
return;
6006 for (
auto &
object : objects) {
6009 if (spec ==
nullptr) {
6010 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
6015 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} mapped multiple times, skipping",
object);
6026static void RailTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6028 std::vector<uint8_t> railtypes;
6029 railtypes.reserve(idcount);
6030 for (uint i = 0; i < idcount; i++) {
6031 uint16_t
id = buf.ReadExtendedByte();
6032 railtypes.push_back(id < RAILTYPE_END ? _cur.grffile->railtype_map[
id] :
INVALID_RAILTYPE);
6035 uint8_t cidcount = buf.ReadByte();
6036 for (uint c = 0; c < cidcount; c++) {
6037 uint8_t ctype = buf.ReadByte();
6038 uint16_t groupid = buf.ReadWord();
6039 if (!IsValidGroupID(groupid,
"RailTypeMapSpriteGroup"))
continue;
6041 if (ctype >= RTSG_END)
continue;
6044 for (
auto &railtype : railtypes) {
6049 rti->
group[ctype] = _cur.spritegroups[groupid];
6058static void RoadTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount, RoadTramType rtt)
6060 std::array<RoadType, ROADTYPE_END> &type_map = (rtt == RTT_TRAM) ? _cur.
grffile->tramtype_map : _cur.grffile->roadtype_map;
6062 std::vector<uint8_t> roadtypes;
6063 roadtypes.reserve(idcount);
6064 for (uint i = 0; i < idcount; i++) {
6065 uint16_t
id = buf.ReadExtendedByte();
6069 uint8_t cidcount = buf.ReadByte();
6070 for (uint c = 0; c < cidcount; c++) {
6071 uint8_t ctype = buf.ReadByte();
6072 uint16_t groupid = buf.ReadWord();
6073 if (!IsValidGroupID(groupid,
"RoadTypeMapSpriteGroup"))
continue;
6075 if (ctype >= ROTSG_END)
continue;
6078 for (
auto &roadtype : roadtypes) {
6083 rti->
group[ctype] = _cur.spritegroups[groupid];
6092static void AirportMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6094 if (_cur.
grffile->airportspec.empty()) {
6095 GrfMsg(1,
"AirportMapSpriteGroup: No airports defined, skipping");
6099 std::vector<uint16_t> airports;
6100 airports.reserve(idcount);
6101 for (uint i = 0; i < idcount; i++) {
6102 airports.push_back(buf.ReadExtendedByte());
6106 uint8_t cidcount = buf.ReadByte();
6107 buf.Skip(cidcount * 3);
6109 uint16_t groupid = buf.ReadWord();
6110 if (!IsValidGroupID(groupid,
"AirportMapSpriteGroup"))
return;
6112 for (
auto &airport : airports) {
6115 if (as ==
nullptr) {
6116 GrfMsg(1,
"AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6124static void AirportTileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6126 if (_cur.
grffile->airtspec.empty()) {
6127 GrfMsg(1,
"AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6131 std::vector<uint16_t> airptiles;
6132 airptiles.reserve(idcount);
6133 for (uint i = 0; i < idcount; i++) {
6134 airptiles.push_back(buf.ReadExtendedByte());
6138 uint8_t cidcount = buf.ReadByte();
6139 buf.Skip(cidcount * 3);
6141 uint16_t groupid = buf.ReadWord();
6142 if (!IsValidGroupID(groupid,
"AirportTileMapSpriteGroup"))
return;
6144 for (
auto &airptile : airptiles) {
6147 if (airtsp ==
nullptr) {
6148 GrfMsg(1,
"AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6156static void RoadStopMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6158 if (_cur.
grffile->roadstops.empty()) {
6159 GrfMsg(1,
"RoadStopMapSpriteGroup: No roadstops defined, skipping");
6163 std::vector<uint16_t> roadstops;
6164 roadstops.reserve(idcount);
6165 for (uint i = 0; i < idcount; i++) {
6166 roadstops.push_back(buf.ReadExtendedByte());
6169 uint8_t cidcount = buf.ReadByte();
6170 for (uint c = 0; c < cidcount; c++) {
6171 uint8_t ctype = buf.ReadByte();
6172 uint16_t groupid = buf.ReadWord();
6173 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
continue;
6175 ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6178 for (
auto &roadstop : roadstops) {
6181 if (roadstopspec ==
nullptr) {
6182 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6190 uint16_t groupid = buf.ReadWord();
6191 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
return;
6193 for (
auto &roadstop : roadstops) {
6196 if (roadstopspec ==
nullptr) {
6197 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6202 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6215static void FeatureMapSpriteGroup(
ByteReader &buf)
6231 uint8_t feature = buf.ReadByte();
6232 uint8_t idcount = buf.ReadByte();
6234 if (feature >= GSF_END) {
6235 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6243 uint16_t groupid = buf.ReadWord();
6244 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
6246 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6255 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6259 case GSF_ROADVEHICLES:
6262 VehicleMapSpriteGroup(buf, feature, idcount);
6266 CanalMapSpriteGroup(buf, idcount);
6270 StationMapSpriteGroup(buf, idcount);
6274 TownHouseMapSpriteGroup(buf, idcount);
6277 case GSF_INDUSTRIES:
6278 IndustryMapSpriteGroup(buf, idcount);
6281 case GSF_INDUSTRYTILES:
6282 IndustrytileMapSpriteGroup(buf, idcount);
6286 CargoMapSpriteGroup(buf, idcount);
6290 AirportMapSpriteGroup(buf, idcount);
6294 ObjectMapSpriteGroup(buf, idcount);
6298 RailTypeMapSpriteGroup(buf, idcount);
6302 RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6306 RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6309 case GSF_AIRPORTTILES:
6310 AirportTileMapSpriteGroup(buf, idcount);
6314 RoadStopMapSpriteGroup(buf, idcount);
6318 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6342 bool new_scheme = _cur.
grffile->grf_version >= 7;
6344 uint8_t feature = buf.ReadByte();
6345 if (feature >= GSF_END && feature != 0x48) {
6346 GrfMsg(1,
"FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6350 uint8_t lang = buf.ReadByte();
6351 uint8_t num = buf.ReadByte();
6352 bool generic =
HasBit(lang, 7);
6355 id = buf.ReadWord();
6356 }
else if (feature <= GSF_AIRCRAFT) {
6357 id = buf.ReadExtendedByte();
6359 id = buf.ReadByte();
6364 uint16_t endid =
id + num;
6366 GrfMsg(6,
"FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6367 id, endid, feature, lang);
6369 for (;
id < endid && buf.HasData();
id++) {
6370 const std::string_view name = buf.ReadString();
6371 GrfMsg(8,
"FeatureNewName: 0x{:04X} <- {}",
id,
StrMakeValid(name));
6375 case GSF_ROADVEHICLES:
6380 if (e ==
nullptr)
break;
6394 switch (
GB(
id, 8, 8)) {
6396 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6397 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6405 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6406 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6413 if (
GB(
id, 0, 8) >= _cur.
grffile->airtspec.size() || _cur.
grffile->airtspec[
GB(
id, 0, 8)] ==
nullptr) {
6414 GrfMsg(1,
"FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring",
GB(
id, 0, 8));
6421 if (
GB(
id, 0, 8) >= _cur.
grffile->housespec.size() || _cur.
grffile->housespec[
GB(
id, 0, 8)] ==
nullptr) {
6422 GrfMsg(1,
"FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.",
GB(
id, 0, 8));
6429 GrfMsg(7,
"FeatureNewName: Unsupported ID (0x{:04X})",
id);
6448 if (offset >= max_sprites) {
6449 GrfMsg(1,
"GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6450 uint orig_num = num;
6455 if (offset + num > max_sprites) {
6456 GrfMsg(4,
"GraphicsNew: {} sprite overflow, truncating...", name);
6457 uint orig_num = num;
6458 num = std::max(max_sprites - offset, 0);
6459 return orig_num - num;
6473 {
A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT,
"Signal graphics" },
6475 {
A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT,
"Foundation graphics" },
6515 uint8_t type = buf.ReadByte();
6516 uint16_t num = buf.ReadExtendedByte();
6517 uint16_t offset =
HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6523 GrfMsg(2,
"GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6540 GrfMsg(2,
"GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6551 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->
name, type);
6558 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->
name, type, action5_type->
min_sprites, num);
6568 GrfMsg(2,
"GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->
name, type, replace);
6580 bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= ONEWAY_SLOPE_N_OFFSET));
6582 for (; num > 0; num--) {
6586 if (dup_oneway_sprites) {
6587 DupSprite(load_index, load_index + ONEWAY_SLOPE_N_OFFSET);
6588 DupSprite(load_index, load_index + ONEWAY_SLOPE_S_OFFSET);
6604 GrfMsg(3,
"SkipAct5: Skipping {} sprites", _cur.
skip_sprites);
6657 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6687 *value = _game_mode;
6721 *value =
Clamp(snowline * (grffile->grf_version >= 8 ? 1 :
TILE_HEIGHT), 0, 0xFE);
6730 *value = _openttd_newgrf_version;
6745 default:
return false;
6749static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
6768 if (cond_val ==
nullptr) {
6772 uint32_t index = *cond_val / 0x20;
6788 GrfMsg(1,
"Unsupported in-game variable 0x{:02X}", param);
6809 size_t pos = file.
GetPos();
6815 GrfMsg(2,
"CfgApply: Ignoring (next sprite is real, unsupported)");
6818 file.
SeekTo(pos, SEEK_SET);
6824 std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
6827 if (preload_sprite.empty()) {
6828 preload_sprite.resize(num);
6829 file.
ReadBlock(preload_sprite.data(), num);
6833 file.
SeekTo(pos, SEEK_SET);
6844 param_num = buf.ReadByte();
6845 if (param_num == 0xFF)
break;
6849 param_size = buf.ReadByte();
6853 add_value =
HasBit(param_size, 7);
6854 param_size =
GB(param_size, 0, 7);
6857 offset = buf.ReadExtendedByte();
6861 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= std::size(_cur.
grffile->param)) {
6862 GrfMsg(2,
"CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
6866 GrfMsg(8,
"CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
6869 for (i = 0; i < param_size && offset + i < num; i++) {
6870 uint32_t value = GetParamVal(param_num + i / 4,
nullptr);
6873 if (i % 4 == 0) carry =
false;
6876 uint new_value = preload_sprite[offset + i] +
GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
6877 preload_sprite[offset + i] =
GB(new_value, 0, 8);
6879 carry = new_value >= 256;
6881 preload_sprite[offset + i] =
GB(value, (i % 4) * 8, 8);
6913 uint32_t cond_val = 0;
6917 uint8_t param = buf.ReadByte();
6918 uint8_t paramsize = buf.ReadByte();
6919 uint8_t condtype = buf.ReadByte();
6926 switch (paramsize) {
6927 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord();
break;
6928 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF;
break;
6929 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF;
break;
6930 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF;
break;
6934 if (param < 0x80 && std::size(_cur.
grffile->param) <= param) {
6935 GrfMsg(7,
"SkipIf: Param {} undefined, skipping test", param);
6939 GrfMsg(7,
"SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
6944 if (condtype >= 0x0B) {
6975 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6977 }
else if (param == 0x88) {
6987 if (condtype != 10 && c ==
nullptr) {
6988 GrfMsg(7,
"SkipIf: GRFID 0x{:08X} unknown, skipping test", std::byteswap(cond_val));
7015 default: GrfMsg(1,
"SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype);
return;
7019 uint32_t param_val = GetParamVal(param, &cond_val);
7021 case 0x00: result = !!(param_val & (1 << cond_val));
7023 case 0x01: result = !(param_val & (1 << cond_val));
7025 case 0x02: result = (param_val & mask) == cond_val;
7027 case 0x03: result = (param_val & mask) != cond_val;
7029 case 0x04: result = (param_val & mask) < cond_val;
7031 case 0x05: result = (param_val & mask) > cond_val;
7033 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
7038 GrfMsg(2,
"SkipIf: Not skipping sprites, test was false");
7042 uint8_t numsprites = buf.ReadByte();
7049 for (
const auto &label : _cur.grffile->labels) {
7050 if (label.label != numsprites)
continue;
7053 if (choice ==
nullptr) choice = &label;
7055 if (label.nfo_line > _cur.
nfo_line) {
7061 if (choice !=
nullptr) {
7062 GrfMsg(2,
"SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
7068 GrfMsg(2,
"SkipIf: Skipping {} sprites, test was true", numsprites);
7087 uint8_t grf_version = buf.ReadByte();
7088 uint32_t grfid = buf.ReadDWord();
7089 std::string_view name = buf.ReadString();
7093 if (grf_version < 2 || grf_version > 8) {
7095 Debug(grf, 0,
"{}: NewGRF \"{}\" (GRFID {:08X}) uses GRF version {}, which is incompatible with this version of OpenTTD.", _cur.
grfconfig->
filename,
StrMakeValid(name), std::byteswap(grfid), grf_version);
7103 if (buf.HasData()) {
7104 std::string_view info = buf.ReadString();
7122 uint8_t version = buf.ReadByte();
7123 uint32_t grfid = buf.ReadDWord();
7124 std::string_view name = buf.ReadString();
7127 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7131 if (_cur.
grffile->grfid != grfid) {
7132 Debug(grf, 0,
"GRFInfo: GRFID {:08X} in FILESCAN stage does not match GRFID {:08X} in INIT/RESERVE/ACTIVATION stage", std::byteswap(_cur.
grffile->grfid), std::byteswap(grfid));
7136 _cur.
grffile->grf_version = version;
7151 for (
const auto &grm_sprite : _grm_sprites) {
7152 if (grm_sprite.first.grfid != _cur.
grffile->grfid)
continue;
7153 if (grm_sprite.second.first <= first_sprite && grm_sprite.second.first + grm_sprite.second.second >= first_sprite + num_sprites)
return true;
7169 uint8_t num_sets = buf.ReadByte();
7171 for (uint i = 0; i < num_sets; i++) {
7172 uint8_t num_sprites = buf.ReadByte();
7173 uint16_t first_sprite = buf.ReadWord();
7175 GrfMsg(2,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7176 i, num_sprites, first_sprite
7182 GrfMsg(0,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7191 for (uint j = 0; j < num_sprites; j++) {
7192 SpriteID load_index = first_sprite + j;
7198 if (
IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7208 uint8_t num_sets = buf.ReadByte();
7210 for (uint i = 0; i < num_sets; i++) {
7217 GrfMsg(3,
"SkipActA: Skipping {} sprites", _cur.
skip_sprites);
7239 STR_NEWGRF_ERROR_VERSION_NUMBER,
7240 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
7241 STR_NEWGRF_ERROR_UNSET_SWITCH,
7242 STR_NEWGRF_ERROR_INVALID_PARAMETER,
7243 STR_NEWGRF_ERROR_LOAD_BEFORE,
7244 STR_NEWGRF_ERROR_LOAD_AFTER,
7245 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
7249 STR_NEWGRF_ERROR_MSG_INFO,
7250 STR_NEWGRF_ERROR_MSG_WARNING,
7251 STR_NEWGRF_ERROR_MSG_ERROR,
7252 STR_NEWGRF_ERROR_MSG_FATAL
7255 uint8_t severity = buf.ReadByte();
7256 uint8_t lang = buf.ReadByte();
7257 uint8_t message_id = buf.ReadByte();
7260 if (!CheckGrfLangID(lang, _cur.
grffile->grf_version))
return;
7264 if (!
HasBit(severity, 7) && _cur.
stage == GLS_INIT) {
7265 GrfMsg(7,
"GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.
stage);
7270 if (severity >=
lengthof(sevstr)) {
7271 GrfMsg(7,
"GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7273 }
else if (severity == 3) {
7282 if (message_id >=
lengthof(msgstr) && message_id != 0xFF) {
7283 GrfMsg(7,
"GRFLoadError: Invalid message id.");
7287 if (buf.Remaining() <= 1) {
7288 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7298 if (message_id == 0xFF) {
7300 if (buf.HasData()) {
7301 std::string_view message = buf.ReadString();
7305 GrfMsg(7,
"GRFLoadError: No custom message supplied.");
7309 error->
message = msgstr[message_id];
7312 if (buf.HasData()) {
7313 std::string_view data = buf.ReadString();
7317 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7318 error->
data.clear();
7322 for (uint i = 0; i < error->
param_value.size() && buf.HasData(); i++) {
7323 uint param_number = buf.ReadByte();
7335 if (!buf.HasData())
return;
7337 std::string_view text = buf.ReadString();
7344 uint8_t target = buf.ReadByte();
7347 if (target < 0x80 || target == 0x9E)
return;
7361static uint32_t GetPatchVariable(uint8_t param)
7371 case 0x0F:
return 0;
7387 case 0x11:
return SPR_2CCMAP_BASE;
7401 uint8_t map_bits = 0;
7404 uint8_t max_edge = std::max(log_X, log_Y);
7406 if (log_X == log_Y) {
7409 if (max_edge == log_Y)
SetBit(map_bits, 1);
7412 return (map_bits << 24) | (std::min(log_X, log_Y) << 20) | (max_edge << 16) |
7413 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
7422 return SPR_SLOPES_BASE;
7433 GrfMsg(2,
"ParamSet: Unknown Patch variable 0x{:02X}.", param);
7439static uint32_t PerformGRM(uint32_t *grm, uint16_t num_ids, uint16_t count, uint8_t op, uint8_t target,
const char *type)
7452 for (uint i = start; i < num_ids; i++) {
7456 if (op == 2 || op == 3)
break;
7461 if (size == count)
break;
7464 if (size == count) {
7466 if (op == 0 || op == 3) {
7467 GrfMsg(2,
"ParamSet: GRM: Reserving {} {} at {}", count, type, start);
7468 for (uint i = 0; i < count; i++) grm[start + i] = _cur.
grffile->grfid;
7474 if (op != 4 && op != 5) {
7476 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7481 GrfMsg(1,
"ParamSet: GRM: Unable to allocate {} {}", count, type);
7511 uint8_t target = buf.ReadByte();
7512 uint8_t oper = buf.ReadByte();
7513 uint32_t src1 = buf.ReadByte();
7514 uint32_t src2 = buf.ReadByte();
7517 if (buf.Remaining() >= 4) data = buf.ReadDWord();
7526 if (target < 0x80 && target < std::size(_cur.
grffile->param)) {
7527 GrfMsg(7,
"ParamSet: Param {} already defined, skipping", target);
7531 oper =
GB(oper, 0, 7);
7535 if (
GB(data, 0, 8) == 0xFF) {
7536 if (data == 0x0000FFFF) {
7538 src1 = GetPatchVariable(src1);
7542 uint8_t feature =
GB(data, 8, 8);
7543 uint16_t count =
GB(data, 16, 16);
7545 if (_cur.
stage == GLS_RESERVE) {
7546 if (feature == 0x08) {
7550 if (_cur.
spriteid + count >= 16384) {
7551 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7557 GrfMsg(4,
"ParamSet: GRM: Allocated {} sprites at {}", count, _cur.
spriteid);
7564 }
else if (_cur.
stage == GLS_ACTIVATION) {
7593 GrfMsg(4,
"ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7601 GrfMsg(1,
"ParamSet: GRM: Unsupported operation {} for general sprites", op);
7612 default: GrfMsg(1,
"ParamSet: GRM: Unsupported feature 0x{:X}", feature);
return;
7629 }
else if (src1 == 0xFE) {
7641 src1 = (src1 == 0xFF) ? data : GetParamVal(src1,
nullptr);
7642 src2 = (src2 == 0xFF) ? data : GetParamVal(src2,
nullptr);
7664 res = (int32_t)src1 * (int32_t)src2;
7668 if ((int32_t)src2 < 0) {
7669 res = src1 >> -(int32_t)src2;
7671 res = src1 << (src2 & 0x1F);
7676 if ((int32_t)src2 < 0) {
7677 res = (int32_t)src1 >> -(int32_t)src2;
7679 res = (int32_t)src1 << (src2 & 0x1F);
7703 res = (int32_t)src1 / (int32_t)src2;
7719 res = (int32_t)src1 % (int32_t)src2;
7723 default: GrfMsg(0,
"ParamSet: Unknown operation {}, skipping", oper);
return;
7752 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7763 uint32_t safe_bits = 0;
7764 SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
7773 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7777 if (target < 0x80) {
7779 if (target >= std::size(_cur.
grffile->param)) _cur.
grffile->param.resize(target + 1);
7780 _cur.
grffile->param[target] = res;
7782 GrfMsg(7,
"ParamSet: Skipping unknown target 0x{:02X}", target);
7796 uint8_t num = buf.ReadByte();
7798 for (uint i = 0; i < num; i++) {
7799 uint32_t grfid = buf.ReadDWord();
7821 uint8_t num = buf.ReadByte();
7823 for (uint i = 0; i < num; i++) {
7824 uint32_t grfid = buf.ReadDWord();
7828 if (file !=
nullptr && file != _cur.
grfconfig) {
7829 GrfMsg(2,
"GRFInhibit: Deactivating file '{}'", file->
filename);
7846 uint32_t grfid = _cur.
grffile->grfid;
7850 uint8_t
id = buf.ReadByte();
7851 GrfMsg(6,
"FeatureTownName: definition 0x{:02X}",
id & 0x7F);
7856 bool new_scheme = _cur.
grffile->grf_version >= 7;
7858 uint8_t lang = buf.ReadByte();
7864 std::string_view name = buf.ReadString();
7867 GrfMsg(6,
"FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
7871 lang = buf.ReadByte();
7872 }
while (lang != 0);
7873 townname->
styles.emplace_back(style,
id);
7876 uint8_t parts = buf.ReadByte();
7877 GrfMsg(6,
"FeatureTownName: {} parts", parts);
7880 for (uint partnum = 0; partnum < parts; partnum++) {
7882 uint8_t texts = buf.ReadByte();
7883 partlist.
bitstart = buf.ReadByte();
7884 partlist.
bitcount = buf.ReadByte();
7886 GrfMsg(6,
"FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.
bitstart, partlist.
bitcount);
7888 partlist.
parts.reserve(texts);
7889 for (uint textnum = 0; textnum < texts; textnum++) {
7891 part.
prob = buf.ReadByte();
7894 uint8_t ref_id = buf.ReadByte();
7896 GrfMsg(0,
"FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
7897 DelGRFTownName(grfid);
7902 GrfMsg(6,
"FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.
prob & 0x7F);
7904 std::string_view text = buf.ReadString();
7906 GrfMsg(6,
"FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.
text, part.
prob);
7910 GrfMsg(6,
"FeatureTownName: part {}, total probability {}", partnum, partlist.
maxprob);
7922 uint8_t nfo_label = buf.ReadByte();
7926 GrfMsg(2,
"DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
7940 if (file ==
nullptr || file->sound_offset == 0) {
7941 GrfMsg(1,
"ImportGRFSound: Source file not available");
7945 if (sound_id >= file->num_sounds) {
7946 GrfMsg(1,
"ImportGRFSound: Sound effect {} is invalid", sound_id);
7950 GrfMsg(2,
"ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
7952 *sound = *GetSound(file->sound_offset + sound_id);
7955 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7956 sound->priority = 0;
7967 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7968 sound->priority = 0;
7970 if (offs != SIZE_MAX) {
7972 sound->file = _cur.
file;
7973 sound->file_offset = offs;
7974 sound->source = SoundSource::NewGRF;
7986 uint16_t num = buf.ReadWord();
7987 if (num == 0)
return;
7990 if (_cur.
grffile->sound_offset == 0) {
7991 _cur.
grffile->sound_offset = GetNumSounds();
7992 _cur.
grffile->num_sounds = num;
7995 sound = GetSound(_cur.
grffile->sound_offset);
8000 for (
int i = 0; i < num; i++) {
8005 bool invalid = i >= _cur.
grffile->num_sounds;
8007 size_t offs = file.
GetPos();
8012 if (grf_container_version >= 2 && type == 0xFD) {
8015 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
8017 }
else if (len != 4) {
8018 GrfMsg(1,
"GRFSound: Invalid sprite section import");
8028 GrfMsg(1,
"GRFSound: Unexpected RealSprite found, skipping");
8035 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
8043 if (_cur.
stage == GLS_INIT) {
8044 if (grf_container_version >= 2) {
8045 GrfMsg(1,
"GRFSound: Inline sounds are not supported for container version >= 2");
8054 if (_cur.
stage == GLS_ACTIVATION) {
8057 if (file.
ReadByte() != 0) GrfMsg(1,
"GRFSound: Import type mismatch");
8065 GrfMsg(1,
"GRFSound: Unexpected Action {:x} found, skipping", action);
8081 GrfMsg(3,
"SkipAct11: Skipping {} sprites", _cur.
skip_sprites);
8094 uint8_t num_def = buf.ReadByte();
8096 for (uint i = 0; i < num_def; i++) {
8098 uint8_t num_char = buf.ReadByte();
8099 uint16_t base_char = buf.ReadWord();
8101 if (size >= FS_END) {
8102 GrfMsg(1,
"LoadFontGlyph: Size {} is not supported, ignoring", size);
8105 GrfMsg(7,
"LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8107 for (uint c = 0; c < num_char; c++) {
8125 uint8_t num_def = buf.ReadByte();
8127 for (uint i = 0; i < num_def; i++) {
8138 GrfMsg(3,
"SkipAct12: Skipping {} sprites", _cur.
skip_sprites);
8151 uint32_t grfid = buf.ReadDWord();
8154 GrfMsg(7,
"TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13", std::byteswap(grfid));
8163 error->
data =
GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8173 uint8_t language = _cur.
grffile->grf_version >= 8 ? buf.ReadByte() : 0x7F;
8174 uint8_t num_strings = buf.ReadByte();
8175 uint16_t first_id = buf.ReadWord();
8177 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
8178 GrfMsg(7,
"TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
8182 for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8183 std::string_view
string = buf.ReadString();
8185 if (
string.empty()) {
8186 GrfMsg(7,
"TranslateGRFString: Ignoring empty string.");
8219 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8231 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8234 char data = buf.ReadByte();
8242 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8257 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8260 char data = buf.ReadByte();
8266 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8279 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8292 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8297 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8328 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8335 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8345 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8347 }
else if (len != 8) {
8348 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8351 uint32_t min_value = buf.ReadDWord();
8352 uint32_t max_value = buf.ReadDWord();
8353 if (min_value <= max_value) {
8357 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8366 if (len < 1 || len > 3) {
8367 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
8370 uint8_t param_nr = buf.ReadByte();
8371 if (param_nr >= GRFConfig::MAX_NUM_PARAMS) {
8372 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8388 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8410 using Span = std::pair<const AllowedSubtags *, const AllowedSubtags *>;
8413 std::variant<DataHandler, TextHandler, BranchHandler, Span>
handler;
8427 uint8_t type = buf.ReadByte();
8429 uint32_t
id = buf.ReadDWord();
8431 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8433 type = buf.ReadByte();
8437 uint8_t langid = buf.ReadByte();
8438 std::string_view name_string = buf.ReadString();
8446 type = buf.ReadByte();
8470 uint8_t type = buf.ReadByte();
8472 uint32_t
id = buf.ReadDWord();
8474 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8476 type = buf.ReadByte();
8489 type = buf.ReadByte();
8524 uint8_t new_type = buf.ReadByte();
8525 while (new_type != 0) {
8528 new_type = buf.ReadByte();
8539 uint16_t size = buf.ReadWord();
8562 struct type_visitor {
8563 char operator()(
const DataHandler &) {
return 'B'; }
8564 char operator()(
const TextHandler &) {
return 'T'; }
8570 struct evaluate_visitor {
8575 size_t len = buf.ReadWord();
8576 if (buf.Remaining() < len)
return false;
8577 return handler(len, buf);
8582 uint8_t langid = buf.ReadByte();
8583 return handler(langid, buf.ReadString());
8588 return handler(buf);
8593 return HandleNodes(buf, {subtags.first, subtags.second});
8597 for (
const auto &tag : subtags) {
8598 if (tag.id != std::byteswap(
id) || std::visit(type_visitor{}, tag.handler) != type)
continue;
8599 return std::visit(evaluate_visitor{buf}, tag.handler);
8602 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
8614 uint8_t type = buf.ReadByte();
8616 uint32_t
id = buf.ReadDWord();
8617 if (!
HandleNode(type,
id, buf, subtags))
return false;
8618 type = buf.ReadByte();
8739 file->stations.clear();
8747 file->housespec.clear();
8755 file->airportspec.clear();
8756 file->airtspec.clear();
8764 file->industryspec.clear();
8765 file->indtspec.clear();
8773 file->objectspec.clear();
8777static void ResetCustomRoadStops()
8780 file->roadstops.clear();
8809 CleanUpGRFTownNames();
8869 ResetCustomRoadStops();
8895 _grf_id_overrides.clear();
8897 InitializeSoundPool();
8927 if (!cs->IsValid())
continue;
8942 if (newfile !=
nullptr) {
8948 newfile =
new GRFFile(config);
8966 for (
Price i = PR_BEGIN; i < PR_END; i++) {
8986 this->param = config.
param;
8997 CargoType cargo_type = GetCargoTypeByLabel(label);
8998 if (cargo_type != INVALID_CARGO)
return label;
9018 default: NOT_REACHED();
9023 return std::visit(visitor{}, label);
9031 CargoTypes original_known_cargoes = 0;
9039 bool only_defaultcargo;
9047 if (
_gted[engine].defaultcargo_grf ==
nullptr) {
9050 static constexpr LandscapeType T = LandscapeType::Temperate;
9054 static const struct DefaultRefitMasks {
9059 } _default_refit_masks[] = {
9061 {{T, A, S }, CT_MAIL,
CC_MAIL, 0},
9064 {{T, A }, CT_COAL,
CC_BULK, 0},
9065 {{ S }, CT_COPPER_ORE,
CC_BULK, 0},
9081 switch (label.base()) {
9085 _gted[engine].cargo_disallowed = 0;
9090 _gted[engine].cargo_disallowed = 0;
9109 _gted[engine].cargo_disallowed = 0;
9113 for (
const auto &drm : _default_refit_masks) {
9115 if (drm.cargo_label != label)
continue;
9117 _gted[engine].cargo_allowed = drm.cargo_allowed;
9118 _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9123 _gted[engine].ctt_exclude_mask = original_known_cargoes;
9126 _gted[engine].UpdateRefittability(
_gted[engine].cargo_allowed != 0);
9133 CargoTypes mask = 0;
9134 CargoTypes not_mask = 0;
9135 CargoTypes xor_mask = ei->refit_mask;
9141 if (
_gted[engine].cargo_allowed != 0) {
9144 if ((
_gted[engine].cargo_allowed & cs->classes) != 0 && (
_gted[engine].cargo_allowed_required & cs->classes) ==
_gted[engine].cargo_allowed_required)
SetBit(mask, cs->Index());
9145 if (
_gted[engine].cargo_disallowed & cs->classes)
SetBit(not_mask, cs->Index());
9149 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) &
_cargo_mask;
9152 ei->refit_mask |=
_gted[engine].ctt_include_mask;
9153 ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
9157 if (file ==
nullptr) file = e->
GetGRF();
9160 uint8_t local_slot = file->
cargo_map[cs->Index()];
9166 case 1:
SetBit(ei->refit_mask, cs->Index());
break;
9167 case 2:
ClrBit(ei->refit_mask, cs->Index());
break;
9181 ei->cargo_type = INVALID_CARGO;
9189 if (file ==
nullptr) file = e->
GetGRF();
9190 if (file !=
nullptr && file->grf_version >= 8 && !file->
cargo_list.empty()) {
9192 uint8_t best_local_slot = UINT8_MAX;
9194 uint8_t local_slot = file->
cargo_map[cargo_type];
9195 if (local_slot < best_local_slot) {
9196 best_local_slot = local_slot;
9197 ei->cargo_type = cargo_type;
9227 for (uint i = 0; i < CF_END; i++) {
9239 if (e->
GetGRF() ==
nullptr) {
9240 auto found = std::ranges::find(_engine_mngr.mappings[e->
type], e->
index, &EngineIDMapping::engine);
9241 if (found == std::end(_engine_mngr.mappings[e->
type]) || found->grfid != INVALID_GRFID || found->internal_id != found->substitute_id) {
9242 e->info.
string_id = STR_NEWGRF_INVALID_ENGINE;
9275 default: NOT_REACHED();
9287 if (parent != e->
index)
continue;
9292 GrfMsg(1,
"FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", e->
grf_prop.
local_id, e->
GetGRF()->filename);
9308 switch (cs.label.base()) {
9310 case CT_MAIL.base(): cs.town_production_effect =
TPE_MAIL;
break;
9311 default: cs.town_production_effect =
TPE_NONE;
break;
9314 if (!cs.IsValid()) {
9315 cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO;
9316 cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
9317 cs.abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
9341 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} as multitile, but no suitable tiles follow. Disabling house.", filename, hs->
grf_prop.
local_id);
9351 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines multitile house {} with non-zero population on additional tiles. Disabling house.", filename, hs->
grf_prop.
local_id);
9359 Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->
grf_prop.
local_id);
9366 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} without a size but marked it as available. Disabling house.", filename, hs->
grf_prop.
local_id);
9389 if (min_year == 0)
return;
9416 if (file->housespec.empty())
continue;
9418 size_t num_houses = file->housespec.size();
9419 for (
size_t i = 0; i < num_houses; i++) {
9420 HouseSpec *hs = file->housespec[i].get();
9422 if (hs ==
nullptr)
continue;
9424 const HouseSpec *next1 = (i + 1 < num_houses ? file->housespec[i + 1].get() :
nullptr);
9425 const HouseSpec *next2 = (i + 2 < num_houses ? file->housespec[i + 2].get() :
nullptr);
9426 const HouseSpec *next3 = (i + 3 < num_houses ? file->housespec[i + 3].get() :
nullptr);
9485 for (
const auto &indsp : file->industryspec) {
9486 if (indsp ==
nullptr || !indsp->
enabled)
continue;
9491 for (
const auto &indtsp : file->indtspec) {
9492 if (indtsp !=
nullptr) {
9493 _industile_mngr.SetEntitySpec(indtsp.get());
9498 for (
auto &indsp : _industry_specs) {
9505 indsp.
name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9517 for (
auto &indtsp : _industry_tile_specs) {
9533 for (
auto &objectspec : file->objectspec) {
9534 if (objectspec !=
nullptr && objectspec->grf_prop.HasGrfFile() && objectspec->IsEnabled()) {
9551 for (
auto &as : file->airportspec) {
9552 if (as !=
nullptr && as->
enabled) {
9553 _airport_mngr.SetEntitySpec(as.get());
9557 for (
auto &ats : file->airtspec) {
9558 if (ats !=
nullptr && ats->enabled) {
9559 _airporttile_mngr.SetEntitySpec(ats.get());
9571static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9585 static const SpecialSpriteHandler handlers[][GLS_END] = {
9586 {
nullptr, SafeChangeInfo,
nullptr,
nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9587 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9588 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, NewSpriteGroup, },
9589 {
nullptr,
GRFUnsafe,
nullptr,
nullptr,
nullptr, FeatureMapSpriteGroup, },
9590 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, FeatureNewName, },
9591 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9592 {
nullptr,
nullptr,
nullptr, CfgApply, CfgApply, CfgApply, },
9593 {
nullptr,
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, },
9594 { ScanInfo,
nullptr,
nullptr, GRFInfo, GRFInfo, GRFInfo, },
9595 {
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, SkipIf, },
9596 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9597 {
nullptr,
nullptr,
nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9598 {
nullptr,
nullptr,
nullptr, GRFComment,
nullptr, GRFComment, },
9600 {
nullptr, SafeGRFInhibit,
nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9603 { SkipAct11,
GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9606 {
StaticGRFInfo,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, },
9611 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9612 if (it == _grf_line_to_action6_sprite_override.end()) {
9618 buf = _grf_line_to_action6_sprite_override[location].data();
9619 GrfMsg(7,
"DecodeSpecialSprite: Using preloaded pseudo sprite data");
9628 uint8_t action = br.ReadByte();
9630 if (action == 0xFF) {
9631 GrfMsg(2,
"DecodeSpecialSprite: Unexpected data block, skipping");
9632 }
else if (action == 0xFE) {
9633 GrfMsg(2,
"DecodeSpecialSprite: Unexpected import block, skipping");
9634 }
else if (action >=
lengthof(handlers)) {
9635 GrfMsg(7,
"DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
9636 }
else if (handlers[action][stage] ==
nullptr) {
9637 GrfMsg(7,
"DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
9639 GrfMsg(7,
"DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9640 handlers[action][stage](br);
9643 GrfMsg(1,
"DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9659 Debug(grf, 2,
"LoadNewGRFFile: Reading NewGRF-file '{}'", config.
filename);
9662 if (grf_container_version == 0) {
9663 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9667 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9673 if (grf_container_version >= 2) file.
ReadDword();
9676 if (grf_container_version >= 2) {
9678 uint8_t compression = file.
ReadByte();
9679 if (compression != 0) {
9680 Debug(grf, 7,
"LoadNewGRFFile: Unsupported compression format");
9689 if (num == 4 && file.
ReadByte() == 0xFF) {
9692 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9700 while ((num = (grf_container_version >= 2 ? file.
ReadDword() : file.
ReadWord())) != 0) {
9706 DecodeSpecialSprite(buf.
Allocate(num), num, stage);
9717 GrfMsg(0,
"LoadNewGRFFile: Unexpected sprite, disabling");
9718 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9722 if (grf_container_version >= 2 && type == 0xFD) {
9745 const std::string &filename = config.
filename;
9756 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
9758 if (_cur.
grffile ==
nullptr) UserError(
"File '{}' lost in cache.\n", filename);
9765 SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
9819 DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0);
9820 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
9821 DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2);
9822 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
9823 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
9824 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
9835 static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
9839 std::vector<int> grf_overrides(num_grfs, -1);
9840 for (
int i = 0; i < num_grfs; i++) {
9842 auto it = _grf_id_overrides.find(source->grfid);
9843 if (it == std::end(_grf_id_overrides))
continue;
9844 uint32_t
override = it->second;
9847 if (dest ==
nullptr)
continue;
9850 assert(grf_overrides[i] >= 0);
9854 for (
int i = 0; i < num_grfs; i++) {
9855 if (grf_overrides[i] < 0 || grf_overrides[i] >= i)
continue;
9863 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9866 Debug(grf, 3,
"'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
9872 for (
int i = num_grfs - 1; i >= 0; i--) {
9873 if (grf_overrides[i] < 0 || grf_overrides[i] <= i)
continue;
9881 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9884 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
9890 for (
int i = 0; i < num_grfs; i++) {
9891 if (grf_overrides[i] < 0)
continue;
9899 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9900 if (!
HasBit(features, _price_base_specs[p].grf_feature))
continue;
9902 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
9910 if (file->grf_version >= 8)
continue;
9911 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9912 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9914 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9917 price_base_multipliers[p] = price_base_multipliers[fallback_price];
9924 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9925 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9926 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9928 price_base_multipliers[p] = 0;
9933 Debug(grf, 3,
"'{}' sets global price base multiplier {}", file->
filename, p);
9935 price_base_multipliers[p] = 0;
9937 Debug(grf, 3,
"'{}' sets local price base multiplier {}", file->
filename, p);
9959 _grf_line_to_action6_sprite_override.clear();
10022 if (file ==
nullptr ||
_gted[e->
index].roadtramtype == 0) {
10031 if (
_gted[e->
index].roadtramtype < list->size())
10033 RoadTypeLabel rtl = (*list)[
_gted[e->
index].roadtramtype];
10062 _grm_sprites.clear();
10120 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10127 if (stage == GLS_RESERVE) {
10128 static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10129 { std::byteswap(0x44442202), std::byteswap(0x44440111) },
10130 { std::byteswap(0x6D620402), std::byteswap(0x6D620401) },
10131 { std::byteswap(0x4D656f20), std::byteswap(0x4D656F17) },
10133 for (
const auto &grf_override : default_grf_overrides) {
10139 uint num_non_static = 0;
10141 _cur.
stage = stage;
10148 Debug(grf, 0,
"NewGRF file is missing '{}'; disabling", c->
filename);
10157 Debug(grf, 0,
"'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->
filename);
10159 c->
error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10168 if (stage == GLS_RESERVE) {
10170 }
else if (stage == GLS_ACTIVATION) {
10175 Debug(sprite, 2,
"LoadNewGRF: Currently {} sprites are loaded", _cur.
spriteid);
static const uint INVALID_AIRPORTTILE
id for an invalid airport tile
static const uint NEW_AIRPORTTILE_OFFSET
offset of first newgrf airport tile
static const uint NUM_AIRPORTTILES_PER_GRF
Number of airport tiles per NewGRF; limited to 255 to allow extending Action3 with an extended byte l...
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
@ NUM_AIRPORTS_PER_GRF
Maximal number of airports per NewGRF.
Class for backupping variables and making sure they are restored later.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr T AssignBit(T &x, const uint8_t y, bool value)
Assigns a bit in a variable.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr enable_if_t< is_integral_v< T >, T > byteswap(T x) noexcept
Custom implementation of std::byteswap; remove once we build with C++23.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
constexpr uint SPRITES_PER_BRIDGE_PIECE
Number of sprites there are per bridge piece.
static const uint MAX_BRIDGES
Maximal number of available bridge specs.
BridgeSpec _bridge[MAX_BRIDGES]
The specification of all bridges.
void ResetBridges()
Reset the data been eventually changed by the grf loaded.
Tables with default industry layouts and behaviours.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
MixedCargoType
Mixed cargo types for definitions with cargo that can vary depending on climate.
@ MCT_GRAIN_WHEAT_MAIZE
Cargo can be grain, wheat or maize.
@ MCT_LIVESTOCK_FRUIT
Cargo can be livestock or fruit.
@ MCT_VALUABLES_GOLD_DIAMONDS
Cargo can be valuables, gold or diamonds.
static constexpr CargoLabel CT_PASSENGERS
Available types of cargo Labels may be re-used between different climates.
StrongType::Typedef< uint32_t, struct CargoLabelTag, StrongType::Compare > CargoLabel
Globally unique label of a cargo type.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
std::span< const CargoLabel > GetClimateDependentCargoTranslationTable()
Get default climate-dependent cargo translation table for a NewGRF, used if the NewGRF does not provi...
bool IsDefaultCargo(CargoType cargo_type)
Test if a cargo is a default cargo type.
CargoTypes _standard_cargo_mask
Bitmask of real cargo types available.
std::span< const CargoLabel > GetClimateIndependentCargoTranslationTable()
Get default climate-independent cargo translation table for a NewGRF, used if the NewGRF does not pro...
void BuildCargoLabelMap()
Build cargo label map.
void SetupCargoForClimate(LandscapeType l)
Set up the default cargo types for the given landscape type.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
CargoTypes _cargo_mask
Bitmask of cargo types available.
@ CC_REFRIGERATED
Refrigerated cargo (Food, Fruit)
@ CC_ARMOURED
Armoured cargo (Valuables, Gold, Diamonds)
@ CC_BULK
Bulk cargo (Coal, Grain etc., Ores, Fruit)
@ CC_EXPRESS
Express cargo (Goods, Food, Candy, but also possible for passengers)
@ CC_LIQUID
Liquids (Oil, Water, Rubber)
@ CC_PIECE_GOODS
Piece goods (Livestock, Wood, Steel, Paper)
@ CC_PASSENGERS
Passengers.
@ INVALID_TPE
Invalid town production effect.
@ TPE_NONE
Town will not produce this cargo type.
@ TPE_PASSENGERS
Cargo behaves passenger-like for production.
@ TPE_MAIL
Cargo behaves mail-like for production.
uint16_t CargoClasses
Bitmask of cargo classes.
@ TAE_GOODS
Cargo behaves goods/candy-like.
@ TAE_NONE
Cargo has no effect.
@ TAE_PASSENGERS
Cargo behaves passenger-like.
@ TAE_MAIL
Cargo behaves mail-like.
@ TAE_FOOD
Cargo behaves food/fizzy-drinks-like.
@ TAE_WATER
Cargo behaves water-like.
Class to read from a NewGRF file.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this EnumBitSet.
constexpr EnumBitSet & Set(Tenum value)
Set the enum value.
constexpr bool Any(const EnumBitSet &other) const
Test if any of the enum values are set.
constexpr EnumBitSet & Reset(Tenum value)
Reset the enum value to not set.
constexpr bool Test(Tenum value) const
Test if the enum value is set.
void SetEntitySpec(const HouseSpec *hs)
Install the specs into the HouseSpecs array It will find itself the proper slot on which it will go.
void SetEntitySpec(IndustrySpec *inds)
Method to install the new industry data in its proper slot The slot assignment is internal of this me...
static void Assign(Tspec *spec)
Assign a spec to one of the classes.
StringID name
Name of this class.
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
static void Reset()
Reset the classes, i.e.
void SetEntitySpec(ObjectSpec *spec)
Method to install the new object data in its proper slot The slot assignment is internal of this meth...
void ResetMapping()
Resets the mapping, which is used while initializing game.
virtual uint16_t GetID(uint16_t grf_local_id, uint32_t grfid) const
Return the ID (if ever available) of a previously inserted entity.
void Add(uint16_t local_id, uint32_t grfid, uint entity_type)
Since the entity IDs defined by the GRF file does not necessarily correlate to those used by the game...
virtual uint16_t AddEntityID(uint16_t grf_local_id, uint32_t grfid, uint16_t substitute_id)
Reserves a place in the mapping array for an entity to be installed.
This struct contains all the info that is needed to draw and construct tracks.
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
TimerGameCalendar::Date introduction_date
Introduction date.
RailTypes powered_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype generates power
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
RailTypes introduction_required_railtypes
Bitmask of railtypes that are required for this railtype to be introduced at a given introduction_dat...
uint8_t sorting_order
The sorting order of this railtype for the toolbar dropdown.
RailTypeLabel label
Unique 32 bit rail type identifier.
struct RailTypeInfo::@24 strings
Strings associated with the rail type.
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this rail type.
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
uint8_t map_colour
Colour on mini-map.
StringID menu_text
Name of this rail type in the main toolbar dropdown.
StringID name
Name of this rail type.
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel
uint8_t fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations.
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
RailTypeFlags flags
Bit mask of rail type flags.
uint8_t curve_speed
Multiplier for curve maximum speed advantage.
uint16_t cost_multiplier
Cost multiplier for building this rail type.
StringID replace_text
Text used in the autoreplace GUI.
RailTypeLabelList alternate_labels
Rail type labels this type provides in addition to the main label.
StringID build_caption
Caption of the build vehicle GUI for this rail type.
StringID new_loco
Name of an engine for this type of rail in the engine preview GUI.
const GRFFile * grffile[RTSG_END]
NewGRF providing the Action3 for the railtype.
uint8_t acceleration_type
Acceleration type of this rail type.
void ReadBlock(void *ptr, size_t size)
Read a block.
size_t GetPos() const
Get position in the file.
void SeekTo(size_t pos, int mode)
Seek in the current file.
std::string filename
Full name of the file; relative path to subdir plus the extension of the file.
uint8_t ReadByte()
Read a byte from the file.
uint32_t ReadDword()
Read a double word (32 bits) from the file (in low endian format).
void SkipBytes(size_t n)
Skip n bytes ahead in the file.
uint16_t ReadWord()
Read a word (16 bits) from the file (in low endian format).
A reusable buffer that can be used for places that temporary allocate a bit of memory and do that ver...
T * Allocate(size_t count)
Get buffer of at least count times T.
StringID menu_text
Name of this rail type in the main toolbar dropdown.
StringID replace_text
Text used in the autoreplace GUI.
RoadTypeLabelList alternate_labels
Road type labels this type provides in addition to the main label.
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
TimerGameCalendar::Date introduction_date
Introduction date.
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this road type.
RoadTypeFlags flags
Bit mask of road type flags.
uint8_t map_colour
Colour on mini-map.
const GRFFile * grffile[ROTSG_END]
NewGRF providing the Action3 for the roadtype.
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
StringID name
Name of this rail type.
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
struct RoadTypeInfo::@27 strings
Strings associated with the rail type.
StringID new_engine
Name of an engine for this type of road in the engine preview GUI.
RoadTypes introduction_required_roadtypes
Bitmask of roadtypes that are required for this roadtype to be introduced at a given introduction_dat...
uint16_t cost_multiplier
Cost multiplier for building this road type.
StringID build_caption
Caption of the build vehicle GUI for this rail type.
RandomAccessFile with some extra information specific for sprite files.
uint8_t GetContainerVersion() const
Get the version number of container type used by the file.
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static DateFract date_fract
Fractional part of the day.
static constexpr TimerGame< struct Calendar >::Year ORIGINAL_MAX_YEAR
The maximum year of the original TTD.
static constexpr TimerGame< struct Calendar >::Year MIN_YEAR
The absolute minimum year in OTTD.
static constexpr TimerGame< struct Calendar >::Year ORIGINAL_BASE_YEAR
The minimum starting year/base year of the original TTD.
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
static Date date
Current date in days (day counter).
static Year year
Current year, starting at 0.
static DateFract date_fract
Fractional part of the day.
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
uint16_t DateFract
The fraction of a date we're in, i.e.
static constexpr bool IsLeapYear(Year year)
Checks whether the given year is a leap year or not.
Configuration options of the network stuff.
static const uint NETWORK_MAX_GRF_COUNT
Maximum number of GRFs that can be sent.
Some simple functions to help with accessing containers.
int find_index(Container const &container, typename Container::const_reference item)
Helper function to get the index of an item Consider using std::set, std::unordered_set or std::flat_...
void ResetCurrencies(bool preserve_custom)
Will fill _currency_specs array with default values from origin_currency_specs Called only from newgr...
uint8_t GetNewgrfCurrencyIdConverted(uint8_t grfcurr_id)
Will return the ottd's index correspondence to the ttdpatch's id.
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Functions to handle different currencies.
@ CURRENCY_END
always the last item
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Direction
Defines the 8 directions on the map.
void SetPriceBaseMultiplier(Price price, int factor)
Change a price base by the given factor.
void ResetPriceBaseMultipliers()
Reset changes to the price base multipliers.
Price
Enumeration of all base prices for use with Prices.
void SetYearEngineAgingStops()
Compute the value for _year_engine_aging_stops.
const uint8_t _engine_counts[4]
Number of engines of each vehicle type in original engine data.
void SetupEngines()
Initialise the engine pool with the data from the original vehicles.
const uint8_t _engine_offsets[4]
Offset of the first engine of each vehicle type in original engine data.
@ HasVariants
Set if engine has variants.
@ IsFolded
Set if display of variants should be folded (hidden).
Functions related to engines.
@ RoadIsTram
Road vehicle is a tram/light rail vehicle.
@ Uses2CC
Vehicle uses two company colours.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
EngineClass
Type of rail engine.
@ EC_DIESEL
Diesel rail engine.
@ EC_STEAM
Steam rail engine.
@ EC_MAGLEV
Maglev engine.
@ EC_ELECTRIC
Electric rail engine.
@ EC_MONORAIL
Mono rail engine.
@ RAILVEH_SINGLEHEAD
indicates a "standalone" locomotive
@ RAILVEH_WAGON
simple wagon, not motorized
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Functions related to errors.
Error reporting related functions.
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
Check whether the given file exists.
Functions for Standard In/Out file operations.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Declarations for savegames operations.
Functions to read fonts from files and cache them.
void SetUnicodeGlyph(FontSize size, char32_t key, SpriteID sprite)
Map a SpriteID to the font size and key.
bool _generating_world
Whether we are generating the map or not.
Functions related to world/map generation.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
FontSize
Available font sizes.
uint32_t PaletteID
The number of the palette.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
bool IsSnowLineSet()
Has a snow line table already been loaded.
void ClearSnowLine()
Clear the variable snow line table and free the memory.
void SetSnowLine(std::unique_ptr< SnowLine > &&snow_line)
Set a variable snow line, as loaded from a newgrf file.
static const HouseID NUM_HOUSES
Total number of houses.
static const HouseID NEW_HOUSE_OFFSET
Offset for new houses.
static const HouseID NUM_HOUSES_PER_GRF
Number of supported houses per NewGRF.
static const uint HOUSE_ORIGINAL_NUM_ACCEPTS
Original number of accepted cargo types.
@ HZ_ZONALL
1F This is just to englobe all above types at once
@ HZ_CLIMALL
Bitmask of all climate bits.
@ HZ_SUBARTC_ABOVE
11 800 can appear in sub-arctic climate above the snow line
@ HZ_ZON1
0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb
void ResetIndustries()
This function initialize the spec arrays of both industry and industry tiles.
void SortIndustryTypes()
Initialize the list of sorted industry types.
Accessors for industries.
@ GFX_WATERTILE_SPECIALCHECK
not really a tile, but rather a very special check
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
static const IndustryType NEW_INDUSTRYOFFSET
original number of industry types
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF; limited to 255 to allow extending Action3 with an extend...
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
static const int INDUSTRY_ORIGINAL_NUM_OUTPUTS
Original number of produced cargo types.
static const IndustryType NUM_INDUSTRYTYPES_PER_GRF
maximum number of industry types per NewGRF; limited to 128 because bit 7 has a special meaning in so...
IndustryTileSpecialFlags
Flags for miscellaneous industry tile specialities.
IndustryLifeType
Available types of industry lifetimes.
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
@ CHECK_NOTHING
Always succeeds.
IndustryBehaviour
Various industry behaviours mostly to represent original TTD specialities.
Functions related to OTTD's landscape.
static const uint SNOW_LINE_DAYS
Number of days in each month in the snow line table.
static const uint SNOW_LINE_MONTHS
Number of months in the snow line table.
LandscapeType
Landscape types.
Information about languages and their files.
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
const LanguageMetadata * GetLanguage(uint8_t newgrflangid)
Get the language with the given NewGRF language ID.
static const uint8_t MAX_NUM_CASES
Maximum number of supported cases.
LiveryScheme
List of different livery schemes.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
void MemSetT(T *ptr, uint8_t value, size_t num=1)
Type-safe version of memset().
static constexpr CargoType SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoType SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoType SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
bool _networking
are we in networking mode?
static void FinaliseObjectsArray()
Add all new objects to the object array.
static void FinalisePriceBaseMultipliers()
Decide whether price base multipliers of grfs shall apply globally or only to the grf specifying them...
std::span< const Action5Type > GetAction5Types()
Get list of all action 5 types.
static void ResetCustomStations()
Reset and clear all NewGRF stations.
static void SkipAct12(ByteReader &buf)
Action 0x12 (SKIP)
static std::vector< GRFTempEngineData > _gted
Temporary engine data used during NewGRF loading.
static CargoLabel GetActiveCargoLabel(const std::initializer_list< CargoLabel > &labels)
Find first cargo label that exists and is active from a list of cargo labels.
bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
Reads a variable common to VarAction2 and Action7/9/D.
static bool ChangeGRFParamType(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'TYPE' to set the typeof a parameter.
bool(* BranchHandler)(ByteReader &)
Type of callback function for branch nodes.
static ChangeInfoResult RoadVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for road vehicles.
static uint16_t SanitizeSpriteOffset(uint16_t &num, uint16_t offset, int max_sprites, const std::string_view name)
Sanitize incoming sprite offsets for Action 5 graphics replacements.
static void FinaliseIndustriesArray()
Add all new industries to the industry array.
static bool ChangeGRFParamLimits(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'LIMI' to set the min/max value of a parameter.
std::span< const CargoLabel > GetCargoTranslationTable(const GRFFile &grffile)
Get the cargo translation table to use for the given GRF file.
static ChangeInfoResult LoadTranslationTable(uint first, uint last, ByteReader &buf, TGetTableFunc gettable, std::string_view name)
Load a cargo- or railtype-translation table.
static bool ChangeGRFNumUsedParams(size_t len, ByteReader &buf)
Callback function for 'INFO'->'NPAR' to set the number of valid parameters.
void ResetPersistentNewGRFData()
Reset NewGRF data which is stored persistently in savegames.
static constexpr AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
static uint32_t _grm_cargoes[NUM_CARGO *2]
Contains the GRF ID of the owner of a cargo if it has been reserved.
static bool ChangeGRFURL(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'URL_' to set the newgrf url.
static ChangeInfoResult AirportChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for airports.
bool(* DataHandler)(size_t, ByteReader &)
Type of callback function for binary nodes.
static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, ByteReader &buf)
Define properties common to all vehicles.
static void FinaliseAirportsArray()
Add all new airports to the airport array.
static GRFFile * GetFileByFilename(const std::string &filename)
Obtain a NewGRF file by its filename.
static bool ChangeGRFParamDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter.
static ChangeInfoResult CanalChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for water features.
static ChangeInfoResult StationChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for stations.
static ChangeInfoResult SoundEffectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for sound effects.
static bool ChangeGRFMinVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'MINV' to the minimum compatible version of the NewGRF.
static bool IsHouseSpecValid(HouseSpec *hs, const HouseSpec *next1, const HouseSpec *next2, const HouseSpec *next3, const std::string &filename)
Check if a given housespec is valid and disable it if it's not.
static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
static void TranslateGRFStrings(ByteReader &buf)
Action 0x13.
static void GRFUnsafe(ByteReader &)
Set the current NewGRF as unsafe for static use.
static void DefineGotoLabel(ByteReader &buf)
Action 0x10 - Define goto label.
static void ActivateOldShore()
Relocates the old shore sprites at new positions.
static void EnsureEarlyHouse(HouseZones bitmask)
Make sure there is at least one house available in the year 0 for the given climate / housezone combi...
static const uint NUM_STATIONS_PER_GRF
The maximum amount of stations a single GRF is allowed to add.
static void ParamSet(ByteReader &buf)
Action 0x0D: Set parameter.
static bool ChangeGRFParamValueNames(ByteReader &buf)
Callback function for 'INFO'->'PARA'->param_num->'VALU' to set the names of some parameter values (ty...
static GRFFile * GetCurrentGRFOverride()
Get overridden GRF for current GRF if present.
static void FinaliseEngineArray()
Check for invalid engines.
static const SpriteGroup * CreateGroupFromGroupID(uint8_t feature, uint8_t setid, uint8_t type, uint16_t spriteid)
Helper function to either create a callback or a result sprite group.
static bool HandleParameterInfo(ByteReader &buf)
Callback function for 'INFO'->'PARA' to set extra information about the parameters.
static void ReadSpriteLayoutRegisters(ByteReader &buf, TileLayoutFlags flags, bool is_parent, NewGRFSpriteLayout *dts, uint index)
Preprocess the TileLayoutFlags and read register modifiers from the GRF.
static GRFParameterInfo * _cur_parameter
The parameter which info is currently changed by the newgrf.
static bool HandleNodes(ByteReader &buf, std::span< const AllowedSubtags > tags)
Handle the contents of a 'C' choice of an Action14.
static uint32_t _grm_engines[256]
Contains the GRF ID of the owner of a vehicle if it has been reserved.
static void ResetNewGRFErrors()
Clear all NewGRF errors.
uint8_t _misc_grf_features
Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E.
static void LoadNewGRFFileFromFile(GRFConfig &config, GrfLoadingStage stage, SpriteFile &file)
Load a particular NewGRF from a SpriteFile.
static void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid)
Set the override for a NewGRF.
static bool ChangeGRFName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'NAME' to add a translation to the newgrf name.
static std::vector< StringIDMapping > _string_to_grf_mapping
Strings to be mapped during load.
StringID MapGRFStringID(uint32_t grfid, GRFStringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
static ChangeInfoResult AircraftVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for aircraft.
static ChangeInfoResult GlobalVarChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for global variables.
static void LoadGRFSound(size_t offs, SoundEntry *sound)
Load a sound from a file.
bool(* TextHandler)(uint8_t, std::string_view str)
Type of callback function for text nodes.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
static const uint MAX_SPRITEGROUP
Maximum GRF-local ID for a spritegroup.
static ChangeInfoResult ObjectChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for objects.
void LoadNewGRF(SpriteID load_index, uint num_baseset)
Load all the NewGRFs.
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig &c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
static void InitializeGRFSpecial()
Initialize the TTDPatch flags.
static constexpr AllowedSubtags _tags_root[]
Action14 root tags.
static std::string ReadDWordAsString(ByteReader &reader)
Helper to read a DWord worth of bytes from the reader and to return it as a valid string.
static void ClearTemporaryNewGRFData(GRFFile *gf)
Reset all NewGRFData that was used only while processing data.
static ChangeInfoResult CargoChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for cargoes.
static StringID TTDPStringIDToOTTDStringIDMapping(GRFStringID str)
Perform a mapping from TTDPatch's string IDs to OpenTTD's string IDs, but only for the ones we are aw...
static void FinaliseCanals()
Set to use the correct action0 properties for each canal feature.
static bool IsValidNewGRFImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular NewGRF vehicle.
static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
Ignore properties for objects.
void ResetNewGRFData()
Reset all NewGRF loaded data.
static bool IsGRMReservedSprite(SpriteID first_sprite, uint16_t num_sprites)
Check if a sprite ID range is within the GRM reversed range for the currently loading NewGRF.
static void CalculateRefitMasks()
Precalculate refit masks from cargo classes for all vehicles.
void FinaliseCargoArray()
Check for invalid cargoes.
static CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for ships.
static GRFFile * GetFileByGRFID(uint32_t grfid)
Obtain a NewGRF file by its grfID.
static ChangeInfoResult IgnoreRoadStopProperty(uint prop, ByteReader &buf)
Ignore properties for roadstops.
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader &buf)
Ignore an industry property.
static void BuildCargoTranslationMap()
Construct the Cargo Mapping.
static bool ChangeGRFParamMask(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'MASK' to set the parameter and bits to use.
static void ImportGRFSound(SoundEntry *sound)
Process a sound import from another GRF file.
static bool SkipUnknownInfo(ByteReader &buf, uint8_t type)
Try to skip the current node and all subnodes (if it's a branch node).
static ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for rail vehicles.
static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader &buf)
Ignore a house property.
static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industries.
static bool ReadSpriteLayout(ByteReader &buf, uint num_building_sprites, bool use_cur_spritesets, uint8_t feature, bool allow_var10, bool no_z_position, NewGRFSpriteLayout *dts)
Read a spritelayout from the GRF.
void GrfMsgI(int severity, const std::string &msg)
Debug() function dedicated to newGRF debugging messages Function is essentially the same as Debug(grf...
static void ResetCustomHouses()
Reset and clear all NewGRF houses.
EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal_id)
Return the ID of a new engine.
static ChangeInfoResult RoadTypeChangeInfo(uint first, uint last, int prop, ByteReader &buf, RoadTramType rtt)
Define properties for roadtypes.
static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
static ChangeInfoResult IndustrytilesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industry tiles.
static void LoadFontGlyph(ByteReader &buf)
Action 0x12.
static void ResetCustomIndustries()
Reset and clear all NewGRF industries.
static std::vector< GRFFile * > _grf_files
List of all loaded GRF files.
static void ResetCustomObjects()
Reset and clear all NewObjects.
static void ConvertTTDBasePrice(uint32_t base_pointer, const char *error_location, Price *index)
Converts TTD(P) Base Price pointers into the enum used by OTTD See http://wiki.ttdpatch....
static void FinaliseHouseArray()
Add all new houses to the house array.
static bool ChangeGRFPalette(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PALS' to set the number of valid parameters.
static constexpr auto _action5_types
The information about action 5 types.
static void InitNewGRFFile(const GRFConfig &config)
Prepare loading a NewGRF file with its config.
ChangeInfoResult
Possible return values for the FeatureChangeInfo functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_DISABLED
GRF was disabled due to error.
@ CIR_UNKNOWN
Variable is unknown.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
static bool ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
Validate the industry layout; e.g.
static TileLayoutFlags ReadSpriteLayoutSprite(ByteReader &buf, bool read_flags, bool invert_action1_flag, bool use_cur_spritesets, int feature, PalSpriteID *grf_sprite, uint16_t *max_sprite_offset=nullptr, uint16_t *max_palette_offset=nullptr)
Read a sprite and a palette from the GRF and convert them into a format suitable to OpenTTD.
static void ActivateOldTramDepot()
Replocate the old tram depot sprites to the new position, if no new ones were loaded.
static uint32_t _ttdpatch_flags[8]
32 * 8 = 256 flags.
static ChangeInfoResult RailTypeChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for railtypes.
void LoadNewGRFFile(GRFConfig &config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
Load a particular NewGRF.
static void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
static Engine * GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access=false)
Returns the engine associated to a certain internal_id, resp.
static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite)
Map the colour modifiers of TTDPatch to those that Open is using.
static void AfterLoadGRFs()
Finish loading NewGRFs and execute needed post-processing.
static bool ChangeGRFParamName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter.
static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, std::span< const AllowedSubtags > subtags)
Handle the nodes of an Action14.
static void ResetNewGRF()
Reset and clear all NewGRFs.
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
Callback function for 'INFO'->'BLTR' to set the blitter info.
static GRFError * DisableGrf(StringID message=STR_NULL, GRFConfig *config=nullptr)
Disable a GRF.
static void FeatureTownName(ByteReader &buf)
Action 0x0F - Define Town names.
static void ResetCustomAirports()
Reset and clear all NewGRF airports.
static ChangeInfoResult BridgeChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for bridges.
static std::vector< CachedCallback > _cached_callback_groups
Sorted list of cached callback result spritegroups.
static ChangeInfoResult TownHouseChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for houses.
static constexpr AllowedSubtags _tags_parameters[]
Action14 parameter tags.
@ SHORE_REPLACE_ACTION_A
Shore sprites were replaced by ActionA (using grass tiles for the corner-shores).
@ SHORE_REPLACE_NONE
No shore sprites were replaced.
@ SHORE_REPLACE_ONLY_NEW
Only corner-shores were loaded by Action5 (openttd(w/d).grf only).
@ SHORE_REPLACE_ACTION_5
Shore sprites were replaced by Action5.
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
@ TRAMWAY_REPLACE_DEPOT_NO_TRACK
Electrified depot graphics without tram track were loaded.
@ TRAMWAY_REPLACE_DEPOT_NONE
No tram depot graphics were loaded.
@ GMB_TRAIN_WIDTH_32_PIXELS
Use 32 pixels per train vehicle in depot gui and vehicle details. Never set in the global variable;.
Information about NewGRF Action 5.
@ A5BLOCK_ALLOW_OFFSET
Allow replacing any subset by specifiing an offset.
@ A5BLOCK_INVALID
unknown/not-implemented type
@ A5BLOCK_FIXED
Only allow replacing a whole block of sprites. (TTDP compatible)
void BindAirportSpecs()
Tie all airportspecs to their class.
NewGRF handling of airports.
TTDPAirportType
Allow incrementing of AirportClassID variables.
NewGRF handling of airport tiles.
static const uint8_t ANIM_STATUS_NO_ANIMATION
There is no animation.
@ CustomRefit
Custom refit mask.
@ CBID_VEHICLE_CUSTOM_REFIT
Called to get custom engine refit mask.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
std::array< WaterFeature, CF_END > _water_feature
Table of canal 'feature' sprite groups.
Handling of NewGRF canals.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Cargo support for NewGRFs.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
TileLayoutFlags
Flags to enable register usage in sprite layouts.
@ TLF_BB_Z_OFFSET
Add signed offset to bounding box Z positions from register TileLayoutRegisters::delta....
@ TLF_CUSTOM_PALETTE
Palette is from Action 1 (moved to SPRITE_MODIFIER_CUSTOM_SPRITE in palette during loading).
@ TLF_SPRITE
Add signed offset to sprite from register TileLayoutRegisters::sprite.
@ TLF_CHILD_X_OFFSET
Add signed offset to child sprite X positions from register TileLayoutRegisters::delta....
@ TLF_DRAWING_FLAGS
Flags which are still required after loading the GRF.
@ TLF_DODRAW
Only draw sprite if value of register TileLayoutRegisters::dodraw is non-zero.
@ TLF_PALETTE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the palette, even if it is no action-1 palet...
@ TLF_NON_GROUND_FLAGS
Flags which do not work for the (first) ground sprite.
@ TLF_BB_XY_OFFSET
Add signed offset to bounding box X and Y positions from register TileLayoutRegisters::delta....
@ TLF_SPRITE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the sprite, even if it is no action-1 sprite...
@ TLF_PALETTE_VAR10
Resolve palette with a specific value in variable 10.
@ TLF_SPRITE_VAR10
Resolve sprite with a specific value in variable 10.
@ TLF_KNOWN_FLAGS
Known flags. Any unknown set flag will disable the GRF.
@ TLF_PALETTE
Add signed offset to palette from register TileLayoutRegisters::palette.
@ TLF_CHILD_Y_OFFSET
Add signed offset to child sprite Y positions from register TileLayoutRegisters::delta....
static const uint TLR_MAX_VAR10
Maximum value for var 10.
GRFConfigList _grfconfig
First item in list of current GRF set up.
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
@ GCS_INITIALISED
GRF file has been initialised.
@ GCS_DISABLED
GRF file is disabled.
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
@ GCS_UNKNOWN
The status of this grf file is unknown.
@ GCS_ACTIVATED
GRF file has been activated.
@ InitOnly
GRF file is processed up to GLS_INIT.
@ Reserved
GRF file passed GLS_RESERVE stage.
@ System
GRF file is an openttd-internal system grf.
@ Static
GRF file is used statically (can be used in any MP game)
@ Unsafe
GRF file is unsafe for static usage.
@ Invalid
GRF is unusable with this version of OpenTTD.
GRFParameterType
The possible types of a newgrf parameter.
@ PTYPE_UINT_ENUM
The parameter allows a range of numbers, each of which can have a special name.
@ PTYPE_END
Invalid parameter type.
GRFPalette
Information that can/has to be stored about a GRF's palette.
@ GRFP_GRF_UNSET
The NewGRF provided no information.
@ GRFP_BLT_UNSET
The NewGRF provided no information or doesn't care about a 32 bpp blitter.
@ GRFP_GRF_WINDOWS
The NewGRF says the Windows palette can be used.
@ GRFP_GRF_DOS
The NewGRF says the DOS palette can be used.
@ GRFP_GRF_ANY
The NewGRF says any palette can be used.
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
@ GRFP_USE_MASK
Bitmask to get only the use palette use states.
void SetEngineGRF(EngineID engine, const GRFFile *file)
Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters etc during a game.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
void CommitVehicleListOrderChanges()
Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
void AlterVehicleListOrder(EngineID engine, uint16_t target)
Record a vehicle ListOrderChange.
Functions for NewGRF engines.
void AddGenericCallback(uint8_t feature, const GRFFile *file, const SpriteGroup *group)
Add a generic feature callback sprite group to the appropriate feature list.
void ResetGenericCallbacks()
Reset all generic feature callback sprite groups.
Functions related to NewGRF houses.
IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32_t grf_id)
Map the GRF local type to an industry type.
Functions for NewGRF industries.
void ResetObjects()
This function initialize the spec arrays of objects.
Functions related to NewGRF objects.
static const uint8_t OBJECT_SIZE_1X1
The value of a NewGRF's size property when the object is 1x1 tiles: low nibble for X,...
@ Uses2CC
Object wants 2CC colour mapping.
@ PROP_AIRCRAFT_PASSENGER_CAPACITY
Passenger Capacity.
@ PROP_ROADVEH_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_TRAIN_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_TRAIN_CURVE_SPEED_MOD
Modifier to maximum speed in curves.
@ PROP_ROADVEH_WEIGHT
Weight in 1/4 t.
@ PROP_TRAIN_COST_FACTOR
Purchase cost (if dualheaded: sum of both vehicles)
@ PROP_TRAIN_USER_DATA
User defined data for vehicle variable 0x42.
@ PROP_TRAIN_WEIGHT
Weight in t (if dualheaded: for each single vehicle)
@ PROP_AIRCRAFT_RANGE
Aircraft range.
@ PROP_TRAIN_CARGO_CAPACITY
Capacity (if dualheaded: for each single vehicle)
@ PROP_AIRCRAFT_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_VEHICLE_LOAD_AMOUNT
Loading speed.
@ PROP_ROADVEH_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_TRAIN_TRACTIVE_EFFORT
Tractive effort coefficient in 1/256.
@ PROP_SHIP_CARGO_CAPACITY
Capacity.
@ PROP_ROADVEH_TRACTIVE_EFFORT
Tractive effort coefficient in 1/256.
@ PROP_SHIP_COST_FACTOR
Purchase cost.
@ PROP_ROADVEH_CARGO_CAPACITY
Capacity.
@ PROP_AIRCRAFT_SPEED
Max. speed: 1 unit = 8 mph = 12.8 km-ish/h.
@ PROP_AIRCRAFT_MAIL_CAPACITY
Mail Capacity.
@ PROP_SHIP_SPEED
Max. speed: 1 unit = 1/3.2 mph = 0.5 km-ish/h.
@ PROP_SHIP_RUNNING_COST_FACTOR
Yearly runningcost.
@ PROP_TRAIN_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_ROADVEH_COST_FACTOR
Purchase cost.
@ PROP_ROADVEH_SHORTEN_FACTOR
Shorter vehicles.
@ PROP_ROADVEH_POWER
Power in 10 HP.
@ PROP_SHIP_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_AIRCRAFT_COST_FACTOR
Purchase cost.
@ PROP_TRAIN_RUNNING_COST_FACTOR
Yearly runningcost (if dualheaded: sum of both vehicles)
@ PROP_AIRCRAFT_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
@ PROP_TRAIN_POWER
Power in hp (if dualheaded: sum of both vehicles)
@ PROP_TRAIN_SPEED
Max. speed: 1 unit = 1/1.6 mph = 1 km-ish/h.
@ PROP_ROADVEH_SPEED
Max. speed: 1 unit = 1/0.8 mph = 2 km-ish/h.
NewGRF definitions and structures for road stops.
RoadStopDrawMode
Different draw modes to disallow rendering of some parts of the stop or road.
RoadStopAvailabilityType
Various different options for availability, restricting the roadstop to be only for busses or for tru...
static const int NUM_ROADSTOPS_PER_GRF
The maximum amount of roadstops a single GRF is allowed to add.
SoundEntry * AllocateSound(uint num)
Allocate sound slots.
SoundID GetNewGRFSoundID(const GRFFile *file, SoundID sound_id)
Resolve NewGRF sound ID.
Functions related to NewGRF provided sounds.
DeterministicSpriteGroupAdjustOperation
@ VSG_SCOPE_SELF
Resolved object itself.
@ VSG_SCOPE_PARENT
Related object of the resolved one.
@ VSG_SCOPE_RELATIVE
Relative position (vehicles only)
Header file for NewGRF stations.
uint16_t GetStationLayoutKey(uint8_t platforms, uint8_t length)
Get the station layout key for a given station layout size.
void CleanUpStrings()
House cleaning.
static void AddGRFTextToList(GRFTextList &list, uint8_t langid, std::string_view text_to_add)
Add a new text to a GRFText list.
std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool allow_newlines, std::string_view str, StringControlCode byte80)
Translate TTDPatch string codes into something OpenTTD can handle (better).
StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
StringID AddGRFString(uint32_t grfid, GRFStringID stringid, uint8_t langid_to_add, bool new_scheme, bool allow_newlines, std::string_view text_to_add, StringID def_string)
Add the new read string into our structure.
Header of Action 04 "universal holder" structure and functions.
StrongType::Typedef< uint16_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
std::vector< GRFText > GRFTextList
A GRF text with a list of translations.
static const char32_t NFO_UTF8_IDENTIFIER
This character (thorn) indicates a unicode string to NFO.
Header of Action 0F "universal holder" structure and functions.
static const ObjectType NUM_OBJECTS_PER_GRF
Number of supported objects per NewGRF.
RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
Get the rail type for a given label.
RailType AllocateRailType(RailTypeLabel label)
Allocate a new rail type label.
void InitRailTypes()
Resolve sprites of custom rail types.
void ResetRailTypes()
Reset all rail type information to its default values.
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
RailType
Enumeration for all possible railtypes.
@ RAILTYPE_END
Used for iterations.
@ INVALID_RAILTYPE
Flag for invalid railtype.
@ RAILTYPE_ELECTRIC
Electric rails.
@ RAILTYPE_RAIL
Standard non-electric rails.
declaration of OTTD revision dependent variables
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
Get the road type for a given label.
void ResetRoadTypes()
Reset all road type information to its default values.
void InitRoadTypes()
Resolve sprites of custom road types.
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
Allocate a new road type label.
RoadType
The different roadtypes we support.
@ INVALID_ROADTYPE
flag for invalid roadtype
@ ROADTYPE_ROAD
Basic road type.
@ ROADTYPE_END
Used for iterations.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
@ SP_CUSTOM
No profile, special "custom" highscore.
Slope
Enumeration for the slope-type.
void BuildLinkStatsLegend()
Populate legend table for the link stat view.
void BuildIndustriesLegend()
Fills an array for the industries legends.
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
SpriteFile & OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap)
Open/get the SpriteFile that is cached for use in the sprite cache.
bool LoadNextSprite(SpriteID load_index, SpriteFile &file, uint file_sprite_id)
Load a real or recolour sprite.
size_t GetGRFSpriteOffset(uint32_t id)
Get the file offset for a specific sprite in the sprite section of a GRF.
bool SkipSpriteData(SpriteFile &file, uint8_t type, uint16_t num)
Skip the given amount of sprite graphics data.
void ReadGRFSpriteOffsets(SpriteFile &file)
Parse the sprite section of GRFs.
static constexpr uint8_t SPRITE_MODIFIER_OPAQUE
Set when a sprite must not ever be displayed transparently.
static const SpriteID SPR_AQUEDUCT_BASE
Sprites for the Aqueduct.
static const SpriteID SPR_OPENTTD_BASE
Extra graphic spritenumbers.
static const SpriteID SPR_TRACKS_FOR_SLOPES_BASE
Sprites for 'highlighting' tracks on sloped land.
static const SpriteID SPR_ROAD_WAYPOINTS_BASE
Road waypoint sprites.
static constexpr uint8_t PALETTE_MODIFIER_TRANSPARENT
when a sprite is to be displayed transparently, this bit needs to be set.
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
static const SpriteID SPR_AIRPORT_PREVIEW_BASE
Airport preview sprites.
static constexpr uint8_t PALETTE_MODIFIER_COLOUR
this bit is set when a recolouring process is in action
static const SpriteID SPR_ONEWAY_BASE
One way road sprites.
static const SpriteID SPR_SHORE_BASE
shore tiles - action 05-0D
static constexpr uint MAX_CATCHMENT
Maximum catchment for airports with "modified catchment" enabled.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
static void StrMakeValid(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Functions related to low-level strings.
size_t ttd_strnlen(const char *str, size_t maxlen)
Get the length of a string, within a limited buffer.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const uint MAX_LANG
Maximum number of languages supported by the game, and the NewGRF specs.
Information about a single action 5 type.
Action5BlockType block_type
How is this Action5 type processed?
uint16_t max_sprites
If the Action5 contains more sprites, only the first max_sprites sprites will be used.
uint16_t min_sprites
If the Action5 contains less sprites, the whole block will be ignored.
SpriteID sprite_base
Load the sprites starting from this sprite.
const std::string_view name
Name for error messages.
Information about a aircraft vehicle.
uint16_t max_speed
Maximum speed (1 unit = 8 mph = 12.8 km-ish/h)
uint8_t mail_capacity
Mail capacity (bags).
uint8_t subtype
Type of aircraft.
uint16_t passenger_capacity
Passenger capacity (persons).
uint16_t max_range
Maximum range of this aircraft.
Defines the data structure for an airport.
static void ResetAirports()
This function initializes the airportspec array.
struct GRFFileProps grf_prop
Properties related to the grf file.
static AirportSpec * GetWithoutOverride(uint8_t type)
Retrieve airport spec for the given airport.
bool enabled
Entity still available (by default true). Newgrf can disable it, though.
Defines the data structure of each individual tile of an airport.
static const AirportTileSpec * Get(StationGfx gfx)
Retrieve airport tile spec for the given airport tile.
GRFFileProps grf_prop
properties related the the grf file
static void ResetAirportTiles()
This function initializes the tile array of AirportTileSpec.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Struct containing information about a single bridge type.
uint16_t price
the price multiplier
uint8_t min_length
the minimum length (not counting start and end tile)
StringID material
the string that contains the bridge description
TimerGameCalendar::Year avail_year
the year where it becomes available
PalSpriteID ** sprite_table
table of sprites for drawing the bridge
StringID transport_name[2]
description of the bridge, when built for road or rail
uint8_t flags
bit 0 set: disable drawing of far pillars.
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
uint16_t max_length
the maximum length (not counting start and end tile)
Canal properties local to the NewGRF.
CanalCallbackMasks callback_mask
Bitmask of canal callbacks that have to be called.
uint8_t flags
Flags controlling display.
Specification of a cargo type.
int32_t initial_payment
Initial payment rate before inflation is applied.
CargoClasses classes
Classes of this cargo type.
uint16_t multiplier
Capacity multiplier for vehicles. (8 fractional bits)
StringID units_volume
Name of a single unit of cargo of this type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
StringID abbrev
Two letter abbreviation for this cargo type.
uint8_t bitnum
Cargo bit number, is INVALID_CARGO_BITNUM for a non-used spec.
StringID quantifier
Text for multiple units of cargo of this type.
SpriteID sprite
Icon to display this cargo type, may be 0xFFF (which means to resolve an action123 chain).
bool is_freight
Cargo type is considered to be freight (affects train freight multiplier).
uint8_t weight
Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
CargoLabel label
Unique label of the cargo type.
const struct GRFFile * grffile
NewGRF where group belongs to.
static IterateWrapper Iterate(size_t from=0)
Returns an iterable ensemble of all valid CargoSpec.
static CargoSpec array[NUM_CARGO]
Array holding all CargoSpecs.
StringID name
Name of this type of cargo.
TownProductionEffect town_production_effect
The effect on town cargo production.
TownAcceptanceEffect town_acceptance_effect
The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
CargoCallbackMasks callback_mask
Bitmask of cargo callbacks that have to be called.
uint16_t town_production_multiplier
Town production multipler, if commanded by TownProductionEffect.
bool IsValid() const
Tests for validity of this cargospec.
StringID name_single
Name of a single entity of this type of cargo.
bool build_on_slopes
allow building on slopes
uint16_t max_bridge_length
maximum length of bridges
uint8_t map_height_limit
the maximum allowed heightlevel
uint8_t train_signal_side
show signals on left / driving / right side
uint8_t parameter
Used for variables between 0x60 and 0x7F inclusive.
A tile child sprite and palette to draw for stations etc, with 3D bounding box.
int8_t delta_z
0x80 identifies child sprites
bool IsParentSprite() const
Check whether this is a parent sprite with a boundingbox.
bool IsTerminator() const
Check whether this is a sequence terminator.
int8_t delta_x
0x80 is sequence terminator
Ground palette sprite of a tile, together with its sprite layout.
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
PalSpriteID ground
Palette and sprite for the ground.
bool inflation
disable inflation
bool allow_town_roads
towns are allowed to build roads (always allowed when generating world / in SE)
bool station_noise_level
build new airports when the town noise level is still within accepted limits
Information about a vehicle.
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
TimerGameCalendar::Year base_life
Basic duration of engine availability (without random parts). 0xFF means infinite life.
LandscapeTypes climates
Climates supported by the engine.
EngineMiscFlags misc_flags
Miscellaneous flags.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
StringID string_id
Default name of engine.
VehicleCallbackMasks callback_mask
Bitmask of vehicle callbacks that have to be called.
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
int8_t retire_early
Number of years early to retire vehicle.
TimerGameCalendar::Year lifelength
Lifetime of a single vehicle.
void ResetToDefaultMapping()
Initializes the EngineOverrideManager with the default engines.
EngineID UseUnreservedID(VehicleType type, uint16_t grf_local_id, uint32_t grfid, bool static_access)
Look for an unreserved EngineID matching the local id, and reserve it if found.
EngineID GetID(VehicleType type, uint16_t grf_local_id, uint32_t grfid)
Looks up an EngineID in the EngineOverrideManager.
GRFFilePropsBase< NUM_CARGO+2 > grf_prop
Properties related the the grf file.
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Information about GRF, used in the game and (part of it) in savegames.
GRFTextWrapper url
NOSAVE: URL belonging to this GRF.
uint8_t palette
GRFPalette, bitset.
GRFTextWrapper info
NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
std::vector< std::optional< GRFParameterInfo > > param_info
NOSAVE: extra information about the parameters.
uint32_t version
NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown.
std::vector< uint32_t > param
GRF parameters.
bool has_param_defaults
NOSAVE: did this newgrf specify any defaults for it's parameters.
GRFTextWrapper name
NOSAVE: GRF name (Action 0x08)
GRFStatus status
NOSAVE: GRFStatus, enum.
std::optional< GRFError > error
NOSAVE: Error/Warning during GRF loading (Action 0x0B)
GRFConfigFlags flags
NOSAVE: GCF_Flags, bitset.
uint8_t num_valid_params
NOSAVE: Number of valid parameters (action 0x14)
std::string filename
Filename - either with or without full path.
GRFIdentifier ident
grfid and md5sum to uniquely identify newgrfs
const char * GetName() const
Get the name of this grf.
uint32_t min_loadable_version
NOSAVE: Minimum compatible version a NewGRF can define.
Information about why GRF had problems during initialisation.
std::array< uint32_t, 2 > param_value
Values of GRF parameters to show for message and custom_message.
StringID message
Default message.
std::string custom_message
Custom message (if present)
std::string data
Additional data for message and custom_message.
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
const struct GRFFile * grffile
grf file that introduced this entity
std::array< const struct SpriteGroup *, Tcnt > spritegroup
pointers to the different sprites of the entity
Dynamic data of a loaded NewGRF.
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoType -> local ID)
std::vector< RailTypeLabel > railtype_list
Railtype translation table.
uint32_t GetParam(uint number) const
Get GRF Parameter with range checking.
CanalProperties canal_local_properties[CF_END]
Canal properties as set by this NewGRF.
GRFFile(const struct GRFConfig &config)
Constructor for GRFFile.
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
uint32_t grf_features
Bitset of GrfSpecFeature the grf uses.
std::vector< RoadTypeLabel > tramtype_list
Roadtype translation table (tram)
std::vector< CargoLabel > cargo_list
Cargo translation table (local ID -> label)
uint traininfo_vehicle_width
Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details.
int traininfo_vehicle_pitch
Vertical offset for drawing train images in depot GUI and vehicle details.
std::unordered_map< uint8_t, LanguageMap > language_map
Mappings related to the languages.
std::vector< GRFLabel > labels
List of labels.
PriceMultipliers price_base_multipliers
Price base multipliers as set by the grf.
uint32_t grfid
GRF ID (defined by Action 0x08)
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
ShoreReplacement shore
In which way shore sprites were replaced.
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
TramReplacement tram
In which way tram depots were replaced.
Information about one grf parameter.
uint8_t param_nr
GRF parameter to store content in.
uint32_t min_value
The minimal value this parameter can have.
uint8_t num_bit
Number of bits to use for this parameter.
uint8_t first_bit
First bit to use in the GRF parameter.
uint32_t max_value
The maximal value of this parameter.
GRFParameterType type
The type of this parameter.
std::vector< ValueName > value_names
Names for each value.
uint32_t def_value
Default value of this parameter.
GRFTextList name
The name of this parameter.
GRFTextList desc
The description of this parameter.
Temporary engine data used when loading only.
CargoTypes ctt_exclude_mask
Cargo types always excluded from the refit mask.
Refittability
Summary state of refittability properties.
@ UNSET
No properties assigned. Default refit masks shall be activated.
@ EMPTY
GRF defined vehicle as not-refittable. The vehicle shall only carry the default cargo.
@ NONEMPTY
GRF defined the vehicle as refittable. If the refitmask is empty after translation (cargotypes not av...
Refittability refittability
Did the newgrf set any refittability property? If not, default refittability will be applied.
CargoClasses cargo_disallowed
Bitmask of cargo classes that are disallowed as a refit.
CargoTypes ctt_include_mask
Cargo types always included in the refit mask.
uint8_t rv_max_speed
Temporary storage of RV prop 15, maximum speed in mph/0.8.
CargoClasses cargo_allowed
Bitmask of cargo classes that are allowed as a refit.
void UpdateRefittability(bool non_empty)
Update the summary refittability on setting a refittability property.
CargoClasses cargo_allowed_required
Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
const GRFFile * defaultcargo_grf
GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
std::vector< NamePartList > partlists[MAX_LISTS]
Lists of town name parts.
static const uint MAX_LISTS
Maximum number of town name lists that can be defined per GRF.
std::vector< TownNameStyle > styles
Style names defined by the Town Name NewGRF.
LandscapeType landscape
the landscape we're currently in
TimerGameCalendar::Year starting_year
starting date
uint32_t generation_seed
noise seed for world generation
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
StationSettings station
settings related to station management
VehicleSettings vehicle
options for vehicles
OrderSettings order
settings related to orders
Definition of a single Action1 spriteset.
uint num_sprites
Number of sprites in the set.
SpriteID sprite
SpriteID of the first sprite of the set.
Temporary data during loading of GRFs.
SpriteFile * file
File of currently processed GRF file.
GRFFile * grffile
Currently processed GRF file.
void AddSpriteSets(uint8_t feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents)
Records new spritesets.
uint32_t nfo_line
Currently processed pseudo sprite number in the GRF.
SpriteID spriteid
First available SpriteID for loading realsprites.
GRFConfig * grfconfig
Config of the currently processed GRF file.
SpriteID GetSprite(uint8_t feature, uint set) const
Returns the first sprite of a spriteset.
bool IsValidSpriteSet(uint8_t feature, uint set) const
Check whether a specific set is defined.
uint GetNumEnts(uint8_t feature, uint set) const
Returns the number of sprites in a spriteset.
bool HasValidSpriteSets(uint8_t feature) const
Check whether there are any valid spritesets for a feature.
std::map< uint, SpriteSet > spritesets[GSF_END]
Currently referenceable spritesets.
void ClearDataForNextFile()
Clear temporary data before processing the next file in the current loading stage.
GrfLoadingStage stage
Current loading stage.
int skip_sprites
Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file)
CargoType accepts_cargo[HOUSE_NUM_ACCEPTS]
input cargo slots
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
CargoLabel accepts_cargo_label[HOUSE_ORIGINAL_NUM_ACCEPTS]
input landscape cargo slots
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
BuildingFlags building_flags
some flags that describe the house (size, stadium etc...)
uint8_t population
population (Zero on other tiles in multi tile house.)
uint8_t cargo_acceptance[HOUSE_NUM_ACCEPTS]
acceptance level for the cargo slots
TimerGameCalendar::Year min_year
introduction year of the house
GRFFileProps grf_prop
Properties related the the grf file.
HouseZones building_availability
where can it be built (climates, zones)
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
CargoType cargo_input[INDUSTRY_NUM_INPUTS]
Which input cargoes to take from (only cb version 2)
CargoType cargo_output[INDUSTRY_NUM_OUTPUTS]
Which output cargoes to add to (only cb version 2)
uint16_t add_output[INDUSTRY_NUM_OUTPUTS]
Add this much output cargo when successful (unsigned, is indirect in cb version 1+)
uint8_t num_input
How many subtract_input values are valid.
int16_t subtract_input[INDUSTRY_NUM_INPUTS]
Take this much of the input cargo (can be negative, is indirect in cb version 1+)
uint8_t version
Production callback version used, or 0xFF if marked invalid.
uint8_t num_output
How many add_output values are valid.
Defines the data structure for constructing industry.
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
StringID name
Displayed name of the industry.
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industries.
IndustryType conflicting[3]
Industries this industry cannot be close to.
GRFFileProps grf_prop
properties related to the grf file
bool enabled
entity still available (by default true).newgrf can disable it, though
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_OUTPUTS > produced_cargo_label
Cargo labels of produced cargo for default industries.
Definition of one tile in an industry tile layout.
Defines the data structure of each individual tile of an industry.
GRFFileProps grf_prop
properties related to the grf file
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industry tiles.
std::array< CargoType, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
Mapping between NewGRF and OpenTTD IDs.
uint8_t newgrf_id
NewGRF's internal ID for a case/gender.
uint8_t openttd_id
OpenTTD's internal ID for a case/gender.
Mapping of language data between a NewGRF and OpenTTD.
static const LanguageMap * GetLanguageMap(uint32_t grfid, uint8_t language_id)
Get the language map associated with a given NewGRF and language.
static debug_inline uint LogX()
Logarithm of the map size along the X side.
static uint LogY()
Logarithm of the map size along the y side.
uint8_t bitcount
Number of bits of random seed to use.
uint16_t maxprob
Total probability of all parts.
std::vector< NamePart > parts
List of parts to choose from.
uint8_t bitstart
Start of random seed bits to use.
uint8_t prob
The relative probability of the following name to appear in the bottom 7 bits.
uint8_t id
If probability bit 7 is set.
std::string text
If probability bit 7 is clear.
NewGRF supplied spritelayout.
void Allocate(uint num_sprites)
Allocate a spritelayout for num_sprites building sprites.
uint consistent_max_offset
Number of sprites in all referenced spritesets.
void Clone(const DrawTileSeqStruct *source)
Clone the building sprites of a spritelayout.
void AllocateRegisters()
Allocate memory for register modifiers.
Allow incrementing of ObjectClassID variables.
GRFFilePropsBase< 2 > grf_prop
Properties related the the grf file.
static void BindToClasses()
Tie all ObjectSpecs to their class.
bool improved_load
improved loading algorithm
bool gradual_loading
load vehicles gradually
Combination of a palette sprite and a 'real' sprite.
SpriteID sprite
The 'real' sprite.
PaletteID pal
The palette (use PAL_NONE) if not needed)
static size_t GetPoolSize()
Returns first unused index.
Tindex index
Index of this pool item.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
void CleanPool() override
Virtual method that deletes all items in the pool.
Describes properties of price bases.
Price fallback_price
Fallback price multiplier for new prices but old grfs.
uint grf_feature
GRF Feature that decides whether price multipliers apply locally or globally, GSF_END if none.
Information about a rail vehicle.
uint16_t power
Power of engine (hp); For multiheaded engines the sum of both engine powers.
uint8_t user_def_data
Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles.
uint8_t running_cost
Running cost of engine; For multiheaded engines the sum of both running costs.
uint8_t cost_factor
Purchase cost factor; For multiheaded engines the sum of both engine prices.
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
RailType intended_railtype
Intended railtype, regardless of elrail being enabled or disabled.
uint16_t pow_wag_power
Extra power applied to consist if wagon should be powered.
uint16_t max_speed
Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
int16_t curve_speed_mod
Modifier to maximum speed in curves (fixed-point binary with 8 fractional bits)
uint16_t weight
Weight of vehicle (tons); For multiheaded engines the weight of each single engine.
uint8_t capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
uint8_t air_drag
Coefficient of air drag.
EngineClass engclass
Class of engine for this vehicle.
uint8_t ai_passenger_only
Bit value to tell AI that this engine is for passenger use only.
RailType railtype
Railtype, mangled if elrail is disabled.
uint8_t tractive_effort
Tractive effort coefficient.
uint8_t pow_wag_weight
Extra weight applied to consist if wagon should be powered.
uint8_t lowest_randbit
Look for this in the per-object randomized bitmask:
VarSpriteGroupScope var_scope
Take this object:
std::vector< const SpriteGroup * > groups
Take the group with appropriate index:
RandomizedSpriteGroupCompareMode cmp_mode
Check for these triggers:
std::vector< const SpriteGroup * > loaded
List of loaded groups (can be SpriteIDs or Callback results)
std::vector< const SpriteGroup * > loading
List of loading groups (can be SpriteIDs or Callback results)
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
Information about a road vehicle.
uint8_t tractive_effort
Coefficient of tractive effort.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
uint8_t air_drag
Coefficient of air drag.
uint8_t power
Power in 10hp units.
RoadType roadtype
Road type.
uint8_t weight
Weight in 1/4t units.
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Iterable ensemble of each set bit in a value.
Information about a ship vehicle.
bool old_refittable
Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask.
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
uint8_t grf_container_ver
NewGRF container version if the sound is from a NewGRF.
bool never_expire_airports
never expire airports
std::unordered_map< uint16_t, std::vector< uint8_t > > layouts
Custom platform layouts, keyed by platform and length combined.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
std::vector< NewGRFSpriteLayout > renderdata
Number of tile layouts.
@ NoWires
Tile should NOT contain catenary wires.
@ Pylons
Tile should contain catenary pylons.
@ Blocked
Tile is blocked to vehicles.
Information for mapping static StringIDs.
uint32_t grfid
Source NewGRF.
std::function< void(StringID)> func
Function for mapping result.
GRFStringID source
Source grf-local GRFStringID.
int16_t x
The x value of the coordinate.
int16_t y
The y value of the coordinate.
Additional modifiers for items in sprite layouts.
uint8_t parent[3]
Registers for signed offsets for the bounding box position of parent sprites.
TileLayoutFlags flags
Flags defining which members are valid and to be used.
uint8_t dodraw
Register deciding whether the sprite shall be drawn at all. Non-zero means drawing.
uint16_t max_sprite_offset
Maximum offset to add to the sprite. (limited by size of the spriteset)
uint8_t palette
Register specifying a signed offset for the palette.
uint8_t sprite_var10
Value for variable 10 when resolving the sprite.
uint16_t max_palette_offset
Maximum offset to add to the palette. (limited by size of the spriteset)
uint8_t palette_var10
Value for variable 10 when resolving the palette.
uint8_t child[2]
Registers for signed offsets for the position of child sprites.
uint8_t sprite
Register specifying a signed offset for the sprite.
Action 2 sprite layout for houses, industry tiles, objects and airport tiles.
uint8_t road_side
the side of the road vehicles drive on
bool wagon_speed_limits
enable wagon speed limits
bool dynamic_engines
enable dynamic allocation of engine data
uint8_t freight_trains
value to multiply the weight of cargo by
uint8_t plane_speed
divisor for speed of aircraft
bool never_expire_vehicles
never expire vehicles
bool disable_elrails
when true, the elrails are disabled
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.
uint8_t _display_opt
What do we want to draw/do?
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
Determines the LiveryScheme for a vehicle.
Base class for all vehicles.
@ VE_TYPE_COUNT
Number of bits used for the effect type.
@ VE_TYPE_START
First bit used for the type of effect.
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
Functions related to vehicles.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.