55 #include "table/strings.h"
72 const 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;
207 template <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)
309 typedef void (*SpecialSpriteHandler)(
ByteReader &buf);
325 RailTypeLabel railtypelabel;
326 uint8_t roadtramtype;
341 }
else if (this->refittability ==
UNSET) {
342 this->refittability =
EMPTY;
347 static std::vector<GRFTempEngineData>
_gted;
362 GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
366 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
371 return this->grfid == other.grfid && this->nfoline == other.nfoline;
375 static std::map<GRFLocation, std::pair<SpriteID, uint16_t>> _grm_sprites;
376 typedef std::map<GRFLocation, std::vector<uint8_t>> GRFLineToSpriteOverride;
377 static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
389 void GrfMsgI(
int severity,
const std::string &msg)
402 if (file->grfid == grfid)
return file;
415 if (file->filename == filename)
return file;
435 if (config !=
nullptr) {
446 if (message == STR_NULL)
return nullptr;
448 config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
450 return &config->error.value();
498 static const StringID units_volume[] = {
499 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
500 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
501 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
502 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
503 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
504 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
505 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
506 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
512 #define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
513 static_assert(stringend - stringid == end - begin); \
514 if (str >= begin && str <= end) return str + (stringid - begin)
517 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
518 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
519 if (str >= 0x004E && str <= 0x006D)
return units_volume[str - 0x004E];
520 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
521 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
522 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
527 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
528 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
529 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
532 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
533 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
534 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
535 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
536 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
539 case 0x4830:
return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
540 case 0x4831:
return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
541 case 0x483B:
return STR_ERROR_CAN_ONLY_BE_POSITIONED;
543 #undef TEXTID_TO_STRINGID
545 if (str == STR_NULL)
return STR_EMPTY;
547 Debug(grf, 0,
"Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
586 static std::map<uint32_t, uint32_t> _grf_id_overrides;
595 if (target_grfid == 0) {
596 _grf_id_overrides.erase(source_grfid);
597 GrfMsg(5,
"SetNewGRFOverride: Removed override of 0x{:X}",
BSWAP32(source_grfid));
599 _grf_id_overrides[source_grfid] = target_grfid;
600 GrfMsg(5,
"SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}",
BSWAP32(source_grfid),
BSWAP32(target_grfid));
616 uint32_t scope_grfid = INVALID_GRFID;
619 scope_grfid = file->grfid;
620 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
621 scope_grfid = it->second;
623 if (grf_match ==
nullptr) {
624 GrfMsg(5,
"Tried mapping from GRFID {:x} to {:x} but target is not loaded",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
626 GrfMsg(5,
"Mapping from GRFID {:x} to {:x}",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
631 EngineID engine = _engine_mngr.
GetID(type, internal_id, scope_grfid);
640 EngineID engine = _engine_mngr.
GetID(type, internal_id, INVALID_GRFID);
646 GrfMsg(5,
"Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
650 if (!static_access) {
652 eid->
grfid = scope_grfid;
658 if (static_access)
return nullptr;
661 GrfMsg(0,
"Can't allocate any more engines");
672 assert(_engine_mngr.size() == e->
index);
673 _engine_mngr.push_back({
688 GrfMsg(5,
"Created new engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
705 uint32_t scope_grfid = INVALID_GRFID;
707 scope_grfid = file->grfid;
708 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
709 scope_grfid = it->second;
713 return _engine_mngr.
GetID(type, internal_id, scope_grfid);
753 grf_sprite->
sprite = buf.ReadWord();
754 grf_sprite->
pal = buf.ReadWord();
759 bool custom_sprite =
HasBit(grf_sprite->
pal, 15) != invert_action1_flag;
763 uint index =
GB(grf_sprite->
sprite, 0, 14);
765 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {}", index);
766 grf_sprite->
sprite = SPR_IMG_QUERY;
767 grf_sprite->
pal = PAL_NONE;
770 if (max_sprite_offset !=
nullptr) *max_sprite_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
775 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
776 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
782 uint index =
GB(grf_sprite->
pal, 0, 14);
784 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {} for 'palette'", index);
785 grf_sprite->
pal = PAL_NONE;
788 if (max_palette_offset !=
nullptr) *max_palette_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
793 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
794 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
823 regs.delta.
parent[0] = buf.ReadByte();
824 regs.delta.
parent[1] = buf.ReadByte();
835 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
sprite_var10,
TLR_MAX_VAR10);
836 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
844 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
palette_var10,
TLR_MAX_VAR10);
845 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
864 bool has_flags =
HasBit(num_building_sprites, 6);
865 ClrBit(num_building_sprites, 6);
868 dts->
Allocate(num_building_sprites);
870 std::vector<uint16_t> max_sprite_offset(num_building_sprites + 1, 0);
871 std::vector<uint16_t> max_palette_offset(num_building_sprites + 1, 0);
878 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses invalid flag 0x{:X} for ground sprite", flags & ~(valid_flags & ~
TLF_NON_GROUND_FLAGS));
879 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
886 for (uint i = 0; i < num_building_sprites; i++) {
889 flags =
ReadSpriteLayoutSprite(buf, has_flags,
false, use_cur_spritesets, feature, &seq->image, max_sprite_offset.data() + i + 1, max_palette_offset.data() + i + 1);
892 if (flags & ~valid_flags) {
893 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses unknown flag 0x{:X}", flags & ~valid_flags);
894 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
899 seq->delta_y = buf.ReadByte();
901 if (!no_z_position) seq->
delta_z = buf.ReadByte();
904 seq->size_x = buf.ReadByte();
905 seq->size_y = buf.ReadByte();
906 seq->size_z = buf.ReadByte();
914 bool is_consistent =
true;
916 for (uint i = 0; i < num_building_sprites + 1; i++) {
917 if (max_sprite_offset[i] > 0) {
921 is_consistent =
false;
925 if (max_palette_offset[i] > 0) {
929 is_consistent =
false;
938 if (!is_consistent || dts->registers !=
nullptr) {
942 for (uint i = 0; i < num_building_sprites + 1; i++) {
957 CargoTypes result = 0;
975 if (base_pointer == 0) {
976 *index = INVALID_PRICE;
980 static const uint32_t start = 0x4B34;
981 static const uint32_t size = 6;
983 if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
984 GrfMsg(1,
"{}: Unsupported running cost base 0x{:04X}, ignoring", error_location, base_pointer);
988 *index = (
Price)((base_pointer - start) / size);
1017 ei->decay_speed = buf.ReadByte();
1034 ei->load_amount = buf.ReadByte();
1056 for (
int i = 0; i < numinfo; i++) {
1065 uint8_t tracktype = buf.ReadByte();
1067 if (tracktype < _cur.grffile->railtype_list.size()) {
1072 switch (tracktype) {
1073 case 0:
_gted[e->
index].railtypelabel = rvi->
engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL;
break;
1074 case 1:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MONO;
break;
1075 case 2:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MAGLEV;
break;
1077 GrfMsg(1,
"RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1090 uint16_t speed = buf.ReadWord();
1091 if (speed == 0xFFFF) speed = 0;
1098 rvi->
power = buf.ReadWord();
1101 if (rvi->
power != 0) {
1119 uint8_t spriteid = buf.ReadByte();
1120 uint8_t orig_spriteid = spriteid;
1124 if (spriteid < 0xFD) spriteid >>= 1;
1126 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1127 rvi->image_index = spriteid;
1129 GrfMsg(1,
"RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1130 rvi->image_index = 0;
1136 uint8_t dual = buf.ReadByte();
1141 rvi->railveh_type = rvi->
power == 0 ?
1153 uint8_t ctype = buf.ReadByte();
1155 if (ctype == 0xFF) {
1157 ei->cargo_type = INVALID_CARGO;
1161 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1168 SB(rvi->
weight, 0, 8, buf.ReadByte());
1176 GrfMsg(2,
"RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1188 uint8_t traction = buf.ReadByte();
1191 if (traction <= 0x07) {
1193 }
else if (traction <= 0x27) {
1195 }
else if (traction <= 0x31) {
1197 }
else if (traction <= 0x37) {
1199 }
else if (traction <= 0x41) {
1225 ei->refit_cost = buf.ReadByte();
1229 uint32_t mask = buf.ReadDWord();
1230 _gted[e->
index].UpdateRefittability(mask != 0);
1267 uint8_t weight = buf.ReadByte();
1270 GrfMsg(2,
"RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1291 _gted[e->
index].cargo_allowed = buf.ReadWord();
1297 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1311 uint8_t count = buf.ReadByte();
1312 _gted[e->
index].UpdateRefittability(prop == 0x2C && count != 0);
1314 CargoTypes &ctt = prop == 0x2C ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1360 for (
int i = 0; i < numinfo; i++) {
1371 _gted[e->
index].roadtramtype = buf.ReadByte() + 1;
1379 rvi->running_cost = buf.ReadByte();
1387 uint8_t spriteid = buf.ReadByte();
1388 uint8_t orig_spriteid = spriteid;
1391 if (spriteid == 0xFF) spriteid = 0xFD;
1393 if (spriteid < 0xFD) spriteid >>= 1;
1395 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1396 rvi->image_index = spriteid;
1398 GrfMsg(1,
"RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1399 rvi->image_index = 0;
1405 rvi->capacity = buf.ReadByte();
1410 uint8_t ctype = buf.ReadByte();
1412 if (ctype == 0xFF) {
1414 ei->cargo_type = INVALID_CARGO;
1418 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1425 rvi->cost_factor = buf.ReadByte();
1433 rvi->
power = buf.ReadByte();
1437 rvi->
weight = buf.ReadByte();
1441 _gted[e->
index].rv_max_speed = buf.ReadByte();
1445 uint32_t mask = buf.ReadDWord();
1446 _gted[e->
index].UpdateRefittability(mask != 0);
1465 ei->refit_cost = buf.ReadByte();
1478 _gted[e->
index].cargo_allowed = buf.ReadWord();
1484 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1516 uint8_t count = buf.ReadByte();
1517 _gted[e->
index].UpdateRefittability(prop == 0x24 && count != 0);
1519 CargoTypes &ctt = prop == 0x24 ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1561 for (
int i = 0; i < numinfo; i++) {
1570 uint8_t spriteid = buf.ReadByte();
1571 uint8_t orig_spriteid = spriteid;
1574 if (spriteid == 0xFF) spriteid = 0xFD;
1576 if (spriteid < 0xFD) spriteid >>= 1;
1578 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1579 svi->image_index = spriteid;
1581 GrfMsg(1,
"ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1582 svi->image_index = 0;
1592 svi->cost_factor = buf.ReadByte();
1601 uint8_t ctype = buf.ReadByte();
1603 if (ctype == 0xFF) {
1605 ei->cargo_type = INVALID_CARGO;
1609 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1616 svi->capacity = buf.ReadWord();
1620 svi->running_cost = buf.ReadByte();
1628 uint32_t mask = buf.ReadDWord();
1629 _gted[e->
index].UpdateRefittability(mask != 0);
1640 ei->refit_cost = buf.ReadByte();
1661 _gted[e->
index].cargo_allowed = buf.ReadWord();
1667 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1695 uint8_t count = buf.ReadByte();
1696 _gted[e->
index].UpdateRefittability(prop == 0x1E && count != 0);
1698 CargoTypes &ctt = prop == 0x1E ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1724 svi->
acceleration = std::max<uint8_t>(1, buf.ReadByte());
1748 for (
int i = 0; i < numinfo; i++) {
1757 uint8_t spriteid = buf.ReadByte();
1758 uint8_t orig_spriteid = spriteid;
1761 if (spriteid == 0xFF) spriteid = 0xFD;
1763 if (spriteid < 0xFD) spriteid >>= 1;
1765 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1766 avi->image_index = spriteid;
1768 GrfMsg(1,
"AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1769 avi->image_index = 0;
1775 if (buf.ReadByte() == 0) {
1787 avi->cost_factor = buf.ReadByte();
1791 avi->
max_speed = (buf.ReadByte() * 128) / 10;
1795 avi->acceleration = buf.ReadByte();
1799 avi->running_cost = buf.ReadByte();
1815 uint32_t mask = buf.ReadDWord();
1816 _gted[e->
index].UpdateRefittability(mask != 0);
1827 ei->refit_cost = buf.ReadByte();
1840 _gted[e->
index].cargo_allowed = buf.ReadWord();
1846 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1864 uint8_t count = buf.ReadByte();
1865 _gted[e->
index].UpdateRefittability(prop == 0x1D && count != 0);
1867 CargoTypes &ctt = prop == 0x1D ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1914 GrfMsg(1,
"StationChangeInfo: Station {} is invalid, max {}, ignoring", stid + numinfo,
NUM_STATIONS_PER_GRF);
1919 if (_cur.
grffile->stations.size() < stid + numinfo) _cur.
grffile->stations.resize(stid + numinfo);
1921 for (
int i = 0; i < numinfo; i++) {
1922 auto &statspec = _cur.
grffile->stations[stid + i];
1925 if (statspec ==
nullptr && prop != 0x08) {
1926 GrfMsg(2,
"StationChangeInfo: Attempt to modify undefined station {}, ignoring", stid + i);
1933 if (statspec ==
nullptr) {
1934 statspec = std::make_unique<StationSpec>();
1938 uint32_t classid = buf.ReadDWord();
1944 uint16_t tiles = buf.ReadExtendedByte();
1945 statspec->renderdata.clear();
1946 statspec->renderdata.reserve(tiles);
1948 for (uint t = 0; t < tiles; t++) {
1952 if (buf.HasData(4) && buf.PeekDWord() == 0) {
1955 dts->
Clone(&_station_display_datas_rail[t % 8]);
1963 static std::vector<DrawTileSeqStruct> tmp_layout;
1970 dtss.
delta_x = buf.ReadByte();
1972 dtss.delta_y = buf.ReadByte();
1973 dtss.
delta_z = buf.ReadByte();
1974 dtss.size_x = buf.ReadByte();
1975 dtss.size_y = buf.ReadByte();
1976 dtss.size_z = buf.ReadByte();
1982 dts->
Clone(tmp_layout.data());
1986 if (statspec->renderdata.size() & 1) {
1987 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
1988 statspec->renderdata.pop_back();
1994 uint16_t srcid = buf.ReadExtendedByte();
1995 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
1997 if (srcstatspec ==
nullptr) {
1998 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid, stid + i);
2002 statspec->renderdata.clear();
2003 statspec->renderdata.reserve(srcstatspec->
renderdata.size());
2005 for (
const auto &it : srcstatspec->
renderdata) {
2013 statspec->callback_mask = buf.ReadByte();
2017 statspec->disallowed_platforms = buf.ReadByte();
2021 statspec->disallowed_lengths = buf.ReadByte();
2025 while (buf.HasData()) {
2026 uint8_t length = buf.ReadByte();
2027 uint8_t number = buf.ReadByte();
2029 if (length == 0 || number == 0)
break;
2031 const uint8_t *buf_layout = buf.ReadBytes(length * number);
2035 layout.assign(buf_layout, buf_layout + length * number);
2038 for (
auto &tile : layout) {
2039 if ((tile & ~1U) != tile) {
2040 GrfMsg(1,
"StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2048 uint16_t srcid = buf.ReadExtendedByte();
2049 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2051 if (srcstatspec ==
nullptr) {
2052 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid, stid + i);
2056 statspec->layouts = srcstatspec->
layouts;
2061 statspec->cargo_threshold = buf.ReadWord();
2065 uint8_t pylons = buf.ReadByte();
2066 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2067 for (
int j = 0; j < 8; ++j) {
2071 statspec->tileflags[j] &= ~
StationSpec::TileFlags::Pylons;
2078 if (_cur.
grffile->grf_version >= 7) {
2081 statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2086 statspec->flags = buf.ReadByte();
2090 uint8_t wires = buf.ReadByte();
2091 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2092 for (
int j = 0; j < 8; ++j) {
2096 statspec->tileflags[j] &= ~
StationSpec::TileFlags::NoWires;
2103 uint8_t blocked = buf.ReadByte();
2104 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2105 for (
int j = 0; j < 8; ++j) {
2106 if (
HasBit(blocked, j)) {
2109 statspec->tileflags[j] &= ~
StationSpec::TileFlags::Blocked;
2116 statspec->animation.
frames = buf.ReadByte();
2117 statspec->animation.status = buf.ReadByte();
2121 statspec->animation.speed = buf.ReadByte();
2125 statspec->animation.triggers = buf.ReadWord();
2131 uint16_t tiles = buf.ReadExtendedByte();
2132 statspec->renderdata.clear();
2133 statspec->renderdata.reserve(tiles);
2135 for (uint t = 0; t < tiles; t++) {
2137 uint num_building_sprites = buf.ReadByte();
2143 if (statspec->renderdata.size() & 1) {
2144 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
2145 statspec->renderdata.pop_back();
2162 AddStringForMapping(buf.ReadWord(), [statspec = statspec.get()](
StringID str) { StationClass::Get(statspec->class_index)->name = str; });
2166 uint16_t tiles = buf.ReadExtendedByte();
2168 statspec->tileflags.assign(flags, flags + tiles);
2193 if (
id + numinfo > CF_END) {
2194 GrfMsg(1,
"CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring",
id + numinfo, CF_END);
2198 for (
int i = 0; i < numinfo; i++) {
2207 cp->
flags = buf.ReadByte();
2232 GrfMsg(1,
"BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", brid + numinfo,
MAX_BRIDGES);
2236 for (
int i = 0; i < numinfo; i++) {
2242 uint8_t year = buf.ReadByte();
2257 bridge->
price = buf.ReadByte();
2261 bridge->
speed = buf.ReadWord();
2262 if (bridge->
speed == 0) bridge->
speed = UINT16_MAX;
2266 uint8_t tableid = buf.ReadByte();
2267 uint8_t numtables = buf.ReadByte();
2274 for (; numtables-- != 0; tableid++) {
2276 GrfMsg(1,
"BridgeChangeInfo: Table {} >= 7, skipping", tableid);
2277 for (uint8_t sprite = 0; sprite < 32; sprite++) buf.ReadDWord();
2282 bridge->
sprite_table[tableid] = MallocT<PalSpriteID>(32);
2285 for (uint8_t sprite = 0; sprite < 32; sprite++) {
2299 bridge->
flags = buf.ReadByte();
2308 if (newone != STR_UNDEFINED) bridge->
material = newone;
2315 if (newone != STR_UNDEFINED) bridge->
transport_name[prop - 0x11] = newone;
2320 bridge->
price = buf.ReadWord();
2377 for (uint j = 0; j < 4; j++) buf.ReadByte();
2381 uint8_t count = buf.ReadByte();
2382 for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2387 buf.Skip(buf.ReadByte() * 2);
2410 GrfMsg(1,
"TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", hid + numinfo,
NUM_HOUSES_PER_GRF);
2415 if (_cur.
grffile->housespec.size() < hid + numinfo) _cur.
grffile->housespec.resize(hid + numinfo);
2417 for (
int i = 0; i < numinfo; i++) {
2418 auto &housespec = _cur.
grffile->housespec[hid + i];
2420 if (prop != 0x08 && housespec ==
nullptr) {
2423 if (cir > ret) ret = cir;
2429 uint8_t subs_id = buf.ReadByte();
2430 if (subs_id == 0xFF) {
2437 GrfMsg(2,
"TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id, hid + i);
2442 if (housespec ==
nullptr) {
2444 housespec = std::make_unique<HouseSpec>(*
HouseSpec::Get(subs_id));
2446 housespec->enabled =
true;
2447 housespec->grf_prop.local_id = hid + i;
2448 housespec->grf_prop.subst_id = subs_id;
2449 housespec->grf_prop.grffile = _cur.
grffile;
2451 housespec->random_colour[0] = COLOUR_RED;
2452 housespec->random_colour[1] = COLOUR_BLUE;
2453 housespec->random_colour[2] = COLOUR_ORANGE;
2454 housespec->random_colour[3] = COLOUR_GREEN;
2457 housespec->building_flags &= ~(BUILDING_IS_CHURCH | BUILDING_IS_STADIUM);
2463 CargoID cid = housespec->accepts_cargo[2];
2464 if (!
IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
2466 housespec->cargo_acceptance[2] = 0;
2473 housespec->building_flags = (BuildingFlags)buf.ReadByte();
2477 uint16_t years = buf.ReadWord();
2484 housespec->population = buf.ReadByte();
2488 housespec->mail_generation = buf.ReadByte();
2493 housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2497 int8_t goods = buf.ReadByte();
2507 housespec->accepts_cargo[2] = cid;
2508 housespec->accepts_cargo_label[2] =
CT_INVALID;
2509 housespec->cargo_acceptance[2] =
abs(goods);
2514 housespec->remove_rating_decrease = buf.ReadWord();
2518 housespec->removal_cost = buf.ReadByte();
2526 housespec->building_availability = (
HouseZones)buf.ReadWord();
2530 housespec->callback_mask |= buf.ReadByte();
2534 uint8_t
override = buf.ReadByte();
2538 GrfMsg(2,
"TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.",
override, hid + i);
2542 _house_mngr.
Add(hid + i, _cur.
grffile->grfid,
override);
2547 housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2551 for (uint j = 0; j < 4; j++) housespec->random_colour[j] =
static_cast<Colours
>(
GB(buf.ReadByte(), 0, 4));
2555 housespec->probability = buf.ReadByte();
2563 housespec->animation.frames = buf.ReadByte();
2564 housespec->animation.status =
GB(housespec->animation.frames, 7, 1);
2565 SB(housespec->animation.frames, 7, 1, 0);
2569 housespec->animation.speed =
Clamp(buf.ReadByte(), 2, 16);
2573 housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.
grffile->grfid);
2577 housespec->callback_mask |= (buf.ReadByte() << 8);
2581 uint32_t cargotypes = buf.ReadDWord();
2584 if (cargotypes == 0xFFFFFFFF)
break;
2588 uint8_t cargo_part =
GB(cargotypes, 8 * j, 8);
2593 housespec->cargo_acceptance[j] = 0;
2595 housespec->accepts_cargo[j] = cargo;
2597 housespec->accepts_cargo_label[j] =
CT_INVALID;
2603 housespec->minimum_life = buf.ReadByte();
2607 uint8_t count = buf.ReadByte();
2608 for (uint8_t j = 0; j < count; j++) {
2616 housespec->min_year = buf.ReadWord();
2620 housespec->max_year = buf.ReadWord();
2625 uint count = buf.ReadByte();
2626 if (count >
lengthof(housespec->accepts_cargo)) {
2634 for (uint i = 0; i <
lengthof(housespec->accepts_cargo); i++) {
2637 housespec->cargo_acceptance[i] = buf.ReadByte();
2639 housespec->accepts_cargo[i] = INVALID_CARGO;
2640 housespec->cargo_acceptance[i] = 0;
2642 housespec->accepts_cargo_label[i] =
CT_INVALID;
2666 if (grffile ==
nullptr)
return nullptr;
2669 if (it == std::end(grffile->
language_map))
return nullptr;
2683 template <
typename T>
2687 GrfMsg(1,
"LoadTranslationTable: {} translation table must start at zero", name);
2691 translation_table.clear();
2692 translation_table.reserve(numinfo);
2693 for (
int i = 0; i < numinfo; i++) {
2694 translation_table.push_back(T(
BSWAP32(buf.ReadDWord())));
2709 for (
int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2743 for (
int i = 0; i < numinfo; i++) {
2746 int factor = buf.ReadByte();
2747 uint price = gvid + i;
2749 if (price < PR_END) {
2752 GrfMsg(1,
"GlobalVarChangeInfo: Price {} out of range, ignoring", price);
2761 if ((newone != STR_UNDEFINED) && (curidx <
CURRENCY_END)) {
2770 uint32_t rate = buf.ReadDWord();
2778 GrfMsg(1,
"GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2785 uint16_t options = buf.ReadWord();
2794 GrfMsg(1,
"GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2806 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2818 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2830 GrfMsg(1,
"GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2837 GrfMsg(1,
"GlobalVarChangeInfo: The snowline can only be set once ({})", numinfo);
2839 GrfMsg(1,
"GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2845 table[i][j] = buf.ReadByte();
2846 if (_cur.
grffile->grf_version >= 8) {
2849 if (table[i][j] >= 128) {
2871 uint curidx = gvid + i;
2873 if (lang ==
nullptr) {
2874 GrfMsg(1,
"GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
2879 while (buf.ReadByte() != 0) {
2887 uint plural_form = buf.ReadByte();
2888 if (plural_form >= LANGUAGE_MAX_PLURAL) {
2889 GrfMsg(1,
"GlobalVarChanceInfo: Plural form {} is out of range, ignoring", plural_form);
2896 uint8_t newgrf_id = buf.ReadByte();
2897 while (newgrf_id != 0) {
2898 std::string_view name = buf.ReadString();
2913 GrfMsg(1,
"GlobalVarChangeInfo: Gender name {} is not known, ignoring",
StrMakeValid(name));
2920 GrfMsg(1,
"GlobalVarChangeInfo: Case name {} is not known, ignoring",
StrMakeValid(name));
2925 newgrf_id = buf.ReadByte();
2961 for (
int i = 0; i < numinfo; i++) {
2985 uint32_t s = buf.ReadDWord();
2986 uint32_t t = buf.ReadDWord();
2993 while (buf.ReadByte() != 0) {
3021 GrfMsg(2,
"CargoChangeInfo: Cargo type {} out of range (max {})", cid + numinfo,
NUM_CARGO - 1);
3025 for (
int i = 0; i < numinfo; i++) {
3030 cs->
bitnum = buf.ReadByte();
3069 cs->
sprite = buf.ReadWord();
3073 cs->
weight = buf.ReadByte();
3077 cs->transit_periods[0] = buf.ReadByte();
3081 cs->transit_periods[1] = buf.ReadByte();
3089 cs->rating_colour = buf.ReadByte();
3093 cs->legend_colour = buf.ReadByte();
3110 uint8_t substitute_type = buf.ReadByte();
3112 switch (substitute_type) {
3119 GrfMsg(1,
"CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3135 cs->
multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3139 uint8_t substitute_type = buf.ReadByte();
3141 switch (substitute_type) {
3145 GrfMsg(1,
"CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3178 if (_cur.
grffile->sound_offset == 0) {
3179 GrfMsg(1,
"SoundEffectChangeInfo: No effects defined, skipping");
3184 GrfMsg(1,
"SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", sid + numinfo,
ORIGINAL_SAMPLE_COUNT + _cur.
grffile->num_sounds);
3188 for (
int i = 0; i < numinfo; i++) {
3193 sound->volume =
Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3197 sound->priority = buf.ReadByte();
3201 SoundID orig_sound = buf.ReadByte();
3204 GrfMsg(1,
"SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound,
ORIGINAL_SAMPLE_COUNT);
3206 SoundEntry *old_sound = GetSound(orig_sound);
3209 *old_sound = *sound;
3251 buf.Skip(buf.ReadByte() * 2);
3274 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", indtid + numinfo,
NUM_INDUSTRYTILES_PER_GRF);
3279 if (_cur.
grffile->indtspec.size() < indtid + numinfo) _cur.
grffile->indtspec.resize(indtid + numinfo);
3281 for (
int i = 0; i < numinfo; i++) {
3282 auto &tsp = _cur.
grffile->indtspec[indtid + i];
3284 if (prop != 0x08 && tsp ==
nullptr) {
3286 if (cir > ret) ret = cir;
3292 uint8_t subs_id = buf.ReadByte();
3295 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id, indtid + i);
3300 if (tsp ==
nullptr) {
3301 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3303 tsp->enabled =
true;
3311 tsp->grf_prop.local_id = indtid + i;
3312 tsp->grf_prop.subst_id = subs_id;
3313 tsp->grf_prop.grffile = _cur.
grffile;
3320 uint8_t ovrid = buf.ReadByte();
3324 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid, indtid + i);
3328 _industile_mngr.
Add(indtid + i, _cur.
grffile->grfid, ovrid);
3335 uint16_t acctp = buf.ReadWord();
3337 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
3338 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
3343 tsp->slopes_refused = (
Slope)buf.ReadByte();
3347 tsp->callback_mask = buf.ReadByte();
3351 tsp->animation.frames = buf.ReadByte();
3352 tsp->animation.status = buf.ReadByte();
3356 tsp->animation.speed = buf.ReadByte();
3360 tsp->animation.triggers = buf.ReadByte();
3368 uint8_t num_cargoes = buf.ReadByte();
3369 if (num_cargoes > std::size(tsp->acceptance)) {
3374 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3375 if (i < num_cargoes) {
3378 tsp->acceptance[i] = (int8_t)buf.ReadByte();
3380 tsp->accepts_cargo[i] = INVALID_CARGO;
3381 tsp->acceptance[i] = 0;
3443 uint8_t num_table = buf.ReadByte();
3444 for (uint8_t j = 0; j < num_table; j++) {
3445 for (uint k = 0;; k++) {
3446 uint8_t x = buf.ReadByte();
3447 if (x == 0xFE && k == 0) {
3453 uint8_t y = buf.ReadByte();
3454 if (x == 0 && y == 0x80)
break;
3456 uint8_t gfx = buf.ReadByte();
3457 if (gfx == 0xFE) buf.ReadWord();
3471 buf.Skip(buf.ReadByte());
3475 int num_inputs = buf.ReadByte();
3476 int num_outputs = buf.ReadByte();
3477 buf.Skip(num_inputs * num_outputs * 2);
3495 const size_t size = layout.size();
3496 if (size == 0)
return false;
3498 for (
size_t i = 0; i < size - 1; i++) {
3499 for (
size_t j = i + 1; j < size; j++) {
3500 if (layout[i].ti.x == layout[j].ti.x &&
3501 layout[i].ti.y == layout[j].ti.y) {
3507 bool have_regular_tile =
false;
3508 for (
const auto &tilelayout : layout) {
3510 have_regular_tile =
true;
3515 return have_regular_tile;
3531 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", indid + numinfo,
NUM_INDUSTRYTYPES_PER_GRF);
3536 if (_cur.
grffile->industryspec.size() < indid + numinfo) _cur.
grffile->industryspec.resize(indid + numinfo);
3538 for (
int i = 0; i < numinfo; i++) {
3539 auto &indsp = _cur.
grffile->industryspec[indid + i];
3541 if (prop != 0x08 && indsp ==
nullptr) {
3543 if (cir > ret) ret = cir;
3549 uint8_t subs_id = buf.ReadByte();
3550 if (subs_id == 0xFF) {
3553 _industry_specs[indid + i].
enabled =
false;
3557 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id, indid + i);
3564 if (indsp ==
nullptr) {
3565 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3567 indsp->enabled =
true;
3568 indsp->grf_prop.local_id = indid + i;
3569 indsp->grf_prop.subst_id = subs_id;
3570 indsp->grf_prop.grffile = _cur.
grffile;
3579 uint8_t ovrid = buf.ReadByte();
3583 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid, indid + i);
3586 indsp->grf_prop.override = ovrid;
3587 _industry_mngr.
Add(indid + i, _cur.
grffile->grfid, ovrid);
3592 uint8_t new_num_layouts = buf.ReadByte();
3593 uint32_t definition_size = buf.ReadDWord();
3594 uint32_t bytes_read = 0;
3595 std::vector<IndustryTileLayout> new_layouts;
3598 for (uint8_t j = 0; j < new_num_layouts; j++) {
3600 layout.reserve(new_num_layouts);
3602 for (uint k = 0;; k++) {
3603 if (bytes_read >= definition_size) {
3604 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.", indid);
3606 definition_size = UINT32_MAX;
3612 it.ti.
x = buf.ReadByte();
3615 if (it.ti.
x == 0xFE && k == 0) {
3617 IndustryType type = buf.ReadByte();
3618 uint8_t laynbr = buf.ReadByte();
3621 if (type >=
lengthof(_origin_industry_specs)) {
3622 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", indid);
3626 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3627 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", indid);
3631 layout = _origin_industry_specs[type].layouts[laynbr];
3635 it.ti.
y = buf.ReadByte();
3638 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
3644 it.gfx = buf.ReadByte();
3647 if (it.gfx == 0xFE) {
3649 int local_tile_id = buf.ReadWord();
3653 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3656 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, indid);
3662 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
3663 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
3672 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
3678 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", indid);
3682 new_layouts.push_back(layout);
3687 indsp->layouts = new_layouts;
3708 indsp->cost_multiplier = buf.ReadByte();
3728 indsp->production_rate[prop - 0x12] = buf.ReadByte();
3732 indsp->minimal_cargo = buf.ReadByte();
3736 uint8_t num_sounds = buf.ReadByte();
3738 std::vector<uint8_t> sounds;
3739 sounds.reserve(num_sounds);
3740 for (uint8_t j = 0; j < num_sounds; ++j) {
3741 sounds.push_back(buf.ReadByte());
3744 indsp->random_sounds = std::move(sounds);
3749 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3761 indsp->map_colour = buf.ReadByte();
3775 uint32_t multiples = buf.ReadDWord();
3776 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
3777 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
3786 indsp->prospecting_chance = buf.ReadDWord();
3791 uint8_t aflag = buf.ReadByte();
3792 SB(indsp->callback_mask, (prop - 0x21) * 8, 8, aflag);
3797 indsp->removal_cost_multiplier = buf.ReadDWord();
3801 uint16_t str = buf.ReadWord();
3803 indsp->station_name = STR_NULL;
3811 uint8_t num_cargoes = buf.ReadByte();
3812 if (num_cargoes > std::size(indsp->produced_cargo)) {
3817 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3818 if (i < num_cargoes) {
3820 indsp->produced_cargo[i] = cargo;
3822 indsp->produced_cargo[i] = INVALID_CARGO;
3830 uint8_t num_cargoes = buf.ReadByte();
3831 if (num_cargoes > std::size(indsp->accepts_cargo)) {
3836 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3837 if (i < num_cargoes) {
3839 indsp->accepts_cargo[i] = cargo;
3841 indsp->accepts_cargo[i] = INVALID_CARGO;
3849 uint8_t num_cargoes = buf.ReadByte();
3850 if (num_cargoes >
lengthof(indsp->production_rate)) {
3855 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
3856 if (i < num_cargoes) {
3857 indsp->production_rate[i] = buf.ReadByte();
3859 indsp->production_rate[i] = 0;
3866 uint8_t num_inputs = buf.ReadByte();
3867 uint8_t num_outputs = buf.ReadByte();
3868 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
3873 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3874 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
3876 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
3877 indsp->input_cargo_multiplier[i][j] = mult;
3905 GrfMsg(1,
"AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", airport + numinfo,
NUM_AIRPORTS_PER_GRF);
3910 if (_cur.
grffile->airportspec.size() < airport + numinfo) _cur.
grffile->airportspec.resize(airport + numinfo);
3912 for (
int i = 0; i < numinfo; i++) {
3913 auto &as = _cur.
grffile->airportspec[airport + i];
3915 if (as ==
nullptr && prop != 0x08 && prop != 0x09) {
3916 GrfMsg(2,
"AirportChangeInfo: Attempt to modify undefined airport {}, ignoring", airport + i);
3922 uint8_t subs_id = buf.ReadByte();
3923 if (subs_id == 0xFF) {
3930 GrfMsg(2,
"AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id, airport + i);
3937 if (as ==
nullptr) {
3941 as->grf_prop.local_id = airport + i;
3942 as->grf_prop.subst_id = subs_id;
3943 as->grf_prop.grffile = _cur.
grffile;
3945 _airport_mngr.
Add(airport + i, _cur.
grffile->grfid, subs_id);
3951 uint8_t num_layouts = buf.ReadByte();
3956 std::vector<AirportTileLayout> layouts;
3957 layouts.reserve(num_layouts);
3959 for (uint8_t j = 0; j != num_layouts; ++j) {
3960 auto &layout = layouts.emplace_back();
3961 layout.rotation =
static_cast<Direction>(buf.ReadByte() & 6);
3964 auto &tile = layout.tiles.emplace_back();
3965 tile.ti.x = buf.ReadByte();
3966 tile.ti.y = buf.ReadByte();
3967 if (tile.ti.x == 0 && tile.ti.y == 0x80) {
3975 tile.gfx = buf.ReadByte();
3977 if (tile.gfx == 0xFE) {
3979 int local_tile_id = buf.ReadWord();
3982 uint16_t tempid = _airporttile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3985 GrfMsg(2,
"AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i);
3990 }
else if (tile.gfx == 0xFF) {
3991 tile.ti.x =
static_cast<int8_t
>(
GB(tile.ti.x, 0, 8));
3992 tile.ti.y =
static_cast<int8_t
>(
GB(tile.ti.y, 0, 8));
3996 if (layout.rotation ==
DIR_E || layout.rotation ==
DIR_W) {
3997 size_x = std::max<uint8_t>(size_x, tile.ti.y + 1);
3998 size_y = std::max<uint8_t>(size_y, tile.ti.x + 1);
4000 size_x = std::max<uint8_t>(size_x, tile.ti.x + 1);
4001 size_y = std::max<uint8_t>(size_y, tile.ti.y + 1);
4005 as->layouts = std::move(layouts);
4006 as->size_x = size_x;
4007 as->size_y = size_y;
4012 as->min_year = buf.ReadWord();
4013 as->max_year = buf.ReadWord();
4026 as->noise_level = buf.ReadByte();
4034 as->maintenance_cost = buf.ReadWord();
4104 GrfMsg(1,
"ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.",
id + numinfo,
NUM_OBJECTS_PER_GRF);
4109 if (_cur.
grffile->objectspec.size() <
id + numinfo) _cur.
grffile->objectspec.resize(
id + numinfo);
4111 for (
int i = 0; i < numinfo; i++) {
4112 auto &spec = _cur.
grffile->objectspec[
id + i];
4114 if (prop != 0x08 && spec ==
nullptr) {
4117 if (cir > ret) ret = cir;
4124 if (spec ==
nullptr) {
4125 spec = std::make_unique<ObjectSpec>();
4131 uint32_t classid = buf.ReadDWord();
4146 spec->climate = buf.ReadByte();
4150 spec->size = buf.ReadByte();
4151 if (
GB(spec->size, 0, 4) == 0 ||
GB(spec->size, 4, 4) == 0) {
4152 GrfMsg(0,
"ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size,
id + i);
4158 spec->build_cost_multiplier = buf.ReadByte();
4159 spec->clear_cost_multiplier = spec->build_cost_multiplier;
4163 spec->introduction_date = buf.ReadDWord();
4167 spec->end_of_life_date = buf.ReadDWord();
4176 spec->animation.frames = buf.ReadByte();
4177 spec->animation.status = buf.ReadByte();
4181 spec->animation.speed = buf.ReadByte();
4185 spec->animation.triggers = buf.ReadWord();
4189 spec->clear_cost_multiplier = buf.ReadByte();
4193 spec->callback_mask = buf.ReadWord();
4197 spec->height = buf.ReadByte();
4201 spec->views = buf.ReadByte();
4202 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
4203 GrfMsg(2,
"ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views,
id + i);
4209 spec->generate_amount = buf.ReadByte();
4236 GrfMsg(1,
"RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4240 for (
int i = 0; i < numinfo; i++) {
4253 uint16_t str = buf.ReadWord();
4255 if (_cur.
grffile->grf_version < 8) {
4285 int n = buf.ReadByte();
4286 for (
int j = 0; j != n; j++) {
4287 RailTypeLabel label = buf.ReadDWord();
4347 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4366 GrfMsg(1,
"RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4370 for (
int i = 0; i < numinfo; i++) {
4374 RailTypeLabel rtl = buf.ReadDWord();
4383 _cur.
grffile->railtype_map[
id + i] = rt;
4401 int n = buf.ReadByte();
4402 for (
int j = 0; j != n; j++) {
4407 GrfMsg(1,
"RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set",
id + i);
4414 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4455 GrfMsg(1,
"RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4459 for (
int i = 0; i < numinfo; i++) {
4472 uint16_t str = buf.ReadWord();
4499 int n = buf.ReadByte();
4500 for (
int j = 0; j != n; j++) {
4501 RoadTypeLabel label = buf.ReadDWord();
4506 if (GetRoadTramType(resolved_rt) == rtt) {
4509 GrfMsg(1,
"RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4554 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4585 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4589 for (
int i = 0; i < numinfo; i++) {
4592 RoadTypeLabel rtl = buf.ReadDWord();
4599 }
else if (GetRoadTramType(rt) != rtt) {
4600 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring",
id + numinfo);
4604 type_map[
id + i] = rt;
4621 int n = buf.ReadByte();
4622 for (
int j = 0; j != n; j++) {
4627 GrfMsg(1,
"RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set",
id + i);
4633 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4657 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_ROAD);
4662 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_TRAM);
4670 GrfMsg(1,
"AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", airtid + numinfo,
NUM_AIRPORTTILES_PER_GRF);
4675 if (_cur.
grffile->airtspec.size() < airtid + numinfo) _cur.
grffile->airtspec.resize(airtid + numinfo);
4677 for (
int i = 0; i < numinfo; i++) {
4678 auto &tsp = _cur.
grffile->airtspec[airtid + i];
4680 if (prop != 0x08 && tsp ==
nullptr) {
4681 GrfMsg(2,
"AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.", airtid + i);
4687 uint8_t subs_id = buf.ReadByte();
4690 GrfMsg(2,
"AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id, airtid + i);
4695 if (tsp ==
nullptr) {
4698 tsp->enabled =
true;
4702 tsp->grf_prop.local_id = airtid + i;
4703 tsp->grf_prop.subst_id = subs_id;
4704 tsp->grf_prop.grffile = _cur.
grffile;
4711 uint8_t
override = buf.ReadByte();
4715 GrfMsg(2,
"AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.",
override, airtid + i);
4719 _airporttile_mngr.
Add(airtid + i, _cur.
grffile->grfid,
override);
4724 tsp->callback_mask = buf.ReadByte();
4728 tsp->animation.frames = buf.ReadByte();
4729 tsp->animation.status = buf.ReadByte();
4733 tsp->animation.speed = buf.ReadByte();
4737 tsp->animation.triggers = buf.ReadByte();
4794 GrfMsg(1,
"RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring",
id + numinfo,
NUM_ROADSTOPS_PER_GRF);
4798 if (_cur.
grffile->roadstops.size() <
id + numinfo) _cur.
grffile->roadstops.resize(
id + numinfo);
4800 for (
int i = 0; i < numinfo; i++) {
4801 auto &rs = _cur.
grffile->roadstops[
id + i];
4803 if (rs ==
nullptr && prop != 0x08) {
4804 GrfMsg(1,
"RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring",
id + i);
4806 if (cir > ret) ret = cir;
4812 if (rs ==
nullptr) {
4813 rs = std::make_unique<RoadStopSpec>();
4816 uint32_t classid = buf.ReadDWord();
4842 rs->animation.frames = buf.ReadByte();
4843 rs->animation.status = buf.ReadByte();
4847 rs->animation.speed = buf.ReadByte();
4851 rs->animation.triggers = buf.ReadWord();
4855 rs->callback_mask = buf.ReadByte();
4859 rs->flags = (uint16_t)buf.ReadDWord();
4863 rs->build_cost_multiplier = buf.ReadByte();
4864 rs->clear_cost_multiplier = buf.ReadByte();
4876 static bool HandleChangeInfoResult(
const char *caller,
ChangeInfoResult cir, uint8_t feature, uint8_t property)
4879 default: NOT_REACHED();
4889 GrfMsg(1,
"{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
4893 GrfMsg(0,
"{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
4906 static void FeatureChangeInfo(
ByteReader &buf)
4919 static const VCI_Handler handler[] = {
4937 AirportTilesChangeInfo,
4942 static_assert(GSF_END ==
lengthof(handler));
4944 uint8_t feature = buf.ReadByte();
4945 uint8_t numprops = buf.ReadByte();
4946 uint numinfo = buf.ReadByte();
4947 uint engine = buf.ReadExtendedByte();
4949 if (feature >= GSF_END) {
4950 GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4954 GrfMsg(6,
"FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
4955 feature, numprops, engine, numinfo);
4957 if (handler[feature] ==
nullptr) {
4958 if (feature != GSF_CARGOES) GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4965 while (numprops-- && buf.HasData()) {
4966 uint8_t prop = buf.ReadByte();
4969 if (HandleChangeInfoResult(
"FeatureChangeInfo", cir, feature, prop))
return;
4976 uint8_t feature = buf.ReadByte();
4977 uint8_t numprops = buf.ReadByte();
4978 uint numinfo = buf.ReadByte();
4979 buf.ReadExtendedByte();
4981 if (feature == GSF_BRIDGES && numprops == 1) {
4982 uint8_t prop = buf.ReadByte();
4985 if (prop == 0x0D)
return;
4986 }
else if (feature == GSF_GLOBALVAR && numprops == 1) {
4987 uint8_t prop = buf.ReadByte();
4990 bool is_safe =
true;
4991 for (uint i = 0; i < numinfo; i++) {
4992 uint32_t s = buf.ReadDWord();
5000 if (is_safe)
return;
5011 static void ReserveChangeInfo(
ByteReader &buf)
5013 uint8_t feature = buf.ReadByte();
5015 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES)
return;
5017 uint8_t numprops = buf.ReadByte();
5018 uint8_t numinfo = buf.ReadByte();
5019 uint8_t index = buf.ReadExtendedByte();
5021 while (numprops-- && buf.HasData()) {
5022 uint8_t prop = buf.ReadByte();
5026 default: NOT_REACHED();
5032 cir = GlobalVarReserveInfo(index, numinfo, prop, buf);
5036 cir = RailTypeReserveInfo(index, numinfo, prop, buf);
5040 cir = RoadTypeReserveInfo(index, numinfo, prop, buf);
5044 cir = TramTypeReserveInfo(index, numinfo, prop, buf);
5048 if (HandleChangeInfoResult(
"ReserveChangeInfo", cir, feature, prop))
return;
5069 uint8_t feature = buf.ReadByte();
5070 uint16_t num_sets = buf.ReadByte();
5071 uint16_t first_set = 0;
5073 if (num_sets == 0 && buf.HasData(3)) {
5076 first_set = buf.ReadExtendedByte();
5077 num_sets = buf.ReadExtendedByte();
5079 uint16_t num_ents = buf.ReadExtendedByte();
5081 if (feature >= GSF_END) {
5083 GrfMsg(1,
"NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.
skip_sprites);
5089 GrfMsg(7,
"New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
5090 _cur.
spriteid, feature, num_sets, num_ents, num_sets * num_ents
5093 for (
int i = 0; i < num_sets * num_ents; i++) {
5103 uint16_t num_sets = buf.ReadByte();
5105 if (num_sets == 0 && buf.HasData(3)) {
5108 buf.ReadExtendedByte();
5109 num_sets = buf.ReadExtendedByte();
5111 uint16_t num_ents = buf.ReadExtendedByte();
5115 GrfMsg(3,
"SkipAct1: Skipping {} sprites", _cur.
skip_sprites);
5120 static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5122 if (
HasBit(groupid, 15)) {
5127 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5128 GrfMsg(1,
"GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
5132 return _cur.spritegroups[groupid];
5145 if (
HasBit(spriteid, 15)) {
5151 GrfMsg(1,
"CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5156 uint num_sprites = _cur.
GetNumEnts(feature, spriteid);
5159 assert(spriteset_start + num_sprites <= _cur.
spriteid);
5180 uint8_t feature = buf.ReadByte();
5181 if (feature >= GSF_END) {
5182 GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5186 uint8_t setid = buf.ReadByte();
5187 uint8_t type = buf.ReadByte();
5211 switch (
GB(type, 2, 2)) {
5212 default: NOT_REACHED();
5213 case 0: group->size = DSG_SIZE_BYTE; varsize = 1;
break;
5214 case 1: group->size = DSG_SIZE_WORD; varsize = 2;
break;
5215 case 2: group->size = DSG_SIZE_DWORD; varsize = 4;
break;
5225 adjust.variable = buf.ReadByte();
5226 if (adjust.variable == 0x7E) {
5228 adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5233 varadjust = buf.ReadByte();
5234 adjust.shift_num =
GB(varadjust, 0, 5);
5235 adjust.type = (DeterministicSpriteGroupAdjustType)
GB(varadjust, 6, 2);
5236 adjust.and_mask = buf.ReadVarSize(varsize);
5238 if (adjust.type != DSGA_TYPE_NONE) {
5239 adjust.add_val = buf.ReadVarSize(varsize);
5240 adjust.divmod_val = buf.ReadVarSize(varsize);
5243 adjust.divmod_val = 0;
5247 }
while (
HasBit(varadjust, 5));
5249 std::vector<DeterministicSpriteGroupRange> ranges;
5250 ranges.resize(buf.ReadByte());
5251 for (
auto &range : ranges) {
5252 range.group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5253 range.low = buf.ReadVarSize(varsize);
5254 range.high = buf.ReadVarSize(varsize);
5257 group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5258 group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5260 group->calculated_result = ranges.empty();
5263 std::vector<uint32_t> bounds;
5264 bounds.reserve(ranges.size());
5265 for (
const auto &range : ranges) {
5266 bounds.push_back(range.low);
5267 if (range.high != UINT32_MAX) bounds.push_back(range.high + 1);
5269 std::sort(bounds.begin(), bounds.end());
5270 bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5272 std::vector<const SpriteGroup *> target;
5273 target.reserve(bounds.size());
5274 for (
const auto &bound : bounds) {
5276 for (
const auto &range : ranges) {
5277 if (range.low <= bound && bound <= range.high) {
5282 target.push_back(t);
5284 assert(target.size() == bounds.size());
5286 for (uint j = 0; j < bounds.size(); ) {
5287 if (target[j] != group->default_group) {
5289 r.group = target[j];
5291 while (j < bounds.size() && target[j] == r.group) {
5294 r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5316 group->count = buf.ReadByte();
5319 uint8_t triggers = buf.ReadByte();
5320 group->triggers =
GB(triggers, 0, 7);
5321 group->
cmp_mode =
HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
5324 uint8_t num_groups = buf.ReadByte();
5326 GrfMsg(1,
"NewSpriteGroup: Random Action 2 nrand should be power of 2");
5329 group->
groups.reserve(num_groups);
5330 for (uint i = 0; i < num_groups; i++) {
5331 group->
groups.push_back(GetGroupFromGroupID(setid, type, buf.ReadWord()));
5342 case GSF_ROADVEHICLES:
5353 uint8_t num_loaded = type;
5354 uint8_t num_loading = buf.ReadByte();
5357 GrfMsg(0,
"NewSpriteGroup: No sprite set to work on! Skipping");
5361 GrfMsg(6,
"NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5362 setid, num_loaded, num_loading);
5364 if (num_loaded + num_loading == 0) {
5365 GrfMsg(1,
"NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5369 if (num_loaded + num_loading == 1) {
5371 uint16_t spriteid = buf.ReadWord();
5373 GrfMsg(8,
"NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5377 std::vector<uint16_t> loaded;
5378 std::vector<uint16_t> loading;
5380 loaded.reserve(num_loaded);
5381 for (uint i = 0; i < num_loaded; i++) {
5382 loaded.push_back(buf.ReadWord());
5383 GrfMsg(8,
"NewSpriteGroup: + rg->loaded[{}] = subset {}", i, loaded[i]);
5386 loading.reserve(num_loading);
5387 for (uint i = 0; i < num_loading; i++) {
5388 loading.push_back(buf.ReadWord());
5389 GrfMsg(8,
"NewSpriteGroup: + rg->loading[{}] = subset {}", i, loading[i]);
5392 bool loaded_same = !loaded.empty() && std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end();
5393 bool loading_same = !loading.empty() && std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end();
5394 if (loaded_same && loading_same && loaded[0] == loading[0]) {
5397 GrfMsg(8,
"NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5406 if (loaded_same && loaded.size() > 1) loaded.resize(1);
5407 group->
loaded.reserve(loaded.size());
5408 for (uint16_t spriteid : loaded) {
5410 group->
loaded.push_back(t);
5413 if (loading_same && loading.size() > 1) loading.resize(1);
5414 group->
loading.reserve(loading.size());
5415 for (uint16_t spriteid : loading) {
5424 case GSF_AIRPORTTILES:
5426 case GSF_INDUSTRYTILES:
5427 case GSF_ROADSTOPS: {
5428 uint8_t num_building_sprites = std::max((uint8_t)1, type);
5436 if (
ReadSpriteLayout(buf, num_building_sprites,
true, feature,
false, type == 0, &group->dts))
return;
5440 case GSF_INDUSTRIES: {
5442 GrfMsg(1,
"NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5460 group->again = buf.ReadByte();
5461 }
else if (type == 1) {
5470 group->again = buf.ReadByte();
5471 }
else if (type == 2) {
5475 error->
data =
"too many inputs (max 16)";
5478 for (uint i = 0; i < group->
num_input; i++) {
5479 uint8_t rawcargo = buf.ReadByte();
5488 error->
data =
"duplicate input cargo";
5497 error->
data =
"too many outputs (max 16)";
5500 for (uint i = 0; i < group->
num_output; i++) {
5501 uint8_t rawcargo = buf.ReadByte();
5508 error->
data =
"duplicate output cargo";
5514 group->again = buf.ReadByte();
5522 default: GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5527 _cur.spritegroups[setid] = act_group;
5530 static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
5538 GrfMsg(1,
"TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (
unsigned int)_cur.
grffile->
cargo_list.size() - 1);
5539 return INVALID_CARGO;
5545 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5546 return INVALID_CARGO;
5549 CargoID cid = GetCargoIDByLabel(cl);
5551 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));
5552 return INVALID_CARGO;
5555 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), cid);
5560 static bool IsValidGroupID(uint16_t groupid,
const char *
function)
5562 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5563 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.",
function, groupid);
5570 static void VehicleMapSpriteGroup(
ByteReader &buf, uint8_t feature, uint8_t idcount)
5572 static std::vector<EngineID> last_engines;
5573 bool wagover =
false;
5576 if (
HasBit(idcount, 7)) {
5579 idcount =
GB(idcount, 0, 7);
5581 if (last_engines.empty()) {
5582 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5586 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5588 last_engines.resize(idcount);
5591 std::vector<EngineID> engines;
5592 engines.reserve(idcount);
5593 for (uint i = 0; i < idcount; i++) {
5599 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, 0, 0);
5603 engines.push_back(e->
index);
5604 if (!wagover) last_engines[i] = engines[i];
5607 uint8_t cidcount = buf.ReadByte();
5608 for (uint c = 0; c < cidcount; c++) {
5609 uint8_t ctype = buf.ReadByte();
5610 uint16_t groupid = buf.ReadWord();
5611 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
5613 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5615 CargoID cid = TranslateCargo(feature, ctype);
5618 for (uint i = 0; i < idcount; i++) {
5621 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5624 SetWagonOverrideSprites(engine, cid, _cur.spritegroups[groupid], last_engines);
5626 SetCustomEngineSprites(engine, cid, _cur.spritegroups[groupid]);
5631 uint16_t groupid = buf.ReadWord();
5632 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
5634 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
5636 for (uint i = 0; i < idcount; i++) {
5649 static void CanalMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5651 std::vector<uint16_t> cfs;
5652 cfs.reserve(idcount);
5653 for (uint i = 0; i < idcount; i++) {
5654 cfs.push_back(buf.ReadExtendedByte());
5657 uint8_t cidcount = buf.ReadByte();
5658 buf.Skip(cidcount * 3);
5660 uint16_t groupid = buf.ReadWord();
5661 if (!IsValidGroupID(groupid,
"CanalMapSpriteGroup"))
return;
5663 for (
auto &cf : cfs) {
5665 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5675 static void StationMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5677 if (_cur.
grffile->stations.empty()) {
5678 GrfMsg(1,
"StationMapSpriteGroup: No stations defined, skipping");
5682 std::vector<uint16_t> stations;
5683 stations.reserve(idcount);
5684 for (uint i = 0; i < idcount; i++) {
5685 stations.push_back(buf.ReadExtendedByte());
5688 uint8_t cidcount = buf.ReadByte();
5689 for (uint c = 0; c < cidcount; c++) {
5690 uint8_t ctype = buf.ReadByte();
5691 uint16_t groupid = buf.ReadWord();
5692 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
continue;
5694 ctype = TranslateCargo(GSF_STATIONS, ctype);
5697 for (
auto &station : stations) {
5700 if (statspec ==
nullptr) {
5701 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5709 uint16_t groupid = buf.ReadWord();
5710 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
return;
5712 for (
auto &station : stations) {
5715 if (statspec ==
nullptr) {
5716 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5721 GrfMsg(1,
"StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
5733 static void TownHouseMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5735 if (_cur.
grffile->housespec.empty()) {
5736 GrfMsg(1,
"TownHouseMapSpriteGroup: No houses defined, skipping");
5740 std::vector<uint16_t> houses;
5741 houses.reserve(idcount);
5742 for (uint i = 0; i < idcount; i++) {
5743 houses.push_back(buf.ReadExtendedByte());
5747 uint8_t cidcount = buf.ReadByte();
5748 buf.Skip(cidcount * 3);
5750 uint16_t groupid = buf.ReadWord();
5751 if (!IsValidGroupID(groupid,
"TownHouseMapSpriteGroup"))
return;
5753 for (
auto &house : houses) {
5756 if (hs ==
nullptr) {
5757 GrfMsg(1,
"TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
5765 static void IndustryMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5767 if (_cur.
grffile->industryspec.empty()) {
5768 GrfMsg(1,
"IndustryMapSpriteGroup: No industries defined, skipping");
5772 std::vector<uint16_t> industries;
5773 industries.reserve(idcount);
5774 for (uint i = 0; i < idcount; i++) {
5775 industries.push_back(buf.ReadExtendedByte());
5779 uint8_t cidcount = buf.ReadByte();
5780 buf.Skip(cidcount * 3);
5782 uint16_t groupid = buf.ReadWord();
5783 if (!IsValidGroupID(groupid,
"IndustryMapSpriteGroup"))
return;
5785 for (
auto &industry : industries) {
5788 if (indsp ==
nullptr) {
5789 GrfMsg(1,
"IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
5797 static void IndustrytileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5799 if (_cur.
grffile->indtspec.empty()) {
5800 GrfMsg(1,
"IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
5804 std::vector<uint16_t> indtiles;
5805 indtiles.reserve(idcount);
5806 for (uint i = 0; i < idcount; i++) {
5807 indtiles.push_back(buf.ReadExtendedByte());
5811 uint8_t cidcount = buf.ReadByte();
5812 buf.Skip(cidcount * 3);
5814 uint16_t groupid = buf.ReadWord();
5815 if (!IsValidGroupID(groupid,
"IndustrytileMapSpriteGroup"))
return;
5817 for (
auto &indtile : indtiles) {
5820 if (indtsp ==
nullptr) {
5821 GrfMsg(1,
"IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
5829 static void CargoMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5831 std::vector<uint16_t> cargoes;
5832 cargoes.reserve(idcount);
5833 for (uint i = 0; i < idcount; i++) {
5834 cargoes.push_back(buf.ReadExtendedByte());
5838 uint8_t cidcount = buf.ReadByte();
5839 buf.Skip(cidcount * 3);
5841 uint16_t groupid = buf.ReadWord();
5842 if (!IsValidGroupID(groupid,
"CargoMapSpriteGroup"))
return;
5844 for (
auto &cid : cargoes) {
5846 GrfMsg(1,
"CargoMapSpriteGroup: Cargo ID {} out of range, skipping", cid);
5852 cs->group = _cur.spritegroups[groupid];
5856 static void ObjectMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5858 if (_cur.
grffile->objectspec.empty()) {
5859 GrfMsg(1,
"ObjectMapSpriteGroup: No object tiles defined, skipping");
5863 std::vector<uint16_t> objects;
5864 objects.reserve(idcount);
5865 for (uint i = 0; i < idcount; i++) {
5866 objects.push_back(buf.ReadExtendedByte());
5869 uint8_t cidcount = buf.ReadByte();
5870 for (uint c = 0; c < cidcount; c++) {
5871 uint8_t ctype = buf.ReadByte();
5872 uint16_t groupid = buf.ReadWord();
5873 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
continue;
5876 if (ctype != 0xFF) {
5877 GrfMsg(1,
"ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
5881 for (
auto &
object : objects) {
5884 if (spec ==
nullptr) {
5885 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5893 uint16_t groupid = buf.ReadWord();
5894 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
return;
5896 for (
auto &
object : objects) {
5899 if (spec ==
nullptr) {
5900 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5905 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} mapped multiple times, skipping",
object);
5915 static void RailTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5917 std::vector<uint8_t> railtypes;
5918 railtypes.reserve(idcount);
5919 for (uint i = 0; i < idcount; i++) {
5920 uint16_t
id = buf.ReadExtendedByte();
5921 railtypes.push_back(id < RAILTYPE_END ? _cur.grffile->railtype_map[
id] :
INVALID_RAILTYPE);
5924 uint8_t cidcount = buf.ReadByte();
5925 for (uint c = 0; c < cidcount; c++) {
5926 uint8_t ctype = buf.ReadByte();
5927 uint16_t groupid = buf.ReadWord();
5928 if (!IsValidGroupID(groupid,
"RailTypeMapSpriteGroup"))
continue;
5930 if (ctype >= RTSG_END)
continue;
5933 for (
auto &railtype : railtypes) {
5938 rti->
group[ctype] = _cur.spritegroups[groupid];
5947 static void RoadTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount, RoadTramType rtt)
5951 std::vector<uint8_t> roadtypes;
5952 roadtypes.reserve(idcount);
5953 for (uint i = 0; i < idcount; i++) {
5954 uint16_t
id = buf.ReadExtendedByte();
5958 uint8_t cidcount = buf.ReadByte();
5959 for (uint c = 0; c < cidcount; c++) {
5960 uint8_t ctype = buf.ReadByte();
5961 uint16_t groupid = buf.ReadWord();
5962 if (!IsValidGroupID(groupid,
"RoadTypeMapSpriteGroup"))
continue;
5964 if (ctype >= ROTSG_END)
continue;
5967 for (
auto &roadtype : roadtypes) {
5972 rti->
group[ctype] = _cur.spritegroups[groupid];
5981 static void AirportMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5983 if (_cur.
grffile->airportspec.empty()) {
5984 GrfMsg(1,
"AirportMapSpriteGroup: No airports defined, skipping");
5988 std::vector<uint16_t> airports;
5989 airports.reserve(idcount);
5990 for (uint i = 0; i < idcount; i++) {
5991 airports.push_back(buf.ReadExtendedByte());
5995 uint8_t cidcount = buf.ReadByte();
5996 buf.Skip(cidcount * 3);
5998 uint16_t groupid = buf.ReadWord();
5999 if (!IsValidGroupID(groupid,
"AirportMapSpriteGroup"))
return;
6001 for (
auto &airport : airports) {
6004 if (as ==
nullptr) {
6005 GrfMsg(1,
"AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6013 static void AirportTileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6015 if (_cur.
grffile->airtspec.empty()) {
6016 GrfMsg(1,
"AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6020 std::vector<uint16_t> airptiles;
6021 airptiles.reserve(idcount);
6022 for (uint i = 0; i < idcount; i++) {
6023 airptiles.push_back(buf.ReadExtendedByte());
6027 uint8_t cidcount = buf.ReadByte();
6028 buf.Skip(cidcount * 3);
6030 uint16_t groupid = buf.ReadWord();
6031 if (!IsValidGroupID(groupid,
"AirportTileMapSpriteGroup"))
return;
6033 for (
auto &airptile : airptiles) {
6036 if (airtsp ==
nullptr) {
6037 GrfMsg(1,
"AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6045 static void RoadStopMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6047 if (_cur.
grffile->roadstops.empty()) {
6048 GrfMsg(1,
"RoadStopMapSpriteGroup: No roadstops defined, skipping");
6052 std::vector<uint16_t> roadstops;
6053 roadstops.reserve(idcount);
6054 for (uint i = 0; i < idcount; i++) {
6055 roadstops.push_back(buf.ReadExtendedByte());
6058 uint8_t cidcount = buf.ReadByte();
6059 for (uint c = 0; c < cidcount; c++) {
6060 uint8_t ctype = buf.ReadByte();
6061 uint16_t groupid = buf.ReadWord();
6062 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
continue;
6064 ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6067 for (
auto &roadstop : roadstops) {
6070 if (roadstopspec ==
nullptr) {
6071 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6079 uint16_t groupid = buf.ReadWord();
6080 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
return;
6082 for (
auto &roadstop : roadstops) {
6085 if (roadstopspec ==
nullptr) {
6086 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6091 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6103 static void FeatureMapSpriteGroup(
ByteReader &buf)
6119 uint8_t feature = buf.ReadByte();
6120 uint8_t idcount = buf.ReadByte();
6122 if (feature >= GSF_END) {
6123 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6131 uint16_t groupid = buf.ReadWord();
6132 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
6134 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6143 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6147 case GSF_ROADVEHICLES:
6150 VehicleMapSpriteGroup(buf, feature, idcount);
6154 CanalMapSpriteGroup(buf, idcount);
6158 StationMapSpriteGroup(buf, idcount);
6162 TownHouseMapSpriteGroup(buf, idcount);
6165 case GSF_INDUSTRIES:
6166 IndustryMapSpriteGroup(buf, idcount);
6169 case GSF_INDUSTRYTILES:
6170 IndustrytileMapSpriteGroup(buf, idcount);
6174 CargoMapSpriteGroup(buf, idcount);
6178 AirportMapSpriteGroup(buf, idcount);
6182 ObjectMapSpriteGroup(buf, idcount);
6186 RailTypeMapSpriteGroup(buf, idcount);
6190 RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6194 RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6197 case GSF_AIRPORTTILES:
6198 AirportTileMapSpriteGroup(buf, idcount);
6202 RoadStopMapSpriteGroup(buf, idcount);
6206 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6230 bool new_scheme = _cur.
grffile->grf_version >= 7;
6232 uint8_t feature = buf.ReadByte();
6233 if (feature >= GSF_END && feature != 0x48) {
6234 GrfMsg(1,
"FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6238 uint8_t lang = buf.ReadByte();
6239 uint8_t num = buf.ReadByte();
6240 bool generic =
HasBit(lang, 7);
6243 id = buf.ReadWord();
6244 }
else if (feature <= GSF_AIRCRAFT) {
6245 id = buf.ReadExtendedByte();
6247 id = buf.ReadByte();
6252 uint16_t endid =
id + num;
6254 GrfMsg(6,
"FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6255 id, endid, feature, lang);
6257 for (;
id < endid && buf.HasData();
id++) {
6258 const std::string_view name = buf.ReadString();
6259 GrfMsg(8,
"FeatureNewName: 0x{:04X} <- {}",
id,
StrMakeValid(name));
6263 case GSF_ROADVEHICLES:
6268 if (e ==
nullptr)
break;
6282 switch (
GB(
id, 8, 8)) {
6284 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6285 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6293 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6294 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6301 if (
GB(
id, 0, 8) >= _cur.
grffile->airtspec.size() || _cur.
grffile->airtspec[
GB(
id, 0, 8)] ==
nullptr) {
6302 GrfMsg(1,
"FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring",
GB(
id, 0, 8));
6309 if (
GB(
id, 0, 8) >= _cur.
grffile->housespec.size() || _cur.
grffile->housespec[
GB(
id, 0, 8)] ==
nullptr) {
6310 GrfMsg(1,
"FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.",
GB(
id, 0, 8));
6312 _cur.
grffile->housespec[
GB(
id, 0, 8)]->building_name =
AddGRFString(_cur.
grffile->grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
6317 GrfMsg(7,
"FeatureNewName: Unsupported ID (0x{:04X})",
id);
6336 if (offset >= max_sprites) {
6337 GrfMsg(1,
"GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6338 uint orig_num = num;
6343 if (offset + num > max_sprites) {
6344 GrfMsg(4,
"GraphicsNew: {} sprite overflow, truncating...", name);
6345 uint orig_num = num;
6346 num = std::max(max_sprites - offset, 0);
6347 return orig_num - num;
6361 {
A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT,
"Signal graphics" },
6363 {
A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT,
"Foundation graphics" },
6403 uint8_t type = buf.ReadByte();
6404 uint16_t num = buf.ReadExtendedByte();
6405 uint16_t offset =
HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6411 GrfMsg(2,
"GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6428 GrfMsg(2,
"GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6439 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->
name, type);
6446 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->
name, type, action5_type->
min_sprites, num);
6456 GrfMsg(2,
"GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->
name, type, replace);
6468 bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= SPR_ONEWAY_SLOPE_N_OFFSET));
6470 for (; num > 0; num--) {
6474 if (dup_oneway_sprites) {
6475 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_N_OFFSET);
6476 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_S_OFFSET);
6492 GrfMsg(3,
"SkipAct5: Skipping {} sprites", _cur.
skip_sprites);
6545 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6575 *value = _game_mode;
6609 *value =
Clamp(snowline * (grffile->grf_version >= 8 ? 1 :
TILE_HEIGHT), 0, 0xFE);
6618 *value = _openttd_newgrf_version;
6633 default:
return false;
6637 static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
6656 if (cond_val ==
nullptr) {
6660 uint32_t index = *cond_val / 0x20;
6676 GrfMsg(1,
"Unsupported in-game variable 0x{:02X}", param);
6697 size_t pos = file.
GetPos();
6703 GrfMsg(2,
"CfgApply: Ignoring (next sprite is real, unsupported)");
6706 file.
SeekTo(pos, SEEK_SET);
6712 std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
6715 if (preload_sprite.empty()) {
6716 preload_sprite.resize(num);
6717 file.
ReadBlock(preload_sprite.data(), num);
6721 file.
SeekTo(pos, SEEK_SET);
6732 param_num = buf.ReadByte();
6733 if (param_num == 0xFF)
break;
6737 param_size = buf.ReadByte();
6741 add_value =
HasBit(param_size, 7);
6742 param_size =
GB(param_size, 0, 7);
6745 offset = buf.ReadExtendedByte();
6749 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= _cur.
grffile->
param_end) {
6750 GrfMsg(2,
"CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
6754 GrfMsg(8,
"CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
6757 for (i = 0; i < param_size && offset + i < num; i++) {
6758 uint32_t value = GetParamVal(param_num + i / 4,
nullptr);
6761 if (i % 4 == 0) carry =
false;
6764 uint new_value = preload_sprite[offset + i] +
GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
6765 preload_sprite[offset + i] =
GB(new_value, 0, 8);
6767 carry = new_value >= 256;
6769 preload_sprite[offset + i] =
GB(value, (i % 4) * 8, 8);
6801 uint32_t cond_val = 0;
6805 uint8_t param = buf.ReadByte();
6806 uint8_t paramsize = buf.ReadByte();
6807 uint8_t condtype = buf.ReadByte();
6814 switch (paramsize) {
6815 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord();
break;
6816 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF;
break;
6817 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF;
break;
6818 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF;
break;
6822 if (param < 0x80 && _cur.grffile->param_end <= param) {
6823 GrfMsg(7,
"SkipIf: Param {} undefined, skipping test", param);
6827 GrfMsg(7,
"SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
6832 if (condtype >= 0x0B) {
6863 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6865 }
else if (param == 0x88) {
6875 if (condtype != 10 && c ==
nullptr) {
6876 GrfMsg(7,
"SkipIf: GRFID 0x{:08X} unknown, skipping test",
BSWAP32(cond_val));
6903 default: GrfMsg(1,
"SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype);
return;
6907 uint32_t param_val = GetParamVal(param, &cond_val);
6909 case 0x00: result = !!(param_val & (1 << cond_val));
6911 case 0x01: result = !(param_val & (1 << cond_val));
6913 case 0x02: result = (param_val & mask) == cond_val;
6915 case 0x03: result = (param_val & mask) != cond_val;
6917 case 0x04: result = (param_val & mask) < cond_val;
6919 case 0x05: result = (param_val & mask) > cond_val;
6921 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6926 GrfMsg(2,
"SkipIf: Not skipping sprites, test was false");
6930 uint8_t numsprites = buf.ReadByte();
6938 if (label.label != numsprites)
continue;
6941 if (choice ==
nullptr) choice = &label;
6943 if (label.nfo_line > _cur.
nfo_line) {
6949 if (choice !=
nullptr) {
6950 GrfMsg(2,
"SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
6956 GrfMsg(2,
"SkipIf: Skipping {} sprites, test was true", numsprites);
6975 uint8_t grf_version = buf.ReadByte();
6976 uint32_t grfid = buf.ReadDWord();
6977 std::string_view name = buf.ReadString();
6981 if (grf_version < 2 || grf_version > 8) {
6991 if (buf.HasData()) {
6992 std::string_view info = buf.ReadString();
7010 uint8_t version = buf.ReadByte();
7011 uint32_t grfid = buf.ReadDWord();
7012 std::string_view name = buf.ReadString();
7015 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7019 if (_cur.
grffile->grfid != grfid) {
7020 Debug(grf, 0,
"GRFInfo: GRFID {:08X} in FILESCAN stage does not match GRFID {:08X} in INIT/RESERVE/ACTIVATION stage",
BSWAP32(_cur.
grffile->grfid),
BSWAP32(grfid));
7024 _cur.
grffile->grf_version = version;
7031 GrfMsg(3,
"GRFInfo: Installing default GRFv{} translation table for {:08X}", version,
BSWAP32(grfid));
7046 for (
const auto &grm_sprite : _grm_sprites) {
7047 if (grm_sprite.first.grfid != _cur.
grffile->grfid)
continue;
7048 if (grm_sprite.second.first <= first_sprite && grm_sprite.second.first + grm_sprite.second.second >= first_sprite + num_sprites)
return true;
7064 uint8_t num_sets = buf.ReadByte();
7066 for (uint i = 0; i < num_sets; i++) {
7067 uint8_t num_sprites = buf.ReadByte();
7068 uint16_t first_sprite = buf.ReadWord();
7070 GrfMsg(2,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7071 i, num_sprites, first_sprite
7077 GrfMsg(0,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7086 for (uint j = 0; j < num_sprites; j++) {
7087 SpriteID load_index = first_sprite + j;
7093 if (
IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7103 uint8_t num_sets = buf.ReadByte();
7105 for (uint i = 0; i < num_sets; i++) {
7112 GrfMsg(3,
"SkipActA: Skipping {} sprites", _cur.
skip_sprites);
7134 STR_NEWGRF_ERROR_VERSION_NUMBER,
7135 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
7136 STR_NEWGRF_ERROR_UNSET_SWITCH,
7137 STR_NEWGRF_ERROR_INVALID_PARAMETER,
7138 STR_NEWGRF_ERROR_LOAD_BEFORE,
7139 STR_NEWGRF_ERROR_LOAD_AFTER,
7140 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
7144 STR_NEWGRF_ERROR_MSG_INFO,
7145 STR_NEWGRF_ERROR_MSG_WARNING,
7146 STR_NEWGRF_ERROR_MSG_ERROR,
7147 STR_NEWGRF_ERROR_MSG_FATAL
7150 uint8_t severity = buf.ReadByte();
7151 uint8_t lang = buf.ReadByte();
7152 uint8_t message_id = buf.ReadByte();
7155 if (!CheckGrfLangID(lang, _cur.
grffile->grf_version))
return;
7159 if (!
HasBit(severity, 7) && _cur.
stage == GLS_INIT) {
7160 GrfMsg(7,
"GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.
stage);
7165 if (severity >=
lengthof(sevstr)) {
7166 GrfMsg(7,
"GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7168 }
else if (severity == 3) {
7177 if (message_id >=
lengthof(msgstr) && message_id != 0xFF) {
7178 GrfMsg(7,
"GRFLoadError: Invalid message id.");
7182 if (buf.Remaining() <= 1) {
7183 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7193 if (message_id == 0xFF) {
7195 if (buf.HasData()) {
7196 std::string_view message = buf.ReadString();
7200 GrfMsg(7,
"GRFLoadError: No custom message supplied.");
7204 error->
message = msgstr[message_id];
7207 if (buf.HasData()) {
7208 std::string_view data = buf.ReadString();
7212 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7213 error->
data.clear();
7217 for (uint i = 0; i < error->
param_value.size() && buf.HasData(); i++) {
7218 uint param_number = buf.ReadByte();
7230 if (!buf.HasData())
return;
7232 std::string_view text = buf.ReadString();
7239 uint8_t target = buf.ReadByte();
7242 if (target < 0x80 || target == 0x9E)
return;
7256 static uint32_t GetPatchVariable(uint8_t param)
7266 case 0x0F:
return 0;
7282 case 0x11:
return SPR_2CCMAP_BASE;
7296 uint8_t map_bits = 0;
7299 uint8_t max_edge = std::max(log_X, log_Y);
7301 if (log_X == log_Y) {
7304 if (max_edge == log_Y)
SetBit(map_bits, 1);
7307 return (map_bits << 24) | (std::min(log_X, log_Y) << 20) | (max_edge << 16) |
7308 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
7317 return SPR_SLOPES_BASE;
7328 GrfMsg(2,
"ParamSet: Unknown Patch variable 0x{:02X}.", param);
7334 static uint32_t PerformGRM(uint32_t *grm, uint16_t num_ids, uint16_t count, uint8_t op, uint8_t target,
const char *type)
7347 for (uint i = start; i < num_ids; i++) {
7351 if (op == 2 || op == 3)
break;
7356 if (size == count)
break;
7359 if (size == count) {
7361 if (op == 0 || op == 3) {
7362 GrfMsg(2,
"ParamSet: GRM: Reserving {} {} at {}", count, type, start);
7363 for (uint i = 0; i < count; i++) grm[start + i] = _cur.
grffile->grfid;
7369 if (op != 4 && op != 5) {
7371 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7376 GrfMsg(1,
"ParamSet: GRM: Unable to allocate {} {}", count, type);
7406 uint8_t target = buf.ReadByte();
7407 uint8_t oper = buf.ReadByte();
7408 uint32_t src1 = buf.ReadByte();
7409 uint32_t src2 = buf.ReadByte();
7412 if (buf.Remaining() >= 4) data = buf.ReadDWord();
7421 if (target < 0x80 && target < _cur.grffile->param_end) {
7422 GrfMsg(7,
"ParamSet: Param {} already defined, skipping", target);
7426 oper =
GB(oper, 0, 7);
7430 if (
GB(data, 0, 8) == 0xFF) {
7431 if (data == 0x0000FFFF) {
7433 src1 = GetPatchVariable(src1);
7437 uint8_t feature =
GB(data, 8, 8);
7438 uint16_t count =
GB(data, 16, 16);
7440 if (_cur.
stage == GLS_RESERVE) {
7441 if (feature == 0x08) {
7445 if (_cur.
spriteid + count >= 16384) {
7446 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7452 GrfMsg(4,
"ParamSet: GRM: Allocated {} sprites at {}", count, _cur.
spriteid);
7459 }
else if (_cur.
stage == GLS_ACTIVATION) {
7488 GrfMsg(4,
"ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7496 GrfMsg(1,
"ParamSet: GRM: Unsupported operation {} for general sprites", op);
7507 default: GrfMsg(1,
"ParamSet: GRM: Unsupported feature 0x{:X}", feature);
return;
7524 }
else if (src1 == 0xFE) {
7536 src1 = (src1 == 0xFF) ? data : GetParamVal(src1,
nullptr);
7537 src2 = (src2 == 0xFF) ? data : GetParamVal(src2,
nullptr);
7559 res = (int32_t)src1 * (int32_t)src2;
7563 if ((int32_t)src2 < 0) {
7564 res = src1 >> -(int32_t)src2;
7566 res = src1 << (src2 & 0x1F);
7571 if ((int32_t)src2 < 0) {
7572 res = (int32_t)src1 >> -(int32_t)src2;
7574 res = (int32_t)src1 << (src2 & 0x1F);
7598 res = (int32_t)src1 / (int32_t)src2;
7614 res = (int32_t)src1 % (int32_t)src2;
7618 default: GrfMsg(0,
"ParamSet: Unknown operation {}, skipping", oper);
return;
7647 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7658 uint32_t safe_bits = 0;
7659 SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
7668 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7672 if (target < 0x80) {
7673 _cur.
grffile->param[target] = res;
7677 GrfMsg(7,
"ParamSet: Skipping unknown target 0x{:02X}", target);
7691 uint8_t num = buf.ReadByte();
7693 for (uint i = 0; i < num; i++) {
7694 uint32_t grfid = buf.ReadDWord();
7716 uint8_t num = buf.ReadByte();
7718 for (uint i = 0; i < num; i++) {
7719 uint32_t grfid = buf.ReadDWord();
7723 if (file !=
nullptr && file != _cur.
grfconfig) {
7724 GrfMsg(2,
"GRFInhibit: Deactivating file '{}'", file->
filename);
7741 uint32_t grfid = _cur.
grffile->grfid;
7745 uint8_t
id = buf.ReadByte();
7746 GrfMsg(6,
"FeatureTownName: definition 0x{:02X}",
id & 0x7F);
7751 bool new_scheme = _cur.
grffile->grf_version >= 7;
7753 uint8_t lang = buf.ReadByte();
7759 std::string_view name = buf.ReadString();
7762 GrfMsg(6,
"FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
7764 style =
AddGRFString(grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
7766 lang = buf.ReadByte();
7767 }
while (lang != 0);
7768 townname->
styles.emplace_back(style,
id);
7771 uint8_t parts = buf.ReadByte();
7772 GrfMsg(6,
"FeatureTownName: {} parts", parts);
7775 for (uint partnum = 0; partnum < parts; partnum++) {
7777 uint8_t texts = buf.ReadByte();
7778 partlist.
bitstart = buf.ReadByte();
7779 partlist.
bitcount = buf.ReadByte();
7781 GrfMsg(6,
"FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.
bitstart, partlist.
bitcount);
7783 partlist.
parts.reserve(texts);
7784 for (uint textnum = 0; textnum < texts; textnum++) {
7786 part.
prob = buf.ReadByte();
7789 uint8_t ref_id = buf.ReadByte();
7791 GrfMsg(0,
"FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
7792 DelGRFTownName(grfid);
7797 GrfMsg(6,
"FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.
prob & 0x7F);
7799 std::string_view text = buf.ReadString();
7801 GrfMsg(6,
"FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.
text, part.
prob);
7805 GrfMsg(6,
"FeatureTownName: part {}, total probability {}", partnum, partlist.
maxprob);
7817 uint8_t nfo_label = buf.ReadByte();
7821 GrfMsg(2,
"DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
7835 if (file ==
nullptr || file->sound_offset == 0) {
7836 GrfMsg(1,
"ImportGRFSound: Source file not available");
7840 if (sound_id >= file->num_sounds) {
7841 GrfMsg(1,
"ImportGRFSound: Sound effect {} is invalid", sound_id);
7845 GrfMsg(2,
"ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
7847 *sound = *GetSound(file->sound_offset + sound_id);
7850 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7851 sound->priority = 0;
7862 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7863 sound->priority = 0;
7865 if (offs != SIZE_MAX) {
7867 sound->file = _cur.
file;
7868 sound->file_offset = offs;
7880 uint16_t num = buf.ReadWord();
7881 if (num == 0)
return;
7884 if (_cur.
grffile->sound_offset == 0) {
7885 _cur.
grffile->sound_offset = GetNumSounds();
7886 _cur.
grffile->num_sounds = num;
7889 sound = GetSound(_cur.
grffile->sound_offset);
7894 for (
int i = 0; i < num; i++) {
7899 bool invalid = i >= _cur.
grffile->num_sounds;
7901 size_t offs = file.
GetPos();
7906 if (grf_container_version >= 2 && type == 0xFD) {
7909 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
7911 }
else if (len != 4) {
7912 GrfMsg(1,
"GRFSound: Invalid sprite section import");
7922 GrfMsg(1,
"GRFSound: Unexpected RealSprite found, skipping");
7929 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
7937 if (_cur.
stage == GLS_INIT) {
7938 if (grf_container_version >= 2) {
7939 GrfMsg(1,
"GRFSound: Inline sounds are not supported for container version >= 2");
7948 if (_cur.
stage == GLS_ACTIVATION) {
7951 if (file.
ReadByte() != 0) GrfMsg(1,
"GRFSound: Import type mismatch");
7959 GrfMsg(1,
"GRFSound: Unexpected Action {:x} found, skipping", action);
7975 GrfMsg(3,
"SkipAct11: Skipping {} sprites", _cur.
skip_sprites);
7988 uint8_t num_def = buf.ReadByte();
7990 for (uint i = 0; i < num_def; i++) {
7992 uint8_t num_char = buf.ReadByte();
7993 uint16_t base_char = buf.ReadWord();
7995 if (size >= FS_END) {
7996 GrfMsg(1,
"LoadFontGlyph: Size {} is not supported, ignoring", size);
7999 GrfMsg(7,
"LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8001 for (uint c = 0; c < num_char; c++) {
8019 uint8_t num_def = buf.ReadByte();
8021 for (uint i = 0; i < num_def; i++) {
8032 GrfMsg(3,
"SkipAct12: Skipping {} sprites", _cur.
skip_sprites);
8045 uint32_t grfid = buf.ReadDWord();
8048 GrfMsg(7,
"TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13",
BSWAP32(grfid));
8057 error->
data =
GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8067 uint8_t language = _cur.
grffile->grf_version >= 8 ? buf.ReadByte() : 0x7F;
8068 uint8_t num_strings = buf.ReadByte();
8069 uint16_t first_id = buf.ReadWord();
8071 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
8072 GrfMsg(7,
"TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
8076 for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8077 std::string_view
string = buf.ReadString();
8079 if (
string.empty()) {
8080 GrfMsg(7,
"TranslateGRFString: Ignoring empty string.");
8084 AddGRFString(grfid, first_id + i, language,
true,
true,
string, STR_UNDEFINED);
8113 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8125 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8128 char data = buf.ReadByte();
8136 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8151 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8154 char data = buf.ReadByte();
8160 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8173 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8186 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8191 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8222 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8229 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8239 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8241 }
else if (len != 8) {
8242 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8245 uint32_t min_value = buf.ReadDWord();
8246 uint32_t max_value = buf.ReadDWord();
8247 if (min_value <= max_value) {
8251 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8260 if (len < 1 || len > 3) {
8261 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
8264 uint8_t param_nr = buf.ReadByte();
8266 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8282 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8318 this->handler.data = handler;
8330 this->handler.text = handler;
8342 this->handler.call_handler =
true;
8343 this->handler.u.branch = handler;
8355 this->handler.call_handler =
false;
8356 this->handler.u.subtags =
subtags;
8385 uint8_t type = buf.ReadByte();
8387 uint32_t
id = buf.ReadDWord();
8389 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8391 type = buf.ReadByte();
8395 uint8_t langid = buf.ReadByte();
8396 std::string_view name_string = buf.ReadString();
8407 type = buf.ReadByte();
8432 uint8_t type = buf.ReadByte();
8434 uint32_t
id = buf.ReadDWord();
8436 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8438 type = buf.ReadByte();
8451 type = buf.ReadByte();
8488 uint8_t new_type = buf.ReadByte();
8489 while (new_type != 0) {
8492 new_type = buf.ReadByte();
8503 uint16_t size = buf.ReadWord();
8527 while ((tag = &subtags[i++])->type != 0) {
8530 default: NOT_REACHED();
8533 uint8_t langid = buf.ReadByte();
8534 return tag->handler.
text(langid, buf.ReadString());
8538 size_t len = buf.ReadWord();
8539 if (buf.Remaining() < len)
return false;
8540 return tag->handler.
data(len, buf);
8545 return tag->handler.u.branch(buf);
8551 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
8563 uint8_t type = buf.ReadByte();
8565 uint32_t
id = buf.ReadDWord();
8566 if (!
HandleNode(type,
id, buf, subtags))
return false;
8567 type = buf.ReadByte();
8688 file->stations.clear();
8696 file->housespec.clear();
8704 file->airportspec.clear();
8705 file->airtspec.clear();
8713 file->industryspec.clear();
8714 file->indtspec.clear();
8722 file->objectspec.clear();
8726 static void ResetCustomRoadStops()
8729 file->roadstops.clear();
8758 CleanUpGRFTownNames();
8818 ResetCustomRoadStops();
8844 _grf_id_overrides.clear();
8846 InitializeSoundPool();
8873 if (!cs->IsValid())
continue;
8888 if (newfile !=
nullptr) {
8894 newfile =
new GRFFile(config);
8912 for (
Price i = PR_BEGIN; i < PR_END; i++) {
8917 std::fill(std::begin(this->railtype_map), std::end(this->railtype_map),
INVALID_RAILTYPE);
8924 std::fill(std::begin(this->roadtype_map), std::end(this->roadtype_map),
INVALID_ROADTYPE);
8928 std::fill(std::begin(this->tramtype_map), std::end(this->tramtype_map),
INVALID_ROADTYPE);
8933 this->param = config->
param;
8945 CargoID cid = GetCargoIDByLabel(label);
8946 if (cid != INVALID_CARGO)
return label;
8958 if (std::holds_alternative<CargoLabel>(label))
return std::get<CargoLabel>(label);
8959 if (std::holds_alternative<MixedCargoType>(label)) {
8960 switch (std::get<MixedCargoType>(label)) {
8964 default: NOT_REACHED();
8975 CargoTypes original_known_cargoes = 0;
8983 bool only_defaultcargo;
8991 if (
_gted[engine].defaultcargo_grf ==
nullptr) {
8994 static constexpr uint8_t T = 1 << LT_TEMPERATE;
8995 static constexpr uint8_t A = 1 << LT_ARCTIC;
8996 static constexpr uint8_t S = 1 << LT_TROPIC;
8997 static constexpr uint8_t Y = 1 << LT_TOYLAND;
8998 static const struct DefaultRefitMasks {
9003 } _default_refit_masks[] = {
9005 {T | A | S , CT_MAIL,
CC_MAIL, 0},
9008 {T | A , CT_COAL,
CC_BULK, 0},
9009 { S , CT_COPPER_ORE,
CC_BULK, 0},
9025 switch (label.base()) {
9029 _gted[engine].cargo_disallowed = 0;
9034 _gted[engine].cargo_disallowed = 0;
9053 _gted[engine].cargo_disallowed = 0;
9057 for (
const auto &drm : _default_refit_masks) {
9059 if (drm.cargo_label != label)
continue;
9061 _gted[engine].cargo_allowed = drm.cargo_allowed;
9062 _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9067 _gted[engine].ctt_exclude_mask = original_known_cargoes;
9070 _gted[engine].UpdateRefittability(
_gted[engine].cargo_allowed != 0);
9077 CargoTypes mask = 0;
9078 CargoTypes not_mask = 0;
9079 CargoTypes xor_mask = ei->refit_mask;
9085 if (
_gted[engine].cargo_allowed != 0) {
9088 if (
_gted[engine].cargo_allowed & cs->classes)
SetBit(mask, cs->Index());
9089 if (
_gted[engine].cargo_disallowed & cs->classes)
SetBit(not_mask, cs->Index());
9093 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) &
_cargo_mask;
9096 ei->refit_mask |=
_gted[engine].ctt_include_mask;
9097 ei->refit_mask &= ~
_gted[engine].ctt_exclude_mask;
9106 ei->cargo_type = INVALID_CARGO;
9114 if (file ==
nullptr) file = e->
GetGRF();
9115 if (file !=
nullptr && file->grf_version >= 8 && !file->
cargo_list.empty()) {
9117 uint8_t best_local_slot = UINT8_MAX;
9119 uint8_t local_slot = file->
cargo_map[cargo_type];
9120 if (local_slot < best_local_slot) {
9121 best_local_slot = local_slot;
9122 ei->cargo_type = cargo_type;
9152 for (uint i = 0; i < CF_END; i++) {
9164 if (e->
GetGRF() ==
nullptr) {
9167 e->info.
string_id = STR_NEWGRF_INVALID_ENGINE;
9200 default: NOT_REACHED();
9212 if (parent != e->
index)
continue;
9217 GrfMsg(1,
"FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", _engine_mngr[e->
index].internal_id, e->
GetGRF()->filename);
9233 switch (cs.label.base()) {
9235 case CT_MAIL.base(): cs.town_production_effect =
TPE_MAIL;
break;
9236 default: cs.town_production_effect =
TPE_NONE;
break;
9239 if (!cs.IsValid()) {
9240 cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO;
9241 cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
9242 cs.abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
9266 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} as multitile, but no suitable tiles follow. Disabling house.", filename, hs->
grf_prop.
local_id);
9276 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);
9284 Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->
grf_prop.
local_id);
9291 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);
9314 if (min_year == 0)
return;
9341 if (file->housespec.empty())
continue;
9343 size_t num_houses = file->housespec.size();
9344 for (
size_t i = 0; i < num_houses; i++) {
9345 HouseSpec *hs = file->housespec[i].get();
9347 if (hs ==
nullptr)
continue;
9349 const HouseSpec *next1 = (i + 1 < num_houses ? file->housespec[i + 1].get() :
nullptr);
9350 const HouseSpec *next2 = (i + 2 < num_houses ? file->housespec[i + 2].get() :
nullptr);
9351 const HouseSpec *next3 = (i + 3 < num_houses ? file->housespec[i + 3].get() :
nullptr);
9410 for (
const auto &indsp : file->industryspec) {
9411 if (indsp ==
nullptr || !indsp->
enabled)
continue;
9418 if (strid != STR_UNDEFINED) indsp->
name = strid;
9421 if (strid != STR_UNDEFINED) indsp->
closure_text = strid;
9436 if (strid != STR_UNDEFINED) indsp->
station_name = strid;
9442 for (
const auto &indtsp : file->indtspec) {
9443 if (indtsp !=
nullptr) {
9444 _industile_mngr.SetEntitySpec(indtsp.get());
9449 for (
auto &indsp : _industry_specs) {
9456 indsp.
name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9460 for (
size_t i = 0; i < std::size(indsp.produced_cargo); ++i) {
9463 for (
size_t i = 0; i < std::size(indsp.
accepts_cargo); ++i) {
9468 for (
auto &indtsp : _industry_tile_specs) {
9484 for (
auto &objectspec : file->objectspec) {
9485 if (objectspec !=
nullptr && objectspec->grf_prop.grffile !=
nullptr && objectspec->IsEnabled()) {
9502 for (
auto &as : file->airportspec) {
9503 if (as !=
nullptr && as->
enabled) {
9504 _airport_mngr.SetEntitySpec(as.get());
9508 for (
auto &ats : file->airtspec) {
9509 if (ats !=
nullptr && ats->enabled) {
9510 _airporttile_mngr.SetEntitySpec(ats.get());
9522 static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9536 static const SpecialSpriteHandler handlers[][GLS_END] = {
9537 {
nullptr, SafeChangeInfo,
nullptr,
nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9538 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9539 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, NewSpriteGroup, },
9540 {
nullptr,
GRFUnsafe,
nullptr,
nullptr,
nullptr, FeatureMapSpriteGroup, },
9541 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, FeatureNewName, },
9542 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9543 {
nullptr,
nullptr,
nullptr, CfgApply, CfgApply, CfgApply, },
9544 {
nullptr,
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, },
9545 { ScanInfo,
nullptr,
nullptr, GRFInfo, GRFInfo, GRFInfo, },
9546 {
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, SkipIf, },
9547 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9548 {
nullptr,
nullptr,
nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9549 {
nullptr,
nullptr,
nullptr, GRFComment,
nullptr, GRFComment, },
9551 {
nullptr, SafeGRFInhibit,
nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9554 { SkipAct11,
GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9557 {
StaticGRFInfo,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, },
9562 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9563 if (it == _grf_line_to_action6_sprite_override.end()) {
9569 buf = _grf_line_to_action6_sprite_override[location].data();
9570 GrfMsg(7,
"DecodeSpecialSprite: Using preloaded pseudo sprite data");
9579 uint8_t action = br.ReadByte();
9581 if (action == 0xFF) {
9582 GrfMsg(2,
"DecodeSpecialSprite: Unexpected data block, skipping");
9583 }
else if (action == 0xFE) {
9584 GrfMsg(2,
"DecodeSpecialSprite: Unexpected import block, skipping");
9585 }
else if (action >=
lengthof(handlers)) {
9586 GrfMsg(7,
"DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
9587 }
else if (handlers[action][stage] ==
nullptr) {
9588 GrfMsg(7,
"DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
9590 GrfMsg(7,
"DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9591 handlers[action][stage](br);
9594 GrfMsg(1,
"DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9610 Debug(grf, 2,
"LoadNewGRFFile: Reading NewGRF-file '{}'", config->
filename);
9613 if (grf_container_version == 0) {
9614 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9618 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9624 if (grf_container_version >= 2) file.
ReadDword();
9627 if (grf_container_version >= 2) {
9629 uint8_t compression = file.
ReadByte();
9630 if (compression != 0) {
9631 Debug(grf, 7,
"LoadNewGRFFile: Unsupported compression format");
9640 if (num == 4 && file.
ReadByte() == 0xFF) {
9643 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9651 while ((num = (grf_container_version >= 2 ? file.
ReadDword() : file.
ReadWord())) != 0) {
9657 DecodeSpecialSprite(buf.
Allocate(num), num, stage);
9668 GrfMsg(0,
"LoadNewGRFFile: Unexpected sprite, disabling");
9669 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9673 if (grf_container_version >= 2 && type == 0xFD) {
9696 const std::string &filename = config->
filename;
9707 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
9709 if (_cur.
grffile ==
nullptr) UserError(
"File '{}' lost in cache.\n", filename);
9716 SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
9770 DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0);
9771 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
9772 DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2);
9773 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
9774 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
9775 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
9786 static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
9790 std::vector<int> grf_overrides(num_grfs, -1);
9791 for (
int i = 0; i < num_grfs; i++) {
9793 auto it = _grf_id_overrides.find(source->grfid);
9794 if (it == std::end(_grf_id_overrides))
continue;
9795 uint32_t
override = it->second;
9798 if (dest ==
nullptr)
continue;
9801 assert(grf_overrides[i] >= 0);
9805 for (
int i = 0; i < num_grfs; i++) {
9806 if (grf_overrides[i] < 0 || grf_overrides[i] >= i)
continue;
9814 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9817 Debug(grf, 3,
"'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
9823 for (
int i = num_grfs - 1; i >= 0; i--) {
9824 if (grf_overrides[i] < 0 || grf_overrides[i] <= i)
continue;
9832 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9835 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
9841 for (
int i = 0; i < num_grfs; i++) {
9842 if (grf_overrides[i] < 0)
continue;
9850 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9851 if (!
HasBit(features, _price_base_specs[p].grf_feature))
continue;
9853 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
9861 if (file->grf_version >= 8)
continue;
9862 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9863 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9865 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9868 price_base_multipliers[p] = price_base_multipliers[fallback_price];
9875 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9876 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9877 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9879 price_base_multipliers[p] = 0;
9884 Debug(grf, 3,
"'{}' sets global price base multiplier {}", file->
filename, p);
9886 price_base_multipliers[p] = 0;
9888 Debug(grf, 3,
"'{}' sets local price base multiplier {}", file->
filename, p);
9906 _grf_line_to_action6_sprite_override.clear();
9969 if (file ==
nullptr ||
_gted[e->
index].roadtramtype == 0) {
9978 if (
_gted[e->
index].roadtramtype < list->size())
9980 RoadTypeLabel rtl = (*list)[
_gted[e->
index].roadtramtype];
10009 _grm_sprites.clear();
10067 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10074 if (stage == GLS_RESERVE) {
10075 static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10080 for (
const auto &grf_override : default_grf_overrides) {
10086 uint num_non_static = 0;
10088 _cur.
stage = stage;
10095 Debug(grf, 0,
"NewGRF file is missing '{}'; disabling", c->
filename);
10104 Debug(grf, 0,
"'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->
filename);
10106 c->
error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10115 if (stage == GLS_RESERVE) {
10117 }
else if (stage == GLS_ACTIVATION) {
10122 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
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
@ NUM_AIRPORTS_PER_GRF
Maximal number of airports per NewGRF.
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...
Class for backupping variables and making sure they are restored later.
constexpr bool HasExactlyOneBit(T value)
Test whether value has exactly 1 bit set.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is 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.
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr static debug_inline 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.
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 CargoID
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
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.
@ 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 const CargoID NUM_CARGO
Maximum number of cargo types in a game.
bool IsDefaultCargo(CargoID cid)
Test if a cargo is a default cargo type.
std::span< const CargoLabel > GetDefaultCargoTranslationTable(uint8_t grf_version)
Get default cargo translation table for a NewGRF, used if the NewGRF does not provide its own.
CargoTypes _standard_cargo_mask
Bitmask of real cargo types available.
void BuildCargoLabelMap()
Build cargo label map.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
void SetupCargoForClimate(LandscapeID l)
Set up the default cargo types for the given landscape type.
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.
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.
struct RailTypeInfo::@26 strings
Strings associated with the rail type.
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.
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).
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.
struct RoadTypeInfo::@29 strings
Strings associated with the rail type.
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.
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.
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
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
@ EF_USES_2CC
Vehicle uses two company colours.
@ EF_ROAD_TRAM
Road vehicle is a tram/light rail vehicle.
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.
void SetSnowLine(uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
Set a variable snow line, as loaded from a newgrf file.
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.
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; limited to 255 to allow extending Action3 with an extended byt...
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...
IndustryLifeType
Available types of industry lifetimes.
@ CHECK_NOTHING
Always succeeds.
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
IndustryBehaviour
Various industry behaviours mostly to represent original TTD specialities.
IndustryTileSpecialFlags
Flags for miscellaneous industry tile 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.
Information about languages and their files.
const LanguageMetadata * GetLanguage(uint8_t newgrflangid)
Get the language with the given NewGRF language ID.
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
static const uint8_t MAX_NUM_CASES
Maximum number of supported cases.
LiveryScheme
List of different livery schemes.
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.
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
void MemSetT(T *ptr, uint8_t value, size_t num=1)
Type-safe version of memset().
static constexpr CargoID SG_DEFAULT
Default type used when no more-specific cargo matches.
static constexpr CargoID SG_PURCHASE
Used in purchase lists before an item exists.
static constexpr CargoID 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...
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.
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader &buf, std::vector< T > &translation_table, const char *name)
Load a cargo- or railtype-translation table.
bool(* BranchHandler)(ByteReader &)
Type of callback function for branch nodes.
StringID MapGRFStringID(uint32_t grfid, StringID str)
Used when setting an object's property to map to the GRF's strings while taking in consideration the ...
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.
static void AddStringForMapping(StringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
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 ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, ByteReader &buf)
Define properties for stations.
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 RoadVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for road vehicles.
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.
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.
std::span< const Action5Type > GetAction5Types()
Get list of all action 5 types.
static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, ByteReader &buf)
Define properties for airports.
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 id, int numinfo, int prop, ByteReader &buf)
Define properties for water features.
static void InitNewGRFFile(const GRFConfig *config)
Prepare loading a NewGRF file with its config.
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 ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, ByteReader &buf)
Define properties for global variables.
static GRFError * DisableGrf(StringID message=STR_NULL, GRFConfig *config=nullptr)
Disable a GRF.
AllowedSubtags _tags_root[]
Action14 root tags.
static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteReader &buf)
Define properties for cargoes.
static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteReader &buf)
Define properties for bridges.
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 void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file)
Load a particular NewGRF from a SpriteFile.
static void FinaliseEngineArray()
Check for invalid engines.
static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader &buf)
Define properties for industry tiles.
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 ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for aircraft.
static uint32_t _grm_engines[256]
Contains the GRF ID of the owner of a vehicle if it has been reserved.
static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, AllowedSubtags subtags[])
Handle the nodes of an Action14.
static void ResetNewGRFErrors()
Clear all NewGRF errors.
uint8_t _misc_grf_features
Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E.
AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for ships.
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.
static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf, RoadTramType rtt)
Define properties for roadtypes.
static void LoadGRFSound(size_t offs, SoundEntry *sound)
Load a sound from a file.
static StringID TTDPStringIDToOTTDStringIDMapping(StringID str)
Perform a mapping from TTDPatch's string IDs to OpenTTD's string IDs, but only for the ones we are aw...
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.
void LoadNewGRF(SpriteID load_index, uint num_baseset)
Load all the NewGRFs.
static void InitializeGRFSpecial()
Initialize the TTDPatch flags.
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 void FinaliseCanals()
Set to use the correct action0 properties for each canal feature.
AllowedSubtags _tags_parameters[]
Action14 parameter tags.
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 bool IsValidNewGRFImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular NewGRF vehicle.
static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for railtypes.
void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
Load a particular NewGRF.
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 ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for rail vehicles.
static CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
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 ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader &buf)
Define properties for industries.
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 IgnoreTownHouseProperty(int prop, ByteReader &buf)
Ignore a house property.
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 bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
static bool HandleNodes(ByteReader &buf, AllowedSubtags subtags[])
Handle the contents of a 'C' choice of an Action14.
static GRFFile * GetFileByGRFID(uint32_t grfid)
Obtain a NewGRF file by its grfID.
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 bool ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
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 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 DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
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 GRFFile * GetFileByFilename(const std::string &filename)
Obtain a NewGRF file by its filename.
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
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 void ResetNewGRF()
Reset and clear all NewGRFs.
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, ByteReader &buf)
Define properties for sound effects.
static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
Callback function for 'INFO'->'BLTR' to set the blitter info.
static void FeatureTownName(ByteReader &buf)
Action 0x0F - Define Town names.
static void ResetCustomAirports()
Reset and clear all NewGRF airports.
static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for objects.
static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader &buf)
Define properties for houses.
@ GMB_TRAIN_WIDTH_32_PIXELS
Use 32 pixels per train vehicle in depot gui and vehicle details. Never set in the global variable;.
@ 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.
@ 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.
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.
WaterFeature _water_feature[CF_END]
Table of canal 'feature' sprite groups.
Handling of NewGRF canals.
CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoID.
Cargo support for NewGRFs.
static const uint TLR_MAX_VAR10
Maximum value for var 10.
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_VAR10_FLAGS
Flags which refer to using multiple action-1-2-3 chains.
@ 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....
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
GRFConfig * _grfconfig
First item in list of current GRF set up.
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_MASK
Bitmask to only get the blitter information.
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
@ GRFP_USE_MASK
Bitmask to get only the use palette use states.
@ GRFP_GRF_MASK
Bitmask to get only the NewGRF supplied information.
@ GCF_INIT_ONLY
GRF file is processed up to GLS_INIT.
@ GCF_INVALID
GRF is unusable with this version of OpenTTD.
@ GCF_STATIC
GRF file is used statically (can be used in any MP game)
@ GCF_UNSAFE
GRF file is unsafe for static usage.
@ GCF_RESERVED
GRF file passed GLS_RESERVE stage.
@ GCF_SYSTEM
GRF file is an openttd-internal system grf.
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.
@ 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.
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.
void AlterVehicleListOrder(EngineID engine, uint target)
Record a vehicle ListOrderChange.
void CommitVehicleListOrderChanges()
Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
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.
ObjectOverrideManager _object_mngr(NEW_OBJECT_OFFSET, NUM_OBJECTS, INVALID_OBJECT_TYPE)
The override manager for our 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,...
ObjectFlags
Various object behaviours.
@ OBJECT_FLAG_2CC_COLOUR
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.
SoundID GetNewGRFSoundID(const GRFFile *file, SoundID sound_id)
Resolve NewGRF sound ID.
SoundEntry * AllocateSound(uint num)
Allocate sound slots.
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 AddGRFString(uint32_t grfid, uint16_t 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.
StringID GetGRFStringID(uint32_t grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
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.
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
void InitRailTypes()
Resolve sprites of custom rail types.
void ResetRailTypes()
Reset all rail type information to its default values.
RailTypeFlags
Railtype flags.
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.
RoadTypeFlags
Roadtype flags.
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.
uint8_t frames
The number of frames.
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.
uint8_t 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.
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.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
uint8_t callback_mask
Bitmask of cargo callbacks that have to be called.
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.
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
uint32_t grfid
The GRF ID of the file the entity belongs to.
uint8_t substitute_id
The (original) entity ID to use if this GRF is not available (currently not used)
uint16_t internal_id
The internal ID within the GRF file.
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.
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
uint8_t misc_flags
Miscellaneous flags.
StringID string_id
Default name of engine.
uint8_t climates
Climates supported by the engine.
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
uint16_t callback_mask
Bitmask of vehicle callbacks that have to be called.
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 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.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
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.
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.
uint8_t flags
NOSAVE: GCF_Flags, 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.
bool has_param_defaults
NOSAVE: did this newgrf specify any defaults for it's parameters.
GRFTextWrapper name
NOSAVE: GRF name (Action 0x08)
uint8_t num_params
Number of used parameters.
struct GRFConfig * next
NOSAVE: Next item in the linked list.
GRFStatus status
NOSAVE: GRFStatus, enum.
std::optional< GRFError > error
NOSAVE: Error/Warning during GRF loading (Action 0x0B)
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.
std::array< uint32_t, 0x80 > param
GRF parameters.
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.
uint16_t local_id
id defined by the grf file for 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.
uint param_end
one more than the highest set parameter
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoID -> 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.
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
uint32_t grf_features
Bitset of GrfSpecFeature the grf uses.
GRFFile(const struct GRFConfig *config)
Constructor for GRFFile.
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.
std::map< uint32_t, GRFTextList > value_names
Names for each value.
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.
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 refittability
Did the newgrf set any refittability property? If not, default refittability will be applied.
CargoTypes ctt_include_mask
Cargo types always included in 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...
uint8_t rv_max_speed
Temporary storage of RV prop 15, maximum speed in mph/0.8.
void UpdateRefittability(bool non_empty)
Update the summary refittability on setting a refittability property.
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.
uint8_t 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)
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]
input cargo slots
CargoLabel accepts_cargo_label[HOUSE_NUM_ACCEPTS]
input landscape cargo slots
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
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.
uint16_t add_output[INDUSTRY_NUM_OUTPUTS]
Add this much output cargo when successful (unsigned, is indirect in cb version 1+)
CargoID cargo_input[INDUSTRY_NUM_INPUTS]
Which input cargoes to take from (only cb version 2)
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.
CargoID cargo_output[INDUSTRY_NUM_OUTPUTS]
Which output cargoes to add to (only cb version 2)
Defines the data structure for constructing industry.
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
StringID production_up_text
Message appearing when the industry's production is increasing.
StringID name
Displayed name of the industry.
IndustryType conflicting[3]
Industries this industry cannot be close to.
GRFFileProps grf_prop
properties related to the grf file
StringID production_down_text
Message appearing when the industry's production is decreasing.
StringID station_name
Default name for nearby station.
StringID closure_text
Message appearing when the industry closes.
StringID new_industry_text
Message appearing when the industry is built.
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition of one tile in an industry tile layout.
Defines the data structure of each individual tile of an industry.
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
GRFFileProps grf_prop
properties related to the grf file
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 Titem * Get(size_t index)
Returns Titem with given index.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
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.
@ NoWires
Tile should NOT contain catenary wires.
@ Pylons
Tile should contain catenary pylons.
@ Blocked
Tile is blocked to vehicles.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
CargoTypes cargo_triggers
Bitmask of cargo types which cause trigger re-randomizing.
std::vector< NewGRFSpriteLayout > renderdata
Number of tile layouts.
Information for mapping static StringIDs.
uint32_t grfid
Source NewGRF.
StringID source
Source StringID (GRF local).
std::function< void(StringID)> func
Function for mapping result.
Templated helper to make a type-safe 'typedef' representing a single POD value.
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
uint8_t callback_mask
Bitmask of canal callbacks that have to be called.
const SpriteGroup * group
Sprite group to start resolving.
const GRFFile * grffile
NewGRF where 'group' belongs to.
uint8_t flags
Flags controlling display.
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.