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);
326 RailTypeLabel railtypelabel;
327 uint8_t roadtramtype;
342 }
else if (this->refittability ==
UNSET) {
343 this->refittability =
EMPTY;
348 static std::vector<GRFTempEngineData>
_gted;
363 GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
367 return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
372 return this->grfid == other.grfid && this->nfoline == other.nfoline;
376 static std::map<GRFLocation, std::pair<SpriteID, uint16_t>> _grm_sprites;
377 typedef std::map<GRFLocation, std::vector<uint8_t>> GRFLineToSpriteOverride;
378 static GRFLineToSpriteOverride _grf_line_to_action6_sprite_override;
390 void GrfMsgI(
int severity,
const std::string &msg)
403 if (file->grfid == grfid)
return file;
416 if (file->filename == filename)
return file;
436 if (config !=
nullptr) {
447 if (message == STR_NULL)
return nullptr;
449 config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
451 return &config->error.value();
499 static const StringID units_volume[] = {
500 STR_ITEMS, STR_PASSENGERS, STR_TONS, STR_BAGS,
501 STR_LITERS, STR_ITEMS, STR_CRATES, STR_TONS,
502 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
503 STR_TONS, STR_TONS, STR_TONS, STR_BAGS,
504 STR_TONS, STR_TONS, STR_BAGS, STR_LITERS,
505 STR_TONS, STR_LITERS, STR_TONS, STR_ITEMS,
506 STR_BAGS, STR_LITERS, STR_TONS, STR_ITEMS,
507 STR_TONS, STR_ITEMS, STR_LITERS, STR_ITEMS
513 #define TEXTID_TO_STRINGID(begin, end, stringid, stringend) \
514 static_assert(stringend - stringid == end - begin); \
515 if (str >= begin && str <= end) return str + (stringid - begin)
518 TEXTID_TO_STRINGID(0x000E, 0x002D, STR_CARGO_PLURAL_NOTHING, STR_CARGO_PLURAL_FIZZY_DRINKS);
519 TEXTID_TO_STRINGID(0x002E, 0x004D, STR_CARGO_SINGULAR_NOTHING, STR_CARGO_SINGULAR_FIZZY_DRINK);
520 if (str >= 0x004E && str <= 0x006D)
return units_volume[str - 0x004E];
521 TEXTID_TO_STRINGID(0x006E, 0x008D, STR_QUANTITY_NOTHING, STR_QUANTITY_FIZZY_DRINKS);
522 TEXTID_TO_STRINGID(0x008E, 0x00AD, STR_ABBREV_NOTHING, STR_ABBREV_FIZZY_DRINKS);
523 TEXTID_TO_STRINGID(0x00D1, 0x00E0, STR_COLOUR_DARK_BLUE, STR_COLOUR_WHITE);
528 TEXTID_TO_STRINGID(0x200F, 0x201F, STR_TOWN_BUILDING_NAME_TALL_OFFICE_BLOCK_1, STR_TOWN_BUILDING_NAME_OLD_HOUSES_1);
529 TEXTID_TO_STRINGID(0x2036, 0x2041, STR_TOWN_BUILDING_NAME_COTTAGES_1, STR_TOWN_BUILDING_NAME_SHOPPING_MALL_1);
530 TEXTID_TO_STRINGID(0x2059, 0x205C, STR_TOWN_BUILDING_NAME_IGLOO_1, STR_TOWN_BUILDING_NAME_PIGGY_BANK_1);
533 TEXTID_TO_STRINGID(0x4802, 0x4826, STR_INDUSTRY_NAME_COAL_MINE, STR_INDUSTRY_NAME_SUGAR_MINE);
534 TEXTID_TO_STRINGID(0x482D, 0x482E, STR_NEWS_INDUSTRY_CONSTRUCTION, STR_NEWS_INDUSTRY_PLANTED);
535 TEXTID_TO_STRINGID(0x4832, 0x4834, STR_NEWS_INDUSTRY_CLOSURE_GENERAL, STR_NEWS_INDUSTRY_CLOSURE_LACK_OF_TREES);
536 TEXTID_TO_STRINGID(0x4835, 0x4838, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_INCREASE_FARM);
537 TEXTID_TO_STRINGID(0x4839, 0x483A, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_GENERAL, STR_NEWS_INDUSTRY_PRODUCTION_DECREASE_FARM);
540 case 0x4830:
return STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY;
541 case 0x4831:
return STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED;
542 case 0x483B:
return STR_ERROR_CAN_ONLY_BE_POSITIONED;
544 #undef TEXTID_TO_STRINGID
546 if (str == STR_NULL)
return STR_EMPTY;
548 Debug(grf, 0,
"Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
587 static std::map<uint32_t, uint32_t> _grf_id_overrides;
596 if (target_grfid == 0) {
597 _grf_id_overrides.erase(source_grfid);
598 GrfMsg(5,
"SetNewGRFOverride: Removed override of 0x{:X}",
BSWAP32(source_grfid));
600 _grf_id_overrides[source_grfid] = target_grfid;
601 GrfMsg(5,
"SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}",
BSWAP32(source_grfid),
BSWAP32(target_grfid));
617 uint32_t scope_grfid = INVALID_GRFID;
620 scope_grfid = file->grfid;
621 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
622 scope_grfid = it->second;
624 if (grf_match ==
nullptr) {
625 GrfMsg(5,
"Tried mapping from GRFID {:x} to {:x} but target is not loaded",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
627 GrfMsg(5,
"Mapping from GRFID {:x} to {:x}",
BSWAP32(file->grfid),
BSWAP32(scope_grfid));
632 EngineID engine = _engine_mngr.
GetID(type, internal_id, scope_grfid);
641 EngineID engine = _engine_mngr.
GetID(type, internal_id, INVALID_GRFID);
647 GrfMsg(5,
"Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
651 if (!static_access) {
653 eid->
grfid = scope_grfid;
659 if (static_access)
return nullptr;
662 GrfMsg(0,
"Can't allocate any more engines");
673 assert(_engine_mngr.size() == e->
index);
674 _engine_mngr.push_back({
689 GrfMsg(5,
"Created new engine at index {} for GRFID {:x}, type {}, index {}", e->
index,
BSWAP32(file->grfid), type, internal_id);
706 uint32_t scope_grfid = INVALID_GRFID;
708 scope_grfid = file->grfid;
709 if (
auto it = _grf_id_overrides.find(file->grfid); it != std::end(_grf_id_overrides)) {
710 scope_grfid = it->second;
714 return _engine_mngr.
GetID(type, internal_id, scope_grfid);
754 grf_sprite->
sprite = buf.ReadWord();
755 grf_sprite->
pal = buf.ReadWord();
760 bool custom_sprite =
HasBit(grf_sprite->
pal, 15) != invert_action1_flag;
764 uint index =
GB(grf_sprite->
sprite, 0, 14);
766 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {}", index);
767 grf_sprite->
sprite = SPR_IMG_QUERY;
768 grf_sprite->
pal = PAL_NONE;
771 if (max_sprite_offset !=
nullptr) *max_sprite_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
776 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
777 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
783 uint index =
GB(grf_sprite->
pal, 0, 14);
785 GrfMsg(1,
"ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {} for 'palette'", index);
786 grf_sprite->
pal = PAL_NONE;
789 if (max_palette_offset !=
nullptr) *max_palette_offset = use_cur_spritesets ? _cur.
GetNumEnts(feature, index) : UINT16_MAX;
794 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
795 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
824 regs.delta.
parent[0] = buf.ReadByte();
825 regs.delta.
parent[1] = buf.ReadByte();
836 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
sprite_var10,
TLR_MAX_VAR10);
837 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
845 GrfMsg(1,
"ReadSpriteLayoutRegisters: Spritelayout specifies var10 ({}) exceeding the maximal allowed value {}", regs.
palette_var10,
TLR_MAX_VAR10);
846 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
865 bool has_flags =
HasBit(num_building_sprites, 6);
866 ClrBit(num_building_sprites, 6);
869 dts->
Allocate(num_building_sprites);
871 std::vector<uint16_t> max_sprite_offset(num_building_sprites + 1, 0);
872 std::vector<uint16_t> max_palette_offset(num_building_sprites + 1, 0);
879 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses invalid flag 0x{:X} for ground sprite", flags & ~(valid_flags & ~
TLF_NON_GROUND_FLAGS));
880 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
887 for (uint i = 0; i < num_building_sprites; i++) {
890 flags =
ReadSpriteLayoutSprite(buf, has_flags,
false, use_cur_spritesets, feature, &seq->image, max_sprite_offset.data() + i + 1, max_palette_offset.data() + i + 1);
893 if (flags & ~valid_flags) {
894 GrfMsg(1,
"ReadSpriteLayout: Spritelayout uses unknown flag 0x{:X}", flags & ~valid_flags);
895 DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
900 seq->delta_y = buf.ReadByte();
902 if (!no_z_position) seq->
delta_z = buf.ReadByte();
905 seq->size_x = buf.ReadByte();
906 seq->size_y = buf.ReadByte();
907 seq->size_z = buf.ReadByte();
915 bool is_consistent =
true;
917 for (uint i = 0; i < num_building_sprites + 1; i++) {
918 if (max_sprite_offset[i] > 0) {
922 is_consistent =
false;
926 if (max_palette_offset[i] > 0) {
930 is_consistent =
false;
939 if (!is_consistent || dts->registers !=
nullptr) {
943 for (uint i = 0; i < num_building_sprites + 1; i++) {
958 CargoTypes result = 0;
976 if (base_pointer == 0) {
977 *index = INVALID_PRICE;
981 static const uint32_t start = 0x4B34;
982 static const uint32_t size = 6;
984 if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
985 GrfMsg(1,
"{}: Unsupported running cost base 0x{:04X}, ignoring", error_location, base_pointer);
989 *index = (
Price)((base_pointer - start) / size);
1018 ei->decay_speed = buf.ReadByte();
1035 ei->load_amount = buf.ReadByte();
1057 for (
int i = 0; i < numinfo; i++) {
1066 uint8_t tracktype = buf.ReadByte();
1068 if (tracktype < _cur.grffile->railtype_list.size()) {
1073 switch (tracktype) {
1074 case 0:
_gted[e->
index].railtypelabel = rvi->
engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL;
break;
1075 case 1:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MONO;
break;
1076 case 2:
_gted[e->
index].railtypelabel = RAILTYPE_LABEL_MAGLEV;
break;
1078 GrfMsg(1,
"RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1091 uint16_t speed = buf.ReadWord();
1092 if (speed == 0xFFFF) speed = 0;
1099 rvi->
power = buf.ReadWord();
1102 if (rvi->
power != 0) {
1120 uint8_t spriteid = buf.ReadByte();
1121 uint8_t orig_spriteid = spriteid;
1125 if (spriteid < 0xFD) spriteid >>= 1;
1127 if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1128 rvi->image_index = spriteid;
1130 GrfMsg(1,
"RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1131 rvi->image_index = 0;
1137 uint8_t dual = buf.ReadByte();
1142 rvi->railveh_type = rvi->
power == 0 ?
1154 uint8_t ctype = buf.ReadByte();
1156 if (ctype == 0xFF) {
1158 ei->cargo_type = INVALID_CARGO;
1162 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1169 SB(rvi->
weight, 0, 8, buf.ReadByte());
1177 GrfMsg(2,
"RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1189 uint8_t traction = buf.ReadByte();
1192 if (traction <= 0x07) {
1194 }
else if (traction <= 0x27) {
1196 }
else if (traction <= 0x31) {
1198 }
else if (traction <= 0x37) {
1200 }
else if (traction <= 0x41) {
1226 ei->refit_cost = buf.ReadByte();
1230 uint32_t mask = buf.ReadDWord();
1231 _gted[e->
index].UpdateRefittability(mask != 0);
1268 uint8_t weight = buf.ReadByte();
1271 GrfMsg(2,
"RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1292 _gted[e->
index].cargo_allowed = buf.ReadWord();
1298 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1312 uint8_t count = buf.ReadByte();
1313 _gted[e->
index].UpdateRefittability(prop == 0x2C && count != 0);
1315 CargoTypes &ctt = prop == 0x2C ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1341 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1365 for (
int i = 0; i < numinfo; i++) {
1376 _gted[e->
index].roadtramtype = buf.ReadByte() + 1;
1384 rvi->running_cost = buf.ReadByte();
1392 uint8_t spriteid = buf.ReadByte();
1393 uint8_t orig_spriteid = spriteid;
1396 if (spriteid == 0xFF) spriteid = 0xFD;
1398 if (spriteid < 0xFD) spriteid >>= 1;
1400 if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1401 rvi->image_index = spriteid;
1403 GrfMsg(1,
"RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1404 rvi->image_index = 0;
1410 rvi->capacity = buf.ReadByte();
1415 uint8_t ctype = buf.ReadByte();
1417 if (ctype == 0xFF) {
1419 ei->cargo_type = INVALID_CARGO;
1423 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1430 rvi->cost_factor = buf.ReadByte();
1438 rvi->
power = buf.ReadByte();
1442 rvi->
weight = buf.ReadByte();
1446 _gted[e->
index].rv_max_speed = buf.ReadByte();
1450 uint32_t mask = buf.ReadDWord();
1451 _gted[e->
index].UpdateRefittability(mask != 0);
1470 ei->refit_cost = buf.ReadByte();
1483 _gted[e->
index].cargo_allowed = buf.ReadWord();
1489 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1521 uint8_t count = buf.ReadByte();
1522 _gted[e->
index].UpdateRefittability(prop == 0x24 && count != 0);
1524 CargoTypes &ctt = prop == 0x24 ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1546 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1570 for (
int i = 0; i < numinfo; i++) {
1579 uint8_t spriteid = buf.ReadByte();
1580 uint8_t orig_spriteid = spriteid;
1583 if (spriteid == 0xFF) spriteid = 0xFD;
1585 if (spriteid < 0xFD) spriteid >>= 1;
1587 if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1588 svi->image_index = spriteid;
1590 GrfMsg(1,
"ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1591 svi->image_index = 0;
1601 svi->cost_factor = buf.ReadByte();
1610 uint8_t ctype = buf.ReadByte();
1612 if (ctype == 0xFF) {
1614 ei->cargo_type = INVALID_CARGO;
1618 if (ei->cargo_type == INVALID_CARGO) GrfMsg(2,
"ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1625 svi->capacity = buf.ReadWord();
1629 svi->running_cost = buf.ReadByte();
1637 uint32_t mask = buf.ReadDWord();
1638 _gted[e->
index].UpdateRefittability(mask != 0);
1649 ei->refit_cost = buf.ReadByte();
1670 _gted[e->
index].cargo_allowed = buf.ReadWord();
1676 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1704 uint8_t count = buf.ReadByte();
1705 _gted[e->
index].UpdateRefittability(prop == 0x1E && count != 0);
1707 CargoTypes &ctt = prop == 0x1E ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1733 svi->
acceleration = std::max<uint8_t>(1, buf.ReadByte());
1737 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1761 for (
int i = 0; i < numinfo; i++) {
1770 uint8_t spriteid = buf.ReadByte();
1771 uint8_t orig_spriteid = spriteid;
1774 if (spriteid == 0xFF) spriteid = 0xFD;
1776 if (spriteid < 0xFD) spriteid >>= 1;
1778 if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1779 avi->image_index = spriteid;
1781 GrfMsg(1,
"AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1782 avi->image_index = 0;
1788 if (buf.ReadByte() == 0) {
1800 avi->cost_factor = buf.ReadByte();
1804 avi->
max_speed = (buf.ReadByte() * 128) / 10;
1808 avi->acceleration = buf.ReadByte();
1812 avi->running_cost = buf.ReadByte();
1828 uint32_t mask = buf.ReadDWord();
1829 _gted[e->
index].UpdateRefittability(mask != 0);
1840 ei->refit_cost = buf.ReadByte();
1853 _gted[e->
index].cargo_allowed = buf.ReadWord();
1859 _gted[e->
index].cargo_disallowed = buf.ReadWord();
1877 uint8_t count = buf.ReadByte();
1878 _gted[e->
index].UpdateRefittability(prop == 0x1D && count != 0);
1880 CargoTypes &ctt = prop == 0x1D ?
_gted[e->
index].ctt_include_mask :
_gted[e->
index].ctt_exclude_mask;
1906 _gted[e->
index].cargo_allowed_required = buf.ReadWord();
1931 GrfMsg(1,
"StationChangeInfo: Station {} is invalid, max {}, ignoring", stid + numinfo,
NUM_STATIONS_PER_GRF);
1936 if (_cur.
grffile->stations.size() < stid + numinfo) _cur.
grffile->stations.resize(stid + numinfo);
1938 for (
int i = 0; i < numinfo; i++) {
1939 auto &statspec = _cur.
grffile->stations[stid + i];
1942 if (statspec ==
nullptr && prop != 0x08) {
1943 GrfMsg(2,
"StationChangeInfo: Attempt to modify undefined station {}, ignoring", stid + i);
1950 if (statspec ==
nullptr) {
1951 statspec = std::make_unique<StationSpec>();
1955 uint32_t classid = buf.ReadDWord();
1961 uint16_t tiles = buf.ReadExtendedByte();
1962 statspec->renderdata.clear();
1963 statspec->renderdata.reserve(tiles);
1965 for (uint t = 0; t < tiles; t++) {
1969 if (buf.HasData(4) && buf.PeekDWord() == 0) {
1972 dts->
Clone(&_station_display_datas_rail[t % 8]);
1980 static std::vector<DrawTileSeqStruct> tmp_layout;
1987 dtss.
delta_x = buf.ReadByte();
1989 dtss.delta_y = buf.ReadByte();
1990 dtss.
delta_z = buf.ReadByte();
1991 dtss.size_x = buf.ReadByte();
1992 dtss.size_y = buf.ReadByte();
1993 dtss.size_z = buf.ReadByte();
1999 dts->
Clone(tmp_layout.data());
2003 if (statspec->renderdata.size() & 1) {
2004 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
2005 statspec->renderdata.pop_back();
2011 uint16_t srcid = buf.ReadExtendedByte();
2012 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2014 if (srcstatspec ==
nullptr) {
2015 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid, stid + i);
2019 statspec->renderdata.clear();
2020 statspec->renderdata.reserve(srcstatspec->
renderdata.size());
2022 for (
const auto &it : srcstatspec->
renderdata) {
2030 statspec->callback_mask = buf.ReadByte();
2034 statspec->disallowed_platforms = buf.ReadByte();
2038 statspec->disallowed_lengths = buf.ReadByte();
2042 while (buf.HasData()) {
2043 uint8_t length = buf.ReadByte();
2044 uint8_t number = buf.ReadByte();
2046 if (length == 0 || number == 0)
break;
2048 const uint8_t *buf_layout = buf.ReadBytes(length * number);
2052 layout.assign(buf_layout, buf_layout + length * number);
2055 for (
auto &tile : layout) {
2056 if ((tile & ~1U) != tile) {
2057 GrfMsg(1,
"StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2065 uint16_t srcid = buf.ReadExtendedByte();
2066 const StationSpec *srcstatspec = srcid >= _cur.
grffile->stations.size() ? nullptr : _cur.
grffile->stations[srcid].get();
2068 if (srcstatspec ==
nullptr) {
2069 GrfMsg(1,
"StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid, stid + i);
2073 statspec->layouts = srcstatspec->
layouts;
2078 statspec->cargo_threshold = buf.ReadWord();
2082 uint8_t pylons = buf.ReadByte();
2083 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2084 for (
int j = 0; j < 8; ++j) {
2088 statspec->tileflags[j] &= ~
StationSpec::TileFlags::Pylons;
2095 if (_cur.
grffile->grf_version >= 7) {
2098 statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2103 statspec->flags = buf.ReadByte();
2107 uint8_t wires = buf.ReadByte();
2108 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2109 for (
int j = 0; j < 8; ++j) {
2113 statspec->tileflags[j] &= ~
StationSpec::TileFlags::NoWires;
2120 uint8_t blocked = buf.ReadByte();
2121 if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2122 for (
int j = 0; j < 8; ++j) {
2123 if (
HasBit(blocked, j)) {
2126 statspec->tileflags[j] &= ~
StationSpec::TileFlags::Blocked;
2133 statspec->animation.
frames = buf.ReadByte();
2134 statspec->animation.status = buf.ReadByte();
2138 statspec->animation.speed = buf.ReadByte();
2142 statspec->animation.triggers = buf.ReadWord();
2148 uint16_t tiles = buf.ReadExtendedByte();
2149 statspec->renderdata.clear();
2150 statspec->renderdata.reserve(tiles);
2152 for (uint t = 0; t < tiles; t++) {
2154 uint num_building_sprites = buf.ReadByte();
2160 if (statspec->renderdata.size() & 1) {
2161 GrfMsg(1,
"StationChangeInfo: Station {} defines an odd number of sprite layouts, dropping the last item", stid + i);
2162 statspec->renderdata.pop_back();
2179 AddStringForMapping(buf.ReadWord(), [statspec = statspec.get()](
StringID str) { StationClass::Get(statspec->class_index)->name = str; });
2183 uint16_t tiles = buf.ReadExtendedByte();
2185 statspec->tileflags.assign(flags, flags + tiles);
2210 if (
id + numinfo > CF_END) {
2211 GrfMsg(1,
"CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring",
id + numinfo, CF_END);
2215 for (
int i = 0; i < numinfo; i++) {
2224 cp->
flags = buf.ReadByte();
2249 GrfMsg(1,
"BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", brid + numinfo,
MAX_BRIDGES);
2253 for (
int i = 0; i < numinfo; i++) {
2259 uint8_t year = buf.ReadByte();
2274 bridge->
price = buf.ReadByte();
2278 bridge->
speed = buf.ReadWord();
2279 if (bridge->
speed == 0) bridge->
speed = UINT16_MAX;
2283 uint8_t tableid = buf.ReadByte();
2284 uint8_t numtables = buf.ReadByte();
2291 for (; numtables-- != 0; tableid++) {
2293 GrfMsg(1,
"BridgeChangeInfo: Table {} >= 7, skipping", tableid);
2294 for (uint8_t sprite = 0; sprite < 32; sprite++) buf.ReadDWord();
2299 bridge->
sprite_table[tableid] = MallocT<PalSpriteID>(32);
2302 for (uint8_t sprite = 0; sprite < 32; sprite++) {
2316 bridge->
flags = buf.ReadByte();
2325 if (newone != STR_UNDEFINED) bridge->
material = newone;
2332 if (newone != STR_UNDEFINED) bridge->
transport_name[prop - 0x11] = newone;
2337 bridge->
price = buf.ReadWord();
2394 for (uint j = 0; j < 4; j++) buf.ReadByte();
2398 uint8_t count = buf.ReadByte();
2399 for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2404 buf.Skip(buf.ReadByte() * 2);
2427 GrfMsg(1,
"TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", hid + numinfo,
NUM_HOUSES_PER_GRF);
2432 if (_cur.
grffile->housespec.size() < hid + numinfo) _cur.
grffile->housespec.resize(hid + numinfo);
2434 for (
int i = 0; i < numinfo; i++) {
2435 auto &housespec = _cur.
grffile->housespec[hid + i];
2437 if (prop != 0x08 && housespec ==
nullptr) {
2440 if (cir > ret) ret = cir;
2446 uint8_t subs_id = buf.ReadByte();
2447 if (subs_id == 0xFF) {
2454 GrfMsg(2,
"TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id, hid + i);
2459 if (housespec ==
nullptr) {
2461 housespec = std::make_unique<HouseSpec>(*
HouseSpec::Get(subs_id));
2463 housespec->enabled =
true;
2464 housespec->grf_prop.local_id = hid + i;
2465 housespec->grf_prop.subst_id = subs_id;
2466 housespec->grf_prop.grffile = _cur.
grffile;
2468 housespec->random_colour[0] = COLOUR_RED;
2469 housespec->random_colour[1] = COLOUR_BLUE;
2470 housespec->random_colour[2] = COLOUR_ORANGE;
2471 housespec->random_colour[3] = COLOUR_GREEN;
2474 housespec->building_flags &= ~(BUILDING_IS_CHURCH | BUILDING_IS_STADIUM);
2480 CargoID cid = housespec->accepts_cargo[2];
2481 if (!
IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
2483 housespec->cargo_acceptance[2] = 0;
2490 housespec->building_flags = (BuildingFlags)buf.ReadByte();
2494 uint16_t years = buf.ReadWord();
2501 housespec->population = buf.ReadByte();
2505 housespec->mail_generation = buf.ReadByte();
2510 housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2514 int8_t goods = buf.ReadByte();
2524 housespec->accepts_cargo[2] = cid;
2525 housespec->accepts_cargo_label[2] =
CT_INVALID;
2526 housespec->cargo_acceptance[2] =
abs(goods);
2531 housespec->remove_rating_decrease = buf.ReadWord();
2535 housespec->removal_cost = buf.ReadByte();
2543 housespec->building_availability = (
HouseZones)buf.ReadWord();
2547 housespec->callback_mask |= buf.ReadByte();
2551 uint8_t
override = buf.ReadByte();
2555 GrfMsg(2,
"TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.",
override, hid + i);
2559 _house_mngr.
Add(hid + i, _cur.
grffile->grfid,
override);
2564 housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2568 for (uint j = 0; j < 4; j++) housespec->random_colour[j] =
static_cast<Colours
>(
GB(buf.ReadByte(), 0, 4));
2572 housespec->probability = buf.ReadByte();
2580 housespec->animation.frames = buf.ReadByte();
2581 housespec->animation.status =
GB(housespec->animation.frames, 7, 1);
2582 SB(housespec->animation.frames, 7, 1, 0);
2586 housespec->animation.speed =
Clamp(buf.ReadByte(), 2, 16);
2590 housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.
grffile->grfid);
2594 housespec->callback_mask |= (buf.ReadByte() << 8);
2598 uint32_t cargotypes = buf.ReadDWord();
2601 if (cargotypes == 0xFFFFFFFF)
break;
2605 uint8_t cargo_part =
GB(cargotypes, 8 * j, 8);
2610 housespec->cargo_acceptance[j] = 0;
2612 housespec->accepts_cargo[j] = cargo;
2614 housespec->accepts_cargo_label[j] =
CT_INVALID;
2620 housespec->minimum_life = buf.ReadByte();
2624 uint8_t count = buf.ReadByte();
2625 for (uint8_t j = 0; j < count; j++) {
2633 housespec->min_year = buf.ReadWord();
2637 housespec->max_year = buf.ReadWord();
2642 uint count = buf.ReadByte();
2643 if (count >
lengthof(housespec->accepts_cargo)) {
2651 for (uint i = 0; i <
lengthof(housespec->accepts_cargo); i++) {
2654 housespec->cargo_acceptance[i] = buf.ReadByte();
2656 housespec->accepts_cargo[i] = INVALID_CARGO;
2657 housespec->cargo_acceptance[i] = 0;
2659 if (i < std::size(housespec->accepts_cargo_label)) housespec->accepts_cargo_label[i] =
CT_INVALID;
2683 if (grffile ==
nullptr)
return nullptr;
2686 if (it == std::end(grffile->
language_map))
return nullptr;
2700 template <
typename T>
2704 GrfMsg(1,
"LoadTranslationTable: {} translation table must start at zero", name);
2708 translation_table.clear();
2709 translation_table.reserve(numinfo);
2710 for (
int i = 0; i < numinfo; i++) {
2711 translation_table.push_back(T(
BSWAP32(buf.ReadDWord())));
2726 for (
int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2760 for (
int i = 0; i < numinfo; i++) {
2763 int factor = buf.ReadByte();
2764 uint price = gvid + i;
2766 if (price < PR_END) {
2769 GrfMsg(1,
"GlobalVarChangeInfo: Price {} out of range, ignoring", price);
2778 if ((newone != STR_UNDEFINED) && (curidx <
CURRENCY_END)) {
2787 uint32_t rate = buf.ReadDWord();
2795 GrfMsg(1,
"GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2802 uint16_t options = buf.ReadWord();
2811 GrfMsg(1,
"GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2823 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2835 GrfMsg(1,
"GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2847 GrfMsg(1,
"GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2854 GrfMsg(1,
"GlobalVarChangeInfo: The snowline can only be set once ({})", numinfo);
2856 GrfMsg(1,
"GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2862 table[i][j] = buf.ReadByte();
2863 if (_cur.
grffile->grf_version >= 8) {
2866 if (table[i][j] >= 128) {
2888 uint curidx = gvid + i;
2890 if (lang ==
nullptr) {
2891 GrfMsg(1,
"GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
2896 while (buf.ReadByte() != 0) {
2904 uint plural_form = buf.ReadByte();
2905 if (plural_form >= LANGUAGE_MAX_PLURAL) {
2906 GrfMsg(1,
"GlobalVarChanceInfo: Plural form {} is out of range, ignoring", plural_form);
2913 uint8_t newgrf_id = buf.ReadByte();
2914 while (newgrf_id != 0) {
2915 std::string_view name = buf.ReadString();
2930 GrfMsg(1,
"GlobalVarChangeInfo: Gender name {} is not known, ignoring",
StrMakeValid(name));
2937 GrfMsg(1,
"GlobalVarChangeInfo: Case name {} is not known, ignoring",
StrMakeValid(name));
2942 newgrf_id = buf.ReadByte();
2978 for (
int i = 0; i < numinfo; i++) {
3002 uint32_t s = buf.ReadDWord();
3003 uint32_t t = buf.ReadDWord();
3010 while (buf.ReadByte() != 0) {
3038 GrfMsg(2,
"CargoChangeInfo: Cargo type {} out of range (max {})", cid + numinfo,
NUM_CARGO - 1);
3042 for (
int i = 0; i < numinfo; i++) {
3047 cs->
bitnum = buf.ReadByte();
3086 cs->
sprite = buf.ReadWord();
3090 cs->
weight = buf.ReadByte();
3094 cs->transit_periods[0] = buf.ReadByte();
3098 cs->transit_periods[1] = buf.ReadByte();
3106 cs->rating_colour = buf.ReadByte();
3110 cs->legend_colour = buf.ReadByte();
3127 uint8_t substitute_type = buf.ReadByte();
3129 switch (substitute_type) {
3136 GrfMsg(1,
"CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3152 cs->
multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3156 uint8_t substitute_type = buf.ReadByte();
3158 switch (substitute_type) {
3162 GrfMsg(1,
"CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3195 if (_cur.
grffile->sound_offset == 0) {
3196 GrfMsg(1,
"SoundEffectChangeInfo: No effects defined, skipping");
3201 GrfMsg(1,
"SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", sid + numinfo,
ORIGINAL_SAMPLE_COUNT + _cur.
grffile->num_sounds);
3205 for (
int i = 0; i < numinfo; i++) {
3210 sound->volume =
Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3214 sound->priority = buf.ReadByte();
3218 SoundID orig_sound = buf.ReadByte();
3221 GrfMsg(1,
"SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound,
ORIGINAL_SAMPLE_COUNT);
3223 SoundEntry *old_sound = GetSound(orig_sound);
3226 *old_sound = *sound;
3268 buf.Skip(buf.ReadByte() * 2);
3291 GrfMsg(1,
"IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", indtid + numinfo,
NUM_INDUSTRYTILES_PER_GRF);
3296 if (_cur.
grffile->indtspec.size() < indtid + numinfo) _cur.
grffile->indtspec.resize(indtid + numinfo);
3298 for (
int i = 0; i < numinfo; i++) {
3299 auto &tsp = _cur.
grffile->indtspec[indtid + i];
3301 if (prop != 0x08 && tsp ==
nullptr) {
3303 if (cir > ret) ret = cir;
3309 uint8_t subs_id = buf.ReadByte();
3312 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id, indtid + i);
3317 if (tsp ==
nullptr) {
3318 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3320 tsp->enabled =
true;
3328 tsp->grf_prop.local_id = indtid + i;
3329 tsp->grf_prop.subst_id = subs_id;
3330 tsp->grf_prop.grffile = _cur.
grffile;
3337 uint8_t ovrid = buf.ReadByte();
3341 GrfMsg(2,
"IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid, indtid + i);
3345 _industile_mngr.
Add(indtid + i, _cur.
grffile->grfid, ovrid);
3352 uint16_t acctp = buf.ReadWord();
3354 tsp->acceptance[prop - 0x0A] =
Clamp(
GB(acctp, 8, 8), 0, 16);
3355 tsp->accepts_cargo_label[prop - 0x0A] =
CT_INVALID;
3360 tsp->slopes_refused = (
Slope)buf.ReadByte();
3364 tsp->callback_mask = buf.ReadByte();
3368 tsp->animation.frames = buf.ReadByte();
3369 tsp->animation.status = buf.ReadByte();
3373 tsp->animation.speed = buf.ReadByte();
3377 tsp->animation.triggers = buf.ReadByte();
3385 uint8_t num_cargoes = buf.ReadByte();
3386 if (num_cargoes > std::size(tsp->acceptance)) {
3391 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3392 if (i < num_cargoes) {
3395 tsp->acceptance[i] = (int8_t)buf.ReadByte();
3397 tsp->accepts_cargo[i] = INVALID_CARGO;
3398 tsp->acceptance[i] = 0;
3400 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] =
CT_INVALID;
3460 uint8_t num_table = buf.ReadByte();
3461 for (uint8_t j = 0; j < num_table; j++) {
3462 for (uint k = 0;; k++) {
3463 uint8_t x = buf.ReadByte();
3464 if (x == 0xFE && k == 0) {
3470 uint8_t y = buf.ReadByte();
3471 if (x == 0 && y == 0x80)
break;
3473 uint8_t gfx = buf.ReadByte();
3474 if (gfx == 0xFE) buf.ReadWord();
3488 buf.Skip(buf.ReadByte());
3492 int num_inputs = buf.ReadByte();
3493 int num_outputs = buf.ReadByte();
3494 buf.Skip(num_inputs * num_outputs * 2);
3512 const size_t size = layout.size();
3513 if (size == 0)
return false;
3515 for (
size_t i = 0; i < size - 1; i++) {
3516 for (
size_t j = i + 1; j < size; j++) {
3517 if (layout[i].ti.x == layout[j].ti.x &&
3518 layout[i].ti.y == layout[j].ti.y) {
3524 bool have_regular_tile =
false;
3525 for (
const auto &tilelayout : layout) {
3527 have_regular_tile =
true;
3532 return have_regular_tile;
3548 GrfMsg(1,
"IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", indid + numinfo,
NUM_INDUSTRYTYPES_PER_GRF);
3553 if (_cur.
grffile->industryspec.size() < indid + numinfo) _cur.
grffile->industryspec.resize(indid + numinfo);
3555 for (
int i = 0; i < numinfo; i++) {
3556 auto &indsp = _cur.
grffile->industryspec[indid + i];
3558 if (prop != 0x08 && indsp ==
nullptr) {
3560 if (cir > ret) ret = cir;
3566 uint8_t subs_id = buf.ReadByte();
3567 if (subs_id == 0xFF) {
3570 _industry_specs[indid + i].
enabled =
false;
3574 GrfMsg(2,
"_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id, indid + i);
3581 if (indsp ==
nullptr) {
3582 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3584 indsp->enabled =
true;
3585 indsp->grf_prop.local_id = indid + i;
3586 indsp->grf_prop.subst_id = subs_id;
3587 indsp->grf_prop.grffile = _cur.
grffile;
3596 uint8_t ovrid = buf.ReadByte();
3600 GrfMsg(2,
"IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid, indid + i);
3603 indsp->grf_prop.override = ovrid;
3604 _industry_mngr.
Add(indid + i, _cur.
grffile->grfid, ovrid);
3609 uint8_t new_num_layouts = buf.ReadByte();
3610 uint32_t definition_size = buf.ReadDWord();
3611 uint32_t bytes_read = 0;
3612 std::vector<IndustryTileLayout> new_layouts;
3615 for (uint8_t j = 0; j < new_num_layouts; j++) {
3617 layout.reserve(new_num_layouts);
3619 for (uint k = 0;; k++) {
3620 if (bytes_read >= definition_size) {
3621 GrfMsg(3,
"IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.", indid);
3623 definition_size = UINT32_MAX;
3628 it.ti.
x = buf.ReadByte();
3631 if (it.ti.
x == 0xFE && k == 0) {
3633 IndustryType type = buf.ReadByte();
3634 uint8_t laynbr = buf.ReadByte();
3637 if (type >=
lengthof(_origin_industry_specs)) {
3638 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", indid);
3642 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3643 GrfMsg(1,
"IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", indid);
3647 layout = _origin_industry_specs[type].layouts[laynbr];
3651 it.ti.
y = buf.ReadByte();
3654 if (it.ti.
x == 0 && it.ti.
y == 0x80) {
3660 it.gfx = buf.ReadByte();
3663 if (it.gfx == 0xFE) {
3665 int local_tile_id = buf.ReadWord();
3669 int tempid = _industile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
3672 GrfMsg(2,
"IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, indid);
3678 it.ti.
x = (int8_t)
GB(it.ti.
x, 0, 8);
3679 it.ti.
y = (int8_t)
GB(it.ti.
y, 0, 8);
3688 if (_cur.
grffile->grf_version < 8 && it.ti.
x < 0) it.ti.
y += 1;
3694 GrfMsg(1,
"IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", indid);
3698 new_layouts.push_back(layout);
3703 indsp->layouts = new_layouts;
3724 indsp->cost_multiplier = buf.ReadByte();
3744 indsp->production_rate[prop - 0x12] = buf.ReadByte();
3748 indsp->minimal_cargo = buf.ReadByte();
3752 uint8_t num_sounds = buf.ReadByte();
3754 std::vector<uint8_t> sounds;
3755 sounds.reserve(num_sounds);
3756 for (uint8_t j = 0; j < num_sounds; ++j) {
3757 sounds.push_back(buf.ReadByte());
3760 indsp->random_sounds = std::move(sounds);
3765 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3777 indsp->map_colour = buf.ReadByte();
3791 uint32_t multiples = buf.ReadDWord();
3792 indsp->input_cargo_multiplier[prop - 0x1C][0] =
GB(multiples, 0, 16);
3793 indsp->input_cargo_multiplier[prop - 0x1C][1] =
GB(multiples, 16, 16);
3802 indsp->prospecting_chance = buf.ReadDWord();
3807 uint8_t aflag = buf.ReadByte();
3808 SB(indsp->callback_mask, (prop - 0x21) * 8, 8, aflag);
3813 indsp->removal_cost_multiplier = buf.ReadDWord();
3817 uint16_t str = buf.ReadWord();
3819 indsp->station_name = STR_NULL;
3827 uint8_t num_cargoes = buf.ReadByte();
3828 if (num_cargoes > std::size(indsp->produced_cargo)) {
3833 for (
size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3834 if (i < num_cargoes) {
3836 indsp->produced_cargo[i] = cargo;
3838 indsp->produced_cargo[i] = INVALID_CARGO;
3840 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] =
CT_INVALID;
3846 uint8_t num_cargoes = buf.ReadByte();
3847 if (num_cargoes > std::size(indsp->accepts_cargo)) {
3852 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3853 if (i < num_cargoes) {
3855 indsp->accepts_cargo[i] = cargo;
3857 indsp->accepts_cargo[i] = INVALID_CARGO;
3859 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] =
CT_INVALID;
3865 uint8_t num_cargoes = buf.ReadByte();
3866 if (num_cargoes >
lengthof(indsp->production_rate)) {
3871 for (uint i = 0; i <
lengthof(indsp->production_rate); i++) {
3872 if (i < num_cargoes) {
3873 indsp->production_rate[i] = buf.ReadByte();
3875 indsp->production_rate[i] = 0;
3882 uint8_t num_inputs = buf.ReadByte();
3883 uint8_t num_outputs = buf.ReadByte();
3884 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
3889 for (
size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3890 for (
size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
3892 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
3893 indsp->input_cargo_multiplier[i][j] = mult;
3921 GrfMsg(1,
"AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", airport + numinfo,
NUM_AIRPORTS_PER_GRF);
3926 if (_cur.
grffile->airportspec.size() < airport + numinfo) _cur.
grffile->airportspec.resize(airport + numinfo);
3928 for (
int i = 0; i < numinfo; i++) {
3929 auto &as = _cur.
grffile->airportspec[airport + i];
3931 if (as ==
nullptr && prop != 0x08 && prop != 0x09) {
3932 GrfMsg(2,
"AirportChangeInfo: Attempt to modify undefined airport {}, ignoring", airport + i);
3938 uint8_t subs_id = buf.ReadByte();
3939 if (subs_id == 0xFF) {
3946 GrfMsg(2,
"AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id, airport + i);
3953 if (as ==
nullptr) {
3957 as->grf_prop.local_id = airport + i;
3958 as->grf_prop.subst_id = subs_id;
3959 as->grf_prop.grffile = _cur.
grffile;
3961 _airport_mngr.
Add(airport + i, _cur.
grffile->grfid, subs_id);
3967 uint8_t num_layouts = buf.ReadByte();
3972 std::vector<AirportTileLayout> layouts;
3973 layouts.reserve(num_layouts);
3975 for (uint8_t j = 0; j != num_layouts; ++j) {
3976 auto &layout = layouts.emplace_back();
3977 layout.rotation =
static_cast<Direction>(buf.ReadByte() & 6);
3980 auto &tile = layout.tiles.emplace_back();
3981 tile.ti.x = buf.ReadByte();
3982 tile.ti.y = buf.ReadByte();
3983 if (tile.ti.x == 0 && tile.ti.y == 0x80) {
3991 tile.gfx = buf.ReadByte();
3993 if (tile.gfx == 0xFE) {
3995 int local_tile_id = buf.ReadWord();
3998 uint16_t tempid = _airporttile_mngr.
GetID(local_tile_id, _cur.
grffile->grfid);
4001 GrfMsg(2,
"AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i);
4006 }
else if (tile.gfx == 0xFF) {
4007 tile.ti.x =
static_cast<int8_t
>(
GB(tile.ti.x, 0, 8));
4008 tile.ti.y =
static_cast<int8_t
>(
GB(tile.ti.y, 0, 8));
4012 if (layout.rotation ==
DIR_E || layout.rotation ==
DIR_W) {
4013 size_x = std::max<uint8_t>(size_x, tile.ti.y + 1);
4014 size_y = std::max<uint8_t>(size_y, tile.ti.x + 1);
4016 size_x = std::max<uint8_t>(size_x, tile.ti.x + 1);
4017 size_y = std::max<uint8_t>(size_y, tile.ti.y + 1);
4021 as->layouts = std::move(layouts);
4022 as->size_x = size_x;
4023 as->size_y = size_y;
4028 as->min_year = buf.ReadWord();
4029 as->max_year = buf.ReadWord();
4042 as->noise_level = buf.ReadByte();
4050 as->maintenance_cost = buf.ReadWord();
4120 GrfMsg(1,
"ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.",
id + numinfo,
NUM_OBJECTS_PER_GRF);
4125 if (_cur.
grffile->objectspec.size() <
id + numinfo) _cur.
grffile->objectspec.resize(
id + numinfo);
4127 for (
int i = 0; i < numinfo; i++) {
4128 auto &spec = _cur.
grffile->objectspec[
id + i];
4130 if (prop != 0x08 && spec ==
nullptr) {
4133 if (cir > ret) ret = cir;
4140 if (spec ==
nullptr) {
4141 spec = std::make_unique<ObjectSpec>();
4147 uint32_t classid = buf.ReadDWord();
4162 spec->climate = buf.ReadByte();
4166 spec->size = buf.ReadByte();
4167 if (
GB(spec->size, 0, 4) == 0 ||
GB(spec->size, 4, 4) == 0) {
4168 GrfMsg(0,
"ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size,
id + i);
4174 spec->build_cost_multiplier = buf.ReadByte();
4175 spec->clear_cost_multiplier = spec->build_cost_multiplier;
4179 spec->introduction_date = buf.ReadDWord();
4183 spec->end_of_life_date = buf.ReadDWord();
4192 spec->animation.frames = buf.ReadByte();
4193 spec->animation.status = buf.ReadByte();
4197 spec->animation.speed = buf.ReadByte();
4201 spec->animation.triggers = buf.ReadWord();
4205 spec->clear_cost_multiplier = buf.ReadByte();
4209 spec->callback_mask = buf.ReadWord();
4213 spec->height = buf.ReadByte();
4217 spec->views = buf.ReadByte();
4218 if (spec->views != 1 && spec->views != 2 && spec->views != 4) {
4219 GrfMsg(2,
"ObjectChangeInfo: Invalid number of views ({}) for object id {}. Ignoring.", spec->views,
id + i);
4225 spec->generate_amount = buf.ReadByte();
4252 GrfMsg(1,
"RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4256 for (
int i = 0; i < numinfo; i++) {
4269 uint16_t str = buf.ReadWord();
4271 if (_cur.
grffile->grf_version < 8) {
4301 int n = buf.ReadByte();
4302 for (
int j = 0; j != n; j++) {
4303 RailTypeLabel label = buf.ReadDWord();
4363 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4382 GrfMsg(1,
"RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring",
id + numinfo,
RAILTYPE_END);
4386 for (
int i = 0; i < numinfo; i++) {
4390 RailTypeLabel rtl = buf.ReadDWord();
4399 _cur.
grffile->railtype_map[
id + i] = rt;
4417 int n = buf.ReadByte();
4418 for (
int j = 0; j != n; j++) {
4423 GrfMsg(1,
"RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set",
id + i);
4430 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4471 GrfMsg(1,
"RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4475 for (
int i = 0; i < numinfo; i++) {
4488 uint16_t str = buf.ReadWord();
4515 int n = buf.ReadByte();
4516 for (
int j = 0; j != n; j++) {
4517 RoadTypeLabel label = buf.ReadDWord();
4522 if (GetRoadTramType(resolved_rt) == rtt) {
4525 GrfMsg(1,
"RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4570 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4601 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring",
id + numinfo,
ROADTYPE_END);
4605 for (
int i = 0; i < numinfo; i++) {
4608 RoadTypeLabel rtl = buf.ReadDWord();
4615 }
else if (GetRoadTramType(rt) != rtt) {
4616 GrfMsg(1,
"RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring",
id + numinfo);
4620 type_map[
id + i] = rt;
4637 int n = buf.ReadByte();
4638 for (
int j = 0; j != n; j++) {
4643 GrfMsg(1,
"RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set",
id + i);
4649 for (
int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4673 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_ROAD);
4678 return RoadTypeReserveInfo(
id, numinfo, prop, buf, RTT_TRAM);
4686 GrfMsg(1,
"AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", airtid + numinfo,
NUM_AIRPORTTILES_PER_GRF);
4691 if (_cur.
grffile->airtspec.size() < airtid + numinfo) _cur.
grffile->airtspec.resize(airtid + numinfo);
4693 for (
int i = 0; i < numinfo; i++) {
4694 auto &tsp = _cur.
grffile->airtspec[airtid + i];
4696 if (prop != 0x08 && tsp ==
nullptr) {
4697 GrfMsg(2,
"AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.", airtid + i);
4703 uint8_t subs_id = buf.ReadByte();
4706 GrfMsg(2,
"AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id, airtid + i);
4711 if (tsp ==
nullptr) {
4714 tsp->enabled =
true;
4718 tsp->grf_prop.local_id = airtid + i;
4719 tsp->grf_prop.subst_id = subs_id;
4720 tsp->grf_prop.grffile = _cur.
grffile;
4727 uint8_t
override = buf.ReadByte();
4731 GrfMsg(2,
"AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.",
override, airtid + i);
4735 _airporttile_mngr.
Add(airtid + i, _cur.
grffile->grfid,
override);
4740 tsp->callback_mask = buf.ReadByte();
4744 tsp->animation.frames = buf.ReadByte();
4745 tsp->animation.status = buf.ReadByte();
4749 tsp->animation.speed = buf.ReadByte();
4753 tsp->animation.triggers = buf.ReadByte();
4810 GrfMsg(1,
"RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring",
id + numinfo,
NUM_ROADSTOPS_PER_GRF);
4814 if (_cur.
grffile->roadstops.size() <
id + numinfo) _cur.
grffile->roadstops.resize(
id + numinfo);
4816 for (
int i = 0; i < numinfo; i++) {
4817 auto &rs = _cur.
grffile->roadstops[
id + i];
4819 if (rs ==
nullptr && prop != 0x08) {
4820 GrfMsg(1,
"RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring",
id + i);
4822 if (cir > ret) ret = cir;
4828 if (rs ==
nullptr) {
4829 rs = std::make_unique<RoadStopSpec>();
4832 uint32_t classid = buf.ReadDWord();
4858 rs->animation.frames = buf.ReadByte();
4859 rs->animation.status = buf.ReadByte();
4863 rs->animation.speed = buf.ReadByte();
4867 rs->animation.triggers = buf.ReadWord();
4871 rs->callback_mask = buf.ReadByte();
4875 rs->flags = (uint16_t)buf.ReadDWord();
4879 rs->build_cost_multiplier = buf.ReadByte();
4880 rs->clear_cost_multiplier = buf.ReadByte();
4892 static bool HandleChangeInfoResult(
const char *caller,
ChangeInfoResult cir, uint8_t feature, uint8_t property)
4895 default: NOT_REACHED();
4905 GrfMsg(1,
"{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
4909 GrfMsg(0,
"{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
4922 static void FeatureChangeInfo(
ByteReader &buf)
4935 static const VCI_Handler handler[] = {
4953 AirportTilesChangeInfo,
4958 static_assert(GSF_END ==
lengthof(handler));
4960 uint8_t feature = buf.ReadByte();
4961 uint8_t numprops = buf.ReadByte();
4962 uint numinfo = buf.ReadByte();
4963 uint engine = buf.ReadExtendedByte();
4965 if (feature >= GSF_END) {
4966 GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4970 GrfMsg(6,
"FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
4971 feature, numprops, engine, numinfo);
4973 if (handler[feature] ==
nullptr) {
4974 if (feature != GSF_CARGOES) GrfMsg(1,
"FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4981 while (numprops-- && buf.HasData()) {
4982 uint8_t prop = buf.ReadByte();
4985 if (HandleChangeInfoResult(
"FeatureChangeInfo", cir, feature, prop))
return;
4992 uint8_t feature = buf.ReadByte();
4993 uint8_t numprops = buf.ReadByte();
4994 uint numinfo = buf.ReadByte();
4995 buf.ReadExtendedByte();
4997 if (feature == GSF_BRIDGES && numprops == 1) {
4998 uint8_t prop = buf.ReadByte();
5001 if (prop == 0x0D)
return;
5002 }
else if (feature == GSF_GLOBALVAR && numprops == 1) {
5003 uint8_t prop = buf.ReadByte();
5006 bool is_safe =
true;
5007 for (uint i = 0; i < numinfo; i++) {
5008 uint32_t s = buf.ReadDWord();
5016 if (is_safe)
return;
5027 static void ReserveChangeInfo(
ByteReader &buf)
5029 uint8_t feature = buf.ReadByte();
5031 if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES)
return;
5033 uint8_t numprops = buf.ReadByte();
5034 uint8_t numinfo = buf.ReadByte();
5035 uint8_t index = buf.ReadExtendedByte();
5037 while (numprops-- && buf.HasData()) {
5038 uint8_t prop = buf.ReadByte();
5042 default: NOT_REACHED();
5048 cir = GlobalVarReserveInfo(index, numinfo, prop, buf);
5052 cir = RailTypeReserveInfo(index, numinfo, prop, buf);
5056 cir = RoadTypeReserveInfo(index, numinfo, prop, buf);
5060 cir = TramTypeReserveInfo(index, numinfo, prop, buf);
5064 if (HandleChangeInfoResult(
"ReserveChangeInfo", cir, feature, prop))
return;
5085 uint8_t feature = buf.ReadByte();
5086 uint16_t num_sets = buf.ReadByte();
5087 uint16_t first_set = 0;
5089 if (num_sets == 0 && buf.HasData(3)) {
5092 first_set = buf.ReadExtendedByte();
5093 num_sets = buf.ReadExtendedByte();
5095 uint16_t num_ents = buf.ReadExtendedByte();
5097 if (feature >= GSF_END) {
5099 GrfMsg(1,
"NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.
skip_sprites);
5105 GrfMsg(7,
"New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
5106 _cur.
spriteid, feature, num_sets, num_ents, num_sets * num_ents
5109 for (
int i = 0; i < num_sets * num_ents; i++) {
5119 uint16_t num_sets = buf.ReadByte();
5121 if (num_sets == 0 && buf.HasData(3)) {
5124 buf.ReadExtendedByte();
5125 num_sets = buf.ReadExtendedByte();
5127 uint16_t num_ents = buf.ReadExtendedByte();
5131 GrfMsg(3,
"SkipAct1: Skipping {} sprites", _cur.
skip_sprites);
5136 static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5138 if (
HasBit(groupid, 15)) {
5143 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5144 GrfMsg(1,
"GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
5148 return _cur.spritegroups[groupid];
5161 if (
HasBit(spriteid, 15)) {
5167 GrfMsg(1,
"CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5172 uint num_sprites = _cur.
GetNumEnts(feature, spriteid);
5175 assert(spriteset_start + num_sprites <= _cur.
spriteid);
5196 uint8_t feature = buf.ReadByte();
5197 if (feature >= GSF_END) {
5198 GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5202 uint8_t setid = buf.ReadByte();
5203 uint8_t type = buf.ReadByte();
5227 switch (
GB(type, 2, 2)) {
5228 default: NOT_REACHED();
5229 case 0: group->size = DSG_SIZE_BYTE; varsize = 1;
break;
5230 case 1: group->size = DSG_SIZE_WORD; varsize = 2;
break;
5231 case 2: group->size = DSG_SIZE_DWORD; varsize = 4;
break;
5241 adjust.variable = buf.ReadByte();
5242 if (adjust.variable == 0x7E) {
5244 adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5249 varadjust = buf.ReadByte();
5250 adjust.shift_num =
GB(varadjust, 0, 5);
5251 adjust.type = (DeterministicSpriteGroupAdjustType)
GB(varadjust, 6, 2);
5252 adjust.and_mask = buf.ReadVarSize(varsize);
5254 if (adjust.type != DSGA_TYPE_NONE) {
5255 adjust.add_val = buf.ReadVarSize(varsize);
5256 adjust.divmod_val = buf.ReadVarSize(varsize);
5259 adjust.divmod_val = 0;
5263 }
while (
HasBit(varadjust, 5));
5265 std::vector<DeterministicSpriteGroupRange> ranges;
5266 ranges.resize(buf.ReadByte());
5267 for (
auto &range : ranges) {
5268 range.group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5269 range.low = buf.ReadVarSize(varsize);
5270 range.high = buf.ReadVarSize(varsize);
5273 group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5274 group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5276 group->calculated_result = ranges.empty();
5279 std::vector<uint32_t> bounds;
5280 bounds.reserve(ranges.size());
5281 for (
const auto &range : ranges) {
5282 bounds.push_back(range.low);
5283 if (range.high != UINT32_MAX) bounds.push_back(range.high + 1);
5285 std::sort(bounds.begin(), bounds.end());
5286 bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5288 std::vector<const SpriteGroup *> target;
5289 target.reserve(bounds.size());
5290 for (
const auto &bound : bounds) {
5292 for (
const auto &range : ranges) {
5293 if (range.low <= bound && bound <= range.high) {
5298 target.push_back(t);
5300 assert(target.size() == bounds.size());
5302 for (uint j = 0; j < bounds.size(); ) {
5303 if (target[j] != group->default_group) {
5305 r.group = target[j];
5307 while (j < bounds.size() && target[j] == r.group) {
5310 r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5332 group->count = buf.ReadByte();
5335 uint8_t triggers = buf.ReadByte();
5336 group->triggers =
GB(triggers, 0, 7);
5337 group->
cmp_mode =
HasBit(triggers, 7) ? RSG_CMP_ALL : RSG_CMP_ANY;
5340 uint8_t num_groups = buf.ReadByte();
5342 GrfMsg(1,
"NewSpriteGroup: Random Action 2 nrand should be power of 2");
5345 group->
groups.reserve(num_groups);
5346 for (uint i = 0; i < num_groups; i++) {
5347 group->
groups.push_back(GetGroupFromGroupID(setid, type, buf.ReadWord()));
5358 case GSF_ROADVEHICLES:
5369 uint8_t num_loaded = type;
5370 uint8_t num_loading = buf.ReadByte();
5373 GrfMsg(0,
"NewSpriteGroup: No sprite set to work on! Skipping");
5377 GrfMsg(6,
"NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5378 setid, num_loaded, num_loading);
5380 if (num_loaded + num_loading == 0) {
5381 GrfMsg(1,
"NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5385 if (num_loaded + num_loading == 1) {
5387 uint16_t spriteid = buf.ReadWord();
5389 GrfMsg(8,
"NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5393 std::vector<uint16_t> loaded;
5394 std::vector<uint16_t> loading;
5396 loaded.reserve(num_loaded);
5397 for (uint i = 0; i < num_loaded; i++) {
5398 loaded.push_back(buf.ReadWord());
5399 GrfMsg(8,
"NewSpriteGroup: + rg->loaded[{}] = subset {}", i, loaded[i]);
5402 loading.reserve(num_loading);
5403 for (uint i = 0; i < num_loading; i++) {
5404 loading.push_back(buf.ReadWord());
5405 GrfMsg(8,
"NewSpriteGroup: + rg->loading[{}] = subset {}", i, loading[i]);
5408 bool loaded_same = !loaded.empty() && std::adjacent_find(loaded.begin(), loaded.end(), std::not_equal_to<>()) == loaded.end();
5409 bool loading_same = !loading.empty() && std::adjacent_find(loading.begin(), loading.end(), std::not_equal_to<>()) == loading.end();
5410 if (loaded_same && loading_same && loaded[0] == loading[0]) {
5413 GrfMsg(8,
"NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5422 if (loaded_same && loaded.size() > 1) loaded.resize(1);
5423 group->
loaded.reserve(loaded.size());
5424 for (uint16_t spriteid : loaded) {
5426 group->
loaded.push_back(t);
5429 if (loading_same && loading.size() > 1) loading.resize(1);
5430 group->
loading.reserve(loading.size());
5431 for (uint16_t spriteid : loading) {
5440 case GSF_AIRPORTTILES:
5442 case GSF_INDUSTRYTILES:
5443 case GSF_ROADSTOPS: {
5444 uint8_t num_building_sprites = std::max((uint8_t)1, type);
5452 if (
ReadSpriteLayout(buf, num_building_sprites,
true, feature,
false, type == 0, &group->dts))
return;
5456 case GSF_INDUSTRIES: {
5458 GrfMsg(1,
"NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5476 group->again = buf.ReadByte();
5477 }
else if (type == 1) {
5486 group->again = buf.ReadByte();
5487 }
else if (type == 2) {
5491 error->
data =
"too many inputs (max 16)";
5494 for (uint i = 0; i < group->
num_input; i++) {
5495 uint8_t rawcargo = buf.ReadByte();
5504 error->
data =
"duplicate input cargo";
5513 error->
data =
"too many outputs (max 16)";
5516 for (uint i = 0; i < group->
num_output; i++) {
5517 uint8_t rawcargo = buf.ReadByte();
5524 error->
data =
"duplicate output cargo";
5530 group->again = buf.ReadByte();
5538 default: GrfMsg(1,
"NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5543 _cur.spritegroups[setid] = act_group;
5546 static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
5554 GrfMsg(1,
"TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (
unsigned int)_cur.
grffile->
cargo_list.size() - 1);
5555 return INVALID_CARGO;
5561 GrfMsg(5,
"TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5562 return INVALID_CARGO;
5565 CargoID cid = GetCargoIDByLabel(cl);
5567 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));
5568 return INVALID_CARGO;
5571 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);
5576 static bool IsValidGroupID(uint16_t groupid,
const char *
function)
5578 if (groupid >
MAX_SPRITEGROUP || _cur.spritegroups[groupid] ==
nullptr) {
5579 GrfMsg(1,
"{}: Spritegroup 0x{:04X} out of range or empty, skipping.",
function, groupid);
5586 static void VehicleMapSpriteGroup(
ByteReader &buf, uint8_t feature, uint8_t idcount)
5588 static std::vector<EngineID> last_engines;
5589 bool wagover =
false;
5592 if (
HasBit(idcount, 7)) {
5595 idcount =
GB(idcount, 0, 7);
5597 if (last_engines.empty()) {
5598 GrfMsg(0,
"VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5602 GrfMsg(6,
"VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5604 last_engines.resize(idcount);
5607 std::vector<EngineID> engines;
5608 engines.reserve(idcount);
5609 for (uint i = 0; i < idcount; i++) {
5615 HandleChangeInfoResult(
"VehicleMapSpriteGroup",
CIR_INVALID_ID, 0, 0);
5619 engines.push_back(e->
index);
5620 if (!wagover) last_engines[i] = engines[i];
5623 uint8_t cidcount = buf.ReadByte();
5624 for (uint c = 0; c < cidcount; c++) {
5625 uint8_t ctype = buf.ReadByte();
5626 uint16_t groupid = buf.ReadWord();
5627 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
continue;
5629 GrfMsg(8,
"VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5631 CargoID cid = TranslateCargo(feature, ctype);
5634 for (uint i = 0; i < idcount; i++) {
5637 GrfMsg(7,
"VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5640 SetWagonOverrideSprites(engine, cid, _cur.spritegroups[groupid], last_engines);
5642 SetCustomEngineSprites(engine, cid, _cur.spritegroups[groupid]);
5647 uint16_t groupid = buf.ReadWord();
5648 if (!IsValidGroupID(groupid,
"VehicleMapSpriteGroup"))
return;
5650 GrfMsg(8,
"-- Default group id 0x{:04X}", groupid);
5652 for (uint i = 0; i < idcount; i++) {
5665 static void CanalMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5667 std::vector<uint16_t> cfs;
5668 cfs.reserve(idcount);
5669 for (uint i = 0; i < idcount; i++) {
5670 cfs.push_back(buf.ReadExtendedByte());
5673 uint8_t cidcount = buf.ReadByte();
5674 buf.Skip(cidcount * 3);
5676 uint16_t groupid = buf.ReadWord();
5677 if (!IsValidGroupID(groupid,
"CanalMapSpriteGroup"))
return;
5679 for (
auto &cf : cfs) {
5681 GrfMsg(1,
"CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5691 static void StationMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5693 if (_cur.
grffile->stations.empty()) {
5694 GrfMsg(1,
"StationMapSpriteGroup: No stations defined, skipping");
5698 std::vector<uint16_t> stations;
5699 stations.reserve(idcount);
5700 for (uint i = 0; i < idcount; i++) {
5701 stations.push_back(buf.ReadExtendedByte());
5704 uint8_t cidcount = buf.ReadByte();
5705 for (uint c = 0; c < cidcount; c++) {
5706 uint8_t ctype = buf.ReadByte();
5707 uint16_t groupid = buf.ReadWord();
5708 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
continue;
5710 ctype = TranslateCargo(GSF_STATIONS, ctype);
5713 for (
auto &station : stations) {
5716 if (statspec ==
nullptr) {
5717 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5725 uint16_t groupid = buf.ReadWord();
5726 if (!IsValidGroupID(groupid,
"StationMapSpriteGroup"))
return;
5728 for (
auto &station : stations) {
5731 if (statspec ==
nullptr) {
5732 GrfMsg(1,
"StationMapSpriteGroup: Station {} undefined, skipping", station);
5737 GrfMsg(1,
"StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
5749 static void TownHouseMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5751 if (_cur.
grffile->housespec.empty()) {
5752 GrfMsg(1,
"TownHouseMapSpriteGroup: No houses defined, skipping");
5756 std::vector<uint16_t> houses;
5757 houses.reserve(idcount);
5758 for (uint i = 0; i < idcount; i++) {
5759 houses.push_back(buf.ReadExtendedByte());
5763 uint8_t cidcount = buf.ReadByte();
5764 buf.Skip(cidcount * 3);
5766 uint16_t groupid = buf.ReadWord();
5767 if (!IsValidGroupID(groupid,
"TownHouseMapSpriteGroup"))
return;
5769 for (
auto &house : houses) {
5772 if (hs ==
nullptr) {
5773 GrfMsg(1,
"TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
5781 static void IndustryMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5783 if (_cur.
grffile->industryspec.empty()) {
5784 GrfMsg(1,
"IndustryMapSpriteGroup: No industries defined, skipping");
5788 std::vector<uint16_t> industries;
5789 industries.reserve(idcount);
5790 for (uint i = 0; i < idcount; i++) {
5791 industries.push_back(buf.ReadExtendedByte());
5795 uint8_t cidcount = buf.ReadByte();
5796 buf.Skip(cidcount * 3);
5798 uint16_t groupid = buf.ReadWord();
5799 if (!IsValidGroupID(groupid,
"IndustryMapSpriteGroup"))
return;
5801 for (
auto &industry : industries) {
5804 if (indsp ==
nullptr) {
5805 GrfMsg(1,
"IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
5813 static void IndustrytileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5815 if (_cur.
grffile->indtspec.empty()) {
5816 GrfMsg(1,
"IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
5820 std::vector<uint16_t> indtiles;
5821 indtiles.reserve(idcount);
5822 for (uint i = 0; i < idcount; i++) {
5823 indtiles.push_back(buf.ReadExtendedByte());
5827 uint8_t cidcount = buf.ReadByte();
5828 buf.Skip(cidcount * 3);
5830 uint16_t groupid = buf.ReadWord();
5831 if (!IsValidGroupID(groupid,
"IndustrytileMapSpriteGroup"))
return;
5833 for (
auto &indtile : indtiles) {
5836 if (indtsp ==
nullptr) {
5837 GrfMsg(1,
"IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
5845 static void CargoMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5847 std::vector<uint16_t> cargoes;
5848 cargoes.reserve(idcount);
5849 for (uint i = 0; i < idcount; i++) {
5850 cargoes.push_back(buf.ReadExtendedByte());
5854 uint8_t cidcount = buf.ReadByte();
5855 buf.Skip(cidcount * 3);
5857 uint16_t groupid = buf.ReadWord();
5858 if (!IsValidGroupID(groupid,
"CargoMapSpriteGroup"))
return;
5860 for (
auto &cid : cargoes) {
5862 GrfMsg(1,
"CargoMapSpriteGroup: Cargo ID {} out of range, skipping", cid);
5868 cs->group = _cur.spritegroups[groupid];
5872 static void ObjectMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5874 if (_cur.
grffile->objectspec.empty()) {
5875 GrfMsg(1,
"ObjectMapSpriteGroup: No object tiles defined, skipping");
5879 std::vector<uint16_t> objects;
5880 objects.reserve(idcount);
5881 for (uint i = 0; i < idcount; i++) {
5882 objects.push_back(buf.ReadExtendedByte());
5885 uint8_t cidcount = buf.ReadByte();
5886 for (uint c = 0; c < cidcount; c++) {
5887 uint8_t ctype = buf.ReadByte();
5888 uint16_t groupid = buf.ReadWord();
5889 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
continue;
5892 if (ctype != 0xFF) {
5893 GrfMsg(1,
"ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
5897 for (
auto &
object : objects) {
5900 if (spec ==
nullptr) {
5901 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5909 uint16_t groupid = buf.ReadWord();
5910 if (!IsValidGroupID(groupid,
"ObjectMapSpriteGroup"))
return;
5912 for (
auto &
object : objects) {
5915 if (spec ==
nullptr) {
5916 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} undefined, skipping",
object);
5921 GrfMsg(1,
"ObjectMapSpriteGroup: Object {} mapped multiple times, skipping",
object);
5931 static void RailTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5933 std::vector<uint8_t> railtypes;
5934 railtypes.reserve(idcount);
5935 for (uint i = 0; i < idcount; i++) {
5936 uint16_t
id = buf.ReadExtendedByte();
5937 railtypes.push_back(id < RAILTYPE_END ? _cur.grffile->railtype_map[
id] :
INVALID_RAILTYPE);
5940 uint8_t cidcount = buf.ReadByte();
5941 for (uint c = 0; c < cidcount; c++) {
5942 uint8_t ctype = buf.ReadByte();
5943 uint16_t groupid = buf.ReadWord();
5944 if (!IsValidGroupID(groupid,
"RailTypeMapSpriteGroup"))
continue;
5946 if (ctype >= RTSG_END)
continue;
5949 for (
auto &railtype : railtypes) {
5954 rti->
group[ctype] = _cur.spritegroups[groupid];
5963 static void RoadTypeMapSpriteGroup(
ByteReader &buf, uint8_t idcount, RoadTramType rtt)
5967 std::vector<uint8_t> roadtypes;
5968 roadtypes.reserve(idcount);
5969 for (uint i = 0; i < idcount; i++) {
5970 uint16_t
id = buf.ReadExtendedByte();
5974 uint8_t cidcount = buf.ReadByte();
5975 for (uint c = 0; c < cidcount; c++) {
5976 uint8_t ctype = buf.ReadByte();
5977 uint16_t groupid = buf.ReadWord();
5978 if (!IsValidGroupID(groupid,
"RoadTypeMapSpriteGroup"))
continue;
5980 if (ctype >= ROTSG_END)
continue;
5983 for (
auto &roadtype : roadtypes) {
5988 rti->
group[ctype] = _cur.spritegroups[groupid];
5997 static void AirportMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
5999 if (_cur.
grffile->airportspec.empty()) {
6000 GrfMsg(1,
"AirportMapSpriteGroup: No airports defined, skipping");
6004 std::vector<uint16_t> airports;
6005 airports.reserve(idcount);
6006 for (uint i = 0; i < idcount; i++) {
6007 airports.push_back(buf.ReadExtendedByte());
6011 uint8_t cidcount = buf.ReadByte();
6012 buf.Skip(cidcount * 3);
6014 uint16_t groupid = buf.ReadWord();
6015 if (!IsValidGroupID(groupid,
"AirportMapSpriteGroup"))
return;
6017 for (
auto &airport : airports) {
6020 if (as ==
nullptr) {
6021 GrfMsg(1,
"AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6029 static void AirportTileMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6031 if (_cur.
grffile->airtspec.empty()) {
6032 GrfMsg(1,
"AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6036 std::vector<uint16_t> airptiles;
6037 airptiles.reserve(idcount);
6038 for (uint i = 0; i < idcount; i++) {
6039 airptiles.push_back(buf.ReadExtendedByte());
6043 uint8_t cidcount = buf.ReadByte();
6044 buf.Skip(cidcount * 3);
6046 uint16_t groupid = buf.ReadWord();
6047 if (!IsValidGroupID(groupid,
"AirportTileMapSpriteGroup"))
return;
6049 for (
auto &airptile : airptiles) {
6052 if (airtsp ==
nullptr) {
6053 GrfMsg(1,
"AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6061 static void RoadStopMapSpriteGroup(
ByteReader &buf, uint8_t idcount)
6063 if (_cur.
grffile->roadstops.empty()) {
6064 GrfMsg(1,
"RoadStopMapSpriteGroup: No roadstops defined, skipping");
6068 std::vector<uint16_t> roadstops;
6069 roadstops.reserve(idcount);
6070 for (uint i = 0; i < idcount; i++) {
6071 roadstops.push_back(buf.ReadExtendedByte());
6074 uint8_t cidcount = buf.ReadByte();
6075 for (uint c = 0; c < cidcount; c++) {
6076 uint8_t ctype = buf.ReadByte();
6077 uint16_t groupid = buf.ReadWord();
6078 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
continue;
6080 ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6083 for (
auto &roadstop : roadstops) {
6086 if (roadstopspec ==
nullptr) {
6087 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6095 uint16_t groupid = buf.ReadWord();
6096 if (!IsValidGroupID(groupid,
"RoadStopMapSpriteGroup"))
return;
6098 for (
auto &roadstop : roadstops) {
6101 if (roadstopspec ==
nullptr) {
6102 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6107 GrfMsg(1,
"RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6119 static void FeatureMapSpriteGroup(
ByteReader &buf)
6135 uint8_t feature = buf.ReadByte();
6136 uint8_t idcount = buf.ReadByte();
6138 if (feature >= GSF_END) {
6139 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6147 uint16_t groupid = buf.ReadWord();
6148 if (!IsValidGroupID(groupid,
"FeatureMapSpriteGroup"))
return;
6150 GrfMsg(6,
"FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6159 GrfMsg(6,
"FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6163 case GSF_ROADVEHICLES:
6166 VehicleMapSpriteGroup(buf, feature, idcount);
6170 CanalMapSpriteGroup(buf, idcount);
6174 StationMapSpriteGroup(buf, idcount);
6178 TownHouseMapSpriteGroup(buf, idcount);
6181 case GSF_INDUSTRIES:
6182 IndustryMapSpriteGroup(buf, idcount);
6185 case GSF_INDUSTRYTILES:
6186 IndustrytileMapSpriteGroup(buf, idcount);
6190 CargoMapSpriteGroup(buf, idcount);
6194 AirportMapSpriteGroup(buf, idcount);
6198 ObjectMapSpriteGroup(buf, idcount);
6202 RailTypeMapSpriteGroup(buf, idcount);
6206 RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6210 RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6213 case GSF_AIRPORTTILES:
6214 AirportTileMapSpriteGroup(buf, idcount);
6218 RoadStopMapSpriteGroup(buf, idcount);
6222 GrfMsg(1,
"FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6246 bool new_scheme = _cur.
grffile->grf_version >= 7;
6248 uint8_t feature = buf.ReadByte();
6249 if (feature >= GSF_END && feature != 0x48) {
6250 GrfMsg(1,
"FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6254 uint8_t lang = buf.ReadByte();
6255 uint8_t num = buf.ReadByte();
6256 bool generic =
HasBit(lang, 7);
6259 id = buf.ReadWord();
6260 }
else if (feature <= GSF_AIRCRAFT) {
6261 id = buf.ReadExtendedByte();
6263 id = buf.ReadByte();
6268 uint16_t endid =
id + num;
6270 GrfMsg(6,
"FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6271 id, endid, feature, lang);
6273 for (;
id < endid && buf.HasData();
id++) {
6274 const std::string_view name = buf.ReadString();
6275 GrfMsg(8,
"FeatureNewName: 0x{:04X} <- {}",
id,
StrMakeValid(name));
6279 case GSF_ROADVEHICLES:
6284 if (e ==
nullptr)
break;
6298 switch (
GB(
id, 8, 8)) {
6300 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6301 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6309 if (
GB(
id, 0, 8) >= _cur.
grffile->stations.size() || _cur.
grffile->stations[
GB(
id, 0, 8)] ==
nullptr) {
6310 GrfMsg(1,
"FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring",
GB(
id, 0, 8));
6317 if (
GB(
id, 0, 8) >= _cur.
grffile->airtspec.size() || _cur.
grffile->airtspec[
GB(
id, 0, 8)] ==
nullptr) {
6318 GrfMsg(1,
"FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring",
GB(
id, 0, 8));
6325 if (
GB(
id, 0, 8) >= _cur.
grffile->housespec.size() || _cur.
grffile->housespec[
GB(
id, 0, 8)] ==
nullptr) {
6326 GrfMsg(1,
"FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.",
GB(
id, 0, 8));
6328 _cur.
grffile->housespec[
GB(
id, 0, 8)]->building_name =
AddGRFString(_cur.
grffile->grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
6333 GrfMsg(7,
"FeatureNewName: Unsupported ID (0x{:04X})",
id);
6352 if (offset >= max_sprites) {
6353 GrfMsg(1,
"GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6354 uint orig_num = num;
6359 if (offset + num > max_sprites) {
6360 GrfMsg(4,
"GraphicsNew: {} sprite overflow, truncating...", name);
6361 uint orig_num = num;
6362 num = std::max(max_sprites - offset, 0);
6363 return orig_num - num;
6377 {
A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT,
"Signal graphics" },
6379 {
A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT,
"Foundation graphics" },
6419 uint8_t type = buf.ReadByte();
6420 uint16_t num = buf.ReadExtendedByte();
6421 uint16_t offset =
HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6427 GrfMsg(2,
"GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6444 GrfMsg(2,
"GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6455 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->
name, type);
6462 GrfMsg(1,
"GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->
name, type, action5_type->
min_sprites, num);
6472 GrfMsg(2,
"GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->
name, type, replace);
6484 bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= SPR_ONEWAY_SLOPE_N_OFFSET));
6486 for (; num > 0; num--) {
6490 if (dup_oneway_sprites) {
6491 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_N_OFFSET);
6492 DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_S_OFFSET);
6508 GrfMsg(3,
"SkipAct5: Skipping {} sprites", _cur.
skip_sprites);
6561 *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6591 *value = _game_mode;
6625 *value =
Clamp(snowline * (grffile->grf_version >= 8 ? 1 :
TILE_HEIGHT), 0, 0xFE);
6634 *value = _openttd_newgrf_version;
6649 default:
return false;
6653 static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
6672 if (cond_val ==
nullptr) {
6676 uint32_t index = *cond_val / 0x20;
6692 GrfMsg(1,
"Unsupported in-game variable 0x{:02X}", param);
6713 size_t pos = file.
GetPos();
6719 GrfMsg(2,
"CfgApply: Ignoring (next sprite is real, unsupported)");
6722 file.
SeekTo(pos, SEEK_SET);
6728 std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
6731 if (preload_sprite.empty()) {
6732 preload_sprite.resize(num);
6733 file.
ReadBlock(preload_sprite.data(), num);
6737 file.
SeekTo(pos, SEEK_SET);
6748 param_num = buf.ReadByte();
6749 if (param_num == 0xFF)
break;
6753 param_size = buf.ReadByte();
6757 add_value =
HasBit(param_size, 7);
6758 param_size =
GB(param_size, 0, 7);
6761 offset = buf.ReadExtendedByte();
6765 if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= _cur.
grffile->
param_end) {
6766 GrfMsg(2,
"CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
6770 GrfMsg(8,
"CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
6773 for (i = 0; i < param_size && offset + i < num; i++) {
6774 uint32_t value = GetParamVal(param_num + i / 4,
nullptr);
6777 if (i % 4 == 0) carry =
false;
6780 uint new_value = preload_sprite[offset + i] +
GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0);
6781 preload_sprite[offset + i] =
GB(new_value, 0, 8);
6783 carry = new_value >= 256;
6785 preload_sprite[offset + i] =
GB(value, (i % 4) * 8, 8);
6817 uint32_t cond_val = 0;
6821 uint8_t param = buf.ReadByte();
6822 uint8_t paramsize = buf.ReadByte();
6823 uint8_t condtype = buf.ReadByte();
6830 switch (paramsize) {
6831 case 8: cond_val = buf.ReadDWord(); mask = buf.ReadDWord();
break;
6832 case 4: cond_val = buf.ReadDWord(); mask = 0xFFFFFFFF;
break;
6833 case 2: cond_val = buf.ReadWord(); mask = 0x0000FFFF;
break;
6834 case 1: cond_val = buf.ReadByte(); mask = 0x000000FF;
break;
6838 if (param < 0x80 && _cur.grffile->param_end <= param) {
6839 GrfMsg(7,
"SkipIf: Param {} undefined, skipping test", param);
6843 GrfMsg(7,
"SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
6848 if (condtype >= 0x0B) {
6879 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6881 }
else if (param == 0x88) {
6891 if (condtype != 10 && c ==
nullptr) {
6892 GrfMsg(7,
"SkipIf: GRFID 0x{:08X} unknown, skipping test",
BSWAP32(cond_val));
6919 default: GrfMsg(1,
"SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype);
return;
6923 uint32_t param_val = GetParamVal(param, &cond_val);
6925 case 0x00: result = !!(param_val & (1 << cond_val));
6927 case 0x01: result = !(param_val & (1 << cond_val));
6929 case 0x02: result = (param_val & mask) == cond_val;
6931 case 0x03: result = (param_val & mask) != cond_val;
6933 case 0x04: result = (param_val & mask) < cond_val;
6935 case 0x05: result = (param_val & mask) > cond_val;
6937 default: GrfMsg(1,
"SkipIf: Unsupported condition type {:02X}. Ignoring", condtype);
return;
6942 GrfMsg(2,
"SkipIf: Not skipping sprites, test was false");
6946 uint8_t numsprites = buf.ReadByte();
6954 if (label.label != numsprites)
continue;
6957 if (choice ==
nullptr) choice = &label;
6959 if (label.nfo_line > _cur.
nfo_line) {
6965 if (choice !=
nullptr) {
6966 GrfMsg(2,
"SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
6972 GrfMsg(2,
"SkipIf: Skipping {} sprites, test was true", numsprites);
6991 uint8_t grf_version = buf.ReadByte();
6992 uint32_t grfid = buf.ReadDWord();
6993 std::string_view name = buf.ReadString();
6997 if (grf_version < 2 || grf_version > 8) {
7007 if (buf.HasData()) {
7008 std::string_view info = buf.ReadString();
7026 uint8_t version = buf.ReadByte();
7027 uint32_t grfid = buf.ReadDWord();
7028 std::string_view name = buf.ReadString();
7031 DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7035 if (_cur.
grffile->grfid != grfid) {
7036 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));
7040 _cur.
grffile->grf_version = version;
7047 GrfMsg(3,
"GRFInfo: Installing default GRFv{} translation table for {:08X}", version,
BSWAP32(grfid));
7062 for (
const auto &grm_sprite : _grm_sprites) {
7063 if (grm_sprite.first.grfid != _cur.
grffile->grfid)
continue;
7064 if (grm_sprite.second.first <= first_sprite && grm_sprite.second.first + grm_sprite.second.second >= first_sprite + num_sprites)
return true;
7080 uint8_t num_sets = buf.ReadByte();
7082 for (uint i = 0; i < num_sets; i++) {
7083 uint8_t num_sprites = buf.ReadByte();
7084 uint16_t first_sprite = buf.ReadWord();
7086 GrfMsg(2,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7087 i, num_sprites, first_sprite
7093 GrfMsg(0,
"SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7102 for (uint j = 0; j < num_sprites; j++) {
7103 SpriteID load_index = first_sprite + j;
7109 if (
IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7119 uint8_t num_sets = buf.ReadByte();
7121 for (uint i = 0; i < num_sets; i++) {
7128 GrfMsg(3,
"SkipActA: Skipping {} sprites", _cur.
skip_sprites);
7150 STR_NEWGRF_ERROR_VERSION_NUMBER,
7151 STR_NEWGRF_ERROR_DOS_OR_WINDOWS,
7152 STR_NEWGRF_ERROR_UNSET_SWITCH,
7153 STR_NEWGRF_ERROR_INVALID_PARAMETER,
7154 STR_NEWGRF_ERROR_LOAD_BEFORE,
7155 STR_NEWGRF_ERROR_LOAD_AFTER,
7156 STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER,
7160 STR_NEWGRF_ERROR_MSG_INFO,
7161 STR_NEWGRF_ERROR_MSG_WARNING,
7162 STR_NEWGRF_ERROR_MSG_ERROR,
7163 STR_NEWGRF_ERROR_MSG_FATAL
7166 uint8_t severity = buf.ReadByte();
7167 uint8_t lang = buf.ReadByte();
7168 uint8_t message_id = buf.ReadByte();
7171 if (!CheckGrfLangID(lang, _cur.
grffile->grf_version))
return;
7175 if (!
HasBit(severity, 7) && _cur.
stage == GLS_INIT) {
7176 GrfMsg(7,
"GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.
stage);
7181 if (severity >=
lengthof(sevstr)) {
7182 GrfMsg(7,
"GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7184 }
else if (severity == 3) {
7193 if (message_id >=
lengthof(msgstr) && message_id != 0xFF) {
7194 GrfMsg(7,
"GRFLoadError: Invalid message id.");
7198 if (buf.Remaining() <= 1) {
7199 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7209 if (message_id == 0xFF) {
7211 if (buf.HasData()) {
7212 std::string_view message = buf.ReadString();
7216 GrfMsg(7,
"GRFLoadError: No custom message supplied.");
7220 error->
message = msgstr[message_id];
7223 if (buf.HasData()) {
7224 std::string_view data = buf.ReadString();
7228 GrfMsg(7,
"GRFLoadError: No message data supplied.");
7229 error->
data.clear();
7233 for (uint i = 0; i < error->
param_value.size() && buf.HasData(); i++) {
7234 uint param_number = buf.ReadByte();
7246 if (!buf.HasData())
return;
7248 std::string_view text = buf.ReadString();
7255 uint8_t target = buf.ReadByte();
7258 if (target < 0x80 || target == 0x9E)
return;
7272 static uint32_t GetPatchVariable(uint8_t param)
7282 case 0x0F:
return 0;
7298 case 0x11:
return SPR_2CCMAP_BASE;
7312 uint8_t map_bits = 0;
7315 uint8_t max_edge = std::max(log_X, log_Y);
7317 if (log_X == log_Y) {
7320 if (max_edge == log_Y)
SetBit(map_bits, 1);
7323 return (map_bits << 24) | (std::min(log_X, log_Y) << 20) | (max_edge << 16) |
7324 (log_X << 12) | (log_Y << 8) | (log_X + log_Y);
7333 return SPR_SLOPES_BASE;
7344 GrfMsg(2,
"ParamSet: Unknown Patch variable 0x{:02X}.", param);
7350 static uint32_t PerformGRM(uint32_t *grm, uint16_t num_ids, uint16_t count, uint8_t op, uint8_t target,
const char *type)
7363 for (uint i = start; i < num_ids; i++) {
7367 if (op == 2 || op == 3)
break;
7372 if (size == count)
break;
7375 if (size == count) {
7377 if (op == 0 || op == 3) {
7378 GrfMsg(2,
"ParamSet: GRM: Reserving {} {} at {}", count, type, start);
7379 for (uint i = 0; i < count; i++) grm[start + i] = _cur.
grffile->grfid;
7385 if (op != 4 && op != 5) {
7387 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7392 GrfMsg(1,
"ParamSet: GRM: Unable to allocate {} {}", count, type);
7422 uint8_t target = buf.ReadByte();
7423 uint8_t oper = buf.ReadByte();
7424 uint32_t src1 = buf.ReadByte();
7425 uint32_t src2 = buf.ReadByte();
7428 if (buf.Remaining() >= 4) data = buf.ReadDWord();
7437 if (target < 0x80 && target < _cur.grffile->param_end) {
7438 GrfMsg(7,
"ParamSet: Param {} already defined, skipping", target);
7442 oper =
GB(oper, 0, 7);
7446 if (
GB(data, 0, 8) == 0xFF) {
7447 if (data == 0x0000FFFF) {
7449 src1 = GetPatchVariable(src1);
7453 uint8_t feature =
GB(data, 8, 8);
7454 uint16_t count =
GB(data, 16, 16);
7456 if (_cur.
stage == GLS_RESERVE) {
7457 if (feature == 0x08) {
7461 if (_cur.
spriteid + count >= 16384) {
7462 GrfMsg(0,
"ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7468 GrfMsg(4,
"ParamSet: GRM: Allocated {} sprites at {}", count, _cur.
spriteid);
7475 }
else if (_cur.
stage == GLS_ACTIVATION) {
7504 GrfMsg(4,
"ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7512 GrfMsg(1,
"ParamSet: GRM: Unsupported operation {} for general sprites", op);
7523 default: GrfMsg(1,
"ParamSet: GRM: Unsupported feature 0x{:X}", feature);
return;
7540 }
else if (src1 == 0xFE) {
7552 src1 = (src1 == 0xFF) ? data : GetParamVal(src1,
nullptr);
7553 src2 = (src2 == 0xFF) ? data : GetParamVal(src2,
nullptr);
7575 res = (int32_t)src1 * (int32_t)src2;
7579 if ((int32_t)src2 < 0) {
7580 res = src1 >> -(int32_t)src2;
7582 res = src1 << (src2 & 0x1F);
7587 if ((int32_t)src2 < 0) {
7588 res = (int32_t)src1 >> -(int32_t)src2;
7590 res = (int32_t)src1 << (src2 & 0x1F);
7614 res = (int32_t)src1 / (int32_t)src2;
7630 res = (int32_t)src1 % (int32_t)src2;
7634 default: GrfMsg(0,
"ParamSet: Unknown operation {}, skipping", oper);
return;
7663 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7674 uint32_t safe_bits = 0;
7675 SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
7684 GrfMsg(7,
"ParamSet: Skipping unimplemented target 0x{:02X}", target);
7688 if (target < 0x80) {
7689 _cur.
grffile->param[target] = res;
7693 GrfMsg(7,
"ParamSet: Skipping unknown target 0x{:02X}", target);
7707 uint8_t num = buf.ReadByte();
7709 for (uint i = 0; i < num; i++) {
7710 uint32_t grfid = buf.ReadDWord();
7732 uint8_t num = buf.ReadByte();
7734 for (uint i = 0; i < num; i++) {
7735 uint32_t grfid = buf.ReadDWord();
7739 if (file !=
nullptr && file != _cur.
grfconfig) {
7740 GrfMsg(2,
"GRFInhibit: Deactivating file '{}'", file->
filename);
7757 uint32_t grfid = _cur.
grffile->grfid;
7761 uint8_t
id = buf.ReadByte();
7762 GrfMsg(6,
"FeatureTownName: definition 0x{:02X}",
id & 0x7F);
7767 bool new_scheme = _cur.
grffile->grf_version >= 7;
7769 uint8_t lang = buf.ReadByte();
7775 std::string_view name = buf.ReadString();
7778 GrfMsg(6,
"FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
7780 style =
AddGRFString(grfid,
id, lang, new_scheme,
false, name, STR_UNDEFINED);
7782 lang = buf.ReadByte();
7783 }
while (lang != 0);
7784 townname->
styles.emplace_back(style,
id);
7787 uint8_t parts = buf.ReadByte();
7788 GrfMsg(6,
"FeatureTownName: {} parts", parts);
7791 for (uint partnum = 0; partnum < parts; partnum++) {
7793 uint8_t texts = buf.ReadByte();
7794 partlist.
bitstart = buf.ReadByte();
7795 partlist.
bitcount = buf.ReadByte();
7797 GrfMsg(6,
"FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.
bitstart, partlist.
bitcount);
7799 partlist.
parts.reserve(texts);
7800 for (uint textnum = 0; textnum < texts; textnum++) {
7802 part.
prob = buf.ReadByte();
7805 uint8_t ref_id = buf.ReadByte();
7807 GrfMsg(0,
"FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
7808 DelGRFTownName(grfid);
7813 GrfMsg(6,
"FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.
prob & 0x7F);
7815 std::string_view text = buf.ReadString();
7817 GrfMsg(6,
"FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.
text, part.
prob);
7821 GrfMsg(6,
"FeatureTownName: part {}, total probability {}", partnum, partlist.
maxprob);
7833 uint8_t nfo_label = buf.ReadByte();
7837 GrfMsg(2,
"DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
7851 if (file ==
nullptr || file->sound_offset == 0) {
7852 GrfMsg(1,
"ImportGRFSound: Source file not available");
7856 if (sound_id >= file->num_sounds) {
7857 GrfMsg(1,
"ImportGRFSound: Sound effect {} is invalid", sound_id);
7861 GrfMsg(2,
"ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
7863 *sound = *GetSound(file->sound_offset + sound_id);
7866 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7867 sound->priority = 0;
7878 sound->volume = SOUND_EFFECT_MAX_VOLUME;
7879 sound->priority = 0;
7881 if (offs != SIZE_MAX) {
7883 sound->file = _cur.
file;
7884 sound->file_offset = offs;
7896 uint16_t num = buf.ReadWord();
7897 if (num == 0)
return;
7900 if (_cur.
grffile->sound_offset == 0) {
7901 _cur.
grffile->sound_offset = GetNumSounds();
7902 _cur.
grffile->num_sounds = num;
7905 sound = GetSound(_cur.
grffile->sound_offset);
7910 for (
int i = 0; i < num; i++) {
7915 bool invalid = i >= _cur.
grffile->num_sounds;
7917 size_t offs = file.
GetPos();
7922 if (grf_container_version >= 2 && type == 0xFD) {
7925 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
7927 }
else if (len != 4) {
7928 GrfMsg(1,
"GRFSound: Invalid sprite section import");
7938 GrfMsg(1,
"GRFSound: Unexpected RealSprite found, skipping");
7945 GrfMsg(1,
"GRFSound: Sound index out of range (multiple Action 11?)");
7953 if (_cur.
stage == GLS_INIT) {
7954 if (grf_container_version >= 2) {
7955 GrfMsg(1,
"GRFSound: Inline sounds are not supported for container version >= 2");
7964 if (_cur.
stage == GLS_ACTIVATION) {
7967 if (file.
ReadByte() != 0) GrfMsg(1,
"GRFSound: Import type mismatch");
7975 GrfMsg(1,
"GRFSound: Unexpected Action {:x} found, skipping", action);
7991 GrfMsg(3,
"SkipAct11: Skipping {} sprites", _cur.
skip_sprites);
8004 uint8_t num_def = buf.ReadByte();
8006 for (uint i = 0; i < num_def; i++) {
8008 uint8_t num_char = buf.ReadByte();
8009 uint16_t base_char = buf.ReadWord();
8011 if (size >= FS_END) {
8012 GrfMsg(1,
"LoadFontGlyph: Size {} is not supported, ignoring", size);
8015 GrfMsg(7,
"LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8017 for (uint c = 0; c < num_char; c++) {
8035 uint8_t num_def = buf.ReadByte();
8037 for (uint i = 0; i < num_def; i++) {
8048 GrfMsg(3,
"SkipAct12: Skipping {} sprites", _cur.
skip_sprites);
8061 uint32_t grfid = buf.ReadDWord();
8064 GrfMsg(7,
"TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13",
BSWAP32(grfid));
8073 error->
data =
GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8083 uint8_t language = _cur.
grffile->grf_version >= 8 ? buf.ReadByte() : 0x7F;
8084 uint8_t num_strings = buf.ReadByte();
8085 uint16_t first_id = buf.ReadWord();
8087 if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
8088 GrfMsg(7,
"TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
8092 for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8093 std::string_view
string = buf.ReadString();
8095 if (
string.empty()) {
8096 GrfMsg(7,
"TranslateGRFString: Ignoring empty string.");
8100 AddGRFString(grfid, first_id + i, language,
true,
true,
string, STR_UNDEFINED);
8129 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8141 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8144 char data = buf.ReadByte();
8152 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8167 GrfMsg(2,
"StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8170 char data = buf.ReadByte();
8176 GrfMsg(2,
"StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8189 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8202 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8207 GrfMsg(2,
"StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8238 GrfMsg(2,
"StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8245 GrfMsg(3,
"StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8255 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8257 }
else if (len != 8) {
8258 GrfMsg(2,
"StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8261 uint32_t min_value = buf.ReadDWord();
8262 uint32_t max_value = buf.ReadDWord();
8263 if (min_value <= max_value) {
8267 GrfMsg(2,
"StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8276 if (len < 1 || len > 3) {
8277 GrfMsg(2,
"StaticGRFInfo: expected 1 to 3 bytes for 'INFO'->'PARA'->'MASK' but got {}, ignoring this field", len);
8280 uint8_t param_nr = buf.ReadByte();
8282 GrfMsg(2,
"StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8298 GrfMsg(2,
"StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8334 this->handler.data = handler;
8346 this->handler.text = handler;
8358 this->handler.call_handler =
true;
8359 this->handler.u.branch = handler;
8371 this->handler.call_handler =
false;
8372 this->handler.u.subtags =
subtags;
8401 uint8_t type = buf.ReadByte();
8403 uint32_t
id = buf.ReadDWord();
8405 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8407 type = buf.ReadByte();
8411 uint8_t langid = buf.ReadByte();
8412 std::string_view name_string = buf.ReadString();
8423 type = buf.ReadByte();
8448 uint8_t type = buf.ReadByte();
8450 uint32_t
id = buf.ReadDWord();
8452 GrfMsg(2,
"StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8454 type = buf.ReadByte();
8467 type = buf.ReadByte();
8504 uint8_t new_type = buf.ReadByte();
8505 while (new_type != 0) {
8508 new_type = buf.ReadByte();
8519 uint16_t size = buf.ReadWord();
8543 while ((tag = &subtags[i++])->type != 0) {
8546 default: NOT_REACHED();
8549 uint8_t langid = buf.ReadByte();
8550 return tag->handler.
text(langid, buf.ReadString());
8554 size_t len = buf.ReadWord();
8555 if (buf.Remaining() < len)
return false;
8556 return tag->handler.
data(len, buf);
8561 return tag->handler.u.branch(buf);
8567 GrfMsg(2,
"StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type,
id);
8579 uint8_t type = buf.ReadByte();
8581 uint32_t
id = buf.ReadDWord();
8582 if (!
HandleNode(type,
id, buf, subtags))
return false;
8583 type = buf.ReadByte();
8704 file->stations.clear();
8712 file->housespec.clear();
8720 file->airportspec.clear();
8721 file->airtspec.clear();
8729 file->industryspec.clear();
8730 file->indtspec.clear();
8738 file->objectspec.clear();
8742 static void ResetCustomRoadStops()
8745 file->roadstops.clear();
8774 CleanUpGRFTownNames();
8834 ResetCustomRoadStops();
8860 _grf_id_overrides.clear();
8862 InitializeSoundPool();
8889 if (!cs->IsValid())
continue;
8904 if (newfile !=
nullptr) {
8910 newfile =
new GRFFile(config);
8928 for (
Price i = PR_BEGIN; i < PR_END; i++) {
8933 std::fill(std::begin(this->railtype_map), std::end(this->railtype_map),
INVALID_RAILTYPE);
8940 std::fill(std::begin(this->roadtype_map), std::end(this->roadtype_map),
INVALID_ROADTYPE);
8944 std::fill(std::begin(this->tramtype_map), std::end(this->tramtype_map),
INVALID_ROADTYPE);
8949 this->param = config->
param;
8961 CargoID cid = GetCargoIDByLabel(label);
8962 if (cid != INVALID_CARGO)
return label;
8982 default: NOT_REACHED();
8987 return std::visit(visitor{}, label);
8995 CargoTypes original_known_cargoes = 0;
9003 bool only_defaultcargo;
9011 if (
_gted[engine].defaultcargo_grf ==
nullptr) {
9014 static constexpr uint8_t T = 1 << LT_TEMPERATE;
9015 static constexpr uint8_t A = 1 << LT_ARCTIC;
9016 static constexpr uint8_t S = 1 << LT_TROPIC;
9017 static constexpr uint8_t Y = 1 << LT_TOYLAND;
9018 static const struct DefaultRefitMasks {
9023 } _default_refit_masks[] = {
9025 {T | A | S , CT_MAIL,
CC_MAIL, 0},
9028 {T | A , CT_COAL,
CC_BULK, 0},
9029 { S , CT_COPPER_ORE,
CC_BULK, 0},
9045 switch (label.base()) {
9049 _gted[engine].cargo_disallowed = 0;
9054 _gted[engine].cargo_disallowed = 0;
9073 _gted[engine].cargo_disallowed = 0;
9077 for (
const auto &drm : _default_refit_masks) {
9079 if (drm.cargo_label != label)
continue;
9081 _gted[engine].cargo_allowed = drm.cargo_allowed;
9082 _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9087 _gted[engine].ctt_exclude_mask = original_known_cargoes;
9090 _gted[engine].UpdateRefittability(
_gted[engine].cargo_allowed != 0);
9097 CargoTypes mask = 0;
9098 CargoTypes not_mask = 0;
9099 CargoTypes xor_mask = ei->refit_mask;
9105 if (
_gted[engine].cargo_allowed != 0) {
9108 if ((
_gted[engine].cargo_allowed & cs->classes) != 0 && (
_gted[engine].cargo_allowed_required & cs->classes) ==
_gted[engine].cargo_allowed_required)
SetBit(mask, cs->Index());
9109 if (
_gted[engine].cargo_disallowed & cs->classes)
SetBit(not_mask, cs->Index());
9113 ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) &
_cargo_mask;
9116 ei->refit_mask |=
_gted[engine].ctt_include_mask;
9117 ei->refit_mask &= ~
_gted[engine].ctt_exclude_mask;
9121 if (file ==
nullptr) file = e->
GetGRF();
9124 uint8_t local_slot = file->
cargo_map[cs->Index()];
9130 case 1:
SetBit(ei->refit_mask, cs->Index());
break;
9131 case 2:
ClrBit(ei->refit_mask, cs->Index());
break;
9145 ei->cargo_type = INVALID_CARGO;
9153 if (file ==
nullptr) file = e->
GetGRF();
9154 if (file !=
nullptr && file->grf_version >= 8 && !file->
cargo_list.empty()) {
9156 uint8_t best_local_slot = UINT8_MAX;
9158 uint8_t local_slot = file->
cargo_map[cargo_type];
9159 if (local_slot < best_local_slot) {
9160 best_local_slot = local_slot;
9161 ei->cargo_type = cargo_type;
9191 for (uint i = 0; i < CF_END; i++) {
9203 if (e->
GetGRF() ==
nullptr) {
9206 e->info.
string_id = STR_NEWGRF_INVALID_ENGINE;
9239 default: NOT_REACHED();
9251 if (parent != e->
index)
continue;
9256 GrfMsg(1,
"FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", _engine_mngr[e->
index].internal_id, e->
GetGRF()->filename);
9272 switch (cs.label.base()) {
9274 case CT_MAIL.base(): cs.town_production_effect =
TPE_MAIL;
break;
9275 default: cs.town_production_effect =
TPE_NONE;
break;
9278 if (!cs.IsValid()) {
9279 cs.name = cs.name_single = cs.units_volume = STR_NEWGRF_INVALID_CARGO;
9280 cs.quantifier = STR_NEWGRF_INVALID_CARGO_QUANTITY;
9281 cs.abbrev = STR_NEWGRF_INVALID_CARGO_ABBREV;
9305 if (!filename.empty())
Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} as multitile, but no suitable tiles follow. Disabling house.", filename, hs->
grf_prop.
local_id);
9315 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);
9323 Debug(grf, 1,
"FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->
grf_prop.
local_id);
9330 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);
9353 if (min_year == 0)
return;
9380 if (file->housespec.empty())
continue;
9382 size_t num_houses = file->housespec.size();
9383 for (
size_t i = 0; i < num_houses; i++) {
9384 HouseSpec *hs = file->housespec[i].get();
9386 if (hs ==
nullptr)
continue;
9388 const HouseSpec *next1 = (i + 1 < num_houses ? file->housespec[i + 1].get() :
nullptr);
9389 const HouseSpec *next2 = (i + 2 < num_houses ? file->housespec[i + 2].get() :
nullptr);
9390 const HouseSpec *next3 = (i + 3 < num_houses ? file->housespec[i + 3].get() :
nullptr);
9449 for (
const auto &indsp : file->industryspec) {
9450 if (indsp ==
nullptr || !indsp->
enabled)
continue;
9457 if (strid != STR_UNDEFINED) indsp->
name = strid;
9460 if (strid != STR_UNDEFINED) indsp->
closure_text = strid;
9475 if (strid != STR_UNDEFINED) indsp->
station_name = strid;
9481 for (
const auto &indtsp : file->indtspec) {
9482 if (indtsp !=
nullptr) {
9483 _industile_mngr.SetEntitySpec(indtsp.get());
9488 for (
auto &indsp : _industry_specs) {
9495 indsp.
name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9507 for (
auto &indtsp : _industry_tile_specs) {
9523 for (
auto &objectspec : file->objectspec) {
9524 if (objectspec !=
nullptr && objectspec->grf_prop.grffile !=
nullptr && objectspec->IsEnabled()) {
9541 for (
auto &as : file->airportspec) {
9542 if (as !=
nullptr && as->
enabled) {
9543 _airport_mngr.SetEntitySpec(as.get());
9547 for (
auto &ats : file->airtspec) {
9548 if (ats !=
nullptr && ats->enabled) {
9549 _airporttile_mngr.SetEntitySpec(ats.get());
9561 static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9575 static const SpecialSpriteHandler handlers[][GLS_END] = {
9576 {
nullptr, SafeChangeInfo,
nullptr,
nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9577 { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9578 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, NewSpriteGroup, },
9579 {
nullptr,
GRFUnsafe,
nullptr,
nullptr,
nullptr, FeatureMapSpriteGroup, },
9580 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, FeatureNewName, },
9581 { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9582 {
nullptr,
nullptr,
nullptr, CfgApply, CfgApply, CfgApply, },
9583 {
nullptr,
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, },
9584 { ScanInfo,
nullptr,
nullptr, GRFInfo, GRFInfo, GRFInfo, },
9585 {
nullptr,
nullptr,
nullptr, SkipIf, SkipIf, SkipIf, },
9586 { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9587 {
nullptr,
nullptr,
nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9588 {
nullptr,
nullptr,
nullptr, GRFComment,
nullptr, GRFComment, },
9590 {
nullptr, SafeGRFInhibit,
nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9593 { SkipAct11,
GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9596 {
StaticGRFInfo,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr, },
9601 GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9602 if (it == _grf_line_to_action6_sprite_override.end()) {
9608 buf = _grf_line_to_action6_sprite_override[location].data();
9609 GrfMsg(7,
"DecodeSpecialSprite: Using preloaded pseudo sprite data");
9618 uint8_t action = br.ReadByte();
9620 if (action == 0xFF) {
9621 GrfMsg(2,
"DecodeSpecialSprite: Unexpected data block, skipping");
9622 }
else if (action == 0xFE) {
9623 GrfMsg(2,
"DecodeSpecialSprite: Unexpected import block, skipping");
9624 }
else if (action >=
lengthof(handlers)) {
9625 GrfMsg(7,
"DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
9626 }
else if (handlers[action][stage] ==
nullptr) {
9627 GrfMsg(7,
"DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
9629 GrfMsg(7,
"DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9630 handlers[action][stage](br);
9633 GrfMsg(1,
"DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9649 Debug(grf, 2,
"LoadNewGRFFile: Reading NewGRF-file '{}'", config->
filename);
9652 if (grf_container_version == 0) {
9653 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9657 if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9663 if (grf_container_version >= 2) file.
ReadDword();
9666 if (grf_container_version >= 2) {
9668 uint8_t compression = file.
ReadByte();
9669 if (compression != 0) {
9670 Debug(grf, 7,
"LoadNewGRFFile: Unsupported compression format");
9679 if (num == 4 && file.
ReadByte() == 0xFF) {
9682 Debug(grf, 7,
"LoadNewGRFFile: Custom .grf has invalid format");
9690 while ((num = (grf_container_version >= 2 ? file.
ReadDword() : file.
ReadWord())) != 0) {
9696 DecodeSpecialSprite(buf.
Allocate(num), num, stage);
9707 GrfMsg(0,
"LoadNewGRFFile: Unexpected sprite, disabling");
9708 DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9712 if (grf_container_version >= 2 && type == 0xFD) {
9735 const std::string &filename = config->
filename;
9746 if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
9748 if (_cur.
grffile ==
nullptr) UserError(
"File '{}' lost in cache.\n", filename);
9755 SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
9809 DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0);
9810 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
9811 DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2);
9812 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
9813 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
9814 DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
9825 static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
9829 std::vector<int> grf_overrides(num_grfs, -1);
9830 for (
int i = 0; i < num_grfs; i++) {
9832 auto it = _grf_id_overrides.find(source->grfid);
9833 if (it == std::end(_grf_id_overrides))
continue;
9834 uint32_t
override = it->second;
9837 if (dest ==
nullptr)
continue;
9840 assert(grf_overrides[i] >= 0);
9844 for (
int i = 0; i < num_grfs; i++) {
9845 if (grf_overrides[i] < 0 || grf_overrides[i] >= i)
continue;
9853 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9856 Debug(grf, 3,
"'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
9862 for (
int i = num_grfs - 1; i >= 0; i--) {
9863 if (grf_overrides[i] < 0 || grf_overrides[i] <= i)
continue;
9871 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9874 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
9880 for (
int i = 0; i < num_grfs; i++) {
9881 if (grf_overrides[i] < 0)
continue;
9889 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9890 if (!
HasBit(features, _price_base_specs[p].grf_feature))
continue;
9892 Debug(grf, 3,
"Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
9900 if (file->grf_version >= 8)
continue;
9901 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9902 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9904 if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9907 price_base_multipliers[p] = price_base_multipliers[fallback_price];
9914 PriceMultipliers &price_base_multipliers = file->price_base_multipliers;
9915 for (
Price p = PR_BEGIN; p < PR_END; p++) {
9916 if (price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9918 price_base_multipliers[p] = 0;
9923 Debug(grf, 3,
"'{}' sets global price base multiplier {}", file->
filename, p);
9925 price_base_multipliers[p] = 0;
9927 Debug(grf, 3,
"'{}' sets local price base multiplier {}", file->
filename, p);
9945 _grf_line_to_action6_sprite_override.clear();
10008 if (file ==
nullptr ||
_gted[e->
index].roadtramtype == 0) {
10017 if (
_gted[e->
index].roadtramtype < list->size())
10019 RoadTypeLabel rtl = (*list)[
_gted[e->
index].roadtramtype];
10048 _grm_sprites.clear();
10106 for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10113 if (stage == GLS_RESERVE) {
10114 static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10119 for (
const auto &grf_override : default_grf_overrides) {
10125 uint num_non_static = 0;
10127 _cur.
stage = stage;
10134 Debug(grf, 0,
"NewGRF file is missing '{}'; disabling", c->
filename);
10143 Debug(grf, 0,
"'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->
filename);
10145 c->
error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10154 if (stage == GLS_RESERVE) {
10156 }
else if (stage == GLS_ACTIVATION) {
10161 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.
MixedCargoType
Mixed cargo types for definitions with cargo that can vary depending on climate.
@ MCT_GRAIN_WHEAT_MAIZE
Cargo can be grain, wheat or maize.
@ MCT_LIVESTOCK_FRUIT
Cargo can be livestock or fruit.
@ MCT_VALUABLES_GOLD_DIAMONDS
Cargo can be valuables, gold or diamonds.
static 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.
@ CBID_VEHICLE_CUSTOM_REFIT
Called to get custom engine refit mask.
@ CBM_VEHICLE_CUSTOM_REFIT
Custom refit mask.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
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.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
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.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
void CommitVehicleListOrderChanges()
Deternine default engine sorting and execute recorded ListOrderChanges from AlterVehicleListOrder.
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.
CargoClasses cargo_disallowed
Bitmask of cargo classes that are disallowed as a refit.
CargoTypes ctt_include_mask
Cargo types always included in the refit mask.
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.
CargoClasses cargo_allowed
Bitmask of cargo classes that are allowed as a refit.
void UpdateRefittability(bool non_empty)
Update the summary refittability on setting a refittability property.
CargoClasses cargo_allowed_required
Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
const GRFFile * defaultcargo_grf
GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
std::vector< NamePartList > partlists[MAX_LISTS]
Lists of town name parts.
static const uint MAX_LISTS
Maximum number of town name lists that can be defined per GRF.
std::vector< TownNameStyle > styles
Style names defined by the Town Name NewGRF.
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
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
CargoLabel accepts_cargo_label[HOUSE_ORIGINAL_NUM_ACCEPTS]
input landscape cargo slots
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
BuildingFlags building_flags
some flags that describe the house (size, stadium etc...)
uint8_t population
population (Zero on other tiles in multi tile house.)
uint8_t cargo_acceptance[HOUSE_NUM_ACCEPTS]
acceptance level for the cargo slots
TimerGameCalendar::Year min_year
introduction year of the house
GRFFileProps grf_prop
Properties related the the grf file.
HouseZones building_availability
where can it be built (climates, zones)
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
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.
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industries.
IndustryType conflicting[3]
Industries this industry cannot be close to.
GRFFileProps grf_prop
properties related to the grf file
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
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_OUTPUTS > produced_cargo_label
Cargo labels of produced cargo for default industries.
Definition of one tile in an industry tile layout.
Defines the data structure of each individual tile of an industry.
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
GRFFileProps grf_prop
properties related to the grf file
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industry tiles.
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.