OpenTTD Source  20241121-master-g67a0fccfad
newgrf.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 
12 #include "core/backup_type.hpp"
13 #include "core/container_func.hpp"
14 #include "debug.h"
15 #include "fileio_func.h"
16 #include "engine_func.h"
17 #include "engine_base.h"
18 #include "bridge.h"
19 #include "town.h"
20 #include "newgrf_engine.h"
21 #include "newgrf_text.h"
22 #include "fontcache.h"
23 #include "currency.h"
24 #include "landscape.h"
25 #include "newgrf_cargo.h"
26 #include "newgrf_house.h"
27 #include "newgrf_sound.h"
28 #include "newgrf_station.h"
29 #include "industrytype.h"
30 #include "industry_map.h"
31 #include "newgrf_act5.h"
32 #include "newgrf_canal.h"
33 #include "newgrf_townname.h"
34 #include "newgrf_industries.h"
35 #include "newgrf_airporttiles.h"
36 #include "newgrf_airport.h"
37 #include "newgrf_object.h"
38 #include "rev.h"
39 #include "fios.h"
40 #include "strings_func.h"
41 #include "timer/timer_game_tick.h"
43 #include "string_func.h"
44 #include "network/core/config.h"
45 #include "smallmap_gui.h"
46 #include "genworld.h"
47 #include "error.h"
48 #include "error_func.h"
49 #include "vehicle_func.h"
50 #include "language.h"
51 #include "vehicle_base.h"
52 #include "road.h"
53 #include "newgrf_roadstop.h"
54 
55 #include "table/strings.h"
56 #include "table/build_industry.h"
57 
58 #include "safeguards.h"
59 
60 /* TTDPatch extended GRF format codec
61  * (c) Petr Baudis 2004 (GPL'd)
62  * Changes by Florian octo Forster are (c) by the OpenTTD development team.
63  *
64  * Contains portions of documentation by TTDPatch team.
65  * Thanks especially to Josef Drexler for the documentation as well as a lot
66  * of help at #tycoon. Also thanks to Michael Blunck for his GRF files which
67  * served as subject to the initial testing of this codec. */
68 
70 static std::vector<GRFFile *> _grf_files;
71 
72 const std::vector<GRFFile *> &GetAllGRFFiles()
73 {
74  return _grf_files;
75 }
76 
78 uint8_t _misc_grf_features = 0;
79 
81 static uint32_t _ttdpatch_flags[8];
82 
85 
86 static const uint MAX_SPRITEGROUP = UINT8_MAX;
87 
90 private:
92  struct SpriteSet {
94  uint num_sprites;
95  };
96 
98  std::map<uint, SpriteSet> spritesets[GSF_END];
99 
100 public:
101  /* Global state */
102  GrfLoadingStage stage;
104 
105  /* Local state in the file */
109  uint32_t nfo_line;
110 
111  /* Kind of return values when processing certain actions */
113 
114  /* Currently referenceable spritegroups */
115  const SpriteGroup *spritegroups[MAX_SPRITEGROUP + 1];
116 
119  {
120  this->nfo_line = 0;
121  this->skip_sprites = 0;
122 
123  for (uint i = 0; i < GSF_END; i++) {
124  this->spritesets[i].clear();
125  }
126 
127  memset(this->spritegroups, 0, sizeof(this->spritegroups));
128  }
129 
138  void AddSpriteSets(uint8_t feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents)
139  {
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;
144  set.num_sprites = numents;
145  }
146  }
147 
154  bool HasValidSpriteSets(uint8_t feature) const
155  {
156  assert(feature < GSF_END);
157  return !this->spritesets[feature].empty();
158  }
159 
167  bool IsValidSpriteSet(uint8_t feature, uint set) const
168  {
169  assert(feature < GSF_END);
170  return this->spritesets[feature].find(set) != this->spritesets[feature].end();
171  }
172 
179  SpriteID GetSprite(uint8_t feature, uint set) const
180  {
181  assert(IsValidSpriteSet(feature, set));
182  return this->spritesets[feature].find(set)->second.sprite;
183  }
184 
191  uint GetNumEnts(uint8_t feature, uint set) const
192  {
193  assert(IsValidSpriteSet(feature, set));
194  return this->spritesets[feature].find(set)->second.num_sprites;
195  }
196 };
197 
198 static GrfProcessingState _cur;
199 
200 
207 template <VehicleType T>
208 static inline bool IsValidNewGRFImageIndex(uint8_t image_index)
209 {
210  return image_index == 0xFD || IsValidImageIndex<T>(image_index);
211 }
212 
214 
216 class ByteReader {
217 protected:
218  uint8_t *data;
219  uint8_t *end;
220 
221 public:
222  ByteReader(uint8_t *data, uint8_t *end) : data(data), end(end) { }
223 
224  inline uint8_t *ReadBytes(size_t size)
225  {
226  if (data + size >= end) {
227  /* Put data at the end, as would happen if every byte had been individually read. */
228  data = end;
229  throw OTTDByteReaderSignal();
230  }
231 
232  uint8_t *ret = data;
233  data += size;
234  return ret;
235  }
236 
237  inline uint8_t ReadByte()
238  {
239  if (data < end) return *(data)++;
240  throw OTTDByteReaderSignal();
241  }
242 
243  uint16_t ReadWord()
244  {
245  uint16_t val = ReadByte();
246  return val | (ReadByte() << 8);
247  }
248 
249  uint16_t ReadExtendedByte()
250  {
251  uint16_t val = ReadByte();
252  return val == 0xFF ? ReadWord() : val;
253  }
254 
255  uint32_t ReadDWord()
256  {
257  uint32_t val = ReadWord();
258  return val | (ReadWord() << 16);
259  }
260 
261  uint32_t PeekDWord()
262  {
263  AutoRestoreBackup backup(this->data, this->data);
264  return this->ReadDWord();
265  }
266 
267  uint32_t ReadVarSize(uint8_t size)
268  {
269  switch (size) {
270  case 1: return ReadByte();
271  case 2: return ReadWord();
272  case 4: return ReadDWord();
273  default:
274  NOT_REACHED();
275  return 0;
276  }
277  }
278 
279  std::string_view ReadString()
280  {
281  char *string = reinterpret_cast<char *>(data);
282  size_t string_length = ttd_strnlen(string, Remaining());
283 
284  /* Skip past the terminating NUL byte if it is present, but not more than remaining. */
285  Skip(std::min(string_length + 1, Remaining()));
286 
287  return std::string_view(string, string_length);
288  }
289 
290  inline size_t Remaining() const
291  {
292  return end - data;
293  }
294 
295  inline bool HasData(size_t count = 1) const
296  {
297  return data + count <= end;
298  }
299 
300  inline void Skip(size_t len)
301  {
302  data += len;
303  /* It is valid to move the buffer to exactly the end of the data,
304  * as there may not be any more data read. */
305  if (data > end) throw OTTDByteReaderSignal();
306  }
307 };
308 
309 typedef void (*SpecialSpriteHandler)(ByteReader &buf);
310 
312 static const uint NUM_STATIONS_PER_GRF = UINT16_MAX - 1;
313 
318  UNSET = 0,
321  };
322 
326  RailTypeLabel railtypelabel;
327  uint8_t roadtramtype;
330  uint8_t rv_max_speed;
331  CargoTypes ctt_include_mask;
332  CargoTypes ctt_exclude_mask;
333 
338  void UpdateRefittability(bool non_empty)
339  {
340  if (non_empty) {
341  this->refittability = NONEMPTY;
342  } else if (this->refittability == UNSET) {
343  this->refittability = EMPTY;
344  }
345  }
346 };
347 
348 static std::vector<GRFTempEngineData> _gted;
349 
354 static uint32_t _grm_engines[256];
355 
357 static uint32_t _grm_cargoes[NUM_CARGO * 2];
358 
359 struct GRFLocation {
360  uint32_t grfid;
361  uint32_t nfoline;
362 
363  GRFLocation(uint32_t grfid, uint32_t nfoline) : grfid(grfid), nfoline(nfoline) { }
364 
365  bool operator<(const GRFLocation &other) const
366  {
367  return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
368  }
369 
370  bool operator == (const GRFLocation &other) const
371  {
372  return this->grfid == other.grfid && this->nfoline == other.nfoline;
373  }
374 };
375 
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;
379 
390 void GrfMsgI(int severity, const std::string &msg)
391 {
392  Debug(grf, severity, "[{}:{}] {}", _cur.grfconfig->filename, _cur.nfo_line, msg);
393 }
394 
400 static GRFFile *GetFileByGRFID(uint32_t grfid)
401 {
402  for (GRFFile * const file : _grf_files) {
403  if (file->grfid == grfid) return file;
404  }
405  return nullptr;
406 }
407 
413 static GRFFile *GetFileByFilename(const std::string &filename)
414 {
415  for (GRFFile * const file : _grf_files) {
416  if (file->filename == filename) return file;
417  }
418  return nullptr;
419 }
420 
423 {
424  gf->labels.clear();
425 }
426 
433 static GRFError *DisableGrf(StringID message = STR_NULL, GRFConfig *config = nullptr)
434 {
435  GRFFile *file;
436  if (config != nullptr) {
437  file = GetFileByGRFID(config->ident.grfid);
438  } else {
439  config = _cur.grfconfig;
440  file = _cur.grffile;
441  }
442 
443  config->status = GCS_DISABLED;
444  if (file != nullptr) ClearTemporaryNewGRFData(file);
445  if (config == _cur.grfconfig) _cur.skip_sprites = -1;
446 
447  if (message == STR_NULL) return nullptr;
448 
449  config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message};
450  if (config == _cur.grfconfig) config->error->param_value[0] = _cur.nfo_line;
451  return &config->error.value();
452 }
453 
458  uint32_t grfid;
460  std::function<void(StringID)> func;
461 
462  StringIDMapping(uint32_t grfid, StringID source, std::function<void(StringID)> &&func) : grfid(grfid), source(source), func(std::move(func)) { }
463 };
464 
466 static std::vector<StringIDMapping> _string_to_grf_mapping;
467 
473 static void AddStringForMapping(StringID source, std::function<void(StringID)> &&func)
474 {
475  func(STR_UNDEFINED);
476  _string_to_grf_mapping.emplace_back(_cur.grffile->grfid, source, std::move(func));
477 }
478 
484 static void AddStringForMapping(StringID source, StringID *target)
485 {
486  AddStringForMapping(source, [target](StringID str) { *target = str; });
487 }
488 
497 {
498  /* StringID table for TextIDs 0x4E->0x6D */
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
508  };
509 
510  /* A string straight from a NewGRF; this was already translated by MapGRFStringID(). */
511  assert(!IsInsideMM(str, 0xD000, 0xD7FF));
512 
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)
516 
517  /* We have some changes in our cargo strings, resulting in some missing. */
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);
524 
525  /* Map building names according to our lang file changes. There are several
526  * ranges of house ids, all of which need to be remapped to allow newgrfs
527  * to use original house names. */
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);
531 
532  /* Same thing for industries */
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);
538 
539  switch (str) {
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;
543  }
544 #undef TEXTID_TO_STRINGID
545 
546  if (str == STR_NULL) return STR_EMPTY;
547 
548  Debug(grf, 0, "Unknown StringID 0x{:04X} remapped to STR_EMPTY. Please open a Feature Request if you need it", str);
549 
550  return STR_EMPTY;
551 }
552 
560 StringID MapGRFStringID(uint32_t grfid, StringID str)
561 {
562  if (IsInsideMM(str, 0xD800, 0x10000)) {
563  /* General text provided by NewGRF.
564  * In the specs this is called the 0xDCxx range (misc persistent texts),
565  * but we meanwhile extended the range to 0xD800-0xFFFF.
566  * Note: We are not involved in the "persistent" business, since we do not store
567  * any NewGRF strings in savegames. */
568  return GetGRFStringID(grfid, str);
569  } else if (IsInsideMM(str, 0xD000, 0xD800)) {
570  /* Callback text provided by NewGRF.
571  * In the specs this is called the 0xD0xx range (misc graphics texts).
572  * These texts can be returned by various callbacks.
573  *
574  * Due to how TTDP implements the GRF-local- to global-textid translation
575  * texts included via 0x80 or 0x81 control codes have to add 0x400 to the textid.
576  * We do not care about that difference and just mask out the 0x400 bit.
577  */
578  str &= ~0x400;
579  return GetGRFStringID(grfid, str);
580  } else {
581  /* The NewGRF wants to include/reference an original TTD string.
582  * Try our best to find an equivalent one. */
584  }
585 }
586 
587 static std::map<uint32_t, uint32_t> _grf_id_overrides;
588 
594 static void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid)
595 {
596  if (target_grfid == 0) {
597  _grf_id_overrides.erase(source_grfid);
598  GrfMsg(5, "SetNewGRFOverride: Removed override of 0x{:X}", BSWAP32(source_grfid));
599  } else {
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));
602  }
603 }
604 
613 static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id, bool static_access = false)
614 {
615  /* Hack for add-on GRFs that need to modify another GRF's engines. This lets
616  * them use the same engine slots. */
617  uint32_t scope_grfid = INVALID_GRFID; // If not using dynamic_engines, all newgrfs share their ID range
619  /* If dynamic_engies is enabled, there can be multiple independent ID ranges. */
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;
623  const GRFFile *grf_match = GetFileByGRFID(scope_grfid);
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));
626  } else {
627  GrfMsg(5, "Mapping from GRFID {:x} to {:x}", BSWAP32(file->grfid), BSWAP32(scope_grfid));
628  }
629  }
630 
631  /* Check if the engine is registered in the override manager */
632  EngineID engine = _engine_mngr.GetID(type, internal_id, scope_grfid);
633  if (engine != INVALID_ENGINE) {
634  Engine *e = Engine::Get(engine);
635  if (e->grf_prop.grffile == nullptr) e->grf_prop.grffile = file;
636  return e;
637  }
638  }
639 
640  /* Check if there is an unreserved slot */
641  EngineID engine = _engine_mngr.GetID(type, internal_id, INVALID_GRFID);
642  if (engine != INVALID_ENGINE) {
643  Engine *e = Engine::Get(engine);
644 
645  if (e->grf_prop.grffile == nullptr) {
646  e->grf_prop.grffile = file;
647  GrfMsg(5, "Replaced engine at index {} for GRFID {:x}, type {}, index {}", e->index, BSWAP32(file->grfid), type, internal_id);
648  }
649 
650  /* Reserve the engine slot */
651  if (!static_access) {
652  EngineIDMapping *eid = _engine_mngr.data() + engine;
653  eid->grfid = scope_grfid; // Note: this is INVALID_GRFID if dynamic_engines is disabled, so no reservation
654  }
655 
656  return e;
657  }
658 
659  if (static_access) return nullptr;
660 
661  if (!Engine::CanAllocateItem()) {
662  GrfMsg(0, "Can't allocate any more engines");
663  return nullptr;
664  }
665 
666  size_t engine_pool_size = Engine::GetPoolSize();
667 
668  /* ... it's not, so create a new one based off an existing engine */
669  Engine *e = new Engine(type, internal_id);
670  e->grf_prop.grffile = file;
671 
672  /* Reserve the engine slot */
673  assert(_engine_mngr.size() == e->index);
674  _engine_mngr.push_back({
675  scope_grfid, // Note: this is INVALID_GRFID if dynamic_engines is disabled, so no reservation
676  internal_id,
677  type,
678  std::min<uint8_t>(internal_id, _engine_counts[type]) // substitute_id == _engine_counts[subtype] means "no substitute"
679  });
680 
681  if (engine_pool_size != Engine::GetPoolSize()) {
682  /* Resize temporary engine data ... */
683  _gted.resize(Engine::GetPoolSize());
684  }
685  if (type == VEH_TRAIN) {
686  _gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
687  }
688 
689  GrfMsg(5, "Created new engine at index {} for GRFID {:x}, type {}, index {}", e->index, BSWAP32(file->grfid), type, internal_id);
690 
691  return e;
692 }
693 
704 EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal_id)
705 {
706  uint32_t scope_grfid = INVALID_GRFID; // If not using dynamic_engines, all newgrfs share their ID range
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;
711  }
712  }
713 
714  return _engine_mngr.GetID(type, internal_id, scope_grfid);
715 }
716 
721 static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite)
722 {
723  if (HasBit(grf_sprite->pal, 14)) {
724  ClrBit(grf_sprite->pal, 14);
725  SetBit(grf_sprite->sprite, SPRITE_MODIFIER_OPAQUE);
726  }
727 
728  if (HasBit(grf_sprite->sprite, 14)) {
729  ClrBit(grf_sprite->sprite, 14);
731  }
732 
733  if (HasBit(grf_sprite->sprite, 15)) {
734  ClrBit(grf_sprite->sprite, 15);
735  SetBit(grf_sprite->sprite, PALETTE_MODIFIER_COLOUR);
736  }
737 }
738 
752 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)
753 {
754  grf_sprite->sprite = buf.ReadWord();
755  grf_sprite->pal = buf.ReadWord();
756  TileLayoutFlags flags = read_flags ? (TileLayoutFlags)buf.ReadWord() : TLF_NOTHING;
757 
758  MapSpriteMappingRecolour(grf_sprite);
759 
760  bool custom_sprite = HasBit(grf_sprite->pal, 15) != invert_action1_flag;
761  ClrBit(grf_sprite->pal, 15);
762  if (custom_sprite) {
763  /* Use sprite from Action 1 */
764  uint index = GB(grf_sprite->sprite, 0, 14);
765  if (use_cur_spritesets && (!_cur.IsValidSpriteSet(feature, index) || _cur.GetNumEnts(feature, index) == 0)) {
766  GrfMsg(1, "ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {}", index);
767  grf_sprite->sprite = SPR_IMG_QUERY;
768  grf_sprite->pal = PAL_NONE;
769  } else {
770  SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
771  if (max_sprite_offset != nullptr) *max_sprite_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
772  SB(grf_sprite->sprite, 0, SPRITE_WIDTH, sprite);
774  }
775  } else if ((flags & TLF_SPRITE_VAR10) && !(flags & TLF_SPRITE_REG_FLAGS)) {
776  GrfMsg(1, "ReadSpriteLayoutSprite: Spritelayout specifies var10 value for non-action-1 sprite");
777  DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
778  return flags;
779  }
780 
781  if (flags & TLF_CUSTOM_PALETTE) {
782  /* Use palette from Action 1 */
783  uint index = GB(grf_sprite->pal, 0, 14);
784  if (use_cur_spritesets && (!_cur.IsValidSpriteSet(feature, index) || _cur.GetNumEnts(feature, index) == 0)) {
785  GrfMsg(1, "ReadSpriteLayoutSprite: Spritelayout uses undefined custom spriteset {} for 'palette'", index);
786  grf_sprite->pal = PAL_NONE;
787  } else {
788  SpriteID sprite = use_cur_spritesets ? _cur.GetSprite(feature, index) : index;
789  if (max_palette_offset != nullptr) *max_palette_offset = use_cur_spritesets ? _cur.GetNumEnts(feature, index) : UINT16_MAX;
790  SB(grf_sprite->pal, 0, SPRITE_WIDTH, sprite);
792  }
793  } else if ((flags & TLF_PALETTE_VAR10) && !(flags & TLF_PALETTE_REG_FLAGS)) {
794  GrfMsg(1, "ReadSpriteLayoutRegisters: Spritelayout specifies var10 value for non-action-1 palette");
795  DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
796  return flags;
797  }
798 
799  return flags;
800 }
801 
810 static void ReadSpriteLayoutRegisters(ByteReader &buf, TileLayoutFlags flags, bool is_parent, NewGRFSpriteLayout *dts, uint index)
811 {
812  if (!(flags & TLF_DRAWING_FLAGS)) return;
813 
814  if (dts->registers == nullptr) dts->AllocateRegisters();
815  TileLayoutRegisters &regs = const_cast<TileLayoutRegisters&>(dts->registers[index]);
816  regs.flags = flags & TLF_DRAWING_FLAGS;
817 
818  if (flags & TLF_DODRAW) regs.dodraw = buf.ReadByte();
819  if (flags & TLF_SPRITE) regs.sprite = buf.ReadByte();
820  if (flags & TLF_PALETTE) regs.palette = buf.ReadByte();
821 
822  if (is_parent) {
823  if (flags & TLF_BB_XY_OFFSET) {
824  regs.delta.parent[0] = buf.ReadByte();
825  regs.delta.parent[1] = buf.ReadByte();
826  }
827  if (flags & TLF_BB_Z_OFFSET) regs.delta.parent[2] = buf.ReadByte();
828  } else {
829  if (flags & TLF_CHILD_X_OFFSET) regs.delta.child[0] = buf.ReadByte();
830  if (flags & TLF_CHILD_Y_OFFSET) regs.delta.child[1] = buf.ReadByte();
831  }
832 
833  if (flags & TLF_SPRITE_VAR10) {
834  regs.sprite_var10 = buf.ReadByte();
835  if (regs.sprite_var10 > TLR_MAX_VAR10) {
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);
838  return;
839  }
840  }
841 
842  if (flags & TLF_PALETTE_VAR10) {
843  regs.palette_var10 = buf.ReadByte();
844  if (regs.palette_var10 > TLR_MAX_VAR10) {
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);
847  return;
848  }
849  }
850 }
851 
863 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)
864 {
865  bool has_flags = HasBit(num_building_sprites, 6);
866  ClrBit(num_building_sprites, 6);
867  TileLayoutFlags valid_flags = TLF_KNOWN_FLAGS;
868  if (!allow_var10) valid_flags &= ~TLF_VAR10_FLAGS;
869  dts->Allocate(num_building_sprites); // allocate before reading groundsprite flags
870 
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);
873 
874  /* Groundsprite */
875  TileLayoutFlags flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &dts->ground, max_sprite_offset.data(), max_palette_offset.data());
876  if (_cur.skip_sprites < 0) return true;
877 
878  if (flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS)) {
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);
881  return true;
882  }
883 
884  ReadSpriteLayoutRegisters(buf, flags, false, dts, 0);
885  if (_cur.skip_sprites < 0) return true;
886 
887  for (uint i = 0; i < num_building_sprites; i++) {
888  DrawTileSeqStruct *seq = const_cast<DrawTileSeqStruct*>(&dts->seq[i]);
889 
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);
891  if (_cur.skip_sprites < 0) return true;
892 
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);
896  return true;
897  }
898 
899  seq->delta_x = buf.ReadByte();
900  seq->delta_y = buf.ReadByte();
901 
902  if (!no_z_position) seq->delta_z = buf.ReadByte();
903 
904  if (seq->IsParentSprite()) {
905  seq->size_x = buf.ReadByte();
906  seq->size_y = buf.ReadByte();
907  seq->size_z = buf.ReadByte();
908  }
909 
910  ReadSpriteLayoutRegisters(buf, flags, seq->IsParentSprite(), dts, i + 1);
911  if (_cur.skip_sprites < 0) return true;
912  }
913 
914  /* Check if the number of sprites per spriteset is consistent */
915  bool is_consistent = true;
916  dts->consistent_max_offset = 0;
917  for (uint i = 0; i < num_building_sprites + 1; i++) {
918  if (max_sprite_offset[i] > 0) {
919  if (dts->consistent_max_offset == 0) {
920  dts->consistent_max_offset = max_sprite_offset[i];
921  } else if (dts->consistent_max_offset != max_sprite_offset[i]) {
922  is_consistent = false;
923  break;
924  }
925  }
926  if (max_palette_offset[i] > 0) {
927  if (dts->consistent_max_offset == 0) {
928  dts->consistent_max_offset = max_palette_offset[i];
929  } else if (dts->consistent_max_offset != max_palette_offset[i]) {
930  is_consistent = false;
931  break;
932  }
933  }
934  }
935 
936  /* When the Action1 sets are unknown, everything should be 0 (no spriteset usage) or UINT16_MAX (some spriteset usage) */
937  assert(use_cur_spritesets || (is_consistent && (dts->consistent_max_offset == 0 || dts->consistent_max_offset == UINT16_MAX)));
938 
939  if (!is_consistent || dts->registers != nullptr) {
940  dts->consistent_max_offset = 0;
941  if (dts->registers == nullptr) dts->AllocateRegisters();
942 
943  for (uint i = 0; i < num_building_sprites + 1; i++) {
944  TileLayoutRegisters &regs = const_cast<TileLayoutRegisters&>(dts->registers[i]);
945  regs.max_sprite_offset = max_sprite_offset[i];
946  regs.max_palette_offset = max_palette_offset[i];
947  }
948  }
949 
950  return false;
951 }
952 
956 static CargoTypes TranslateRefitMask(uint32_t refit_mask)
957 {
958  CargoTypes result = 0;
959  for (uint8_t bit : SetBitIterator(refit_mask)) {
960  CargoID cargo = GetCargoTranslation(bit, _cur.grffile, true);
961  if (IsValidCargoID(cargo)) SetBit(result, cargo);
962  }
963  return result;
964 }
965 
973 static void ConvertTTDBasePrice(uint32_t base_pointer, const char *error_location, Price *index)
974 {
975  /* Special value for 'none' */
976  if (base_pointer == 0) {
977  *index = INVALID_PRICE;
978  return;
979  }
980 
981  static const uint32_t start = 0x4B34;
982  static const uint32_t size = 6;
983 
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);
986  return;
987  }
988 
989  *index = (Price)((base_pointer - start) / size);
990 }
991 
999 };
1000 
1001 typedef ChangeInfoResult (*VCI_Handler)(uint engine, int numinfo, int prop, ByteReader &buf);
1002 
1011 {
1012  switch (prop) {
1013  case 0x00: // Introduction date
1015  break;
1016 
1017  case 0x02: // Decay speed
1018  ei->decay_speed = buf.ReadByte();
1019  break;
1020 
1021  case 0x03: // Vehicle life
1022  ei->lifelength = buf.ReadByte();
1023  break;
1024 
1025  case 0x04: // Model life
1026  ei->base_life = buf.ReadByte();
1027  break;
1028 
1029  case 0x06: // Climates available
1030  ei->climates = buf.ReadByte();
1031  break;
1032 
1033  case PROP_VEHICLE_LOAD_AMOUNT: // 0x07 Loading speed
1034  /* Amount of cargo loaded during a vehicle's "loading tick" */
1035  ei->load_amount = buf.ReadByte();
1036  break;
1037 
1038  default:
1039  return CIR_UNKNOWN;
1040  }
1041 
1042  return CIR_SUCCESS;
1043 }
1044 
1053 static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
1054 {
1056 
1057  for (int i = 0; i < numinfo; i++) {
1058  Engine *e = GetNewEngine(_cur.grffile, VEH_TRAIN, engine + i);
1059  if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles
1060 
1061  EngineInfo *ei = &e->info;
1062  RailVehicleInfo *rvi = &e->u.rail;
1063 
1064  switch (prop) {
1065  case 0x05: { // Track type
1066  uint8_t tracktype = buf.ReadByte();
1067 
1068  if (tracktype < _cur.grffile->railtype_list.size()) {
1069  _gted[e->index].railtypelabel = _cur.grffile->railtype_list[tracktype];
1070  break;
1071  }
1072 
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;
1077  default:
1078  GrfMsg(1, "RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
1079  break;
1080  }
1081  break;
1082  }
1083 
1084  case 0x08: // AI passenger service
1085  /* Tells the AI that this engine is designed for
1086  * passenger services and shouldn't be used for freight. */
1087  rvi->ai_passenger_only = buf.ReadByte();
1088  break;
1089 
1090  case PROP_TRAIN_SPEED: { // 0x09 Speed (1 unit is 1 km-ish/h)
1091  uint16_t speed = buf.ReadWord();
1092  if (speed == 0xFFFF) speed = 0;
1093 
1094  rvi->max_speed = speed;
1095  break;
1096  }
1097 
1098  case PROP_TRAIN_POWER: // 0x0B Power
1099  rvi->power = buf.ReadWord();
1100 
1101  /* Set engine / wagon state based on power */
1102  if (rvi->power != 0) {
1103  if (rvi->railveh_type == RAILVEH_WAGON) {
1104  rvi->railveh_type = RAILVEH_SINGLEHEAD;
1105  }
1106  } else {
1107  rvi->railveh_type = RAILVEH_WAGON;
1108  }
1109  break;
1110 
1111  case PROP_TRAIN_RUNNING_COST_FACTOR: // 0x0D Running cost factor
1112  rvi->running_cost = buf.ReadByte();
1113  break;
1114 
1115  case 0x0E: // Running cost base
1116  ConvertTTDBasePrice(buf.ReadDWord(), "RailVehicleChangeInfo", &rvi->running_cost_class);
1117  break;
1118 
1119  case 0x12: { // Sprite ID
1120  uint8_t spriteid = buf.ReadByte();
1121  uint8_t orig_spriteid = spriteid;
1122 
1123  /* TTD sprite IDs point to a location in a 16bit array, but we use it
1124  * as an array index, so we need it to be half the original value. */
1125  if (spriteid < 0xFD) spriteid >>= 1;
1126 
1127  if (IsValidNewGRFImageIndex<VEH_TRAIN>(spriteid)) {
1128  rvi->image_index = spriteid;
1129  } else {
1130  GrfMsg(1, "RailVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1131  rvi->image_index = 0;
1132  }
1133  break;
1134  }
1135 
1136  case 0x13: { // Dual-headed
1137  uint8_t dual = buf.ReadByte();
1138 
1139  if (dual != 0) {
1140  rvi->railveh_type = RAILVEH_MULTIHEAD;
1141  } else {
1142  rvi->railveh_type = rvi->power == 0 ?
1144  }
1145  break;
1146  }
1147 
1148  case PROP_TRAIN_CARGO_CAPACITY: // 0x14 Cargo capacity
1149  rvi->capacity = buf.ReadByte();
1150  break;
1151 
1152  case 0x15: { // Cargo type
1153  _gted[e->index].defaultcargo_grf = _cur.grffile;
1154  uint8_t ctype = buf.ReadByte();
1155 
1156  if (ctype == 0xFF) {
1157  /* 0xFF is specified as 'use first refittable' */
1158  ei->cargo_type = INVALID_CARGO;
1159  } else {
1160  /* Use translated cargo. Might result in INVALID_CARGO (first refittable), if cargo is not defined. */
1161  ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
1162  if (ei->cargo_type == INVALID_CARGO) GrfMsg(2, "RailVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1163  }
1164  ei->cargo_label = CT_INVALID;
1165  break;
1166  }
1167 
1168  case PROP_TRAIN_WEIGHT: // 0x16 Weight
1169  SB(rvi->weight, 0, 8, buf.ReadByte());
1170  break;
1171 
1172  case PROP_TRAIN_COST_FACTOR: // 0x17 Cost factor
1173  rvi->cost_factor = buf.ReadByte();
1174  break;
1175 
1176  case 0x18: // AI rank
1177  GrfMsg(2, "RailVehicleChangeInfo: Property 0x18 'AI rank' not used by NoAI, ignored.");
1178  buf.ReadByte();
1179  break;
1180 
1181  case 0x19: { // Engine traction type
1182  /* What do the individual numbers mean?
1183  * 0x00 .. 0x07: Steam
1184  * 0x08 .. 0x27: Diesel
1185  * 0x28 .. 0x31: Electric
1186  * 0x32 .. 0x37: Monorail
1187  * 0x38 .. 0x41: Maglev
1188  */
1189  uint8_t traction = buf.ReadByte();
1190  EngineClass engclass;
1191 
1192  if (traction <= 0x07) {
1193  engclass = EC_STEAM;
1194  } else if (traction <= 0x27) {
1195  engclass = EC_DIESEL;
1196  } else if (traction <= 0x31) {
1197  engclass = EC_ELECTRIC;
1198  } else if (traction <= 0x37) {
1199  engclass = EC_MONORAIL;
1200  } else if (traction <= 0x41) {
1201  engclass = EC_MAGLEV;
1202  } else {
1203  break;
1204  }
1205 
1206  if (_cur.grffile->railtype_list.empty()) {
1207  /* Use traction type to select between normal and electrified
1208  * rail only when no translation list is in place. */
1209  if (_gted[e->index].railtypelabel == RAILTYPE_LABEL_RAIL && engclass >= EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_LABEL_ELECTRIC;
1210  if (_gted[e->index].railtypelabel == RAILTYPE_LABEL_ELECTRIC && engclass < EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_LABEL_RAIL;
1211  }
1212 
1213  rvi->engclass = engclass;
1214  break;
1215  }
1216 
1217  case 0x1A: // Alter purchase list sort order
1218  AlterVehicleListOrder(e->index, buf.ReadExtendedByte());
1219  break;
1220 
1221  case 0x1B: // Powered wagons power bonus
1222  rvi->pow_wag_power = buf.ReadWord();
1223  break;
1224 
1225  case 0x1C: // Refit cost
1226  ei->refit_cost = buf.ReadByte();
1227  break;
1228 
1229  case 0x1D: { // Refit cargo
1230  uint32_t mask = buf.ReadDWord();
1231  _gted[e->index].UpdateRefittability(mask != 0);
1232  ei->refit_mask = TranslateRefitMask(mask);
1233  _gted[e->index].defaultcargo_grf = _cur.grffile;
1234  break;
1235  }
1236 
1237  case 0x1E: // Callback
1238  SB(ei->callback_mask, 0, 8, buf.ReadByte());
1239  break;
1240 
1241  case PROP_TRAIN_TRACTIVE_EFFORT: // 0x1F Tractive effort coefficient
1242  rvi->tractive_effort = buf.ReadByte();
1243  break;
1244 
1245  case 0x20: // Air drag
1246  rvi->air_drag = buf.ReadByte();
1247  break;
1248 
1249  case PROP_TRAIN_SHORTEN_FACTOR: // 0x21 Shorter vehicle
1250  rvi->shorten_factor = buf.ReadByte();
1251  break;
1252 
1253  case 0x22: // Visual effect
1254  rvi->visual_effect = buf.ReadByte();
1255  /* Avoid accidentally setting visual_effect to the default value
1256  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
1257  if (rvi->visual_effect == VE_DEFAULT) {
1258  assert(HasBit(rvi->visual_effect, VE_DISABLE_EFFECT));
1260  }
1261  break;
1262 
1263  case 0x23: // Powered wagons weight bonus
1264  rvi->pow_wag_weight = buf.ReadByte();
1265  break;
1266 
1267  case 0x24: { // High byte of vehicle weight
1268  uint8_t weight = buf.ReadByte();
1269 
1270  if (weight > 4) {
1271  GrfMsg(2, "RailVehicleChangeInfo: Nonsensical weight of {} tons, ignoring", weight << 8);
1272  } else {
1273  SB(rvi->weight, 8, 8, weight);
1274  }
1275  break;
1276  }
1277 
1278  case PROP_TRAIN_USER_DATA: // 0x25 User-defined bit mask to set when checking veh. var. 42
1279  rvi->user_def_data = buf.ReadByte();
1280  break;
1281 
1282  case 0x26: // Retire vehicle early
1283  ei->retire_early = buf.ReadByte();
1284  break;
1285 
1286  case 0x27: // Miscellaneous flags
1287  ei->misc_flags = buf.ReadByte();
1289  break;
1290 
1291  case 0x28: // Cargo classes allowed
1292  _gted[e->index].cargo_allowed = buf.ReadWord();
1293  _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
1294  _gted[e->index].defaultcargo_grf = _cur.grffile;
1295  break;
1296 
1297  case 0x29: // Cargo classes disallowed
1298  _gted[e->index].cargo_disallowed = buf.ReadWord();
1299  _gted[e->index].UpdateRefittability(false);
1300  break;
1301 
1302  case 0x2A: // Long format introduction date (days since year 0)
1303  ei->base_intro = buf.ReadDWord();
1304  break;
1305 
1306  case PROP_TRAIN_CARGO_AGE_PERIOD: // 0x2B Cargo aging period
1307  ei->cargo_age_period = buf.ReadWord();
1308  break;
1309 
1310  case 0x2C: // CTT refit include list
1311  case 0x2D: { // CTT refit exclude list
1312  uint8_t count = buf.ReadByte();
1313  _gted[e->index].UpdateRefittability(prop == 0x2C && count != 0);
1314  if (prop == 0x2C) _gted[e->index].defaultcargo_grf = _cur.grffile;
1315  CargoTypes &ctt = prop == 0x2C ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
1316  ctt = 0;
1317  while (count--) {
1318  CargoID ctype = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
1319  if (IsValidCargoID(ctype)) SetBit(ctt, ctype);
1320  }
1321  break;
1322  }
1323 
1324  case PROP_TRAIN_CURVE_SPEED_MOD: // 0x2E Curve speed modifier
1325  rvi->curve_speed_mod = buf.ReadWord();
1326  break;
1327 
1328  case 0x2F: // Engine variant
1329  ei->variant_id = buf.ReadWord();
1330  break;
1331 
1332  case 0x30: // Extra miscellaneous flags
1333  ei->extra_flags = static_cast<ExtraEngineFlags>(buf.ReadDWord());
1334  break;
1335 
1336  case 0x31: // Callback additional mask
1337  SB(ei->callback_mask, 8, 8, buf.ReadByte());
1338  break;
1339 
1340  case 0x32: // Cargo classes required for a refit.
1341  _gted[e->index].cargo_allowed_required = buf.ReadWord();
1342  break;
1343 
1344  default:
1345  ret = CommonVehicleChangeInfo(ei, prop, buf);
1346  break;
1347  }
1348  }
1349 
1350  return ret;
1351 }
1352 
1361 static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
1362 {
1364 
1365  for (int i = 0; i < numinfo; i++) {
1366  Engine *e = GetNewEngine(_cur.grffile, VEH_ROAD, engine + i);
1367  if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles
1368 
1369  EngineInfo *ei = &e->info;
1370  RoadVehicleInfo *rvi = &e->u.road;
1371 
1372  switch (prop) {
1373  case 0x05: // Road/tram type
1374  /* RoadTypeLabel is looked up later after the engine's road/tram
1375  * flag is set, however 0 means the value has not been set. */
1376  _gted[e->index].roadtramtype = buf.ReadByte() + 1;
1377  break;
1378 
1379  case 0x08: // Speed (1 unit is 0.5 kmh)
1380  rvi->max_speed = buf.ReadByte();
1381  break;
1382 
1383  case PROP_ROADVEH_RUNNING_COST_FACTOR: // 0x09 Running cost factor
1384  rvi->running_cost = buf.ReadByte();
1385  break;
1386 
1387  case 0x0A: // Running cost base
1388  ConvertTTDBasePrice(buf.ReadDWord(), "RoadVehicleChangeInfo", &rvi->running_cost_class);
1389  break;
1390 
1391  case 0x0E: { // Sprite ID
1392  uint8_t spriteid = buf.ReadByte();
1393  uint8_t orig_spriteid = spriteid;
1394 
1395  /* cars have different custom id in the GRF file */
1396  if (spriteid == 0xFF) spriteid = 0xFD;
1397 
1398  if (spriteid < 0xFD) spriteid >>= 1;
1399 
1400  if (IsValidNewGRFImageIndex<VEH_ROAD>(spriteid)) {
1401  rvi->image_index = spriteid;
1402  } else {
1403  GrfMsg(1, "RoadVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1404  rvi->image_index = 0;
1405  }
1406  break;
1407  }
1408 
1409  case PROP_ROADVEH_CARGO_CAPACITY: // 0x0F Cargo capacity
1410  rvi->capacity = buf.ReadByte();
1411  break;
1412 
1413  case 0x10: { // Cargo type
1414  _gted[e->index].defaultcargo_grf = _cur.grffile;
1415  uint8_t ctype = buf.ReadByte();
1416 
1417  if (ctype == 0xFF) {
1418  /* 0xFF is specified as 'use first refittable' */
1419  ei->cargo_type = INVALID_CARGO;
1420  } else {
1421  /* Use translated cargo. Might result in INVALID_CARGO (first refittable), if cargo is not defined. */
1422  ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
1423  if (ei->cargo_type == INVALID_CARGO) GrfMsg(2, "RoadVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1424  }
1425  ei->cargo_label = CT_INVALID;
1426  break;
1427  }
1428 
1429  case PROP_ROADVEH_COST_FACTOR: // 0x11 Cost factor
1430  rvi->cost_factor = buf.ReadByte();
1431  break;
1432 
1433  case 0x12: // SFX
1434  rvi->sfx = GetNewGRFSoundID(_cur.grffile, buf.ReadByte());
1435  break;
1436 
1437  case PROP_ROADVEH_POWER: // Power in units of 10 HP.
1438  rvi->power = buf.ReadByte();
1439  break;
1440 
1441  case PROP_ROADVEH_WEIGHT: // Weight in units of 1/4 tons.
1442  rvi->weight = buf.ReadByte();
1443  break;
1444 
1445  case PROP_ROADVEH_SPEED: // Speed in mph/0.8
1446  _gted[e->index].rv_max_speed = buf.ReadByte();
1447  break;
1448 
1449  case 0x16: { // Cargoes available for refitting
1450  uint32_t mask = buf.ReadDWord();
1451  _gted[e->index].UpdateRefittability(mask != 0);
1452  ei->refit_mask = TranslateRefitMask(mask);
1453  _gted[e->index].defaultcargo_grf = _cur.grffile;
1454  break;
1455  }
1456 
1457  case 0x17: // Callback mask
1458  SB(ei->callback_mask, 0, 8, buf.ReadByte());
1459  break;
1460 
1461  case PROP_ROADVEH_TRACTIVE_EFFORT: // Tractive effort coefficient in 1/256.
1462  rvi->tractive_effort = buf.ReadByte();
1463  break;
1464 
1465  case 0x19: // Air drag
1466  rvi->air_drag = buf.ReadByte();
1467  break;
1468 
1469  case 0x1A: // Refit cost
1470  ei->refit_cost = buf.ReadByte();
1471  break;
1472 
1473  case 0x1B: // Retire vehicle early
1474  ei->retire_early = buf.ReadByte();
1475  break;
1476 
1477  case 0x1C: // Miscellaneous flags
1478  ei->misc_flags = buf.ReadByte();
1480  break;
1481 
1482  case 0x1D: // Cargo classes allowed
1483  _gted[e->index].cargo_allowed = buf.ReadWord();
1484  _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
1485  _gted[e->index].defaultcargo_grf = _cur.grffile;
1486  break;
1487 
1488  case 0x1E: // Cargo classes disallowed
1489  _gted[e->index].cargo_disallowed = buf.ReadWord();
1490  _gted[e->index].UpdateRefittability(false);
1491  break;
1492 
1493  case 0x1F: // Long format introduction date (days since year 0)
1494  ei->base_intro = buf.ReadDWord();
1495  break;
1496 
1497  case 0x20: // Alter purchase list sort order
1498  AlterVehicleListOrder(e->index, buf.ReadExtendedByte());
1499  break;
1500 
1501  case 0x21: // Visual effect
1502  rvi->visual_effect = buf.ReadByte();
1503  /* Avoid accidentally setting visual_effect to the default value
1504  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
1505  if (rvi->visual_effect == VE_DEFAULT) {
1506  assert(HasBit(rvi->visual_effect, VE_DISABLE_EFFECT));
1508  }
1509  break;
1510 
1511  case PROP_ROADVEH_CARGO_AGE_PERIOD: // 0x22 Cargo aging period
1512  ei->cargo_age_period = buf.ReadWord();
1513  break;
1514 
1515  case PROP_ROADVEH_SHORTEN_FACTOR: // 0x23 Shorter vehicle
1516  rvi->shorten_factor = buf.ReadByte();
1517  break;
1518 
1519  case 0x24: // CTT refit include list
1520  case 0x25: { // CTT refit exclude list
1521  uint8_t count = buf.ReadByte();
1522  _gted[e->index].UpdateRefittability(prop == 0x24 && count != 0);
1523  if (prop == 0x24) _gted[e->index].defaultcargo_grf = _cur.grffile;
1524  CargoTypes &ctt = prop == 0x24 ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
1525  ctt = 0;
1526  while (count--) {
1527  CargoID ctype = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
1528  if (IsValidCargoID(ctype)) SetBit(ctt, ctype);
1529  }
1530  break;
1531  }
1532 
1533  case 0x26: // Engine variant
1534  ei->variant_id = buf.ReadWord();
1535  break;
1536 
1537  case 0x27: // Extra miscellaneous flags
1538  ei->extra_flags = static_cast<ExtraEngineFlags>(buf.ReadDWord());
1539  break;
1540 
1541  case 0x28: // Callback additional mask
1542  SB(ei->callback_mask, 8, 8, buf.ReadByte());
1543  break;
1544 
1545  case 0x29: // Cargo classes required for a refit.
1546  _gted[e->index].cargo_allowed_required = buf.ReadWord();
1547  break;
1548 
1549  default:
1550  ret = CommonVehicleChangeInfo(ei, prop, buf);
1551  break;
1552  }
1553  }
1554 
1555  return ret;
1556 }
1557 
1566 static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
1567 {
1569 
1570  for (int i = 0; i < numinfo; i++) {
1571  Engine *e = GetNewEngine(_cur.grffile, VEH_SHIP, engine + i);
1572  if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles
1573 
1574  EngineInfo *ei = &e->info;
1575  ShipVehicleInfo *svi = &e->u.ship;
1576 
1577  switch (prop) {
1578  case 0x08: { // Sprite ID
1579  uint8_t spriteid = buf.ReadByte();
1580  uint8_t orig_spriteid = spriteid;
1581 
1582  /* ships have different custom id in the GRF file */
1583  if (spriteid == 0xFF) spriteid = 0xFD;
1584 
1585  if (spriteid < 0xFD) spriteid >>= 1;
1586 
1587  if (IsValidNewGRFImageIndex<VEH_SHIP>(spriteid)) {
1588  svi->image_index = spriteid;
1589  } else {
1590  GrfMsg(1, "ShipVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1591  svi->image_index = 0;
1592  }
1593  break;
1594  }
1595 
1596  case 0x09: // Refittable
1597  svi->old_refittable = (buf.ReadByte() != 0);
1598  break;
1599 
1600  case PROP_SHIP_COST_FACTOR: // 0x0A Cost factor
1601  svi->cost_factor = buf.ReadByte();
1602  break;
1603 
1604  case PROP_SHIP_SPEED: // 0x0B Speed (1 unit is 0.5 km-ish/h). Use 0x23 to achieve higher speeds.
1605  svi->max_speed = buf.ReadByte();
1606  break;
1607 
1608  case 0x0C: { // Cargo type
1609  _gted[e->index].defaultcargo_grf = _cur.grffile;
1610  uint8_t ctype = buf.ReadByte();
1611 
1612  if (ctype == 0xFF) {
1613  /* 0xFF is specified as 'use first refittable' */
1614  ei->cargo_type = INVALID_CARGO;
1615  } else {
1616  /* Use translated cargo. Might result in INVALID_CARGO (first refittable), if cargo is not defined. */
1617  ei->cargo_type = GetCargoTranslation(ctype, _cur.grffile);
1618  if (ei->cargo_type == INVALID_CARGO) GrfMsg(2, "ShipVehicleChangeInfo: Invalid cargo type {}, using first refittable", ctype);
1619  }
1620  ei->cargo_label = CT_INVALID;
1621  break;
1622  }
1623 
1624  case PROP_SHIP_CARGO_CAPACITY: // 0x0D Cargo capacity
1625  svi->capacity = buf.ReadWord();
1626  break;
1627 
1628  case PROP_SHIP_RUNNING_COST_FACTOR: // 0x0F Running cost factor
1629  svi->running_cost = buf.ReadByte();
1630  break;
1631 
1632  case 0x10: // SFX
1633  svi->sfx = GetNewGRFSoundID(_cur.grffile, buf.ReadByte());
1634  break;
1635 
1636  case 0x11: { // Cargoes available for refitting
1637  uint32_t mask = buf.ReadDWord();
1638  _gted[e->index].UpdateRefittability(mask != 0);
1639  ei->refit_mask = TranslateRefitMask(mask);
1640  _gted[e->index].defaultcargo_grf = _cur.grffile;
1641  break;
1642  }
1643 
1644  case 0x12: // Callback mask
1645  SB(ei->callback_mask, 0, 8, buf.ReadByte());
1646  break;
1647 
1648  case 0x13: // Refit cost
1649  ei->refit_cost = buf.ReadByte();
1650  break;
1651 
1652  case 0x14: // Ocean speed fraction
1653  svi->ocean_speed_frac = buf.ReadByte();
1654  break;
1655 
1656  case 0x15: // Canal speed fraction
1657  svi->canal_speed_frac = buf.ReadByte();
1658  break;
1659 
1660  case 0x16: // Retire vehicle early
1661  ei->retire_early = buf.ReadByte();
1662  break;
1663 
1664  case 0x17: // Miscellaneous flags
1665  ei->misc_flags = buf.ReadByte();
1667  break;
1668 
1669  case 0x18: // Cargo classes allowed
1670  _gted[e->index].cargo_allowed = buf.ReadWord();
1671  _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
1672  _gted[e->index].defaultcargo_grf = _cur.grffile;
1673  break;
1674 
1675  case 0x19: // Cargo classes disallowed
1676  _gted[e->index].cargo_disallowed = buf.ReadWord();
1677  _gted[e->index].UpdateRefittability(false);
1678  break;
1679 
1680  case 0x1A: // Long format introduction date (days since year 0)
1681  ei->base_intro = buf.ReadDWord();
1682  break;
1683 
1684  case 0x1B: // Alter purchase list sort order
1685  AlterVehicleListOrder(e->index, buf.ReadExtendedByte());
1686  break;
1687 
1688  case 0x1C: // Visual effect
1689  svi->visual_effect = buf.ReadByte();
1690  /* Avoid accidentally setting visual_effect to the default value
1691  * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
1692  if (svi->visual_effect == VE_DEFAULT) {
1693  assert(HasBit(svi->visual_effect, VE_DISABLE_EFFECT));
1695  }
1696  break;
1697 
1698  case PROP_SHIP_CARGO_AGE_PERIOD: // 0x1D Cargo aging period
1699  ei->cargo_age_period = buf.ReadWord();
1700  break;
1701 
1702  case 0x1E: // CTT refit include list
1703  case 0x1F: { // CTT refit exclude list
1704  uint8_t count = buf.ReadByte();
1705  _gted[e->index].UpdateRefittability(prop == 0x1E && count != 0);
1706  if (prop == 0x1E) _gted[e->index].defaultcargo_grf = _cur.grffile;
1707  CargoTypes &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
1708  ctt = 0;
1709  while (count--) {
1710  CargoID ctype = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
1711  if (IsValidCargoID(ctype)) SetBit(ctt, ctype);
1712  }
1713  break;
1714  }
1715 
1716  case 0x20: // Engine variant
1717  ei->variant_id = buf.ReadWord();
1718  break;
1719 
1720  case 0x21: // Extra miscellaneous flags
1721  ei->extra_flags = static_cast<ExtraEngineFlags>(buf.ReadDWord());
1722  break;
1723 
1724  case 0x22: // Callback additional mask
1725  SB(ei->callback_mask, 8, 8, buf.ReadByte());
1726  break;
1727 
1728  case 0x23: // Speed (1 unit is 0.5 km-ish/h)
1729  svi->max_speed = buf.ReadWord();
1730  break;
1731 
1732  case 0x24: // Acceleration (1 unit is 0.5 km-ish/h per tick)
1733  svi->acceleration = std::max<uint8_t>(1, buf.ReadByte());
1734  break;
1735 
1736  case 0x25: // Cargo classes required for a refit.
1737  _gted[e->index].cargo_allowed_required = buf.ReadWord();
1738  break;
1739 
1740  default:
1741  ret = CommonVehicleChangeInfo(ei, prop, buf);
1742  break;
1743  }
1744  }
1745 
1746  return ret;
1747 }
1748 
1757 static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
1758 {
1760 
1761  for (int i = 0; i < numinfo; i++) {
1762  Engine *e = GetNewEngine(_cur.grffile, VEH_AIRCRAFT, engine + i);
1763  if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles
1764 
1765  EngineInfo *ei = &e->info;
1766  AircraftVehicleInfo *avi = &e->u.air;
1767 
1768  switch (prop) {
1769  case 0x08: { // Sprite ID
1770  uint8_t spriteid = buf.ReadByte();
1771  uint8_t orig_spriteid = spriteid;
1772 
1773  /* aircraft have different custom id in the GRF file */
1774  if (spriteid == 0xFF) spriteid = 0xFD;
1775 
1776  if (spriteid < 0xFD) spriteid >>= 1;
1777 
1778  if (IsValidNewGRFImageIndex<VEH_AIRCRAFT>(spriteid)) {
1779  avi->image_index = spriteid;
1780  } else {
1781  GrfMsg(1, "AircraftVehicleChangeInfo: Invalid Sprite {} specified, ignoring", orig_spriteid);
1782  avi->image_index = 0;
1783  }
1784  break;
1785  }
1786 
1787  case 0x09: // Helicopter
1788  if (buf.ReadByte() == 0) {
1789  avi->subtype = AIR_HELI;
1790  } else {
1791  SB(avi->subtype, 0, 1, 1); // AIR_CTOL
1792  }
1793  break;
1794 
1795  case 0x0A: // Large
1796  AssignBit(avi->subtype, 1, buf.ReadByte() != 0); // AIR_FAST
1797  break;
1798 
1799  case PROP_AIRCRAFT_COST_FACTOR: // 0x0B Cost factor
1800  avi->cost_factor = buf.ReadByte();
1801  break;
1802 
1803  case PROP_AIRCRAFT_SPEED: // 0x0C Speed (1 unit is 8 mph, we translate to 1 unit is 1 km-ish/h)
1804  avi->max_speed = (buf.ReadByte() * 128) / 10;
1805  break;
1806 
1807  case 0x0D: // Acceleration
1808  avi->acceleration = buf.ReadByte();
1809  break;
1810 
1811  case PROP_AIRCRAFT_RUNNING_COST_FACTOR: // 0x0E Running cost factor
1812  avi->running_cost = buf.ReadByte();
1813  break;
1814 
1815  case PROP_AIRCRAFT_PASSENGER_CAPACITY: // 0x0F Passenger capacity
1816  avi->passenger_capacity = buf.ReadWord();
1817  break;
1818 
1819  case PROP_AIRCRAFT_MAIL_CAPACITY: // 0x11 Mail capacity
1820  avi->mail_capacity = buf.ReadByte();
1821  break;
1822 
1823  case 0x12: // SFX
1824  avi->sfx = GetNewGRFSoundID(_cur.grffile, buf.ReadByte());
1825  break;
1826 
1827  case 0x13: { // Cargoes available for refitting
1828  uint32_t mask = buf.ReadDWord();
1829  _gted[e->index].UpdateRefittability(mask != 0);
1830  ei->refit_mask = TranslateRefitMask(mask);
1831  _gted[e->index].defaultcargo_grf = _cur.grffile;
1832  break;
1833  }
1834 
1835  case 0x14: // Callback mask
1836  SB(ei->callback_mask, 0, 8, buf.ReadByte());
1837  break;
1838 
1839  case 0x15: // Refit cost
1840  ei->refit_cost = buf.ReadByte();
1841  break;
1842 
1843  case 0x16: // Retire vehicle early
1844  ei->retire_early = buf.ReadByte();
1845  break;
1846 
1847  case 0x17: // Miscellaneous flags
1848  ei->misc_flags = buf.ReadByte();
1850  break;
1851 
1852  case 0x18: // Cargo classes allowed
1853  _gted[e->index].cargo_allowed = buf.ReadWord();
1854  _gted[e->index].UpdateRefittability(_gted[e->index].cargo_allowed != 0);
1855  _gted[e->index].defaultcargo_grf = _cur.grffile;
1856  break;
1857 
1858  case 0x19: // Cargo classes disallowed
1859  _gted[e->index].cargo_disallowed = buf.ReadWord();
1860  _gted[e->index].UpdateRefittability(false);
1861  break;
1862 
1863  case 0x1A: // Long format introduction date (days since year 0)
1864  ei->base_intro = buf.ReadDWord();
1865  break;
1866 
1867  case 0x1B: // Alter purchase list sort order
1868  AlterVehicleListOrder(e->index, buf.ReadExtendedByte());
1869  break;
1870 
1871  case PROP_AIRCRAFT_CARGO_AGE_PERIOD: // 0x1C Cargo aging period
1872  ei->cargo_age_period = buf.ReadWord();
1873  break;
1874 
1875  case 0x1D: // CTT refit include list
1876  case 0x1E: { // CTT refit exclude list
1877  uint8_t count = buf.ReadByte();
1878  _gted[e->index].UpdateRefittability(prop == 0x1D && count != 0);
1879  if (prop == 0x1D) _gted[e->index].defaultcargo_grf = _cur.grffile;
1880  CargoTypes &ctt = prop == 0x1D ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
1881  ctt = 0;
1882  while (count--) {
1883  CargoID ctype = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
1884  if (IsValidCargoID(ctype)) SetBit(ctt, ctype);
1885  }
1886  break;
1887  }
1888 
1889  case PROP_AIRCRAFT_RANGE: // 0x1F Max aircraft range
1890  avi->max_range = buf.ReadWord();
1891  break;
1892 
1893  case 0x20: // Engine variant
1894  ei->variant_id = buf.ReadWord();
1895  break;
1896 
1897  case 0x21: // Extra miscellaneous flags
1898  ei->extra_flags = static_cast<ExtraEngineFlags>(buf.ReadDWord());
1899  break;
1900 
1901  case 0x22: // Callback additional mask
1902  SB(ei->callback_mask, 8, 8, buf.ReadByte());
1903  break;
1904 
1905  case 0x23: // Cargo classes required for a refit.
1906  _gted[e->index].cargo_allowed_required = buf.ReadWord();
1907  break;
1908 
1909  default:
1910  ret = CommonVehicleChangeInfo(ei, prop, buf);
1911  break;
1912  }
1913  }
1914 
1915  return ret;
1916 }
1917 
1926 static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, ByteReader &buf)
1927 {
1929 
1930  if (stid + numinfo > NUM_STATIONS_PER_GRF) {
1931  GrfMsg(1, "StationChangeInfo: Station {} is invalid, max {}, ignoring", stid + numinfo, NUM_STATIONS_PER_GRF);
1932  return CIR_INVALID_ID;
1933  }
1934 
1935  /* Allocate station specs if necessary */
1936  if (_cur.grffile->stations.size() < stid + numinfo) _cur.grffile->stations.resize(stid + numinfo);
1937 
1938  for (int i = 0; i < numinfo; i++) {
1939  auto &statspec = _cur.grffile->stations[stid + i];
1940 
1941  /* Check that the station we are modifying is defined. */
1942  if (statspec == nullptr && prop != 0x08) {
1943  GrfMsg(2, "StationChangeInfo: Attempt to modify undefined station {}, ignoring", stid + i);
1944  return CIR_INVALID_ID;
1945  }
1946 
1947  switch (prop) {
1948  case 0x08: { // Class ID
1949  /* Property 0x08 is special; it is where the station is allocated */
1950  if (statspec == nullptr) {
1951  statspec = std::make_unique<StationSpec>();
1952  }
1953 
1954  /* Swap classid because we read it in BE meaning WAYP or DFLT */
1955  uint32_t classid = buf.ReadDWord();
1956  statspec->class_index = StationClass::Allocate(BSWAP32(classid));
1957  break;
1958  }
1959 
1960  case 0x09: { // Define sprite layout
1961  uint16_t tiles = buf.ReadExtendedByte();
1962  statspec->renderdata.clear(); // delete earlier loaded stuff
1963  statspec->renderdata.reserve(tiles);
1964 
1965  for (uint t = 0; t < tiles; t++) {
1966  NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back();
1967  dts->consistent_max_offset = UINT16_MAX; // Spritesets are unknown, so no limit.
1968 
1969  if (buf.HasData(4) && buf.PeekDWord() == 0) {
1970  buf.Skip(4);
1971  extern const DrawTileSprites _station_display_datas_rail[8];
1972  dts->Clone(&_station_display_datas_rail[t % 8]);
1973  continue;
1974  }
1975 
1976  ReadSpriteLayoutSprite(buf, false, false, false, GSF_STATIONS, &dts->ground);
1977  /* On error, bail out immediately. Temporary GRF data was already freed */
1978  if (_cur.skip_sprites < 0) return CIR_DISABLED;
1979 
1980  static std::vector<DrawTileSeqStruct> tmp_layout;
1981  tmp_layout.clear();
1982  for (;;) {
1983  /* no relative bounding box support */
1984  DrawTileSeqStruct &dtss = tmp_layout.emplace_back();
1985  MemSetT(&dtss, 0);
1986 
1987  dtss.delta_x = buf.ReadByte();
1988  if (dtss.IsTerminator()) break;
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();
1994 
1995  ReadSpriteLayoutSprite(buf, false, true, false, GSF_STATIONS, &dtss.image);
1996  /* On error, bail out immediately. Temporary GRF data was already freed */
1997  if (_cur.skip_sprites < 0) return CIR_DISABLED;
1998  }
1999  dts->Clone(tmp_layout.data());
2000  }
2001 
2002  /* Number of layouts must be even, alternating X and Y */
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();
2006  }
2007  break;
2008  }
2009 
2010  case 0x0A: { // Copy sprite layout
2011  uint16_t srcid = buf.ReadExtendedByte();
2012  const StationSpec *srcstatspec = srcid >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[srcid].get();
2013 
2014  if (srcstatspec == nullptr) {
2015  GrfMsg(1, "StationChangeInfo: Station {} is not defined, cannot copy sprite layout to {}.", srcid, stid + i);
2016  continue;
2017  }
2018 
2019  statspec->renderdata.clear(); // delete earlier loaded stuff
2020  statspec->renderdata.reserve(srcstatspec->renderdata.size());
2021 
2022  for (const auto &it : srcstatspec->renderdata) {
2023  NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back();
2024  dts->Clone(&it);
2025  }
2026  break;
2027  }
2028 
2029  case 0x0B: // Callback mask
2030  statspec->callback_mask = buf.ReadByte();
2031  break;
2032 
2033  case 0x0C: // Disallowed number of platforms
2034  statspec->disallowed_platforms = buf.ReadByte();
2035  break;
2036 
2037  case 0x0D: // Disallowed platform lengths
2038  statspec->disallowed_lengths = buf.ReadByte();
2039  break;
2040 
2041  case 0x0E: // Define custom layout
2042  while (buf.HasData()) {
2043  uint8_t length = buf.ReadByte();
2044  uint8_t number = buf.ReadByte();
2045 
2046  if (length == 0 || number == 0) break;
2047 
2048  const uint8_t *buf_layout = buf.ReadBytes(length * number);
2049 
2050  /* Create entry in layouts and assign the layout to it. */
2051  auto &layout = statspec->layouts[GetStationLayoutKey(number, length)];
2052  layout.assign(buf_layout, buf_layout + length * number);
2053 
2054  /* Ensure the first bit, axis, is zero. The rest of the value is validated during rendering, as we don't know the range yet. */
2055  for (auto &tile : layout) {
2056  if ((tile & ~1U) != tile) {
2057  GrfMsg(1, "StationChangeInfo: Invalid tile {} in layout {}x{}", tile, length, number);
2058  tile &= ~1U;
2059  }
2060  }
2061  }
2062  break;
2063 
2064  case 0x0F: { // Copy custom layout
2065  uint16_t srcid = buf.ReadExtendedByte();
2066  const StationSpec *srcstatspec = srcid >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[srcid].get();
2067 
2068  if (srcstatspec == nullptr) {
2069  GrfMsg(1, "StationChangeInfo: Station {} is not defined, cannot copy tile layout to {}.", srcid, stid + i);
2070  continue;
2071  }
2072 
2073  statspec->layouts = srcstatspec->layouts;
2074  break;
2075  }
2076 
2077  case 0x10: // Little/lots cargo threshold
2078  statspec->cargo_threshold = buf.ReadWord();
2079  break;
2080 
2081  case 0x11: { // Pylon placement
2082  uint8_t pylons = buf.ReadByte();
2083  if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2084  for (int j = 0; j < 8; ++j) {
2085  if (HasBit(pylons, j)) {
2086  statspec->tileflags[j] |= StationSpec::TileFlags::Pylons;
2087  } else {
2088  statspec->tileflags[j] &= ~StationSpec::TileFlags::Pylons;
2089  }
2090  }
2091  break;
2092  }
2093 
2094  case 0x12: // Cargo types for random triggers
2095  if (_cur.grffile->grf_version >= 7) {
2096  statspec->cargo_triggers = TranslateRefitMask(buf.ReadDWord());
2097  } else {
2098  statspec->cargo_triggers = (CargoTypes)buf.ReadDWord();
2099  }
2100  break;
2101 
2102  case 0x13: // General flags
2103  statspec->flags = buf.ReadByte();
2104  break;
2105 
2106  case 0x14: { // Overhead wire placement
2107  uint8_t wires = buf.ReadByte();
2108  if (statspec->tileflags.size() < 8) statspec->tileflags.resize(8);
2109  for (int j = 0; j < 8; ++j) {
2110  if (HasBit(wires, j)) {
2111  statspec->tileflags[j] |= StationSpec::TileFlags::NoWires;
2112  } else {
2113  statspec->tileflags[j] &= ~StationSpec::TileFlags::NoWires;
2114  }
2115  }
2116  break;
2117  }
2118 
2119  case 0x15: { // Blocked tiles
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)) {
2124  statspec->tileflags[j] |= StationSpec::TileFlags::Blocked;
2125  } else {
2126  statspec->tileflags[j] &= ~StationSpec::TileFlags::Blocked;
2127  }
2128  }
2129  break;
2130  }
2131 
2132  case 0x16: // Animation info
2133  statspec->animation.frames = buf.ReadByte();
2134  statspec->animation.status = buf.ReadByte();
2135  break;
2136 
2137  case 0x17: // Animation speed
2138  statspec->animation.speed = buf.ReadByte();
2139  break;
2140 
2141  case 0x18: // Animation triggers
2142  statspec->animation.triggers = buf.ReadWord();
2143  break;
2144 
2145  /* 0x19 road routing (not implemented) */
2146 
2147  case 0x1A: { // Advanced sprite layout
2148  uint16_t tiles = buf.ReadExtendedByte();
2149  statspec->renderdata.clear(); // delete earlier loaded stuff
2150  statspec->renderdata.reserve(tiles);
2151 
2152  for (uint t = 0; t < tiles; t++) {
2153  NewGRFSpriteLayout *dts = &statspec->renderdata.emplace_back();
2154  uint num_building_sprites = buf.ReadByte();
2155  /* On error, bail out immediately. Temporary GRF data was already freed */
2156  if (ReadSpriteLayout(buf, num_building_sprites, false, GSF_STATIONS, true, false, dts)) return CIR_DISABLED;
2157  }
2158 
2159  /* Number of layouts must be even, alternating X and Y */
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();
2163  }
2164  break;
2165  }
2166 
2167  case 0x1B: // Minimum bridge height (not implemented)
2168  buf.ReadWord();
2169  buf.ReadWord();
2170  buf.ReadWord();
2171  buf.ReadWord();
2172  break;
2173 
2174  case 0x1C: // Station Name
2175  AddStringForMapping(buf.ReadWord(), &statspec->name);
2176  break;
2177 
2178  case 0x1D: // Station Class name
2179  AddStringForMapping(buf.ReadWord(), [statspec = statspec.get()](StringID str) { StationClass::Get(statspec->class_index)->name = str; });
2180  break;
2181 
2182  case 0x1E: { // Extended tile flags (replaces prop 11, 14 and 15)
2183  uint16_t tiles = buf.ReadExtendedByte();
2184  auto flags = reinterpret_cast<const StationSpec::TileFlags *>(buf.ReadBytes(tiles));
2185  statspec->tileflags.assign(flags, flags + tiles);
2186  break;
2187  }
2188 
2189  default:
2190  ret = CIR_UNKNOWN;
2191  break;
2192  }
2193  }
2194 
2195  return ret;
2196 }
2197 
2206 static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
2207 {
2209 
2210  if (id + numinfo > CF_END) {
2211  GrfMsg(1, "CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring", id + numinfo, CF_END);
2212  return CIR_INVALID_ID;
2213  }
2214 
2215  for (int i = 0; i < numinfo; i++) {
2216  CanalProperties *cp = &_cur.grffile->canal_local_properties[id + i];
2217 
2218  switch (prop) {
2219  case 0x08:
2220  cp->callback_mask = buf.ReadByte();
2221  break;
2222 
2223  case 0x09:
2224  cp->flags = buf.ReadByte();
2225  break;
2226 
2227  default:
2228  ret = CIR_UNKNOWN;
2229  break;
2230  }
2231  }
2232 
2233  return ret;
2234 }
2235 
2244 static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteReader &buf)
2245 {
2247 
2248  if (brid + numinfo > MAX_BRIDGES) {
2249  GrfMsg(1, "BridgeChangeInfo: Bridge {} is invalid, max {}, ignoring", brid + numinfo, MAX_BRIDGES);
2250  return CIR_INVALID_ID;
2251  }
2252 
2253  for (int i = 0; i < numinfo; i++) {
2254  BridgeSpec *bridge = &_bridge[brid + i];
2255 
2256  switch (prop) {
2257  case 0x08: { // Year of availability
2258  /* We treat '0' as always available */
2259  uint8_t year = buf.ReadByte();
2260  bridge->avail_year = (year > 0 ? CalendarTime::ORIGINAL_BASE_YEAR + year : 0);
2261  break;
2262  }
2263 
2264  case 0x09: // Minimum length
2265  bridge->min_length = buf.ReadByte();
2266  break;
2267 
2268  case 0x0A: // Maximum length
2269  bridge->max_length = buf.ReadByte();
2270  if (bridge->max_length > 16) bridge->max_length = UINT16_MAX;
2271  break;
2272 
2273  case 0x0B: // Cost factor
2274  bridge->price = buf.ReadByte();
2275  break;
2276 
2277  case 0x0C: // Maximum speed
2278  bridge->speed = buf.ReadWord();
2279  if (bridge->speed == 0) bridge->speed = UINT16_MAX;
2280  break;
2281 
2282  case 0x0D: { // Bridge sprite tables
2283  uint8_t tableid = buf.ReadByte();
2284  uint8_t numtables = buf.ReadByte();
2285 
2286  if (bridge->sprite_table == nullptr) {
2287  /* Allocate memory for sprite table pointers and zero out */
2288  bridge->sprite_table = CallocT<PalSpriteID*>(7);
2289  }
2290 
2291  for (; numtables-- != 0; tableid++) {
2292  if (tableid >= 7) { // skip invalid data
2293  GrfMsg(1, "BridgeChangeInfo: Table {} >= 7, skipping", tableid);
2294  for (uint8_t sprite = 0; sprite < 32; sprite++) buf.ReadDWord();
2295  continue;
2296  }
2297 
2298  if (bridge->sprite_table[tableid] == nullptr) {
2299  bridge->sprite_table[tableid] = MallocT<PalSpriteID>(32);
2300  }
2301 
2302  for (uint8_t sprite = 0; sprite < 32; sprite++) {
2303  SpriteID image = buf.ReadWord();
2304  PaletteID pal = buf.ReadWord();
2305 
2306  bridge->sprite_table[tableid][sprite].sprite = image;
2307  bridge->sprite_table[tableid][sprite].pal = pal;
2308 
2309  MapSpriteMappingRecolour(&bridge->sprite_table[tableid][sprite]);
2310  }
2311  }
2312  break;
2313  }
2314 
2315  case 0x0E: // Flags; bit 0 - disable far pillars
2316  bridge->flags = buf.ReadByte();
2317  break;
2318 
2319  case 0x0F: // Long format year of availability (year since year 0)
2321  break;
2322 
2323  case 0x10: { // purchase string
2324  StringID newone = GetGRFStringID(_cur.grffile->grfid, buf.ReadWord());
2325  if (newone != STR_UNDEFINED) bridge->material = newone;
2326  break;
2327  }
2328 
2329  case 0x11: // description of bridge with rails or roads
2330  case 0x12: {
2331  StringID newone = GetGRFStringID(_cur.grffile->grfid, buf.ReadWord());
2332  if (newone != STR_UNDEFINED) bridge->transport_name[prop - 0x11] = newone;
2333  break;
2334  }
2335 
2336  case 0x13: // 16 bits cost multiplier
2337  bridge->price = buf.ReadWord();
2338  break;
2339 
2340  default:
2341  ret = CIR_UNKNOWN;
2342  break;
2343  }
2344  }
2345 
2346  return ret;
2347 }
2348 
2356 {
2358 
2359  switch (prop) {
2360  case 0x09:
2361  case 0x0B:
2362  case 0x0C:
2363  case 0x0D:
2364  case 0x0E:
2365  case 0x0F:
2366  case 0x11:
2367  case 0x14:
2368  case 0x15:
2369  case 0x16:
2370  case 0x18:
2371  case 0x19:
2372  case 0x1A:
2373  case 0x1B:
2374  case 0x1C:
2375  case 0x1D:
2376  case 0x1F:
2377  buf.ReadByte();
2378  break;
2379 
2380  case 0x0A:
2381  case 0x10:
2382  case 0x12:
2383  case 0x13:
2384  case 0x21:
2385  case 0x22:
2386  buf.ReadWord();
2387  break;
2388 
2389  case 0x1E:
2390  buf.ReadDWord();
2391  break;
2392 
2393  case 0x17:
2394  for (uint j = 0; j < 4; j++) buf.ReadByte();
2395  break;
2396 
2397  case 0x20: {
2398  uint8_t count = buf.ReadByte();
2399  for (uint8_t j = 0; j < count; j++) buf.ReadByte();
2400  break;
2401  }
2402 
2403  case 0x23:
2404  buf.Skip(buf.ReadByte() * 2);
2405  break;
2406 
2407  default:
2408  ret = CIR_UNKNOWN;
2409  break;
2410  }
2411  return ret;
2412 }
2413 
2422 static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader &buf)
2423 {
2425 
2426  if (hid + numinfo > NUM_HOUSES_PER_GRF) {
2427  GrfMsg(1, "TownHouseChangeInfo: Too many houses loaded ({}), max ({}). Ignoring.", hid + numinfo, NUM_HOUSES_PER_GRF);
2428  return CIR_INVALID_ID;
2429  }
2430 
2431  /* Allocate house specs if they haven't been allocated already. */
2432  if (_cur.grffile->housespec.size() < hid + numinfo) _cur.grffile->housespec.resize(hid + numinfo);
2433 
2434  for (int i = 0; i < numinfo; i++) {
2435  auto &housespec = _cur.grffile->housespec[hid + i];
2436 
2437  if (prop != 0x08 && housespec == nullptr) {
2438  /* If the house property 08 is not yet set, ignore this property */
2439  ChangeInfoResult cir = IgnoreTownHouseProperty(prop, buf);
2440  if (cir > ret) ret = cir;
2441  continue;
2442  }
2443 
2444  switch (prop) {
2445  case 0x08: { // Substitute building type, and definition of a new house
2446  uint8_t subs_id = buf.ReadByte();
2447  if (subs_id == 0xFF) {
2448  /* Instead of defining a new house, a substitute house id
2449  * of 0xFF disables the old house with the current id. */
2450  if (hid + i < NEW_HOUSE_OFFSET) HouseSpec::Get(hid + i)->enabled = false;
2451  continue;
2452  } else if (subs_id >= NEW_HOUSE_OFFSET) {
2453  /* The substitute id must be one of the original houses. */
2454  GrfMsg(2, "TownHouseChangeInfo: Attempt to use new house {} as substitute house for {}. Ignoring.", subs_id, hid + i);
2455  continue;
2456  }
2457 
2458  /* Allocate space for this house. */
2459  if (housespec == nullptr) {
2460  /* Only the first property 08 setting copies properties; if you later change it, properties will stay. */
2461  housespec = std::make_unique<HouseSpec>(*HouseSpec::Get(subs_id));
2462 
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;
2467  /* Set default colours for randomization, used if not overridden. */
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;
2472 
2473  /* House flags 40 and 80 are exceptions; these flags are never set automatically. */
2474  housespec->building_flags &= ~(BUILDING_IS_CHURCH | BUILDING_IS_STADIUM);
2475 
2476  /* Make sure that the third cargo type is valid in this
2477  * climate. This can cause problems when copying the properties
2478  * of a house that accepts food, where the new house is valid
2479  * in the temperate climate. */
2480  CargoID cid = housespec->accepts_cargo[2];
2481  if (!IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
2482  if (!IsValidCargoID(cid)) {
2483  housespec->cargo_acceptance[2] = 0;
2484  }
2485  }
2486  break;
2487  }
2488 
2489  case 0x09: // Building flags
2490  housespec->building_flags = (BuildingFlags)buf.ReadByte();
2491  break;
2492 
2493  case 0x0A: { // Availability years
2494  uint16_t years = buf.ReadWord();
2495  housespec->min_year = GB(years, 0, 8) > 150 ? CalendarTime::MAX_YEAR : CalendarTime::ORIGINAL_BASE_YEAR + GB(years, 0, 8);
2496  housespec->max_year = GB(years, 8, 8) > 150 ? CalendarTime::MAX_YEAR : CalendarTime::ORIGINAL_BASE_YEAR + GB(years, 8, 8);
2497  break;
2498  }
2499 
2500  case 0x0B: // Population
2501  housespec->population = buf.ReadByte();
2502  break;
2503 
2504  case 0x0C: // Mail generation multiplier
2505  housespec->mail_generation = buf.ReadByte();
2506  break;
2507 
2508  case 0x0D: // Passenger acceptance
2509  case 0x0E: // Mail acceptance
2510  housespec->cargo_acceptance[prop - 0x0D] = buf.ReadByte();
2511  break;
2512 
2513  case 0x0F: { // Goods/candy, food/fizzy drinks acceptance
2514  int8_t goods = buf.ReadByte();
2515 
2516  /* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
2517  * Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
2518  CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_CANDY) : GetCargoIDByLabel(CT_GOODS)) :
2519  ((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_FIZZY_DRINKS) : GetCargoIDByLabel(CT_FOOD));
2520 
2521  /* Make sure the cargo type is valid in this climate. */
2522  if (!IsValidCargoID(cid)) goods = 0;
2523 
2524  housespec->accepts_cargo[2] = cid;
2525  housespec->accepts_cargo_label[2] = CT_INVALID;
2526  housespec->cargo_acceptance[2] = abs(goods); // but we do need positive value here
2527  break;
2528  }
2529 
2530  case 0x10: // Local authority rating decrease on removal
2531  housespec->remove_rating_decrease = buf.ReadWord();
2532  break;
2533 
2534  case 0x11: // Removal cost multiplier
2535  housespec->removal_cost = buf.ReadByte();
2536  break;
2537 
2538  case 0x12: // Building name ID
2539  AddStringForMapping(buf.ReadWord(), &housespec->building_name);
2540  break;
2541 
2542  case 0x13: // Building availability mask
2543  housespec->building_availability = (HouseZones)buf.ReadWord();
2544  break;
2545 
2546  case 0x14: // House callback mask
2547  housespec->callback_mask |= buf.ReadByte();
2548  break;
2549 
2550  case 0x15: { // House override byte
2551  uint8_t override = buf.ReadByte();
2552 
2553  /* The house being overridden must be an original house. */
2554  if (override >= NEW_HOUSE_OFFSET) {
2555  GrfMsg(2, "TownHouseChangeInfo: Attempt to override new house {} with house id {}. Ignoring.", override, hid + i);
2556  continue;
2557  }
2558 
2559  _house_mngr.Add(hid + i, _cur.grffile->grfid, override);
2560  break;
2561  }
2562 
2563  case 0x16: // Periodic refresh multiplier
2564  housespec->processing_time = std::min<uint8_t>(buf.ReadByte(), 63u);
2565  break;
2566 
2567  case 0x17: // Four random colours to use
2568  for (uint j = 0; j < 4; j++) housespec->random_colour[j] = static_cast<Colours>(GB(buf.ReadByte(), 0, 4));
2569  break;
2570 
2571  case 0x18: // Relative probability of appearing
2572  housespec->probability = buf.ReadByte();
2573  break;
2574 
2575  case 0x19: // Extra flags
2576  housespec->extra_flags = (HouseExtraFlags)buf.ReadByte();
2577  break;
2578 
2579  case 0x1A: // Animation frames
2580  housespec->animation.frames = buf.ReadByte();
2581  housespec->animation.status = GB(housespec->animation.frames, 7, 1);
2582  SB(housespec->animation.frames, 7, 1, 0);
2583  break;
2584 
2585  case 0x1B: // Animation speed
2586  housespec->animation.speed = Clamp(buf.ReadByte(), 2, 16);
2587  break;
2588 
2589  case 0x1C: // Class of the building type
2590  housespec->class_id = AllocateHouseClassID(buf.ReadByte(), _cur.grffile->grfid);
2591  break;
2592 
2593  case 0x1D: // Callback mask part 2
2594  housespec->callback_mask |= (buf.ReadByte() << 8);
2595  break;
2596 
2597  case 0x1E: { // Accepted cargo types
2598  uint32_t cargotypes = buf.ReadDWord();
2599 
2600  /* Check if the cargo types should not be changed */
2601  if (cargotypes == 0xFFFFFFFF) break;
2602 
2603  for (uint j = 0; j < HOUSE_ORIGINAL_NUM_ACCEPTS; j++) {
2604  /* Get the cargo number from the 'list' */
2605  uint8_t cargo_part = GB(cargotypes, 8 * j, 8);
2606  CargoID cargo = GetCargoTranslation(cargo_part, _cur.grffile);
2607 
2608  if (!IsValidCargoID(cargo)) {
2609  /* Disable acceptance of invalid cargo type */
2610  housespec->cargo_acceptance[j] = 0;
2611  } else {
2612  housespec->accepts_cargo[j] = cargo;
2613  }
2614  housespec->accepts_cargo_label[j] = CT_INVALID;
2615  }
2616  break;
2617  }
2618 
2619  case 0x1F: // Minimum life span
2620  housespec->minimum_life = buf.ReadByte();
2621  break;
2622 
2623  case 0x20: { // Cargo acceptance watch list
2624  uint8_t count = buf.ReadByte();
2625  for (uint8_t j = 0; j < count; j++) {
2626  CargoID cargo = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
2627  if (IsValidCargoID(cargo)) SetBit(housespec->watched_cargoes, cargo);
2628  }
2629  break;
2630  }
2631 
2632  case 0x21: // long introduction year
2633  housespec->min_year = buf.ReadWord();
2634  break;
2635 
2636  case 0x22: // long maximum year
2637  housespec->max_year = buf.ReadWord();
2638  if (housespec->max_year == UINT16_MAX) housespec->max_year = CalendarTime::MAX_YEAR;
2639  break;
2640 
2641  case 0x23: { // variable length cargo types accepted
2642  uint count = buf.ReadByte();
2643  if (count > lengthof(housespec->accepts_cargo)) {
2644  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
2645  error->param_value[1] = prop;
2646  return CIR_DISABLED;
2647  }
2648  /* Always write the full accepts_cargo array, and check each index for being inside the
2649  * provided data. This ensures all values are properly initialized, and also avoids
2650  * any risks of array overrun. */
2651  for (uint i = 0; i < lengthof(housespec->accepts_cargo); i++) {
2652  if (i < count) {
2653  housespec->accepts_cargo[i] = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
2654  housespec->cargo_acceptance[i] = buf.ReadByte();
2655  } else {
2656  housespec->accepts_cargo[i] = INVALID_CARGO;
2657  housespec->cargo_acceptance[i] = 0;
2658  }
2659  if (i < std::size(housespec->accepts_cargo_label)) housespec->accepts_cargo_label[i] = CT_INVALID;
2660  }
2661  break;
2662  }
2663 
2664  default:
2665  ret = CIR_UNKNOWN;
2666  break;
2667  }
2668  }
2669 
2670  return ret;
2671 }
2672 
2679 /* static */ const LanguageMap *LanguageMap::GetLanguageMap(uint32_t grfid, uint8_t language_id)
2680 {
2681  /* LanguageID "MAX_LANG", i.e. 7F is any. This language can't have a gender/case mapping, but has to be handled gracefully. */
2682  const GRFFile *grffile = GetFileByGRFID(grfid);
2683  if (grffile == nullptr) return nullptr;
2684 
2685  auto it = grffile->language_map.find(language_id);
2686  if (it == std::end(grffile->language_map)) return nullptr;
2687 
2688  return &it->second;
2689 }
2690 
2700 template <typename T>
2701 static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader &buf, std::vector<T> &translation_table, const char *name)
2702 {
2703  if (gvid != 0) {
2704  GrfMsg(1, "LoadTranslationTable: {} translation table must start at zero", name);
2705  return CIR_INVALID_ID;
2706  }
2707 
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())));
2712  }
2713 
2714  return CIR_SUCCESS;
2715 }
2716 
2723 static std::string ReadDWordAsString(ByteReader &reader)
2724 {
2725  std::string output;
2726  for (int i = 0; i < 4; i++) output.push_back(reader.ReadByte());
2727  return StrMakeValid(output);
2728 }
2729 
2738 static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, ByteReader &buf)
2739 {
2740  /* Properties which are handled as a whole */
2741  switch (prop) {
2742  case 0x09: // Cargo Translation Table; loading during both reservation and activation stage (in case it is selected depending on defined cargos)
2743  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->cargo_list, "Cargo");
2744 
2745  case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
2746  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
2747 
2748  case 0x16: // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
2749  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->roadtype_list, "Road type");
2750 
2751  case 0x17: // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
2752  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->tramtype_list, "Tram type");
2753 
2754  default:
2755  break;
2756  }
2757 
2758  /* Properties which are handled per item */
2760  for (int i = 0; i < numinfo; i++) {
2761  switch (prop) {
2762  case 0x08: { // Cost base factor
2763  int factor = buf.ReadByte();
2764  uint price = gvid + i;
2765 
2766  if (price < PR_END) {
2767  _cur.grffile->price_base_multipliers[price] = std::min<int>(factor - 8, MAX_PRICE_MODIFIER);
2768  } else {
2769  GrfMsg(1, "GlobalVarChangeInfo: Price {} out of range, ignoring", price);
2770  }
2771  break;
2772  }
2773 
2774  case 0x0A: { // Currency display names
2775  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2776  StringID newone = GetGRFStringID(_cur.grffile->grfid, buf.ReadWord());
2777 
2778  if ((newone != STR_UNDEFINED) && (curidx < CURRENCY_END)) {
2779  _currency_specs[curidx].name = newone;
2780  _currency_specs[curidx].code.clear();
2781  }
2782  break;
2783  }
2784 
2785  case 0x0B: { // Currency multipliers
2786  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2787  uint32_t rate = buf.ReadDWord();
2788 
2789  if (curidx < CURRENCY_END) {
2790  /* TTDPatch uses a multiple of 1000 for its conversion calculations,
2791  * which OTTD does not. For this reason, divide grf value by 1000,
2792  * to be compatible */
2793  _currency_specs[curidx].rate = rate / 1000;
2794  } else {
2795  GrfMsg(1, "GlobalVarChangeInfo: Currency multipliers {} out of range, ignoring", curidx);
2796  }
2797  break;
2798  }
2799 
2800  case 0x0C: { // Currency options
2801  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2802  uint16_t options = buf.ReadWord();
2803 
2804  if (curidx < CURRENCY_END) {
2805  _currency_specs[curidx].separator.clear();
2806  _currency_specs[curidx].separator.push_back(GB(options, 0, 8));
2807  /* By specifying only one bit, we prevent errors,
2808  * since newgrf specs said that only 0 and 1 can be set for symbol_pos */
2809  _currency_specs[curidx].symbol_pos = GB(options, 8, 1);
2810  } else {
2811  GrfMsg(1, "GlobalVarChangeInfo: Currency option {} out of range, ignoring", curidx);
2812  }
2813  break;
2814  }
2815 
2816  case 0x0D: { // Currency prefix symbol
2817  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2818  std::string prefix = ReadDWordAsString(buf);
2819 
2820  if (curidx < CURRENCY_END) {
2821  _currency_specs[curidx].prefix = prefix;
2822  } else {
2823  GrfMsg(1, "GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2824  }
2825  break;
2826  }
2827 
2828  case 0x0E: { // Currency suffix symbol
2829  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2830  std::string suffix = ReadDWordAsString(buf);
2831 
2832  if (curidx < CURRENCY_END) {
2833  _currency_specs[curidx].suffix = suffix;
2834  } else {
2835  GrfMsg(1, "GlobalVarChangeInfo: Currency symbol {} out of range, ignoring", curidx);
2836  }
2837  break;
2838  }
2839 
2840  case 0x0F: { // Euro introduction dates
2841  uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
2842  TimerGameCalendar::Year year_euro = buf.ReadWord();
2843 
2844  if (curidx < CURRENCY_END) {
2845  _currency_specs[curidx].to_euro = year_euro;
2846  } else {
2847  GrfMsg(1, "GlobalVarChangeInfo: Euro intro date {} out of range, ignoring", curidx);
2848  }
2849  break;
2850  }
2851 
2852  case 0x10: // Snow line height table
2853  if (numinfo > 1 || IsSnowLineSet()) {
2854  GrfMsg(1, "GlobalVarChangeInfo: The snowline can only be set once ({})", numinfo);
2855  } else if (buf.Remaining() < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
2856  GrfMsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table ({})", buf.Remaining());
2857  } else {
2858  uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
2859 
2860  for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
2861  for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
2862  table[i][j] = buf.ReadByte();
2863  if (_cur.grffile->grf_version >= 8) {
2864  if (table[i][j] != 0xFF) table[i][j] = table[i][j] * (1 + _settings_game.construction.map_height_limit) / 256;
2865  } else {
2866  if (table[i][j] >= 128) {
2867  /* no snow */
2868  table[i][j] = 0xFF;
2869  } else {
2870  table[i][j] = table[i][j] * (1 + _settings_game.construction.map_height_limit) / 128;
2871  }
2872  }
2873  }
2874  }
2875  SetSnowLine(table);
2876  }
2877  break;
2878 
2879  case 0x11: // GRF match for engine allocation
2880  /* This is loaded during the reservation stage, so just skip it here. */
2881  /* Each entry is 8 bytes. */
2882  buf.Skip(8);
2883  break;
2884 
2885  case 0x13: // Gender translation table
2886  case 0x14: // Case translation table
2887  case 0x15: { // Plural form translation
2888  uint curidx = gvid + i; // The current index, i.e. language.
2889  const LanguageMetadata *lang = curidx < MAX_LANG ? GetLanguage(curidx) : nullptr;
2890  if (lang == nullptr) {
2891  GrfMsg(1, "GlobalVarChangeInfo: Language {} is not known, ignoring", curidx);
2892  /* Skip over the data. */
2893  if (prop == 0x15) {
2894  buf.ReadByte();
2895  } else {
2896  while (buf.ReadByte() != 0) {
2897  buf.ReadString();
2898  }
2899  }
2900  break;
2901  }
2902 
2903  if (prop == 0x15) {
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);
2907  } else {
2908  _cur.grffile->language_map[curidx].plural_form = plural_form;
2909  }
2910  break;
2911  }
2912 
2913  uint8_t newgrf_id = buf.ReadByte(); // The NewGRF (custom) identifier.
2914  while (newgrf_id != 0) {
2915  std::string_view name = buf.ReadString(); // The name for the OpenTTD identifier.
2916 
2917  /* We'll just ignore the UTF8 identifier character. This is (fairly)
2918  * safe as OpenTTD's strings gender/cases are usually in ASCII which
2919  * is just a subset of UTF8, or they need the bigger UTF8 characters
2920  * such as Cyrillic. Thus we will simply assume they're all UTF8. */
2921  char32_t c;
2922  size_t len = Utf8Decode(&c, name.data());
2923  if (c == NFO_UTF8_IDENTIFIER) name = name.substr(len);
2924 
2926  map.newgrf_id = newgrf_id;
2927  if (prop == 0x13) {
2928  map.openttd_id = lang->GetGenderIndex(name.data());
2929  if (map.openttd_id >= MAX_NUM_GENDERS) {
2930  GrfMsg(1, "GlobalVarChangeInfo: Gender name {} is not known, ignoring", StrMakeValid(name));
2931  } else {
2932  _cur.grffile->language_map[curidx].gender_map.push_back(map);
2933  }
2934  } else {
2935  map.openttd_id = lang->GetCaseIndex(name.data());
2936  if (map.openttd_id >= MAX_NUM_CASES) {
2937  GrfMsg(1, "GlobalVarChangeInfo: Case name {} is not known, ignoring", StrMakeValid(name));
2938  } else {
2939  _cur.grffile->language_map[curidx].case_map.push_back(map);
2940  }
2941  }
2942  newgrf_id = buf.ReadByte();
2943  }
2944  break;
2945  }
2946 
2947  default:
2948  ret = CIR_UNKNOWN;
2949  break;
2950  }
2951  }
2952 
2953  return ret;
2954 }
2955 
2956 static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, ByteReader &buf)
2957 {
2958  /* Properties which are handled as a whole */
2959  switch (prop) {
2960  case 0x09: // Cargo Translation Table; loading during both reservation and activation stage (in case it is selected depending on defined cargos)
2961  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->cargo_list, "Cargo");
2962 
2963  case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
2964  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
2965 
2966  case 0x16: // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined roadtypes)
2967  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->roadtype_list, "Road type");
2968 
2969  case 0x17: // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined tramtypes)
2970  return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->tramtype_list, "Tram type");
2971 
2972  default:
2973  break;
2974  }
2975 
2976  /* Properties which are handled per item */
2978  for (int i = 0; i < numinfo; i++) {
2979  switch (prop) {
2980  case 0x08: // Cost base factor
2981  case 0x15: // Plural form translation
2982  buf.ReadByte();
2983  break;
2984 
2985  case 0x0A: // Currency display names
2986  case 0x0C: // Currency options
2987  case 0x0F: // Euro introduction dates
2988  buf.ReadWord();
2989  break;
2990 
2991  case 0x0B: // Currency multipliers
2992  case 0x0D: // Currency prefix symbol
2993  case 0x0E: // Currency suffix symbol
2994  buf.ReadDWord();
2995  break;
2996 
2997  case 0x10: // Snow line height table
2998  buf.Skip(SNOW_LINE_MONTHS * SNOW_LINE_DAYS);
2999  break;
3000 
3001  case 0x11: { // GRF match for engine allocation
3002  uint32_t s = buf.ReadDWord();
3003  uint32_t t = buf.ReadDWord();
3004  SetNewGRFOverride(s, t);
3005  break;
3006  }
3007 
3008  case 0x13: // Gender translation table
3009  case 0x14: // Case translation table
3010  while (buf.ReadByte() != 0) {
3011  buf.ReadString();
3012  }
3013  break;
3014 
3015  default:
3016  ret = CIR_UNKNOWN;
3017  break;
3018  }
3019  }
3020 
3021  return ret;
3022 }
3023 
3024 
3033 static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteReader &buf)
3034 {
3036 
3037  if (cid + numinfo > NUM_CARGO) {
3038  GrfMsg(2, "CargoChangeInfo: Cargo type {} out of range (max {})", cid + numinfo, NUM_CARGO - 1);
3039  return CIR_INVALID_ID;
3040  }
3041 
3042  for (int i = 0; i < numinfo; i++) {
3043  CargoSpec *cs = CargoSpec::Get(cid + i);
3044 
3045  switch (prop) {
3046  case 0x08: // Bit number of cargo
3047  cs->bitnum = buf.ReadByte();
3048  if (cs->IsValid()) {
3049  cs->grffile = _cur.grffile;
3050  SetBit(_cargo_mask, cid + i);
3051  } else {
3052  ClrBit(_cargo_mask, cid + i);
3053  }
3055  break;
3056 
3057  case 0x09: // String ID for cargo type name
3058  AddStringForMapping(buf.ReadWord(), &cs->name);
3059  break;
3060 
3061  case 0x0A: // String for 1 unit of cargo
3062  AddStringForMapping(buf.ReadWord(), &cs->name_single);
3063  break;
3064 
3065  case 0x0B: // String for singular quantity of cargo (e.g. 1 tonne of coal)
3066  case 0x1B: // String for cargo units
3067  /* String for units of cargo. This is different in OpenTTD
3068  * (e.g. tonnes) to TTDPatch (e.g. {COMMA} tonne of coal).
3069  * Property 1B is used to set OpenTTD's behaviour. */
3070  AddStringForMapping(buf.ReadWord(), &cs->units_volume);
3071  break;
3072 
3073  case 0x0C: // String for plural quantity of cargo (e.g. 10 tonnes of coal)
3074  case 0x1C: // String for any amount of cargo
3075  /* Strings for an amount of cargo. This is different in OpenTTD
3076  * (e.g. {WEIGHT} of coal) to TTDPatch (e.g. {COMMA} tonnes of coal).
3077  * Property 1C is used to set OpenTTD's behaviour. */
3078  AddStringForMapping(buf.ReadWord(), &cs->quantifier);
3079  break;
3080 
3081  case 0x0D: // String for two letter cargo abbreviation
3082  AddStringForMapping(buf.ReadWord(), &cs->abbrev);
3083  break;
3084 
3085  case 0x0E: // Sprite ID for cargo icon
3086  cs->sprite = buf.ReadWord();
3087  break;
3088 
3089  case 0x0F: // Weight of one unit of cargo
3090  cs->weight = buf.ReadByte();
3091  break;
3092 
3093  case 0x10: // Used for payment calculation
3094  cs->transit_periods[0] = buf.ReadByte();
3095  break;
3096 
3097  case 0x11: // Used for payment calculation
3098  cs->transit_periods[1] = buf.ReadByte();
3099  break;
3100 
3101  case 0x12: // Base cargo price
3102  cs->initial_payment = buf.ReadDWord();
3103  break;
3104 
3105  case 0x13: // Colour for station rating bars
3106  cs->rating_colour = buf.ReadByte();
3107  break;
3108 
3109  case 0x14: // Colour for cargo graph
3110  cs->legend_colour = buf.ReadByte();
3111  break;
3112 
3113  case 0x15: // Freight status
3114  cs->is_freight = (buf.ReadByte() != 0);
3115  break;
3116 
3117  case 0x16: // Cargo classes
3118  cs->classes = buf.ReadWord();
3119  break;
3120 
3121  case 0x17: // Cargo label
3122  cs->label = CargoLabel{BSWAP32(buf.ReadDWord())};
3124  break;
3125 
3126  case 0x18: { // Town growth substitute type
3127  uint8_t substitute_type = buf.ReadByte();
3128 
3129  switch (substitute_type) {
3130  case 0x00: cs->town_acceptance_effect = TAE_PASSENGERS; break;
3131  case 0x02: cs->town_acceptance_effect = TAE_MAIL; break;
3132  case 0x05: cs->town_acceptance_effect = TAE_GOODS; break;
3133  case 0x09: cs->town_acceptance_effect = TAE_WATER; break;
3134  case 0x0B: cs->town_acceptance_effect = TAE_FOOD; break;
3135  default:
3136  GrfMsg(1, "CargoChangeInfo: Unknown town growth substitute value {}, setting to none.", substitute_type);
3137  [[fallthrough]];
3138  case 0xFF: cs->town_acceptance_effect = TAE_NONE; break;
3139  }
3140  break;
3141  }
3142 
3143  case 0x19: // Town growth coefficient
3144  buf.ReadWord();
3145  break;
3146 
3147  case 0x1A: // Bitmask of callbacks to use
3148  cs->callback_mask = buf.ReadByte();
3149  break;
3150 
3151  case 0x1D: // Vehicle capacity muliplier
3152  cs->multiplier = std::max<uint16_t>(1u, buf.ReadWord());
3153  break;
3154 
3155  case 0x1E: { // Town production substitute type
3156  uint8_t substitute_type = buf.ReadByte();
3157 
3158  switch (substitute_type) {
3159  case 0x00: cs->town_production_effect = TPE_PASSENGERS; break;
3160  case 0x02: cs->town_production_effect = TPE_MAIL; break;
3161  default:
3162  GrfMsg(1, "CargoChangeInfo: Unknown town production substitute value {}, setting to none.", substitute_type);
3163  [[fallthrough]];
3164  case 0xFF: cs->town_production_effect = TPE_NONE; break;
3165  }
3166  break;
3167  }
3168 
3169  case 0x1F: // Town production multiplier
3170  cs->town_production_multiplier = std::max<uint16_t>(1U, buf.ReadWord());
3171  break;
3172 
3173  default:
3174  ret = CIR_UNKNOWN;
3175  break;
3176  }
3177  }
3178 
3179  return ret;
3180 }
3181 
3182 
3191 static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, ByteReader &buf)
3192 {
3194 
3195  if (_cur.grffile->sound_offset == 0) {
3196  GrfMsg(1, "SoundEffectChangeInfo: No effects defined, skipping");
3197  return CIR_INVALID_ID;
3198  }
3199 
3200  if (sid + numinfo - ORIGINAL_SAMPLE_COUNT > _cur.grffile->num_sounds) {
3201  GrfMsg(1, "SoundEffectChangeInfo: Attempting to change undefined sound effect ({}), max ({}). Ignoring.", sid + numinfo, ORIGINAL_SAMPLE_COUNT + _cur.grffile->num_sounds);
3202  return CIR_INVALID_ID;
3203  }
3204 
3205  for (int i = 0; i < numinfo; i++) {
3206  SoundEntry *sound = GetSound(sid + i + _cur.grffile->sound_offset - ORIGINAL_SAMPLE_COUNT);
3207 
3208  switch (prop) {
3209  case 0x08: // Relative volume
3210  sound->volume = Clamp(buf.ReadByte(), 0, SOUND_EFFECT_MAX_VOLUME);
3211  break;
3212 
3213  case 0x09: // Priority
3214  sound->priority = buf.ReadByte();
3215  break;
3216 
3217  case 0x0A: { // Override old sound
3218  SoundID orig_sound = buf.ReadByte();
3219 
3220  if (orig_sound >= ORIGINAL_SAMPLE_COUNT) {
3221  GrfMsg(1, "SoundEffectChangeInfo: Original sound {} not defined (max {})", orig_sound, ORIGINAL_SAMPLE_COUNT);
3222  } else {
3223  SoundEntry *old_sound = GetSound(orig_sound);
3224 
3225  /* Literally copy the data of the new sound over the original */
3226  *old_sound = *sound;
3227  }
3228  break;
3229  }
3230 
3231  default:
3232  ret = CIR_UNKNOWN;
3233  break;
3234  }
3235  }
3236 
3237  return ret;
3238 }
3239 
3247 {
3249 
3250  switch (prop) {
3251  case 0x09:
3252  case 0x0D:
3253  case 0x0E:
3254  case 0x10:
3255  case 0x11:
3256  case 0x12:
3257  buf.ReadByte();
3258  break;
3259 
3260  case 0x0A:
3261  case 0x0B:
3262  case 0x0C:
3263  case 0x0F:
3264  buf.ReadWord();
3265  break;
3266 
3267  case 0x13:
3268  buf.Skip(buf.ReadByte() * 2);
3269  break;
3270 
3271  default:
3272  ret = CIR_UNKNOWN;
3273  break;
3274  }
3275  return ret;
3276 }
3277 
3286 static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader &buf)
3287 {
3289 
3290  if (indtid + numinfo > NUM_INDUSTRYTILES_PER_GRF) {
3291  GrfMsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES_PER_GRF);
3292  return CIR_INVALID_ID;
3293  }
3294 
3295  /* Allocate industry tile specs if they haven't been allocated already. */
3296  if (_cur.grffile->indtspec.size() < indtid + numinfo) _cur.grffile->indtspec.resize(indtid + numinfo);
3297 
3298  for (int i = 0; i < numinfo; i++) {
3299  auto &tsp = _cur.grffile->indtspec[indtid + i];
3300 
3301  if (prop != 0x08 && tsp == nullptr) {
3303  if (cir > ret) ret = cir;
3304  continue;
3305  }
3306 
3307  switch (prop) {
3308  case 0x08: { // Substitute industry tile type
3309  uint8_t subs_id = buf.ReadByte();
3310  if (subs_id >= NEW_INDUSTRYTILEOFFSET) {
3311  /* The substitute id must be one of the original industry tile. */
3312  GrfMsg(2, "IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id, indtid + i);
3313  continue;
3314  }
3315 
3316  /* Allocate space for this industry. */
3317  if (tsp == nullptr) {
3318  tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
3319 
3320  tsp->enabled = true;
3321 
3322  /* A copied tile should not have the animation infos copied too.
3323  * The anim_state should be left untouched, though
3324  * It is up to the author to animate them */
3325  tsp->anim_production = INDUSTRYTILE_NOANIM;
3326  tsp->anim_next = INDUSTRYTILE_NOANIM;
3327 
3328  tsp->grf_prop.local_id = indtid + i;
3329  tsp->grf_prop.subst_id = subs_id;
3330  tsp->grf_prop.grffile = _cur.grffile;
3331  _industile_mngr.AddEntityID(indtid + i, _cur.grffile->grfid, subs_id); // pre-reserve the tile slot
3332  }
3333  break;
3334  }
3335 
3336  case 0x09: { // Industry tile override
3337  uint8_t ovrid = buf.ReadByte();
3338 
3339  /* The industry being overridden must be an original industry. */
3340  if (ovrid >= NEW_INDUSTRYTILEOFFSET) {
3341  GrfMsg(2, "IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid, indtid + i);
3342  continue;
3343  }
3344 
3345  _industile_mngr.Add(indtid + i, _cur.grffile->grfid, ovrid);
3346  break;
3347  }
3348 
3349  case 0x0A: // Tile acceptance
3350  case 0x0B:
3351  case 0x0C: {
3352  uint16_t acctp = buf.ReadWord();
3353  tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur.grffile);
3354  tsp->acceptance[prop - 0x0A] = Clamp(GB(acctp, 8, 8), 0, 16);
3355  tsp->accepts_cargo_label[prop - 0x0A] = CT_INVALID;
3356  break;
3357  }
3358 
3359  case 0x0D: // Land shape flags
3360  tsp->slopes_refused = (Slope)buf.ReadByte();
3361  break;
3362 
3363  case 0x0E: // Callback mask
3364  tsp->callback_mask = buf.ReadByte();
3365  break;
3366 
3367  case 0x0F: // Animation information
3368  tsp->animation.frames = buf.ReadByte();
3369  tsp->animation.status = buf.ReadByte();
3370  break;
3371 
3372  case 0x10: // Animation speed
3373  tsp->animation.speed = buf.ReadByte();
3374  break;
3375 
3376  case 0x11: // Triggers for callback 25
3377  tsp->animation.triggers = buf.ReadByte();
3378  break;
3379 
3380  case 0x12: // Special flags
3381  tsp->special_flags = (IndustryTileSpecialFlags)buf.ReadByte();
3382  break;
3383 
3384  case 0x13: { // variable length cargo acceptance
3385  uint8_t num_cargoes = buf.ReadByte();
3386  if (num_cargoes > std::size(tsp->acceptance)) {
3387  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
3388  error->param_value[1] = prop;
3389  return CIR_DISABLED;
3390  }
3391  for (uint i = 0; i < std::size(tsp->acceptance); i++) {
3392  if (i < num_cargoes) {
3393  tsp->accepts_cargo[i] = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
3394  /* Tile acceptance can be negative to counteract the INDTILE_SPECIAL_ACCEPTS_ALL_CARGO flag */
3395  tsp->acceptance[i] = (int8_t)buf.ReadByte();
3396  } else {
3397  tsp->accepts_cargo[i] = INVALID_CARGO;
3398  tsp->acceptance[i] = 0;
3399  }
3400  if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] = CT_INVALID;
3401  }
3402  break;
3403  }
3404 
3405  default:
3406  ret = CIR_UNKNOWN;
3407  break;
3408  }
3409  }
3410 
3411  return ret;
3412 }
3413 
3421 {
3423 
3424  switch (prop) {
3425  case 0x09:
3426  case 0x0B:
3427  case 0x0F:
3428  case 0x12:
3429  case 0x13:
3430  case 0x14:
3431  case 0x17:
3432  case 0x18:
3433  case 0x19:
3434  case 0x21:
3435  case 0x22:
3436  buf.ReadByte();
3437  break;
3438 
3439  case 0x0C:
3440  case 0x0D:
3441  case 0x0E:
3442  case 0x10: // INDUSTRY_ORIGINAL_NUM_OUTPUTS bytes
3443  case 0x1B:
3444  case 0x1F:
3445  case 0x24:
3446  buf.ReadWord();
3447  break;
3448 
3449  case 0x11: // INDUSTRY_ORIGINAL_NUM_INPUTS bytes + 1
3450  case 0x1A:
3451  case 0x1C:
3452  case 0x1D:
3453  case 0x1E:
3454  case 0x20:
3455  case 0x23:
3456  buf.ReadDWord();
3457  break;
3458 
3459  case 0x0A: {
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) {
3465  buf.ReadByte();
3466  buf.ReadByte();
3467  break;
3468  }
3469 
3470  uint8_t y = buf.ReadByte();
3471  if (x == 0 && y == 0x80) break;
3472 
3473  uint8_t gfx = buf.ReadByte();
3474  if (gfx == 0xFE) buf.ReadWord();
3475  }
3476  }
3477  break;
3478  }
3479 
3480  case 0x16:
3481  for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_INPUTS; j++) buf.ReadByte();
3482  break;
3483 
3484  case 0x15:
3485  case 0x25:
3486  case 0x26:
3487  case 0x27:
3488  buf.Skip(buf.ReadByte());
3489  break;
3490 
3491  case 0x28: {
3492  int num_inputs = buf.ReadByte();
3493  int num_outputs = buf.ReadByte();
3494  buf.Skip(num_inputs * num_outputs * 2);
3495  break;
3496  }
3497 
3498  default:
3499  ret = CIR_UNKNOWN;
3500  break;
3501  }
3502  return ret;
3503 }
3504 
3510 static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
3511 {
3512  const size_t size = layout.size();
3513  if (size == 0) return false;
3514 
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) {
3519  return false;
3520  }
3521  }
3522  }
3523 
3524  bool have_regular_tile = false;
3525  for (const auto &tilelayout : layout) {
3526  if (tilelayout.gfx != GFX_WATERTILE_SPECIALCHECK) {
3527  have_regular_tile = true;
3528  break;
3529  }
3530  }
3531 
3532  return have_regular_tile;
3533 }
3534 
3543 static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader &buf)
3544 {
3546 
3547  if (indid + numinfo > NUM_INDUSTRYTYPES_PER_GRF) {
3548  GrfMsg(1, "IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES_PER_GRF);
3549  return CIR_INVALID_ID;
3550  }
3551 
3552  /* Allocate industry specs if they haven't been allocated already. */
3553  if (_cur.grffile->industryspec.size() < indid + numinfo) _cur.grffile->industryspec.resize(indid + numinfo);
3554 
3555  for (int i = 0; i < numinfo; i++) {
3556  auto &indsp = _cur.grffile->industryspec[indid + i];
3557 
3558  if (prop != 0x08 && indsp == nullptr) {
3559  ChangeInfoResult cir = IgnoreIndustryProperty(prop, buf);
3560  if (cir > ret) ret = cir;
3561  continue;
3562  }
3563 
3564  switch (prop) {
3565  case 0x08: { // Substitute industry type
3566  uint8_t subs_id = buf.ReadByte();
3567  if (subs_id == 0xFF) {
3568  /* Instead of defining a new industry, a substitute industry id
3569  * of 0xFF disables the old industry with the current id. */
3570  _industry_specs[indid + i].enabled = false;
3571  continue;
3572  } else if (subs_id >= NEW_INDUSTRYOFFSET) {
3573  /* The substitute id must be one of the original industry. */
3574  GrfMsg(2, "_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id, indid + i);
3575  continue;
3576  }
3577 
3578  /* Allocate space for this industry.
3579  * Only need to do it once. If ever it is called again, it should not
3580  * do anything */
3581  if (indsp == nullptr) {
3582  indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
3583 
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;
3588  /* If the grf industry needs to check its surrounding upon creation, it should
3589  * rely on callbacks, not on the original placement functions */
3590  indsp->check_proc = CHECK_NOTHING;
3591  }
3592  break;
3593  }
3594 
3595  case 0x09: { // Industry type override
3596  uint8_t ovrid = buf.ReadByte();
3597 
3598  /* The industry being overridden must be an original industry. */
3599  if (ovrid >= NEW_INDUSTRYOFFSET) {
3600  GrfMsg(2, "IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid, indid + i);
3601  continue;
3602  }
3603  indsp->grf_prop.override = ovrid;
3604  _industry_mngr.Add(indid + i, _cur.grffile->grfid, ovrid);
3605  break;
3606  }
3607 
3608  case 0x0A: { // Set industry layout(s)
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;
3613  IndustryTileLayout layout;
3614 
3615  for (uint8_t j = 0; j < new_num_layouts; j++) {
3616  layout.clear();
3617  layout.reserve(new_num_layouts);
3618 
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);
3622  /* Avoid warning twice */
3623  definition_size = UINT32_MAX;
3624  }
3625 
3626  IndustryTileLayoutTile &it = layout.emplace_back();
3627 
3628  it.ti.x = buf.ReadByte(); // Offsets from northermost tile
3629  ++bytes_read;
3630 
3631  if (it.ti.x == 0xFE && k == 0) {
3632  /* This means we have to borrow the layout from an old industry */
3633  IndustryType type = buf.ReadByte();
3634  uint8_t laynbr = buf.ReadByte();
3635  bytes_read += 2;
3636 
3637  if (type >= lengthof(_origin_industry_specs)) {
3638  GrfMsg(1, "IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", indid);
3639  DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
3640  return CIR_DISABLED;
3641  }
3642  if (laynbr >= _origin_industry_specs[type].layouts.size()) {
3643  GrfMsg(1, "IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", indid);
3644  DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
3645  return CIR_DISABLED;
3646  }
3647  layout = _origin_industry_specs[type].layouts[laynbr];
3648  break;
3649  }
3650 
3651  it.ti.y = buf.ReadByte(); // Or table definition finalisation
3652  ++bytes_read;
3653 
3654  if (it.ti.x == 0 && it.ti.y == 0x80) {
3655  /* Terminator, remove and finish up */
3656  layout.pop_back();
3657  break;
3658  }
3659 
3660  it.gfx = buf.ReadByte();
3661  ++bytes_read;
3662 
3663  if (it.gfx == 0xFE) {
3664  /* Use a new tile from this GRF */
3665  int local_tile_id = buf.ReadWord();
3666  bytes_read += 2;
3667 
3668  /* Read the ID from the _industile_mngr. */
3669  int tempid = _industile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
3670 
3671  if (tempid == INVALID_INDUSTRYTILE) {
3672  GrfMsg(2, "IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, indid);
3673  } else {
3674  /* Declared as been valid, can be used */
3675  it.gfx = tempid;
3676  }
3677  } else if (it.gfx == GFX_WATERTILE_SPECIALCHECK) {
3678  it.ti.x = (int8_t)GB(it.ti.x, 0, 8);
3679  it.ti.y = (int8_t)GB(it.ti.y, 0, 8);
3680 
3681  /* When there were only 256x256 maps, TileIndex was a uint16_t and
3682  * it.ti was just a TileIndexDiff that was added to it.
3683  * As such negative "x" values were shifted into the "y" position.
3684  * x = -1, y = 1 -> x = 255, y = 0
3685  * Since GRF version 8 the position is interpreted as pair of independent int8.
3686  * For GRF version < 8 we need to emulate the old shifting behaviour.
3687  */
3688  if (_cur.grffile->grf_version < 8 && it.ti.x < 0) it.ti.y += 1;
3689  }
3690  }
3691 
3692  if (!ValidateIndustryLayout(layout)) {
3693  /* The industry layout was not valid, so skip this one. */
3694  GrfMsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", indid);
3695  new_num_layouts--;
3696  j--;
3697  } else {
3698  new_layouts.push_back(layout);
3699  }
3700  }
3701 
3702  /* Install final layout construction in the industry spec */
3703  indsp->layouts = new_layouts;
3704  break;
3705  }
3706 
3707  case 0x0B: // Industry production flags
3708  indsp->life_type = (IndustryLifeType)buf.ReadByte();
3709  break;
3710 
3711  case 0x0C: // Industry closure message
3712  AddStringForMapping(buf.ReadWord(), &indsp->closure_text);
3713  break;
3714 
3715  case 0x0D: // Production increase message
3716  AddStringForMapping(buf.ReadWord(), &indsp->production_up_text);
3717  break;
3718 
3719  case 0x0E: // Production decrease message
3720  AddStringForMapping(buf.ReadWord(), &indsp->production_down_text);
3721  break;
3722 
3723  case 0x0F: // Fund cost multiplier
3724  indsp->cost_multiplier = buf.ReadByte();
3725  break;
3726 
3727  case 0x10: // Production cargo types
3728  for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_OUTPUTS; j++) {
3729  indsp->produced_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
3730  indsp->produced_cargo_label[j] = CT_INVALID;
3731  }
3732  break;
3733 
3734  case 0x11: // Acceptance cargo types
3735  for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_INPUTS; j++) {
3736  indsp->accepts_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
3737  indsp->accepts_cargo_label[j] = CT_INVALID;
3738  }
3739  buf.ReadByte(); // Unnused, eat it up
3740  break;
3741 
3742  case 0x12: // Production multipliers
3743  case 0x13:
3744  indsp->production_rate[prop - 0x12] = buf.ReadByte();
3745  break;
3746 
3747  case 0x14: // Minimal amount of cargo distributed
3748  indsp->minimal_cargo = buf.ReadByte();
3749  break;
3750 
3751  case 0x15: { // Random sound effects
3752  uint8_t num_sounds = buf.ReadByte();
3753 
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());
3758  }
3759 
3760  indsp->random_sounds = std::move(sounds);
3761  break;
3762  }
3763 
3764  case 0x16: // Conflicting industry types
3765  for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
3766  break;
3767 
3768  case 0x17: // Probability in random game
3769  indsp->appear_creation[_settings_game.game_creation.landscape] = buf.ReadByte();
3770  break;
3771 
3772  case 0x18: // Probability during gameplay
3773  indsp->appear_ingame[_settings_game.game_creation.landscape] = buf.ReadByte();
3774  break;
3775 
3776  case 0x19: // Map colour
3777  indsp->map_colour = buf.ReadByte();
3778  break;
3779 
3780  case 0x1A: // Special industry flags to define special behavior
3781  indsp->behaviour = (IndustryBehaviour)buf.ReadDWord();
3782  break;
3783 
3784  case 0x1B: // New industry text ID
3785  AddStringForMapping(buf.ReadWord(), &indsp->new_industry_text);
3786  break;
3787 
3788  case 0x1C: // Input cargo multipliers for the three input cargo types
3789  case 0x1D:
3790  case 0x1E: {
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);
3794  break;
3795  }
3796 
3797  case 0x1F: // Industry name
3798  AddStringForMapping(buf.ReadWord(), &indsp->name);
3799  break;
3800 
3801  case 0x20: // Prospecting success chance
3802  indsp->prospecting_chance = buf.ReadDWord();
3803  break;
3804 
3805  case 0x21: // Callback mask
3806  case 0x22: { // Callback additional mask
3807  uint8_t aflag = buf.ReadByte();
3808  SB(indsp->callback_mask, (prop - 0x21) * 8, 8, aflag);
3809  break;
3810  }
3811 
3812  case 0x23: // removal cost multiplier
3813  indsp->removal_cost_multiplier = buf.ReadDWord();
3814  break;
3815 
3816  case 0x24: { // name for nearby station
3817  uint16_t str = buf.ReadWord();
3818  if (str == 0) {
3819  indsp->station_name = STR_NULL;
3820  } else {
3821  AddStringForMapping(str, &indsp->station_name);
3822  }
3823  break;
3824  }
3825 
3826  case 0x25: { // variable length produced cargoes
3827  uint8_t num_cargoes = buf.ReadByte();
3828  if (num_cargoes > std::size(indsp->produced_cargo)) {
3829  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
3830  error->param_value[1] = prop;
3831  return CIR_DISABLED;
3832  }
3833  for (size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
3834  if (i < num_cargoes) {
3835  CargoID cargo = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
3836  indsp->produced_cargo[i] = cargo;
3837  } else {
3838  indsp->produced_cargo[i] = INVALID_CARGO;
3839  }
3840  if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] = CT_INVALID;
3841  }
3842  break;
3843  }
3844 
3845  case 0x26: { // variable length accepted cargoes
3846  uint8_t num_cargoes = buf.ReadByte();
3847  if (num_cargoes > std::size(indsp->accepts_cargo)) {
3848  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
3849  error->param_value[1] = prop;
3850  return CIR_DISABLED;
3851  }
3852  for (size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
3853  if (i < num_cargoes) {
3854  CargoID cargo = GetCargoTranslation(buf.ReadByte(), _cur.grffile);
3855  indsp->accepts_cargo[i] = cargo;
3856  } else {
3857  indsp->accepts_cargo[i] = INVALID_CARGO;
3858  }
3859  if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] = CT_INVALID;
3860  }
3861  break;
3862  }
3863 
3864  case 0x27: { // variable length production rates
3865  uint8_t num_cargoes = buf.ReadByte();
3866  if (num_cargoes > lengthof(indsp->production_rate)) {
3867  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
3868  error->param_value[1] = prop;
3869  return CIR_DISABLED;
3870  }
3871  for (uint i = 0; i < lengthof(indsp->production_rate); i++) {
3872  if (i < num_cargoes) {
3873  indsp->production_rate[i] = buf.ReadByte();
3874  } else {
3875  indsp->production_rate[i] = 0;
3876  }
3877  }
3878  break;
3879  }
3880 
3881  case 0x28: { // variable size input/output production multiplier table
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)) {
3885  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
3886  error->param_value[1] = prop;
3887  return CIR_DISABLED;
3888  }
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++) {
3891  uint16_t mult = 0;
3892  if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
3893  indsp->input_cargo_multiplier[i][j] = mult;
3894  }
3895  }
3896  break;
3897  }
3898 
3899  default:
3900  ret = CIR_UNKNOWN;
3901  break;
3902  }
3903  }
3904 
3905  return ret;
3906 }
3907 
3916 static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, ByteReader &buf)
3917 {
3919 
3920  if (airport + numinfo > NUM_AIRPORTS_PER_GRF) {
3921  GrfMsg(1, "AirportChangeInfo: Too many airports, trying id ({}), max ({}). Ignoring.", airport + numinfo, NUM_AIRPORTS_PER_GRF);
3922  return CIR_INVALID_ID;
3923  }
3924 
3925  /* Allocate industry specs if they haven't been allocated already. */
3926  if (_cur.grffile->airportspec.size() < airport + numinfo) _cur.grffile->airportspec.resize(airport + numinfo);
3927 
3928  for (int i = 0; i < numinfo; i++) {
3929  auto &as = _cur.grffile->airportspec[airport + i];
3930 
3931  if (as == nullptr && prop != 0x08 && prop != 0x09) {
3932  GrfMsg(2, "AirportChangeInfo: Attempt to modify undefined airport {}, ignoring", airport + i);
3933  return CIR_INVALID_ID;
3934  }
3935 
3936  switch (prop) {
3937  case 0x08: { // Modify original airport
3938  uint8_t subs_id = buf.ReadByte();
3939  if (subs_id == 0xFF) {
3940  /* Instead of defining a new airport, an airport id
3941  * of 0xFF disables the old airport with the current id. */
3942  AirportSpec::GetWithoutOverride(airport + i)->enabled = false;
3943  continue;
3944  } else if (subs_id >= NEW_AIRPORT_OFFSET) {
3945  /* The substitute id must be one of the original airports. */
3946  GrfMsg(2, "AirportChangeInfo: Attempt to use new airport {} as substitute airport for {}. Ignoring.", subs_id, airport + i);
3947  continue;
3948  }
3949 
3950  /* Allocate space for this airport.
3951  * Only need to do it once. If ever it is called again, it should not
3952  * do anything */
3953  if (as == nullptr) {
3954  as = std::make_unique<AirportSpec>(*AirportSpec::GetWithoutOverride(subs_id));
3955 
3956  as->enabled = true;
3957  as->grf_prop.local_id = airport + i;
3958  as->grf_prop.subst_id = subs_id;
3959  as->grf_prop.grffile = _cur.grffile;
3960  /* override the default airport */
3961  _airport_mngr.Add(airport + i, _cur.grffile->grfid, subs_id);
3962  }
3963  break;
3964  }
3965 
3966  case 0x0A: { // Set airport layout
3967  uint8_t num_layouts = buf.ReadByte();
3968  buf.ReadDWord(); // Total size of definition, unneeded.
3969  uint8_t size_x = 0;
3970  uint8_t size_y = 0;
3971 
3972  std::vector<AirportTileLayout> layouts;
3973  layouts.reserve(num_layouts);
3974 
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); // Rotation can only be DIR_NORTH, DIR_EAST, DIR_SOUTH or DIR_WEST.
3978 
3979  for (;;) {
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) {
3984  /* Convert terminator to our own. */
3985  tile.ti.x = -0x80;
3986  tile.ti.y = 0;
3987  tile.gfx = 0;
3988  break;
3989  }
3990 
3991  tile.gfx = buf.ReadByte();
3992 
3993  if (tile.gfx == 0xFE) {
3994  /* Use a new tile from this GRF */
3995  int local_tile_id = buf.ReadWord();
3996 
3997  /* Read the ID from the _airporttile_mngr. */
3998  uint16_t tempid = _airporttile_mngr.GetID(local_tile_id, _cur.grffile->grfid);
3999 
4000  if (tempid == INVALID_AIRPORTTILE) {
4001  GrfMsg(2, "AirportChangeInfo: Attempt to use airport tile {} with airport id {}, not yet defined. Ignoring.", local_tile_id, airport + i);
4002  } else {
4003  /* Declared as been valid, can be used */
4004  tile.gfx = tempid;
4005  }
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));
4009  }
4010 
4011  /* Determine largest size. */
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);
4015  } else {
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);
4018  }
4019  }
4020  }
4021  as->layouts = std::move(layouts);
4022  as->size_x = size_x;
4023  as->size_y = size_y;
4024  break;
4025  }
4026 
4027  case 0x0C:
4028  as->min_year = buf.ReadWord();
4029  as->max_year = buf.ReadWord();
4030  if (as->max_year == 0xFFFF) as->max_year = CalendarTime::MAX_YEAR;
4031  break;
4032 
4033  case 0x0D:
4034  as->ttd_airport_type = (TTDPAirportType)buf.ReadByte();
4035  break;
4036 
4037  case 0x0E:
4038  as->catchment = Clamp(buf.ReadByte(), 1, MAX_CATCHMENT);
4039  break;
4040 
4041  case 0x0F:
4042  as->noise_level = buf.ReadByte();
4043  break;
4044 
4045  case 0x10:
4046  AddStringForMapping(buf.ReadWord(), &as->name);
4047  break;
4048 
4049  case 0x11: // Maintenance cost factor
4050  as->maintenance_cost = buf.ReadWord();
4051  break;
4052 
4053  default:
4054  ret = CIR_UNKNOWN;
4055  break;
4056  }
4057  }
4058 
4059  return ret;
4060 }
4061 
4069 {
4071 
4072  switch (prop) {
4073  case 0x0B:
4074  case 0x0C:
4075  case 0x0D:
4076  case 0x12:
4077  case 0x14:
4078  case 0x16:
4079  case 0x17:
4080  case 0x18:
4081  buf.ReadByte();
4082  break;
4083 
4084  case 0x09:
4085  case 0x0A:
4086  case 0x10:
4087  case 0x11:
4088  case 0x13:
4089  case 0x15:
4090  buf.ReadWord();
4091  break;
4092 
4093  case 0x08:
4094  case 0x0E:
4095  case 0x0F:
4096  buf.ReadDWord();
4097  break;
4098 
4099  default:
4100  ret = CIR_UNKNOWN;
4101  break;
4102  }
4103 
4104  return ret;
4105 }
4106 
4115 static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
4116 {
4118 
4119  if (id + numinfo > NUM_OBJECTS_PER_GRF) {
4120  GrfMsg(1, "ObjectChangeInfo: Too many objects loaded ({}), max ({}). Ignoring.", id + numinfo, NUM_OBJECTS_PER_GRF);
4121  return CIR_INVALID_ID;
4122  }
4123 
4124  /* Allocate object specs if they haven't been allocated already. */
4125  if (_cur.grffile->objectspec.size() < id + numinfo) _cur.grffile->objectspec.resize(id + numinfo);
4126 
4127  for (int i = 0; i < numinfo; i++) {
4128  auto &spec = _cur.grffile->objectspec[id + i];
4129 
4130  if (prop != 0x08 && spec == nullptr) {
4131  /* If the object property 08 is not yet set, ignore this property */
4132  ChangeInfoResult cir = IgnoreObjectProperty(prop, buf);
4133  if (cir > ret) ret = cir;
4134  continue;
4135  }
4136 
4137  switch (prop) {
4138  case 0x08: { // Class ID
4139  /* Allocate space for this object. */
4140  if (spec == nullptr) {
4141  spec = std::make_unique<ObjectSpec>();
4142  spec->views = 1; // Default for NewGRFs that don't set it.
4143  spec->size = OBJECT_SIZE_1X1; // Default for NewGRFs that manage to not set it (1x1)
4144  }
4145 
4146  /* Swap classid because we read it in BE. */
4147  uint32_t classid = buf.ReadDWord();
4148  spec->class_index = ObjectClass::Allocate(BSWAP32(classid));
4149  break;
4150  }
4151 
4152  case 0x09: { // Class name
4153  AddStringForMapping(buf.ReadWord(), [spec = spec.get()](StringID str) { ObjectClass::Get(spec->class_index)->name = str; });
4154  break;
4155  }
4156 
4157  case 0x0A: // Object name
4158  AddStringForMapping(buf.ReadWord(), &spec->name);
4159  break;
4160 
4161  case 0x0B: // Climate mask
4162  spec->climate = buf.ReadByte();
4163  break;
4164 
4165  case 0x0C: // Size
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);
4169  spec->size = OBJECT_SIZE_1X1;
4170  }
4171  break;
4172 
4173  case 0x0D: // Build cost multipler
4174  spec->build_cost_multiplier = buf.ReadByte();
4175  spec->clear_cost_multiplier = spec->build_cost_multiplier;
4176  break;
4177 
4178  case 0x0E: // Introduction date
4179  spec->introduction_date = buf.ReadDWord();
4180  break;
4181 
4182  case 0x0F: // End of life
4183  spec->end_of_life_date = buf.ReadDWord();
4184  break;
4185 
4186  case 0x10: // Flags
4187  spec->flags = (ObjectFlags)buf.ReadWord();
4188  _loaded_newgrf_features.has_2CC |= (spec->flags & OBJECT_FLAG_2CC_COLOUR) != 0;
4189  break;
4190 
4191  case 0x11: // Animation info
4192  spec->animation.frames = buf.ReadByte();
4193  spec->animation.status = buf.ReadByte();
4194  break;
4195 
4196  case 0x12: // Animation speed
4197  spec->animation.speed = buf.ReadByte();
4198  break;
4199 
4200  case 0x13: // Animation triggers
4201  spec->animation.triggers = buf.ReadWord();
4202  break;
4203 
4204  case 0x14: // Removal cost multiplier
4205  spec->clear_cost_multiplier = buf.ReadByte();
4206  break;
4207 
4208  case 0x15: // Callback mask
4209  spec->callback_mask = buf.ReadWord();
4210  break;
4211 
4212  case 0x16: // Building height
4213  spec->height = buf.ReadByte();
4214  break;
4215 
4216  case 0x17: // Views
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);
4220  spec->views = 1;
4221  }
4222  break;
4223 
4224  case 0x18: // Amount placed on 256^2 map on map creation
4225  spec->generate_amount = buf.ReadByte();
4226  break;
4227 
4228  default:
4229  ret = CIR_UNKNOWN;
4230  break;
4231  }
4232  }
4233 
4234  return ret;
4235 }
4236 
4245 static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
4246 {
4248 
4249  extern RailTypeInfo _railtypes[RAILTYPE_END];
4250 
4251  if (id + numinfo > RAILTYPE_END) {
4252  GrfMsg(1, "RailTypeChangeInfo: Rail type {} is invalid, max {}, ignoring", id + numinfo, RAILTYPE_END);
4253  return CIR_INVALID_ID;
4254  }
4255 
4256  for (int i = 0; i < numinfo; i++) {
4257  RailType rt = _cur.grffile->railtype_map[id + i];
4258  if (rt == INVALID_RAILTYPE) return CIR_INVALID_ID;
4259 
4260  RailTypeInfo *rti = &_railtypes[rt];
4261 
4262  switch (prop) {
4263  case 0x08: // Label of rail type
4264  /* Skipped here as this is loaded during reservation stage. */
4265  buf.ReadDWord();
4266  break;
4267 
4268  case 0x09: { // Toolbar caption of railtype (sets name as well for backwards compatibility for grf ver < 8)
4269  uint16_t str = buf.ReadWord();
4271  if (_cur.grffile->grf_version < 8) {
4272  AddStringForMapping(str, &rti->strings.name);
4273  }
4274  break;
4275  }
4276 
4277  case 0x0A: // Menu text of railtype
4278  AddStringForMapping(buf.ReadWord(), &rti->strings.menu_text);
4279  break;
4280 
4281  case 0x0B: // Build window caption
4282  AddStringForMapping(buf.ReadWord(), &rti->strings.build_caption);
4283  break;
4284 
4285  case 0x0C: // Autoreplace text
4286  AddStringForMapping(buf.ReadWord(), &rti->strings.replace_text);
4287  break;
4288 
4289  case 0x0D: // New locomotive text
4290  AddStringForMapping(buf.ReadWord(), &rti->strings.new_loco);
4291  break;
4292 
4293  case 0x0E: // Compatible railtype list
4294  case 0x0F: // Powered railtype list
4295  case 0x18: // Railtype list required for date introduction
4296  case 0x19: // Introduced railtype list
4297  {
4298  /* Rail type compatibility bits are added to the existing bits
4299  * to allow multiple GRFs to modify compatibility with the
4300  * default rail types. */
4301  int n = buf.ReadByte();
4302  for (int j = 0; j != n; j++) {
4303  RailTypeLabel label = buf.ReadDWord();
4304  RailType resolved_rt = GetRailTypeByLabel(BSWAP32(label), false);
4305  if (resolved_rt != INVALID_RAILTYPE) {
4306  switch (prop) {
4307  case 0x0F: SetBit(rti->powered_railtypes, resolved_rt); [[fallthrough]]; // Powered implies compatible.
4308  case 0x0E: SetBit(rti->compatible_railtypes, resolved_rt); break;
4309  case 0x18: SetBit(rti->introduction_required_railtypes, resolved_rt); break;
4310  case 0x19: SetBit(rti->introduces_railtypes, resolved_rt); break;
4311  }
4312  }
4313  }
4314  break;
4315  }
4316 
4317  case 0x10: // Rail Type flags
4318  rti->flags = (RailTypeFlags)buf.ReadByte();
4319  break;
4320 
4321  case 0x11: // Curve speed advantage
4322  rti->curve_speed = buf.ReadByte();
4323  break;
4324 
4325  case 0x12: // Station graphic
4326  rti->fallback_railtype = Clamp(buf.ReadByte(), 0, 2);
4327  break;
4328 
4329  case 0x13: // Construction cost factor
4330  rti->cost_multiplier = buf.ReadWord();
4331  break;
4332 
4333  case 0x14: // Speed limit
4334  rti->max_speed = buf.ReadWord();
4335  break;
4336 
4337  case 0x15: // Acceleration model
4338  rti->acceleration_type = Clamp(buf.ReadByte(), 0, 2);
4339  break;
4340 
4341  case 0x16: // Map colour
4342  rti->map_colour = buf.ReadByte();
4343  break;
4344 
4345  case 0x17: // Introduction date
4346  rti->introduction_date = buf.ReadDWord();
4347  break;
4348 
4349  case 0x1A: // Sort order
4350  rti->sorting_order = buf.ReadByte();
4351  break;
4352 
4353  case 0x1B: // Name of railtype (overridden by prop 09 for grf ver < 8)
4354  AddStringForMapping(buf.ReadWord(), &rti->strings.name);
4355  break;
4356 
4357  case 0x1C: // Maintenance cost factor
4358  rti->maintenance_multiplier = buf.ReadWord();
4359  break;
4360 
4361  case 0x1D: // Alternate rail type label list
4362  /* Skipped here as this is loaded during reservation stage. */
4363  for (int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4364  break;
4365 
4366  default:
4367  ret = CIR_UNKNOWN;
4368  break;
4369  }
4370  }
4371 
4372  return ret;
4373 }
4374 
4375 static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, ByteReader &buf)
4376 {
4378 
4379  extern RailTypeInfo _railtypes[RAILTYPE_END];
4380 
4381  if (id + numinfo > RAILTYPE_END) {
4382  GrfMsg(1, "RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring", id + numinfo, RAILTYPE_END);
4383  return CIR_INVALID_ID;
4384  }
4385 
4386  for (int i = 0; i < numinfo; i++) {
4387  switch (prop) {
4388  case 0x08: // Label of rail type
4389  {
4390  RailTypeLabel rtl = buf.ReadDWord();
4391  rtl = BSWAP32(rtl);
4392 
4393  RailType rt = GetRailTypeByLabel(rtl, false);
4394  if (rt == INVALID_RAILTYPE) {
4395  /* Set up new rail type */
4396  rt = AllocateRailType(rtl);
4397  }
4398 
4399  _cur.grffile->railtype_map[id + i] = rt;
4400  break;
4401  }
4402 
4403  case 0x09: // Toolbar caption of railtype
4404  case 0x0A: // Menu text
4405  case 0x0B: // Build window caption
4406  case 0x0C: // Autoreplace text
4407  case 0x0D: // New loco
4408  case 0x13: // Construction cost
4409  case 0x14: // Speed limit
4410  case 0x1B: // Name of railtype
4411  case 0x1C: // Maintenance cost factor
4412  buf.ReadWord();
4413  break;
4414 
4415  case 0x1D: // Alternate rail type label list
4416  if (_cur.grffile->railtype_map[id + i] != INVALID_RAILTYPE) {
4417  int n = buf.ReadByte();
4418  for (int j = 0; j != n; j++) {
4419  _railtypes[_cur.grffile->railtype_map[id + i]].alternate_labels.push_back(BSWAP32(buf.ReadDWord()));
4420  }
4421  break;
4422  }
4423  GrfMsg(1, "RailTypeReserveInfo: Ignoring property 1D for rail type {} because no label was set", id + i);
4424  [[fallthrough]];
4425 
4426  case 0x0E: // Compatible railtype list
4427  case 0x0F: // Powered railtype list
4428  case 0x18: // Railtype list required for date introduction
4429  case 0x19: // Introduced railtype list
4430  for (int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4431  break;
4432 
4433  case 0x10: // Rail Type flags
4434  case 0x11: // Curve speed advantage
4435  case 0x12: // Station graphic
4436  case 0x15: // Acceleration model
4437  case 0x16: // Map colour
4438  case 0x1A: // Sort order
4439  buf.ReadByte();
4440  break;
4441 
4442  case 0x17: // Introduction date
4443  buf.ReadDWord();
4444  break;
4445 
4446  default:
4447  ret = CIR_UNKNOWN;
4448  break;
4449  }
4450  }
4451 
4452  return ret;
4453 }
4454 
4463 static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf, RoadTramType rtt)
4464 {
4466 
4467  extern RoadTypeInfo _roadtypes[ROADTYPE_END];
4468  RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
4469 
4470  if (id + numinfo > ROADTYPE_END) {
4471  GrfMsg(1, "RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring", id + numinfo, ROADTYPE_END);
4472  return CIR_INVALID_ID;
4473  }
4474 
4475  for (int i = 0; i < numinfo; i++) {
4476  RoadType rt = type_map[id + i];
4477  if (rt == INVALID_ROADTYPE) return CIR_INVALID_ID;
4478 
4479  RoadTypeInfo *rti = &_roadtypes[rt];
4480 
4481  switch (prop) {
4482  case 0x08: // Label of road type
4483  /* Skipped here as this is loaded during reservation stage. */
4484  buf.ReadDWord();
4485  break;
4486 
4487  case 0x09: { // Toolbar caption of roadtype (sets name as well for backwards compatibility for grf ver < 8)
4488  uint16_t str = buf.ReadWord();
4490  break;
4491  }
4492 
4493  case 0x0A: // Menu text of roadtype
4494  AddStringForMapping(buf.ReadWord(), &rti->strings.menu_text);
4495  break;
4496 
4497  case 0x0B: // Build window caption
4498  AddStringForMapping(buf.ReadWord(), &rti->strings.build_caption);
4499  break;
4500 
4501  case 0x0C: // Autoreplace text
4502  AddStringForMapping(buf.ReadWord(), &rti->strings.replace_text);
4503  break;
4504 
4505  case 0x0D: // New engine text
4506  AddStringForMapping(buf.ReadWord(), &rti->strings.new_engine);
4507  break;
4508 
4509  case 0x0F: // Powered roadtype list
4510  case 0x18: // Roadtype list required for date introduction
4511  case 0x19: { // Introduced roadtype list
4512  /* Road type compatibility bits are added to the existing bits
4513  * to allow multiple GRFs to modify compatibility with the
4514  * default road types. */
4515  int n = buf.ReadByte();
4516  for (int j = 0; j != n; j++) {
4517  RoadTypeLabel label = buf.ReadDWord();
4518  RoadType resolved_rt = GetRoadTypeByLabel(BSWAP32(label), false);
4519  if (resolved_rt != INVALID_ROADTYPE) {
4520  switch (prop) {
4521  case 0x0F:
4522  if (GetRoadTramType(resolved_rt) == rtt) {
4523  SetBit(rti->powered_roadtypes, resolved_rt);
4524  } else {
4525  GrfMsg(1, "RoadTypeChangeInfo: Powered road type list: Road type {} road/tram type does not match road type {}, ignoring", resolved_rt, rt);
4526  }
4527  break;
4528  case 0x18: SetBit(rti->introduction_required_roadtypes, resolved_rt); break;
4529  case 0x19: SetBit(rti->introduces_roadtypes, resolved_rt); break;
4530  }
4531  }
4532  }
4533  break;
4534  }
4535 
4536  case 0x10: // Road Type flags
4537  rti->flags = (RoadTypeFlags)buf.ReadByte();
4538  break;
4539 
4540  case 0x13: // Construction cost factor
4541  rti->cost_multiplier = buf.ReadWord();
4542  break;
4543 
4544  case 0x14: // Speed limit
4545  rti->max_speed = buf.ReadWord();
4546  break;
4547 
4548  case 0x16: // Map colour
4549  rti->map_colour = buf.ReadByte();
4550  break;
4551 
4552  case 0x17: // Introduction date
4553  rti->introduction_date = buf.ReadDWord();
4554  break;
4555 
4556  case 0x1A: // Sort order
4557  rti->sorting_order = buf.ReadByte();
4558  break;
4559 
4560  case 0x1B: // Name of roadtype
4561  AddStringForMapping(buf.ReadWord(), &rti->strings.name);
4562  break;
4563 
4564  case 0x1C: // Maintenance cost factor
4565  rti->maintenance_multiplier = buf.ReadWord();
4566  break;
4567 
4568  case 0x1D: // Alternate road type label list
4569  /* Skipped here as this is loaded during reservation stage. */
4570  for (int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4571  break;
4572 
4573  default:
4574  ret = CIR_UNKNOWN;
4575  break;
4576  }
4577  }
4578 
4579  return ret;
4580 }
4581 
4582 static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
4583 {
4584  return RoadTypeChangeInfo(id, numinfo, prop, buf, RTT_ROAD);
4585 }
4586 
4587 static ChangeInfoResult TramTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
4588 {
4589  return RoadTypeChangeInfo(id, numinfo, prop, buf, RTT_TRAM);
4590 }
4591 
4592 
4593 static ChangeInfoResult RoadTypeReserveInfo(uint id, int numinfo, int prop, ByteReader &buf, RoadTramType rtt)
4594 {
4596 
4597  extern RoadTypeInfo _roadtypes[ROADTYPE_END];
4598  RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
4599 
4600  if (id + numinfo > ROADTYPE_END) {
4601  GrfMsg(1, "RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring", id + numinfo, ROADTYPE_END);
4602  return CIR_INVALID_ID;
4603  }
4604 
4605  for (int i = 0; i < numinfo; i++) {
4606  switch (prop) {
4607  case 0x08: { // Label of road type
4608  RoadTypeLabel rtl = buf.ReadDWord();
4609  rtl = BSWAP32(rtl);
4610 
4611  RoadType rt = GetRoadTypeByLabel(rtl, false);
4612  if (rt == INVALID_ROADTYPE) {
4613  /* Set up new road type */
4614  rt = AllocateRoadType(rtl, rtt);
4615  } else if (GetRoadTramType(rt) != rtt) {
4616  GrfMsg(1, "RoadTypeReserveInfo: Road type {} is invalid type (road/tram), ignoring", id + numinfo);
4617  return CIR_INVALID_ID;
4618  }
4619 
4620  type_map[id + i] = rt;
4621  break;
4622  }
4623  case 0x09: // Toolbar caption of roadtype
4624  case 0x0A: // Menu text
4625  case 0x0B: // Build window caption
4626  case 0x0C: // Autoreplace text
4627  case 0x0D: // New loco
4628  case 0x13: // Construction cost
4629  case 0x14: // Speed limit
4630  case 0x1B: // Name of roadtype
4631  case 0x1C: // Maintenance cost factor
4632  buf.ReadWord();
4633  break;
4634 
4635  case 0x1D: // Alternate road type label list
4636  if (type_map[id + i] != INVALID_ROADTYPE) {
4637  int n = buf.ReadByte();
4638  for (int j = 0; j != n; j++) {
4639  _roadtypes[type_map[id + i]].alternate_labels.push_back(BSWAP32(buf.ReadDWord()));
4640  }
4641  break;
4642  }
4643  GrfMsg(1, "RoadTypeReserveInfo: Ignoring property 1D for road type {} because no label was set", id + i);
4644  /* FALL THROUGH */
4645 
4646  case 0x0F: // Powered roadtype list
4647  case 0x18: // Roadtype list required for date introduction
4648  case 0x19: // Introduced roadtype list
4649  for (int j = buf.ReadByte(); j != 0; j--) buf.ReadDWord();
4650  break;
4651 
4652  case 0x10: // Road Type flags
4653  case 0x16: // Map colour
4654  case 0x1A: // Sort order
4655  buf.ReadByte();
4656  break;
4657 
4658  case 0x17: // Introduction date
4659  buf.ReadDWord();
4660  break;
4661 
4662  default:
4663  ret = CIR_UNKNOWN;
4664  break;
4665  }
4666  }
4667 
4668  return ret;
4669 }
4670 
4671 static ChangeInfoResult RoadTypeReserveInfo(uint id, int numinfo, int prop, ByteReader &buf)
4672 {
4673  return RoadTypeReserveInfo(id, numinfo, prop, buf, RTT_ROAD);
4674 }
4675 
4676 static ChangeInfoResult TramTypeReserveInfo(uint id, int numinfo, int prop, ByteReader &buf)
4677 {
4678  return RoadTypeReserveInfo(id, numinfo, prop, buf, RTT_TRAM);
4679 }
4680 
4681 static ChangeInfoResult AirportTilesChangeInfo(uint airtid, int numinfo, int prop, ByteReader &buf)
4682 {
4684 
4685  if (airtid + numinfo > NUM_AIRPORTTILES_PER_GRF) {
4686  GrfMsg(1, "AirportTileChangeInfo: Too many airport tiles loaded ({}), max ({}). Ignoring.", airtid + numinfo, NUM_AIRPORTTILES_PER_GRF);
4687  return CIR_INVALID_ID;
4688  }
4689 
4690  /* Allocate airport tile specs if they haven't been allocated already. */
4691  if (_cur.grffile->airtspec.size() < airtid + numinfo) _cur.grffile->airtspec.resize(airtid + numinfo);
4692 
4693  for (int i = 0; i < numinfo; i++) {
4694  auto &tsp = _cur.grffile->airtspec[airtid + i];
4695 
4696  if (prop != 0x08 && tsp == nullptr) {
4697  GrfMsg(2, "AirportTileChangeInfo: Attempt to modify undefined airport tile {}. Ignoring.", airtid + i);
4698  return CIR_INVALID_ID;
4699  }
4700 
4701  switch (prop) {
4702  case 0x08: { // Substitute airport tile type
4703  uint8_t subs_id = buf.ReadByte();
4704  if (subs_id >= NEW_AIRPORTTILE_OFFSET) {
4705  /* The substitute id must be one of the original airport tiles. */
4706  GrfMsg(2, "AirportTileChangeInfo: Attempt to use new airport tile {} as substitute airport tile for {}. Ignoring.", subs_id, airtid + i);
4707  continue;
4708  }
4709 
4710  /* Allocate space for this airport tile. */
4711  if (tsp == nullptr) {
4712  tsp = std::make_unique<AirportTileSpec>(*AirportTileSpec::Get(subs_id));
4713 
4714  tsp->enabled = true;
4715 
4716  tsp->animation.status = ANIM_STATUS_NO_ANIMATION;
4717 
4718  tsp->grf_prop.local_id = airtid + i;
4719  tsp->grf_prop.subst_id = subs_id;
4720  tsp->grf_prop.grffile = _cur.grffile;
4721  _airporttile_mngr.AddEntityID(airtid + i, _cur.grffile->grfid, subs_id); // pre-reserve the tile slot
4722  }
4723  break;
4724  }
4725 
4726  case 0x09: { // Airport tile override
4727  uint8_t override = buf.ReadByte();
4728 
4729  /* The airport tile being overridden must be an original airport tile. */
4730  if (override >= NEW_AIRPORTTILE_OFFSET) {
4731  GrfMsg(2, "AirportTileChangeInfo: Attempt to override new airport tile {} with airport tile id {}. Ignoring.", override, airtid + i);
4732  continue;
4733  }
4734 
4735  _airporttile_mngr.Add(airtid + i, _cur.grffile->grfid, override);
4736  break;
4737  }
4738 
4739  case 0x0E: // Callback mask
4740  tsp->callback_mask = buf.ReadByte();
4741  break;
4742 
4743  case 0x0F: // Animation information
4744  tsp->animation.frames = buf.ReadByte();
4745  tsp->animation.status = buf.ReadByte();
4746  break;
4747 
4748  case 0x10: // Animation speed
4749  tsp->animation.speed = buf.ReadByte();
4750  break;
4751 
4752  case 0x11: // Animation triggers
4753  tsp->animation.triggers = buf.ReadByte();
4754  break;
4755 
4756  default:
4757  ret = CIR_UNKNOWN;
4758  break;
4759  }
4760  }
4761 
4762  return ret;
4763 }
4764 
4772 {
4774 
4775  switch (prop) {
4776  case 0x09:
4777  case 0x0C:
4778  case 0x0F:
4779  case 0x11:
4780  buf.ReadByte();
4781  break;
4782 
4783  case 0x0A:
4784  case 0x0B:
4785  case 0x0E:
4786  case 0x10:
4787  case 0x15:
4788  buf.ReadWord();
4789  break;
4790 
4791  case 0x08:
4792  case 0x0D:
4793  case 0x12:
4794  buf.ReadDWord();
4795  break;
4796 
4797  default:
4798  ret = CIR_UNKNOWN;
4799  break;
4800  }
4801 
4802  return ret;
4803 }
4804 
4805 static ChangeInfoResult RoadStopChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
4806 {
4808 
4809  if (id + numinfo > NUM_ROADSTOPS_PER_GRF) {
4810  GrfMsg(1, "RoadStopChangeInfo: RoadStop {} is invalid, max {}, ignoring", id + numinfo, NUM_ROADSTOPS_PER_GRF);
4811  return CIR_INVALID_ID;
4812  }
4813 
4814  if (_cur.grffile->roadstops.size() < id + numinfo) _cur.grffile->roadstops.resize(id + numinfo);
4815 
4816  for (int i = 0; i < numinfo; i++) {
4817  auto &rs = _cur.grffile->roadstops[id + i];
4818 
4819  if (rs == nullptr && prop != 0x08) {
4820  GrfMsg(1, "RoadStopChangeInfo: Attempt to modify undefined road stop {}, ignoring", id + i);
4821  ChangeInfoResult cir = IgnoreRoadStopProperty(prop, buf);
4822  if (cir > ret) ret = cir;
4823  continue;
4824  }
4825 
4826  switch (prop) {
4827  case 0x08: { // Road Stop Class ID
4828  if (rs == nullptr) {
4829  rs = std::make_unique<RoadStopSpec>();
4830  }
4831 
4832  uint32_t classid = buf.ReadDWord();
4833  rs->class_index = RoadStopClass::Allocate(BSWAP32(classid));
4834  break;
4835  }
4836 
4837  case 0x09: // Road stop type
4838  rs->stop_type = (RoadStopAvailabilityType)buf.ReadByte();
4839  break;
4840 
4841  case 0x0A: // Road Stop Name
4842  AddStringForMapping(buf.ReadWord(), &rs->name);
4843  break;
4844 
4845  case 0x0B: // Road Stop Class name
4846  AddStringForMapping(buf.ReadWord(), [rs = rs.get()](StringID str) { RoadStopClass::Get(rs->class_index)->name = str; });
4847  break;
4848 
4849  case 0x0C: // The draw mode
4850  rs->draw_mode = static_cast<RoadStopDrawMode>(buf.ReadByte());
4851  break;
4852 
4853  case 0x0D: // Cargo types for random triggers
4854  rs->cargo_triggers = TranslateRefitMask(buf.ReadDWord());
4855  break;
4856 
4857  case 0x0E: // Animation info
4858  rs->animation.frames = buf.ReadByte();
4859  rs->animation.status = buf.ReadByte();
4860  break;
4861 
4862  case 0x0F: // Animation speed
4863  rs->animation.speed = buf.ReadByte();
4864  break;
4865 
4866  case 0x10: // Animation triggers
4867  rs->animation.triggers = buf.ReadWord();
4868  break;
4869 
4870  case 0x11: // Callback mask
4871  rs->callback_mask = buf.ReadByte();
4872  break;
4873 
4874  case 0x12: // General flags
4875  rs->flags = (uint16_t)buf.ReadDWord(); // Future-proofing, size this as 4 bytes, but we only need two byte's worth of flags at present
4876  break;
4877 
4878  case 0x15: // Cost multipliers
4879  rs->build_cost_multiplier = buf.ReadByte();
4880  rs->clear_cost_multiplier = buf.ReadByte();
4881  break;
4882 
4883  default:
4884  ret = CIR_UNKNOWN;
4885  break;
4886  }
4887  }
4888 
4889  return ret;
4890 }
4891 
4892 static bool HandleChangeInfoResult(const char *caller, ChangeInfoResult cir, uint8_t feature, uint8_t property)
4893 {
4894  switch (cir) {
4895  default: NOT_REACHED();
4896 
4897  case CIR_DISABLED:
4898  /* Error has already been printed; just stop parsing */
4899  return true;
4900 
4901  case CIR_SUCCESS:
4902  return false;
4903 
4904  case CIR_UNHANDLED:
4905  GrfMsg(1, "{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
4906  return false;
4907 
4908  case CIR_UNKNOWN:
4909  GrfMsg(0, "{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
4910  [[fallthrough]];
4911 
4912  case CIR_INVALID_ID: {
4913  /* No debug message for an invalid ID, as it has already been output */
4914  GRFError *error = DisableGrf(cir == CIR_INVALID_ID ? STR_NEWGRF_ERROR_INVALID_ID : STR_NEWGRF_ERROR_UNKNOWN_PROPERTY);
4915  if (cir != CIR_INVALID_ID) error->param_value[1] = property;
4916  return true;
4917  }
4918  }
4919 }
4920 
4921 /* Action 0x00 */
4922 static void FeatureChangeInfo(ByteReader &buf)
4923 {
4924  /* <00> <feature> <num-props> <num-info> <id> (<property <new-info>)...
4925  *
4926  * B feature
4927  * B num-props how many properties to change per vehicle/station
4928  * B num-info how many vehicles/stations to change
4929  * E id ID of first vehicle/station to change, if num-info is
4930  * greater than one, this one and the following
4931  * vehicles/stations will be changed
4932  * B property what property to change, depends on the feature
4933  * V new-info new bytes of info (variable size; depends on properties) */
4934 
4935  static const VCI_Handler handler[] = {
4936  /* GSF_TRAINS */ RailVehicleChangeInfo,
4937  /* GSF_ROADVEHICLES */ RoadVehicleChangeInfo,
4938  /* GSF_SHIPS */ ShipVehicleChangeInfo,
4939  /* GSF_AIRCRAFT */ AircraftVehicleChangeInfo,
4940  /* GSF_STATIONS */ StationChangeInfo,
4941  /* GSF_CANALS */ CanalChangeInfo,
4942  /* GSF_BRIDGES */ BridgeChangeInfo,
4943  /* GSF_HOUSES */ TownHouseChangeInfo,
4944  /* GSF_GLOBALVAR */ GlobalVarChangeInfo,
4945  /* GSF_INDUSTRYTILES */ IndustrytilesChangeInfo,
4946  /* GSF_INDUSTRIES */ IndustriesChangeInfo,
4947  /* GSF_CARGOES */ nullptr, // Cargo is handled during reservation
4948  /* GSF_SOUNDFX */ SoundEffectChangeInfo,
4949  /* GSF_AIRPORTS */ AirportChangeInfo,
4950  /* GSF_SIGNALS */ nullptr,
4951  /* GSF_OBJECTS */ ObjectChangeInfo,
4952  /* GSF_RAILTYPES */ RailTypeChangeInfo,
4953  /* GSF_AIRPORTTILES */ AirportTilesChangeInfo,
4954  /* GSF_ROADTYPES */ RoadTypeChangeInfo,
4955  /* GSF_TRAMTYPES */ TramTypeChangeInfo,
4956  /* GSF_ROADSTOPS */ RoadStopChangeInfo,
4957  };
4958  static_assert(GSF_END == lengthof(handler));
4959 
4960  uint8_t feature = buf.ReadByte();
4961  uint8_t numprops = buf.ReadByte();
4962  uint numinfo = buf.ReadByte();
4963  uint engine = buf.ReadExtendedByte();
4964 
4965  if (feature >= GSF_END) {
4966  GrfMsg(1, "FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4967  return;
4968  }
4969 
4970  GrfMsg(6, "FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
4971  feature, numprops, engine, numinfo);
4972 
4973  if (handler[feature] == nullptr) {
4974  if (feature != GSF_CARGOES) GrfMsg(1, "FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
4975  return;
4976  }
4977 
4978  /* Mark the feature as used by the grf */
4979  SetBit(_cur.grffile->grf_features, feature);
4980 
4981  while (numprops-- && buf.HasData()) {
4982  uint8_t prop = buf.ReadByte();
4983 
4984  ChangeInfoResult cir = handler[feature](engine, numinfo, prop, buf);
4985  if (HandleChangeInfoResult("FeatureChangeInfo", cir, feature, prop)) return;
4986  }
4987 }
4988 
4989 /* Action 0x00 (GLS_SAFETYSCAN) */
4990 static void SafeChangeInfo(ByteReader &buf)
4991 {
4992  uint8_t feature = buf.ReadByte();
4993  uint8_t numprops = buf.ReadByte();
4994  uint numinfo = buf.ReadByte();
4995  buf.ReadExtendedByte(); // id
4996 
4997  if (feature == GSF_BRIDGES && numprops == 1) {
4998  uint8_t prop = buf.ReadByte();
4999  /* Bridge property 0x0D is redefinition of sprite layout tables, which
5000  * is considered safe. */
5001  if (prop == 0x0D) return;
5002  } else if (feature == GSF_GLOBALVAR && numprops == 1) {
5003  uint8_t prop = buf.ReadByte();
5004  /* Engine ID Mappings are safe, if the source is static */
5005  if (prop == 0x11) {
5006  bool is_safe = true;
5007  for (uint i = 0; i < numinfo; i++) {
5008  uint32_t s = buf.ReadDWord();
5009  buf.ReadDWord(); // dest
5010  const GRFConfig *grfconfig = GetGRFConfig(s);
5011  if (grfconfig != nullptr && !HasBit(grfconfig->flags, GCF_STATIC)) {
5012  is_safe = false;
5013  break;
5014  }
5015  }
5016  if (is_safe) return;
5017  }
5018  }
5019 
5020  SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
5021 
5022  /* Skip remainder of GRF */
5023  _cur.skip_sprites = -1;
5024 }
5025 
5026 /* Action 0x00 (GLS_RESERVE) */
5027 static void ReserveChangeInfo(ByteReader &buf)
5028 {
5029  uint8_t feature = buf.ReadByte();
5030 
5031  if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES) return;
5032 
5033  uint8_t numprops = buf.ReadByte();
5034  uint8_t numinfo = buf.ReadByte();
5035  uint8_t index = buf.ReadExtendedByte();
5036 
5037  while (numprops-- && buf.HasData()) {
5038  uint8_t prop = buf.ReadByte();
5040 
5041  switch (feature) {
5042  default: NOT_REACHED();
5043  case GSF_CARGOES:
5044  cir = CargoChangeInfo(index, numinfo, prop, buf);
5045  break;
5046 
5047  case GSF_GLOBALVAR:
5048  cir = GlobalVarReserveInfo(index, numinfo, prop, buf);
5049  break;
5050 
5051  case GSF_RAILTYPES:
5052  cir = RailTypeReserveInfo(index, numinfo, prop, buf);
5053  break;
5054 
5055  case GSF_ROADTYPES:
5056  cir = RoadTypeReserveInfo(index, numinfo, prop, buf);
5057  break;
5058 
5059  case GSF_TRAMTYPES:
5060  cir = TramTypeReserveInfo(index, numinfo, prop, buf);
5061  break;
5062  }
5063 
5064  if (HandleChangeInfoResult("ReserveChangeInfo", cir, feature, prop)) return;
5065  }
5066 }
5067 
5068 /* Action 0x01 */
5069 static void NewSpriteSet(ByteReader &buf)
5070 {
5071  /* Basic format: <01> <feature> <num-sets> <num-ent>
5072  * Extended format: <01> <feature> 00 <first-set> <num-sets> <num-ent>
5073  *
5074  * B feature feature to define sprites for
5075  * 0, 1, 2, 3: veh-type, 4: train stations
5076  * E first-set first sprite set to define
5077  * B num-sets number of sprite sets (extended byte in extended format)
5078  * E num-ent how many entries per sprite set
5079  * For vehicles, this is the number of different
5080  * vehicle directions in each sprite set
5081  * Set num-dirs=8, unless your sprites are symmetric.
5082  * In that case, use num-dirs=4.
5083  */
5084 
5085  uint8_t feature = buf.ReadByte();
5086  uint16_t num_sets = buf.ReadByte();
5087  uint16_t first_set = 0;
5088 
5089  if (num_sets == 0 && buf.HasData(3)) {
5090  /* Extended Action1 format.
5091  * Some GRFs define zero sets of zero sprites, though there is actually no use in that. Ignore them. */
5092  first_set = buf.ReadExtendedByte();
5093  num_sets = buf.ReadExtendedByte();
5094  }
5095  uint16_t num_ents = buf.ReadExtendedByte();
5096 
5097  if (feature >= GSF_END) {
5098  _cur.skip_sprites = num_sets * num_ents;
5099  GrfMsg(1, "NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.skip_sprites);
5100  return;
5101  }
5102 
5103  _cur.AddSpriteSets(feature, _cur.spriteid, first_set, num_sets, num_ents);
5104 
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
5107  );
5108 
5109  for (int i = 0; i < num_sets * num_ents; i++) {
5110  _cur.nfo_line++;
5111  LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line);
5112  }
5113 }
5114 
5115 /* Action 0x01 (SKIP) */
5116 static void SkipAct1(ByteReader &buf)
5117 {
5118  buf.ReadByte();
5119  uint16_t num_sets = buf.ReadByte();
5120 
5121  if (num_sets == 0 && buf.HasData(3)) {
5122  /* Extended Action1 format.
5123  * Some GRFs define zero sets of zero sprites, though there is actually no use in that. Ignore them. */
5124  buf.ReadExtendedByte(); // first_set
5125  num_sets = buf.ReadExtendedByte();
5126  }
5127  uint16_t num_ents = buf.ReadExtendedByte();
5128 
5129  _cur.skip_sprites = num_sets * num_ents;
5130 
5131  GrfMsg(3, "SkipAct1: Skipping {} sprites", _cur.skip_sprites);
5132 }
5133 
5134 /* Helper function to either create a callback or link to a previously
5135  * defined spritegroup. */
5136 static const SpriteGroup *GetGroupFromGroupID(uint8_t setid, uint8_t type, uint16_t groupid)
5137 {
5138  if (HasBit(groupid, 15)) {
5140  return new CallbackResultSpriteGroup(groupid, _cur.grffile->grf_version >= 8);
5141  }
5142 
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);
5145  return nullptr;
5146  }
5147 
5148  return _cur.spritegroups[groupid];
5149 }
5150 
5159 static const SpriteGroup *CreateGroupFromGroupID(uint8_t feature, uint8_t setid, uint8_t type, uint16_t spriteid)
5160 {
5161  if (HasBit(spriteid, 15)) {
5163  return new CallbackResultSpriteGroup(spriteid, _cur.grffile->grf_version >= 8);
5164  }
5165 
5166  if (!_cur.IsValidSpriteSet(feature, spriteid)) {
5167  GrfMsg(1, "CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
5168  return nullptr;
5169  }
5170 
5171  SpriteID spriteset_start = _cur.GetSprite(feature, spriteid);
5172  uint num_sprites = _cur.GetNumEnts(feature, spriteid);
5173 
5174  /* Ensure that the sprites are loeded */
5175  assert(spriteset_start + num_sprites <= _cur.spriteid);
5176 
5178  return new ResultSpriteGroup(spriteset_start, num_sprites);
5179 }
5180 
5181 /* Action 0x02 */
5182 static void NewSpriteGroup(ByteReader &buf)
5183 {
5184  /* <02> <feature> <set-id> <type/num-entries> <feature-specific-data...>
5185  *
5186  * B feature see action 1
5187  * B set-id ID of this particular definition
5188  * B type/num-entries
5189  * if 80 or greater, this is a randomized or variational
5190  * list definition, see below
5191  * otherwise it specifies a number of entries, the exact
5192  * meaning depends on the feature
5193  * V feature-specific-data (huge mess, don't even look it up --pasky) */
5194  const SpriteGroup *act_group = nullptr;
5195 
5196  uint8_t feature = buf.ReadByte();
5197  if (feature >= GSF_END) {
5198  GrfMsg(1, "NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5199  return;
5200  }
5201 
5202  uint8_t setid = buf.ReadByte();
5203  uint8_t type = buf.ReadByte();
5204 
5205  /* Sprite Groups are created here but they are allocated from a pool, so
5206  * we do not need to delete anything if there is an exception from the
5207  * ByteReader. */
5208 
5209  switch (type) {
5210  /* Deterministic Sprite Group */
5211  case 0x81: // Self scope, byte
5212  case 0x82: // Parent scope, byte
5213  case 0x85: // Self scope, word
5214  case 0x86: // Parent scope, word
5215  case 0x89: // Self scope, dword
5216  case 0x8A: // Parent scope, dword
5217  {
5218  uint8_t varadjust;
5219  uint8_t varsize;
5220 
5223  group->nfo_line = _cur.nfo_line;
5224  act_group = group;
5225  group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
5226 
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;
5232  }
5233 
5234  /* Loop through the var adjusts. Unfortunately we don't know how many we have
5235  * from the outset, so we shall have to keep reallocing. */
5236  do {
5237  DeterministicSpriteGroupAdjust &adjust = group->adjusts.emplace_back();
5238 
5239  /* The first var adjust doesn't have an operation specified, so we set it to add. */
5240  adjust.operation = group->adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf.ReadByte();
5241  adjust.variable = buf.ReadByte();
5242  if (adjust.variable == 0x7E) {
5243  /* Link subroutine group */
5244  adjust.subroutine = GetGroupFromGroupID(setid, type, buf.ReadByte());
5245  } else {
5246  adjust.parameter = IsInsideMM(adjust.variable, 0x60, 0x80) ? buf.ReadByte() : 0;
5247  }
5248 
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);
5253 
5254  if (adjust.type != DSGA_TYPE_NONE) {
5255  adjust.add_val = buf.ReadVarSize(varsize);
5256  adjust.divmod_val = buf.ReadVarSize(varsize);
5257  } else {
5258  adjust.add_val = 0;
5259  adjust.divmod_val = 0;
5260  }
5261 
5262  /* Continue reading var adjusts while bit 5 is set. */
5263  } while (HasBit(varadjust, 5));
5264 
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);
5271  }
5272 
5273  group->default_group = GetGroupFromGroupID(setid, type, buf.ReadWord());
5274  group->error_group = ranges.empty() ? group->default_group : ranges[0].group;
5275  /* nvar == 0 is a special case -- we turn our value into a callback result */
5276  group->calculated_result = ranges.empty();
5277 
5278  /* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
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);
5284  }
5285  std::sort(bounds.begin(), bounds.end());
5286  bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
5287 
5288  std::vector<const SpriteGroup *> target;
5289  target.reserve(bounds.size());
5290  for (const auto &bound : bounds) {
5291  const SpriteGroup *t = group->default_group;
5292  for (const auto &range : ranges) {
5293  if (range.low <= bound && bound <= range.high) {
5294  t = range.group;
5295  break;
5296  }
5297  }
5298  target.push_back(t);
5299  }
5300  assert(target.size() == bounds.size());
5301 
5302  for (uint j = 0; j < bounds.size(); ) {
5303  if (target[j] != group->default_group) {
5304  DeterministicSpriteGroupRange &r = group->ranges.emplace_back();
5305  r.group = target[j];
5306  r.low = bounds[j];
5307  while (j < bounds.size() && target[j] == r.group) {
5308  j++;
5309  }
5310  r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
5311  } else {
5312  j++;
5313  }
5314  }
5315 
5316  break;
5317  }
5318 
5319  /* Randomized Sprite Group */
5320  case 0x80: // Self scope
5321  case 0x83: // Parent scope
5322  case 0x84: // Relative scope
5323  {
5326  group->nfo_line = _cur.nfo_line;
5327  act_group = group;
5328  group->var_scope = HasBit(type, 1) ? VSG_SCOPE_PARENT : VSG_SCOPE_SELF;
5329 
5330  if (HasBit(type, 2)) {
5331  if (feature <= GSF_AIRCRAFT) group->var_scope = VSG_SCOPE_RELATIVE;
5332  group->count = buf.ReadByte();
5333  }
5334 
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;
5338  group->lowest_randbit = buf.ReadByte();
5339 
5340  uint8_t num_groups = buf.ReadByte();
5341  if (!HasExactlyOneBit(num_groups)) {
5342  GrfMsg(1, "NewSpriteGroup: Random Action 2 nrand should be power of 2");
5343  }
5344 
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()));
5348  }
5349 
5350  break;
5351  }
5352 
5353  /* Neither a variable or randomized sprite group... must be a real group */
5354  default:
5355  {
5356  switch (feature) {
5357  case GSF_TRAINS:
5358  case GSF_ROADVEHICLES:
5359  case GSF_SHIPS:
5360  case GSF_AIRCRAFT:
5361  case GSF_STATIONS:
5362  case GSF_CANALS:
5363  case GSF_CARGOES:
5364  case GSF_AIRPORTS:
5365  case GSF_RAILTYPES:
5366  case GSF_ROADTYPES:
5367  case GSF_TRAMTYPES:
5368  {
5369  uint8_t num_loaded = type;
5370  uint8_t num_loading = buf.ReadByte();
5371 
5372  if (!_cur.HasValidSpriteSets(feature)) {
5373  GrfMsg(0, "NewSpriteGroup: No sprite set to work on! Skipping");
5374  return;
5375  }
5376 
5377  GrfMsg(6, "NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
5378  setid, num_loaded, num_loading);
5379 
5380  if (num_loaded + num_loading == 0) {
5381  GrfMsg(1, "NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
5382  break;
5383  }
5384 
5385  if (num_loaded + num_loading == 1) {
5386  /* Avoid creating 'Real' sprite group if only one option. */
5387  uint16_t spriteid = buf.ReadWord();
5388  act_group = CreateGroupFromGroupID(feature, setid, type, spriteid);
5389  GrfMsg(8, "NewSpriteGroup: one result, skipping RealSpriteGroup = subset {}", spriteid);
5390  break;
5391  }
5392 
5393  std::vector<uint16_t> loaded;
5394  std::vector<uint16_t> loading;
5395 
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]);
5400  }
5401 
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]);
5406  }
5407 
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]) {
5411  /* Both lists only contain the same value, so don't create 'Real' sprite group */
5412  act_group = CreateGroupFromGroupID(feature, setid, type, loaded[0]);
5413  GrfMsg(8, "NewSpriteGroup: same result, skipping RealSpriteGroup = subset {}", loaded[0]);
5414  break;
5415  }
5416 
5418  RealSpriteGroup *group = new RealSpriteGroup();
5419  group->nfo_line = _cur.nfo_line;
5420  act_group = group;
5421 
5422  if (loaded_same && loaded.size() > 1) loaded.resize(1);
5423  group->loaded.reserve(loaded.size());
5424  for (uint16_t spriteid : loaded) {
5425  const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid);
5426  group->loaded.push_back(t);
5427  }
5428 
5429  if (loading_same && loading.size() > 1) loading.resize(1);
5430  group->loading.reserve(loading.size());
5431  for (uint16_t spriteid : loading) {
5432  const SpriteGroup *t = CreateGroupFromGroupID(feature, setid, type, spriteid);
5433  group->loading.push_back(t);
5434  }
5435 
5436  break;
5437  }
5438 
5439  case GSF_HOUSES:
5440  case GSF_AIRPORTTILES:
5441  case GSF_OBJECTS:
5442  case GSF_INDUSTRYTILES:
5443  case GSF_ROADSTOPS: {
5444  uint8_t num_building_sprites = std::max((uint8_t)1, type);
5445 
5448  group->nfo_line = _cur.nfo_line;
5449  act_group = group;
5450 
5451  /* On error, bail out immediately. Temporary GRF data was already freed */
5452  if (ReadSpriteLayout(buf, num_building_sprites, true, feature, false, type == 0, &group->dts)) return;
5453  break;
5454  }
5455 
5456  case GSF_INDUSTRIES: {
5457  if (type > 2) {
5458  GrfMsg(1, "NewSpriteGroup: Unsupported industry production version {}, skipping", type);
5459  break;
5460  }
5461 
5464  group->nfo_line = _cur.nfo_line;
5465  act_group = group;
5466  group->version = type;
5467  if (type == 0) {
5469  for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) {
5470  group->subtract_input[i] = (int16_t)buf.ReadWord(); // signed
5471  }
5473  for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_OUTPUTS; i++) {
5474  group->add_output[i] = buf.ReadWord(); // unsigned
5475  }
5476  group->again = buf.ReadByte();
5477  } else if (type == 1) {
5479  for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_INPUTS; i++) {
5480  group->subtract_input[i] = buf.ReadByte();
5481  }
5483  for (uint i = 0; i < INDUSTRY_ORIGINAL_NUM_OUTPUTS; i++) {
5484  group->add_output[i] = buf.ReadByte();
5485  }
5486  group->again = buf.ReadByte();
5487  } else if (type == 2) {
5488  group->num_input = buf.ReadByte();
5489  if (group->num_input > lengthof(group->subtract_input)) {
5490  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
5491  error->data = "too many inputs (max 16)";
5492  return;
5493  }
5494  for (uint i = 0; i < group->num_input; i++) {
5495  uint8_t rawcargo = buf.ReadByte();
5496  CargoID cargo = GetCargoTranslation(rawcargo, _cur.grffile);
5497  if (!IsValidCargoID(cargo)) {
5498  /* The mapped cargo is invalid. This is permitted at this point,
5499  * as long as the result is not used. Mark it invalid so this
5500  * can be tested later. */
5501  group->version = 0xFF;
5502  } else if (std::find(group->cargo_input, group->cargo_input + i, cargo) != group->cargo_input + i) {
5503  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
5504  error->data = "duplicate input cargo";
5505  return;
5506  }
5507  group->cargo_input[i] = cargo;
5508  group->subtract_input[i] = buf.ReadByte();
5509  }
5510  group->num_output = buf.ReadByte();
5511  if (group->num_output > lengthof(group->add_output)) {
5512  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
5513  error->data = "too many outputs (max 16)";
5514  return;
5515  }
5516  for (uint i = 0; i < group->num_output; i++) {
5517  uint8_t rawcargo = buf.ReadByte();
5518  CargoID cargo = GetCargoTranslation(rawcargo, _cur.grffile);
5519  if (!IsValidCargoID(cargo)) {
5520  /* Mark this result as invalid to use */
5521  group->version = 0xFF;
5522  } else if (std::find(group->cargo_output, group->cargo_output + i, cargo) != group->cargo_output + i) {
5523  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_INDPROD_CALLBACK);
5524  error->data = "duplicate output cargo";
5525  return;
5526  }
5527  group->cargo_output[i] = cargo;
5528  group->add_output[i] = buf.ReadByte();
5529  }
5530  group->again = buf.ReadByte();
5531  } else {
5532  NOT_REACHED();
5533  }
5534  break;
5535  }
5536 
5537  /* Loading of Tile Layout and Production Callback groups would happen here */
5538  default: GrfMsg(1, "NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
5539  }
5540  }
5541  }
5542 
5543  _cur.spritegroups[setid] = act_group;
5544 }
5545 
5546 static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
5547 {
5548  /* Special cargo types for purchase list and stations */
5549  if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return SpriteGroupCargo::SG_DEFAULT_NA;
5550  if (ctype == 0xFF) return SpriteGroupCargo::SG_PURCHASE;
5551 
5552  /* Check if the cargo type is out of bounds of the cargo translation table */
5553  if (ctype >= _cur.grffile->cargo_list.size()) {
5554  GrfMsg(1, "TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (unsigned int)_cur.grffile->cargo_list.size() - 1);
5555  return INVALID_CARGO;
5556  }
5557 
5558  /* Look up the cargo label from the translation table */
5559  CargoLabel cl = _cur.grffile->cargo_list[ctype];
5560  if (cl == CT_INVALID) {
5561  GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
5562  return INVALID_CARGO;
5563  }
5564 
5565  CargoID cid = GetCargoIDByLabel(cl);
5566  if (!IsValidCargoID(cid)) {
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;
5569  }
5570 
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);
5572  return cid;
5573 }
5574 
5575 
5576 static bool IsValidGroupID(uint16_t groupid, const char *function)
5577 {
5578  if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
5579  GrfMsg(1, "{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
5580  return false;
5581  }
5582 
5583  return true;
5584 }
5585 
5586 static void VehicleMapSpriteGroup(ByteReader &buf, uint8_t feature, uint8_t idcount)
5587 {
5588  static std::vector<EngineID> last_engines; // Engine IDs are remembered in case the next action is a wagon override.
5589  bool wagover = false;
5590 
5591  /* Test for 'wagon override' flag */
5592  if (HasBit(idcount, 7)) {
5593  wagover = true;
5594  /* Strip off the flag */
5595  idcount = GB(idcount, 0, 7);
5596 
5597  if (last_engines.empty()) {
5598  GrfMsg(0, "VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
5599  return;
5600  }
5601 
5602  GrfMsg(6, "VehicleMapSpriteGroup: WagonOverride: {} engines, {} wagons", last_engines.size(), idcount);
5603  } else {
5604  last_engines.resize(idcount);
5605  }
5606 
5607  std::vector<EngineID> engines;
5608  engines.reserve(idcount);
5609  for (uint i = 0; i < idcount; i++) {
5610  Engine *e = GetNewEngine(_cur.grffile, (VehicleType)feature, buf.ReadExtendedByte());
5611  if (e == nullptr) {
5612  /* No engine could be allocated?!? Deal with it. Okay,
5613  * this might look bad. Also make sure this NewGRF
5614  * gets disabled, as a half loaded one is bad. */
5615  HandleChangeInfoResult("VehicleMapSpriteGroup", CIR_INVALID_ID, 0, 0);
5616  return;
5617  }
5618 
5619  engines.push_back(e->index);
5620  if (!wagover) last_engines[i] = engines[i];
5621  }
5622 
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;
5628 
5629  GrfMsg(8, "VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
5630 
5631  CargoID cid = TranslateCargo(feature, ctype);
5632  if (!IsValidCargoID(cid)) continue;
5633 
5634  for (uint i = 0; i < idcount; i++) {
5635  EngineID engine = engines[i];
5636 
5637  GrfMsg(7, "VehicleMapSpriteGroup: [{}] Engine {}...", i, engine);
5638 
5639  if (wagover) {
5640  SetWagonOverrideSprites(engine, cid, _cur.spritegroups[groupid], last_engines);
5641  } else {
5642  SetCustomEngineSprites(engine, cid, _cur.spritegroups[groupid]);
5643  }
5644  }
5645  }
5646 
5647  uint16_t groupid = buf.ReadWord();
5648  if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
5649 
5650  GrfMsg(8, "-- Default group id 0x{:04X}", groupid);
5651 
5652  for (uint i = 0; i < idcount; i++) {
5653  EngineID engine = engines[i];
5654 
5655  if (wagover) {
5656  SetWagonOverrideSprites(engine, SpriteGroupCargo::SG_DEFAULT, _cur.spritegroups[groupid], last_engines);
5657  } else {
5658  SetCustomEngineSprites(engine, SpriteGroupCargo::SG_DEFAULT, _cur.spritegroups[groupid]);
5659  SetEngineGRF(engine, _cur.grffile);
5660  }
5661  }
5662 }
5663 
5664 
5665 static void CanalMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5666 {
5667  std::vector<uint16_t> cfs;
5668  cfs.reserve(idcount);
5669  for (uint i = 0; i < idcount; i++) {
5670  cfs.push_back(buf.ReadExtendedByte());
5671  }
5672 
5673  uint8_t cidcount = buf.ReadByte();
5674  buf.Skip(cidcount * 3);
5675 
5676  uint16_t groupid = buf.ReadWord();
5677  if (!IsValidGroupID(groupid, "CanalMapSpriteGroup")) return;
5678 
5679  for (auto &cf : cfs) {
5680  if (cf >= CF_END) {
5681  GrfMsg(1, "CanalMapSpriteGroup: Canal subset {} out of range, skipping", cf);
5682  continue;
5683  }
5684 
5685  _water_feature[cf].grffile = _cur.grffile;
5686  _water_feature[cf].group = _cur.spritegroups[groupid];
5687  }
5688 }
5689 
5690 
5691 static void StationMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5692 {
5693  if (_cur.grffile->stations.empty()) {
5694  GrfMsg(1, "StationMapSpriteGroup: No stations defined, skipping");
5695  return;
5696  }
5697 
5698  std::vector<uint16_t> stations;
5699  stations.reserve(idcount);
5700  for (uint i = 0; i < idcount; i++) {
5701  stations.push_back(buf.ReadExtendedByte());
5702  }
5703 
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;
5709 
5710  ctype = TranslateCargo(GSF_STATIONS, ctype);
5711  if (!IsValidCargoID(ctype)) continue;
5712 
5713  for (auto &station : stations) {
5714  StationSpec *statspec = station >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[station].get();
5715 
5716  if (statspec == nullptr) {
5717  GrfMsg(1, "StationMapSpriteGroup: Station {} undefined, skipping", station);
5718  continue;
5719  }
5720 
5721  statspec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
5722  }
5723  }
5724 
5725  uint16_t groupid = buf.ReadWord();
5726  if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) return;
5727 
5728  for (auto &station : stations) {
5729  StationSpec *statspec = station >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[station].get();
5730 
5731  if (statspec == nullptr) {
5732  GrfMsg(1, "StationMapSpriteGroup: Station {} undefined, skipping", station);
5733  continue;
5734  }
5735 
5736  if (statspec->grf_prop.grffile != nullptr) {
5737  GrfMsg(1, "StationMapSpriteGroup: Station {} mapped multiple times, skipping", station);
5738  continue;
5739  }
5740 
5741  statspec->grf_prop.spritegroup[SpriteGroupCargo::SG_DEFAULT] = _cur.spritegroups[groupid];
5742  statspec->grf_prop.grffile = _cur.grffile;
5743  statspec->grf_prop.local_id = station;
5744  StationClass::Assign(statspec);
5745  }
5746 }
5747 
5748 
5749 static void TownHouseMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5750 {
5751  if (_cur.grffile->housespec.empty()) {
5752  GrfMsg(1, "TownHouseMapSpriteGroup: No houses defined, skipping");
5753  return;
5754  }
5755 
5756  std::vector<uint16_t> houses;
5757  houses.reserve(idcount);
5758  for (uint i = 0; i < idcount; i++) {
5759  houses.push_back(buf.ReadExtendedByte());
5760  }
5761 
5762  /* Skip the cargo type section, we only care about the default group */
5763  uint8_t cidcount = buf.ReadByte();
5764  buf.Skip(cidcount * 3);
5765 
5766  uint16_t groupid = buf.ReadWord();
5767  if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return;
5768 
5769  for (auto &house : houses) {
5770  HouseSpec *hs = house >= _cur.grffile->housespec.size() ? nullptr : _cur.grffile->housespec[house].get();
5771 
5772  if (hs == nullptr) {
5773  GrfMsg(1, "TownHouseMapSpriteGroup: House {} undefined, skipping.", house);
5774  continue;
5775  }
5776 
5777  hs->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
5778  }
5779 }
5780 
5781 static void IndustryMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5782 {
5783  if (_cur.grffile->industryspec.empty()) {
5784  GrfMsg(1, "IndustryMapSpriteGroup: No industries defined, skipping");
5785  return;
5786  }
5787 
5788  std::vector<uint16_t> industries;
5789  industries.reserve(idcount);
5790  for (uint i = 0; i < idcount; i++) {
5791  industries.push_back(buf.ReadExtendedByte());
5792  }
5793 
5794  /* Skip the cargo type section, we only care about the default group */
5795  uint8_t cidcount = buf.ReadByte();
5796  buf.Skip(cidcount * 3);
5797 
5798  uint16_t groupid = buf.ReadWord();
5799  if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return;
5800 
5801  for (auto &industry : industries) {
5802  IndustrySpec *indsp = industry >= _cur.grffile->industryspec.size() ? nullptr : _cur.grffile->industryspec[industry].get();
5803 
5804  if (indsp == nullptr) {
5805  GrfMsg(1, "IndustryMapSpriteGroup: Industry {} undefined, skipping", industry);
5806  continue;
5807  }
5808 
5809  indsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
5810  }
5811 }
5812 
5813 static void IndustrytileMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5814 {
5815  if (_cur.grffile->indtspec.empty()) {
5816  GrfMsg(1, "IndustrytileMapSpriteGroup: No industry tiles defined, skipping");
5817  return;
5818  }
5819 
5820  std::vector<uint16_t> indtiles;
5821  indtiles.reserve(idcount);
5822  for (uint i = 0; i < idcount; i++) {
5823  indtiles.push_back(buf.ReadExtendedByte());
5824  }
5825 
5826  /* Skip the cargo type section, we only care about the default group */
5827  uint8_t cidcount = buf.ReadByte();
5828  buf.Skip(cidcount * 3);
5829 
5830  uint16_t groupid = buf.ReadWord();
5831  if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return;
5832 
5833  for (auto &indtile : indtiles) {
5834  IndustryTileSpec *indtsp = indtile >= _cur.grffile->indtspec.size() ? nullptr : _cur.grffile->indtspec[indtile].get();
5835 
5836  if (indtsp == nullptr) {
5837  GrfMsg(1, "IndustrytileMapSpriteGroup: Industry tile {} undefined, skipping", indtile);
5838  continue;
5839  }
5840 
5841  indtsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
5842  }
5843 }
5844 
5845 static void CargoMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5846 {
5847  std::vector<uint16_t> cargoes;
5848  cargoes.reserve(idcount);
5849  for (uint i = 0; i < idcount; i++) {
5850  cargoes.push_back(buf.ReadExtendedByte());
5851  }
5852 
5853  /* Skip the cargo type section, we only care about the default group */
5854  uint8_t cidcount = buf.ReadByte();
5855  buf.Skip(cidcount * 3);
5856 
5857  uint16_t groupid = buf.ReadWord();
5858  if (!IsValidGroupID(groupid, "CargoMapSpriteGroup")) return;
5859 
5860  for (auto &cid : cargoes) {
5861  if (cid >= NUM_CARGO) {
5862  GrfMsg(1, "CargoMapSpriteGroup: Cargo ID {} out of range, skipping", cid);
5863  continue;
5864  }
5865 
5866  CargoSpec *cs = CargoSpec::Get(cid);
5867  cs->grffile = _cur.grffile;
5868  cs->group = _cur.spritegroups[groupid];
5869  }
5870 }
5871 
5872 static void ObjectMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5873 {
5874  if (_cur.grffile->objectspec.empty()) {
5875  GrfMsg(1, "ObjectMapSpriteGroup: No object tiles defined, skipping");
5876  return;
5877  }
5878 
5879  std::vector<uint16_t> objects;
5880  objects.reserve(idcount);
5881  for (uint i = 0; i < idcount; i++) {
5882  objects.push_back(buf.ReadExtendedByte());
5883  }
5884 
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;
5890 
5891  /* The only valid option here is purchase list sprite groups. */
5892  if (ctype != 0xFF) {
5893  GrfMsg(1, "ObjectMapSpriteGroup: Invalid cargo bitnum {} for objects, skipping.", ctype);
5894  continue;
5895  }
5896 
5897  for (auto &object : objects) {
5898  ObjectSpec *spec = object >= _cur.grffile->objectspec.size() ? nullptr : _cur.grffile->objectspec[object].get();
5899 
5900  if (spec == nullptr) {
5901  GrfMsg(1, "ObjectMapSpriteGroup: Object {} undefined, skipping", object);
5902  continue;
5903  }
5904 
5905  spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_PURCHASE] = _cur.spritegroups[groupid];
5906  }
5907  }
5908 
5909  uint16_t groupid = buf.ReadWord();
5910  if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) return;
5911 
5912  for (auto &object : objects) {
5913  ObjectSpec *spec = object >= _cur.grffile->objectspec.size() ? nullptr : _cur.grffile->objectspec[object].get();
5914 
5915  if (spec == nullptr) {
5916  GrfMsg(1, "ObjectMapSpriteGroup: Object {} undefined, skipping", object);
5917  continue;
5918  }
5919 
5920  if (spec->grf_prop.grffile != nullptr) {
5921  GrfMsg(1, "ObjectMapSpriteGroup: Object {} mapped multiple times, skipping", object);
5922  continue;
5923  }
5924 
5925  spec->grf_prop.spritegroup[OBJECT_SPRITE_GROUP_DEFAULT] = _cur.spritegroups[groupid];
5926  spec->grf_prop.grffile = _cur.grffile;
5927  spec->grf_prop.local_id = object;
5928  }
5929 }
5930 
5931 static void RailTypeMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5932 {
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);
5938  }
5939 
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;
5945 
5946  if (ctype >= RTSG_END) continue;
5947 
5948  extern RailTypeInfo _railtypes[RAILTYPE_END];
5949  for (auto &railtype : railtypes) {
5950  if (railtype != INVALID_RAILTYPE) {
5951  RailTypeInfo *rti = &_railtypes[railtype];
5952 
5953  rti->grffile[ctype] = _cur.grffile;
5954  rti->group[ctype] = _cur.spritegroups[groupid];
5955  }
5956  }
5957  }
5958 
5959  /* Railtypes do not use the default group. */
5960  buf.ReadWord();
5961 }
5962 
5963 static void RoadTypeMapSpriteGroup(ByteReader &buf, uint8_t idcount, RoadTramType rtt)
5964 {
5965  RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
5966 
5967  std::vector<uint8_t> roadtypes;
5968  roadtypes.reserve(idcount);
5969  for (uint i = 0; i < idcount; i++) {
5970  uint16_t id = buf.ReadExtendedByte();
5971  roadtypes.push_back(id < ROADTYPE_END ? type_map[id] : INVALID_ROADTYPE);
5972  }
5973 
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;
5979 
5980  if (ctype >= ROTSG_END) continue;
5981 
5982  extern RoadTypeInfo _roadtypes[ROADTYPE_END];
5983  for (auto &roadtype : roadtypes) {
5984  if (roadtype != INVALID_ROADTYPE) {
5985  RoadTypeInfo *rti = &_roadtypes[roadtype];
5986 
5987  rti->grffile[ctype] = _cur.grffile;
5988  rti->group[ctype] = _cur.spritegroups[groupid];
5989  }
5990  }
5991  }
5992 
5993  /* Roadtypes do not use the default group. */
5994  buf.ReadWord();
5995 }
5996 
5997 static void AirportMapSpriteGroup(ByteReader &buf, uint8_t idcount)
5998 {
5999  if (_cur.grffile->airportspec.empty()) {
6000  GrfMsg(1, "AirportMapSpriteGroup: No airports defined, skipping");
6001  return;
6002  }
6003 
6004  std::vector<uint16_t> airports;
6005  airports.reserve(idcount);
6006  for (uint i = 0; i < idcount; i++) {
6007  airports.push_back(buf.ReadExtendedByte());
6008  }
6009 
6010  /* Skip the cargo type section, we only care about the default group */
6011  uint8_t cidcount = buf.ReadByte();
6012  buf.Skip(cidcount * 3);
6013 
6014  uint16_t groupid = buf.ReadWord();
6015  if (!IsValidGroupID(groupid, "AirportMapSpriteGroup")) return;
6016 
6017  for (auto &airport : airports) {
6018  AirportSpec *as = airport >= _cur.grffile->airportspec.size() ? nullptr : _cur.grffile->airportspec[airport].get();
6019 
6020  if (as == nullptr) {
6021  GrfMsg(1, "AirportMapSpriteGroup: Airport {} undefined, skipping", airport);
6022  continue;
6023  }
6024 
6025  as->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
6026  }
6027 }
6028 
6029 static void AirportTileMapSpriteGroup(ByteReader &buf, uint8_t idcount)
6030 {
6031  if (_cur.grffile->airtspec.empty()) {
6032  GrfMsg(1, "AirportTileMapSpriteGroup: No airport tiles defined, skipping");
6033  return;
6034  }
6035 
6036  std::vector<uint16_t> airptiles;
6037  airptiles.reserve(idcount);
6038  for (uint i = 0; i < idcount; i++) {
6039  airptiles.push_back(buf.ReadExtendedByte());
6040  }
6041 
6042  /* Skip the cargo type section, we only care about the default group */
6043  uint8_t cidcount = buf.ReadByte();
6044  buf.Skip(cidcount * 3);
6045 
6046  uint16_t groupid = buf.ReadWord();
6047  if (!IsValidGroupID(groupid, "AirportTileMapSpriteGroup")) return;
6048 
6049  for (auto &airptile : airptiles) {
6050  AirportTileSpec *airtsp = airptile >= _cur.grffile->airtspec.size() ? nullptr : _cur.grffile->airtspec[airptile].get();
6051 
6052  if (airtsp == nullptr) {
6053  GrfMsg(1, "AirportTileMapSpriteGroup: Airport tile {} undefined, skipping", airptile);
6054  continue;
6055  }
6056 
6057  airtsp->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
6058  }
6059 }
6060 
6061 static void RoadStopMapSpriteGroup(ByteReader &buf, uint8_t idcount)
6062 {
6063  if (_cur.grffile->roadstops.empty()) {
6064  GrfMsg(1, "RoadStopMapSpriteGroup: No roadstops defined, skipping");
6065  return;
6066  }
6067 
6068  std::vector<uint16_t> roadstops;
6069  roadstops.reserve(idcount);
6070  for (uint i = 0; i < idcount; i++) {
6071  roadstops.push_back(buf.ReadExtendedByte());
6072  }
6073 
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;
6079 
6080  ctype = TranslateCargo(GSF_ROADSTOPS, ctype);
6081  if (!IsValidCargoID(ctype)) continue;
6082 
6083  for (auto &roadstop : roadstops) {
6084  RoadStopSpec *roadstopspec = roadstop >= _cur.grffile->roadstops.size() ? nullptr : _cur.grffile->roadstops[roadstop].get();
6085 
6086  if (roadstopspec == nullptr) {
6087  GrfMsg(1, "RoadStopMapSpriteGroup: Road stop {} undefined, skipping", roadstop);
6088  continue;
6089  }
6090 
6091  roadstopspec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
6092  }
6093  }
6094 
6095  uint16_t groupid = buf.ReadWord();
6096  if (!IsValidGroupID(groupid, "RoadStopMapSpriteGroup")) return;
6097 
6098  for (auto &roadstop : roadstops) {
6099  RoadStopSpec *roadstopspec = roadstop >= _cur.grffile->roadstops.size() ? nullptr : _cur.grffile->roadstops[roadstop].get();
6100 
6101  if (roadstopspec == nullptr) {
6102  GrfMsg(1, "RoadStopMapSpriteGroup: Road stop {} undefined, skipping.", roadstop);
6103  continue;
6104  }
6105 
6106  if (roadstopspec->grf_prop.grffile != nullptr) {
6107  GrfMsg(1, "RoadStopMapSpriteGroup: Road stop {} mapped multiple times, skipping", roadstop);
6108  continue;
6109  }
6110 
6111  roadstopspec->grf_prop.spritegroup[SpriteGroupCargo::SG_DEFAULT] = _cur.spritegroups[groupid];
6112  roadstopspec->grf_prop.grffile = _cur.grffile;
6113  roadstopspec->grf_prop.local_id = roadstop;
6114  RoadStopClass::Assign(roadstopspec);
6115  }
6116 }
6117 
6118 /* Action 0x03 */
6119 static void FeatureMapSpriteGroup(ByteReader &buf)
6120 {
6121  /* <03> <feature> <n-id> <ids>... <num-cid> [<cargo-type> <cid>]... <def-cid>
6122  * id-list := [<id>] [id-list]
6123  * cargo-list := <cargo-type> <cid> [cargo-list]
6124  *
6125  * B feature see action 0
6126  * B n-id bits 0-6: how many IDs this definition applies to
6127  * bit 7: if set, this is a wagon override definition (see below)
6128  * E ids the IDs for which this definition applies
6129  * B num-cid number of cargo IDs (sprite group IDs) in this definition
6130  * can be zero, in that case the def-cid is used always
6131  * B cargo-type type of this cargo type (e.g. mail=2, wood=7, see below)
6132  * W cid cargo ID (sprite group ID) for this type of cargo
6133  * W def-cid default cargo ID (sprite group ID) */
6134 
6135  uint8_t feature = buf.ReadByte();
6136  uint8_t idcount = buf.ReadByte();
6137 
6138  if (feature >= GSF_END) {
6139  GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6140  return;
6141  }
6142 
6143  /* If idcount is zero, this is a feature callback */
6144  if (idcount == 0) {
6145  /* Skip number of cargo ids? */
6146  buf.ReadByte();
6147  uint16_t groupid = buf.ReadWord();
6148  if (!IsValidGroupID(groupid, "FeatureMapSpriteGroup")) return;
6149 
6150  GrfMsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
6151 
6152  AddGenericCallback(feature, _cur.grffile, _cur.spritegroups[groupid]);
6153  return;
6154  }
6155 
6156  /* Mark the feature as used by the grf (generic callbacks do not count) */
6157  SetBit(_cur.grffile->grf_features, feature);
6158 
6159  GrfMsg(6, "FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
6160 
6161  switch (feature) {
6162  case GSF_TRAINS:
6163  case GSF_ROADVEHICLES:
6164  case GSF_SHIPS:
6165  case GSF_AIRCRAFT:
6166  VehicleMapSpriteGroup(buf, feature, idcount);
6167  return;
6168 
6169  case GSF_CANALS:
6170  CanalMapSpriteGroup(buf, idcount);
6171  return;
6172 
6173  case GSF_STATIONS:
6174  StationMapSpriteGroup(buf, idcount);
6175  return;
6176 
6177  case GSF_HOUSES:
6178  TownHouseMapSpriteGroup(buf, idcount);
6179  return;
6180 
6181  case GSF_INDUSTRIES:
6182  IndustryMapSpriteGroup(buf, idcount);
6183  return;
6184 
6185  case GSF_INDUSTRYTILES:
6186  IndustrytileMapSpriteGroup(buf, idcount);
6187  return;
6188 
6189  case GSF_CARGOES:
6190  CargoMapSpriteGroup(buf, idcount);
6191  return;
6192 
6193  case GSF_AIRPORTS:
6194  AirportMapSpriteGroup(buf, idcount);
6195  return;
6196 
6197  case GSF_OBJECTS:
6198  ObjectMapSpriteGroup(buf, idcount);
6199  break;
6200 
6201  case GSF_RAILTYPES:
6202  RailTypeMapSpriteGroup(buf, idcount);
6203  break;
6204 
6205  case GSF_ROADTYPES:
6206  RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
6207  break;
6208 
6209  case GSF_TRAMTYPES:
6210  RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
6211  break;
6212 
6213  case GSF_AIRPORTTILES:
6214  AirportTileMapSpriteGroup(buf, idcount);
6215  return;
6216 
6217  case GSF_ROADSTOPS:
6218  RoadStopMapSpriteGroup(buf, idcount);
6219  return;
6220 
6221  default:
6222  GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
6223  return;
6224  }
6225 }
6226 
6227 /* Action 0x04 */
6228 static void FeatureNewName(ByteReader &buf)
6229 {
6230  /* <04> <veh-type> <language-id> <num-veh> <offset> <data...>
6231  *
6232  * B veh-type see action 0 (as 00..07, + 0A
6233  * But IF veh-type = 48, then generic text
6234  * B language-id If bit 6 is set, This is the extended language scheme,
6235  * with up to 64 language.
6236  * Otherwise, it is a mapping where set bits have meaning
6237  * 0 = american, 1 = english, 2 = german, 3 = french, 4 = spanish
6238  * Bit 7 set means this is a generic text, not a vehicle one (or else)
6239  * B num-veh number of vehicles which are getting a new name
6240  * B/W offset number of the first vehicle that gets a new name
6241  * Byte : ID of vehicle to change
6242  * Word : ID of string to change/add
6243  * S data new texts, each of them zero-terminated, after
6244  * which the next name begins. */
6245 
6246  bool new_scheme = _cur.grffile->grf_version >= 7;
6247 
6248  uint8_t feature = buf.ReadByte();
6249  if (feature >= GSF_END && feature != 0x48) {
6250  GrfMsg(1, "FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
6251  return;
6252  }
6253 
6254  uint8_t lang = buf.ReadByte();
6255  uint8_t num = buf.ReadByte();
6256  bool generic = HasBit(lang, 7);
6257  uint16_t id;
6258  if (generic) {
6259  id = buf.ReadWord();
6260  } else if (feature <= GSF_AIRCRAFT) {
6261  id = buf.ReadExtendedByte();
6262  } else {
6263  id = buf.ReadByte();
6264  }
6265 
6266  ClrBit(lang, 7);
6267 
6268  uint16_t endid = id + num;
6269 
6270  GrfMsg(6, "FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
6271  id, endid, feature, lang);
6272 
6273  for (; id < endid && buf.HasData(); id++) {
6274  const std::string_view name = buf.ReadString();
6275  GrfMsg(8, "FeatureNewName: 0x{:04X} <- {}", id, StrMakeValid(name));
6276 
6277  switch (feature) {
6278  case GSF_TRAINS:
6279  case GSF_ROADVEHICLES:
6280  case GSF_SHIPS:
6281  case GSF_AIRCRAFT:
6282  if (!generic) {
6283  Engine *e = GetNewEngine(_cur.grffile, (VehicleType)feature, id, HasBit(_cur.grfconfig->flags, GCF_STATIC));
6284  if (e == nullptr) break;
6285  StringID string = AddGRFString(_cur.grffile->grfid, e->index, lang, new_scheme, false, name, e->info.string_id);
6286  e->info.string_id = string;
6287  } else {
6288  AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, true, name, STR_UNDEFINED);
6289  }
6290  break;
6291 
6292  default:
6293  if (IsInsideMM(id, 0xD000, 0xD400) || IsInsideMM(id, 0xD800, 0x10000)) {
6294  AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, true, name, STR_UNDEFINED);
6295  break;
6296  }
6297 
6298  switch (GB(id, 8, 8)) {
6299  case 0xC4: // Station class name
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));
6302  } else {
6303  StationClassID class_index = _cur.grffile->stations[GB(id, 0, 8)]->class_index;
6304  StationClass::Get(class_index)->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
6305  }
6306  break;
6307 
6308  case 0xC5: // Station name
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));
6311  } else {
6312  _cur.grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
6313  }
6314  break;
6315 
6316  case 0xC7: // Airporttile name
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));
6319  } else {
6320  _cur.grffile->airtspec[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
6321  }
6322  break;
6323 
6324  case 0xC9: // House name
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));
6327  } else {
6328  _cur.grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
6329  }
6330  break;
6331 
6332  default:
6333  GrfMsg(7, "FeatureNewName: Unsupported ID (0x{:04X})", id);
6334  break;
6335  }
6336  break;
6337  }
6338  }
6339 }
6340 
6349 static uint16_t SanitizeSpriteOffset(uint16_t &num, uint16_t offset, int max_sprites, const std::string_view name)
6350 {
6351 
6352  if (offset >= max_sprites) {
6353  GrfMsg(1, "GraphicsNew: {} sprite offset must be less than {}, skipping", name, max_sprites);
6354  uint orig_num = num;
6355  num = 0;
6356  return orig_num;
6357  }
6358 
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;
6364  }
6365 
6366  return 0;
6367 }
6368 
6369 
6371 static constexpr auto _action5_types = std::to_array<Action5Type>({
6372  /* Note: min_sprites should not be changed. Therefore these constants are directly here and not in sprites.h */
6373  /* 0x00 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x00" },
6374  /* 0x01 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x01" },
6375  /* 0x02 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x02" },
6376  /* 0x03 */ { A5BLOCK_INVALID, 0, 0, 0, "Type 0x03" },
6377  /* 0x04 */ { A5BLOCK_ALLOW_OFFSET, SPR_SIGNALS_BASE, 1, PRESIGNAL_SEMAPHORE_AND_PBS_SPRITE_COUNT, "Signal graphics" },
6378  /* 0x05 */ { A5BLOCK_ALLOW_OFFSET, SPR_ELRAIL_BASE, 1, ELRAIL_SPRITE_COUNT, "Rail catenary graphics" },
6379  /* 0x06 */ { A5BLOCK_ALLOW_OFFSET, SPR_SLOPES_BASE, 1, NORMAL_AND_HALFTILE_FOUNDATION_SPRITE_COUNT, "Foundation graphics" },
6380  /* 0x07 */ { A5BLOCK_INVALID, 0, 75, 0, "TTDP GUI graphics" }, // Not used by OTTD.
6381  /* 0x08 */ { A5BLOCK_ALLOW_OFFSET, SPR_CANALS_BASE, 1, CANALS_SPRITE_COUNT, "Canal graphics" },
6382  /* 0x09 */ { A5BLOCK_ALLOW_OFFSET, SPR_ONEWAY_BASE, 1, ONEWAY_SPRITE_COUNT, "One way road graphics" },
6383  /* 0x0A */ { A5BLOCK_ALLOW_OFFSET, SPR_2CCMAP_BASE, 1, TWOCCMAP_SPRITE_COUNT, "2CC colour maps" },
6384  /* 0x0B */ { A5BLOCK_ALLOW_OFFSET, SPR_TRAMWAY_BASE, 1, TRAMWAY_SPRITE_COUNT, "Tramway graphics" },
6385  /* 0x0C */ { A5BLOCK_INVALID, 0, 133, 0, "Snowy temperate tree" }, // Not yet used by OTTD.
6386  /* 0x0D */ { A5BLOCK_FIXED, SPR_SHORE_BASE, 16, SPR_SHORE_SPRITE_COUNT, "Shore graphics" },
6387  /* 0x0E */ { A5BLOCK_INVALID, 0, 0, 0, "New Signals graphics" }, // Not yet used by OTTD.
6388  /* 0x0F */ { A5BLOCK_ALLOW_OFFSET, SPR_TRACKS_FOR_SLOPES_BASE, 1, TRACKS_FOR_SLOPES_SPRITE_COUNT, "Sloped rail track" },
6389  /* 0x10 */ { A5BLOCK_ALLOW_OFFSET, SPR_AIRPORTX_BASE, 1, AIRPORTX_SPRITE_COUNT, "Airport graphics" },
6390  /* 0x11 */ { A5BLOCK_ALLOW_OFFSET, SPR_ROADSTOP_BASE, 1, ROADSTOP_SPRITE_COUNT, "Road stop graphics" },
6391  /* 0x12 */ { A5BLOCK_ALLOW_OFFSET, SPR_AQUEDUCT_BASE, 1, AQUEDUCT_SPRITE_COUNT, "Aqueduct graphics" },
6392  /* 0x13 */ { A5BLOCK_ALLOW_OFFSET, SPR_AUTORAIL_BASE, 1, AUTORAIL_SPRITE_COUNT, "Autorail graphics" },
6393  /* 0x14 */ { A5BLOCK_INVALID, 0, 1, 0, "Flag graphics" }, // deprecated, no longer used.
6394  /* 0x15 */ { A5BLOCK_ALLOW_OFFSET, SPR_OPENTTD_BASE, 1, OPENTTD_SPRITE_COUNT, "OpenTTD GUI graphics" },
6395  /* 0x16 */ { A5BLOCK_ALLOW_OFFSET, SPR_AIRPORT_PREVIEW_BASE, 1, SPR_AIRPORT_PREVIEW_COUNT, "Airport preview graphics" },
6396  /* 0x17 */ { A5BLOCK_ALLOW_OFFSET, SPR_RAILTYPE_TUNNEL_BASE, 1, RAILTYPE_TUNNEL_BASE_COUNT, "Railtype tunnel base" },
6397  /* 0x18 */ { A5BLOCK_ALLOW_OFFSET, SPR_PALETTE_BASE, 1, PALETTE_SPRITE_COUNT, "Palette" },
6398  /* 0x19 */ { A5BLOCK_ALLOW_OFFSET, SPR_ROAD_WAYPOINTS_BASE, 1, ROAD_WAYPOINTS_SPRITE_COUNT, "Road waypoints" },
6399 });
6400 
6405 std::span<const Action5Type> GetAction5Types()
6406 {
6407  return _action5_types;
6408 }
6409 
6410 /* Action 0x05 */
6411 static void GraphicsNew(ByteReader &buf)
6412 {
6413  /* <05> <graphics-type> <num-sprites> <other data...>
6414  *
6415  * B graphics-type What set of graphics the sprites define.
6416  * E num-sprites How many sprites are in this set?
6417  * V other data Graphics type specific data. Currently unused. */
6418 
6419  uint8_t type = buf.ReadByte();
6420  uint16_t num = buf.ReadExtendedByte();
6421  uint16_t offset = HasBit(type, 7) ? buf.ReadExtendedByte() : 0;
6422  ClrBit(type, 7); // Clear the high bit as that only indicates whether there is an offset.
6423 
6424  if ((type == 0x0D) && (num == 10) && HasBit(_cur.grfconfig->flags, GCF_SYSTEM)) {
6425  /* Special not-TTDP-compatible case used in openttd.grf
6426  * Missing shore sprites and initialisation of SPR_SHORE_BASE */
6427  GrfMsg(2, "GraphicsNew: Loading 10 missing shore sprites from extra grf.");
6428  LoadNextSprite(SPR_SHORE_BASE + 0, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_S
6429  LoadNextSprite(SPR_SHORE_BASE + 5, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_W
6430  LoadNextSprite(SPR_SHORE_BASE + 7, *_cur.file, _cur.nfo_line++); // SLOPE_WSE
6431  LoadNextSprite(SPR_SHORE_BASE + 10, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_N
6432  LoadNextSprite(SPR_SHORE_BASE + 11, *_cur.file, _cur.nfo_line++); // SLOPE_NWS
6433  LoadNextSprite(SPR_SHORE_BASE + 13, *_cur.file, _cur.nfo_line++); // SLOPE_ENW
6434  LoadNextSprite(SPR_SHORE_BASE + 14, *_cur.file, _cur.nfo_line++); // SLOPE_SEN
6435  LoadNextSprite(SPR_SHORE_BASE + 15, *_cur.file, _cur.nfo_line++); // SLOPE_STEEP_E
6436  LoadNextSprite(SPR_SHORE_BASE + 16, *_cur.file, _cur.nfo_line++); // SLOPE_EW
6437  LoadNextSprite(SPR_SHORE_BASE + 17, *_cur.file, _cur.nfo_line++); // SLOPE_NS
6439  return;
6440  }
6441 
6442  /* Supported type? */
6443  if ((type >= std::size(_action5_types)) || (_action5_types[type].block_type == A5BLOCK_INVALID)) {
6444  GrfMsg(2, "GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
6445  _cur.skip_sprites = num;
6446  return;
6447  }
6448 
6449  const Action5Type *action5_type = &_action5_types[type];
6450 
6451  /* Contrary to TTDP we allow always to specify too few sprites as we allow always an offset,
6452  * except for the long version of the shore type:
6453  * Ignore offset if not allowed */
6454  if ((action5_type->block_type != A5BLOCK_ALLOW_OFFSET) && (offset != 0)) {
6455  GrfMsg(1, "GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->name, type);
6456  offset = 0;
6457  }
6458 
6459  /* Ignore action5 if too few sprites are specified. (for TTDP compatibility)
6460  * This does not make sense, if <offset> is allowed */
6461  if ((action5_type->block_type == A5BLOCK_FIXED) && (num < action5_type->min_sprites)) {
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);
6463  _cur.skip_sprites = num;
6464  return;
6465  }
6466 
6467  /* Load at most max_sprites sprites. Skip remaining sprites. (for compatibility with TTDP and future extensions) */
6468  uint16_t skip_num = SanitizeSpriteOffset(num, offset, action5_type->max_sprites, action5_type->name);
6469  SpriteID replace = action5_type->sprite_base + offset;
6470 
6471  /* Load <num> sprites starting from <replace>, then skip <skip_num> sprites. */
6472  GrfMsg(2, "GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->name, type, replace);
6473 
6475 
6476  if (type == 0x0B) {
6477  static const SpriteID depot_with_track_offset = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_TRAMWAY_BASE;
6478  static const SpriteID depot_no_track_offset = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_TRAMWAY_BASE;
6479  if (offset <= depot_with_track_offset && offset + num > depot_with_track_offset) _loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_WITH_TRACK;
6480  if (offset <= depot_no_track_offset && offset + num > depot_no_track_offset) _loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_NO_TRACK;
6481  }
6482 
6483  /* If the baseset or grf only provides sprites for flat tiles (pre #10282), duplicate those for use on slopes. */
6484  bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= SPR_ONEWAY_SLOPE_N_OFFSET));
6485 
6486  for (; num > 0; num--) {
6487  _cur.nfo_line++;
6488  SpriteID load_index = (replace == 0 ? _cur.spriteid++ : replace++);
6489  LoadNextSprite(load_index, *_cur.file, _cur.nfo_line);
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);
6493  }
6494  }
6495 
6496  _cur.skip_sprites = skip_num;
6497 }
6498 
6499 /* Action 0x05 (SKIP) */
6500 static void SkipAct5(ByteReader &buf)
6501 {
6502  /* Ignore type byte */
6503  buf.ReadByte();
6504 
6505  /* Skip the sprites of this action */
6506  _cur.skip_sprites = buf.ReadExtendedByte();
6507 
6508  GrfMsg(3, "SkipAct5: Skipping {} sprites", _cur.skip_sprites);
6509 }
6510 
6522 bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
6523 {
6524  switch (param) {
6525  case 0x00: // current date
6526  *value = std::max(TimerGameCalendar::date - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR, TimerGameCalendar::Date(0)).base();
6527  return true;
6528 
6529  case 0x01: // current year
6531  return true;
6532 
6533  case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24)
6534  TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
6535  TimerGameCalendar::Date start_of_year = TimerGameCalendar::ConvertYMDToDate(ymd.year, 0, 1);
6536  *value = ymd.month | (ymd.day - 1) << 8 | (TimerGameCalendar::IsLeapYear(ymd.year) ? 1 << 15 : 0) | (TimerGameCalendar::date - start_of_year).base() << 16;
6537  return true;
6538  }
6539 
6540  case 0x03: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
6542  return true;
6543 
6544  case 0x06: // road traffic side, bit 4 clear=left, set=right
6545  *value = _settings_game.vehicle.road_side << 4;
6546  return true;
6547 
6548  case 0x09: // date fraction
6549  *value = TimerGameCalendar::date_fract * 885;
6550  return true;
6551 
6552  case 0x0A: // animation counter
6553  *value = GB(TimerGameTick::counter, 0, 16);
6554  return true;
6555 
6556  case 0x0B: { // TTDPatch version
6557  uint major = 2;
6558  uint minor = 6;
6559  uint revision = 1; // special case: 2.0.1 is 2.0.10
6560  uint build = 1382;
6561  *value = (major << 24) | (minor << 20) | (revision << 16) | build;
6562  return true;
6563  }
6564 
6565  case 0x0D: // TTD Version, 00=DOS, 01=Windows
6566  *value = _cur.grfconfig->palette & GRFP_USE_MASK;
6567  return true;
6568 
6569  case 0x0E: // Y-offset for train sprites
6570  *value = _cur.grffile->traininfo_vehicle_pitch;
6571  return true;
6572 
6573  case 0x0F: // Rail track type cost factors
6574  *value = 0;
6575  SB(*value, 0, 8, GetRailTypeInfo(RAILTYPE_RAIL)->cost_multiplier); // normal rail
6577  /* skip elrail multiplier - disabled */
6578  SB(*value, 8, 8, GetRailTypeInfo(RAILTYPE_MONO)->cost_multiplier); // monorail
6579  } else {
6580  SB(*value, 8, 8, GetRailTypeInfo(RAILTYPE_ELECTRIC)->cost_multiplier); // electified railway
6581  /* Skip monorail multiplier - no space in result */
6582  }
6583  SB(*value, 16, 8, GetRailTypeInfo(RAILTYPE_MAGLEV)->cost_multiplier); // maglev
6584  return true;
6585 
6586  case 0x11: // current rail tool type
6587  *value = 0; // constant fake value to avoid desync
6588  return true;
6589 
6590  case 0x12: // Game mode
6591  *value = _game_mode;
6592  return true;
6593 
6594  /* case 0x13: // Tile refresh offset to left not implemented */
6595  /* case 0x14: // Tile refresh offset to right not implemented */
6596  /* case 0x15: // Tile refresh offset upwards not implemented */
6597  /* case 0x16: // Tile refresh offset downwards not implemented */
6598  /* case 0x17: // temperate snow line not implemented */
6599 
6600  case 0x1A: // Always -1
6601  *value = UINT_MAX;
6602  return true;
6603 
6604  case 0x1B: // Display options
6605  *value = 0x3F; // constant fake value to avoid desync
6606  return true;
6607 
6608  case 0x1D: // TTD Platform, 00=TTDPatch, 01=OpenTTD
6609  *value = 1;
6610  return true;
6611 
6612  case 0x1E: // Miscellaneous GRF features
6613  *value = _misc_grf_features;
6614 
6615  /* Add the local flags */
6616  assert(!HasBit(*value, GMB_TRAIN_WIDTH_32_PIXELS));
6617  if (_cur.grffile->traininfo_vehicle_width == VEHICLEINFO_FULL_VEHICLE_WIDTH) SetBit(*value, GMB_TRAIN_WIDTH_32_PIXELS);
6618  return true;
6619 
6620  /* case 0x1F: // locale dependent settings not implemented to avoid desync */
6621 
6622  case 0x20: { // snow line height
6623  uint8_t snowline = GetSnowLine();
6625  *value = Clamp(snowline * (grffile->grf_version >= 8 ? 1 : TILE_HEIGHT), 0, 0xFE);
6626  } else {
6627  /* No snow */
6628  *value = 0xFF;
6629  }
6630  return true;
6631  }
6632 
6633  case 0x21: // OpenTTD version
6634  *value = _openttd_newgrf_version;
6635  return true;
6636 
6637  case 0x22: // difficulty level
6638  *value = SP_CUSTOM;
6639  return true;
6640 
6641  case 0x23: // long format date
6642  *value = TimerGameCalendar::date.base();
6643  return true;
6644 
6645  case 0x24: // long format year
6646  *value = TimerGameCalendar::year.base();
6647  return true;
6648 
6649  default: return false;
6650  }
6651 }
6652 
6653 static uint32_t GetParamVal(uint8_t param, uint32_t *cond_val)
6654 {
6655  /* First handle variable common with VarAction2 */
6656  uint32_t value;
6657  if (GetGlobalVariable(param - 0x80, &value, _cur.grffile)) return value;
6658 
6659 
6660  /* Non-common variable */
6661  switch (param) {
6662  case 0x84: { // GRF loading stage
6663  uint32_t res = 0;
6664 
6665  if (_cur.stage > GLS_INIT) SetBit(res, 0);
6666  if (_cur.stage == GLS_RESERVE) SetBit(res, 8);
6667  if (_cur.stage == GLS_ACTIVATION) SetBit(res, 9);
6668  return res;
6669  }
6670 
6671  case 0x85: // TTDPatch flags, only for bit tests
6672  if (cond_val == nullptr) {
6673  /* Supported in Action 0x07 and 0x09, not 0x0D */
6674  return 0;
6675  } else {
6676  uint32_t index = *cond_val / 0x20;
6677  uint32_t param_val = index < lengthof(_ttdpatch_flags) ? _ttdpatch_flags[index] : 0;
6678  *cond_val %= 0x20;
6679  return param_val;
6680  }
6681 
6682  case 0x88: // GRF ID check
6683  return 0;
6684 
6685  /* case 0x99: Global ID offset not implemented */
6686 
6687  default:
6688  /* GRF Parameter */
6689  if (param < 0x80) return _cur.grffile->GetParam(param);
6690 
6691  /* In-game variable. */
6692  GrfMsg(1, "Unsupported in-game variable 0x{:02X}", param);
6693  return UINT_MAX;
6694  }
6695 }
6696 
6697 /* Action 0x06 */
6698 static void CfgApply(ByteReader &buf)
6699 {
6700  /* <06> <param-num> <param-size> <offset> ... <FF>
6701  *
6702  * B param-num Number of parameter to substitute (First = "zero")
6703  * Ignored if that parameter was not specified in newgrf.cfg
6704  * B param-size How many bytes to replace. If larger than 4, the
6705  * bytes of the following parameter are used. In that
6706  * case, nothing is applied unless *all* parameters
6707  * were specified.
6708  * B offset Offset into data from beginning of next sprite
6709  * to place where parameter is to be stored. */
6710 
6711  /* Preload the next sprite */
6712  SpriteFile &file = *_cur.file;
6713  size_t pos = file.GetPos();
6714  uint32_t num = file.GetContainerVersion() >= 2 ? file.ReadDword() : file.ReadWord();
6715  uint8_t type = file.ReadByte();
6716 
6717  /* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */
6718  if (type != 0xFF) {
6719  GrfMsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)");
6720 
6721  /* Reset the file position to the start of the next sprite */
6722  file.SeekTo(pos, SEEK_SET);
6723  return;
6724  }
6725 
6726  /* Get (or create) the override for the next sprite. */
6727  GRFLocation location(_cur.grfconfig->ident.grfid, _cur.nfo_line + 1);
6728  std::vector<uint8_t> &preload_sprite = _grf_line_to_action6_sprite_override[location];
6729 
6730  /* Load new sprite data if it hasn't already been loaded. */
6731  if (preload_sprite.empty()) {
6732  preload_sprite.resize(num);
6733  file.ReadBlock(preload_sprite.data(), num);
6734  }
6735 
6736  /* Reset the file position to the start of the next sprite */
6737  file.SeekTo(pos, SEEK_SET);
6738 
6739  /* Now perform the Action 0x06 on our data. */
6740  for (;;) {
6741  uint i;
6742  uint param_num;
6743  uint param_size;
6744  uint offset;
6745  bool add_value;
6746 
6747  /* Read the parameter to apply. 0xFF indicates no more data to change. */
6748  param_num = buf.ReadByte();
6749  if (param_num == 0xFF) break;
6750 
6751  /* Get the size of the parameter to use. If the size covers multiple
6752  * double words, sequential parameter values are used. */
6753  param_size = buf.ReadByte();
6754 
6755  /* Bit 7 of param_size indicates we should add to the original value
6756  * instead of replacing it. */
6757  add_value = HasBit(param_size, 7);
6758  param_size = GB(param_size, 0, 7);
6759 
6760  /* Where to apply the data to within the pseudo sprite data. */
6761  offset = buf.ReadExtendedByte();
6762 
6763  /* If the parameter is a GRF parameter (not an internal variable) check
6764  * if it (and all further sequential parameters) has been defined. */
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));
6767  break;
6768  }
6769 
6770  GrfMsg(8, "CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
6771 
6772  bool carry = false;
6773  for (i = 0; i < param_size && offset + i < num; i++) {
6774  uint32_t value = GetParamVal(param_num + i / 4, nullptr);
6775  /* Reset carry flag for each iteration of the variable (only really
6776  * matters if param_size is greater than 4) */
6777  if (i % 4 == 0) carry = false;
6778 
6779  if (add_value) {
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);
6782  /* Check if the addition overflowed */
6783  carry = new_value >= 256;
6784  } else {
6785  preload_sprite[offset + i] = GB(value, (i % 4) * 8, 8);
6786  }
6787  }
6788  }
6789 }
6790 
6801 {
6802  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC, c);
6803  error->data = _cur.grfconfig->GetName();
6804 }
6805 
6806 /* Action 0x07
6807  * Action 0x09 */
6808 static void SkipIf(ByteReader &buf)
6809 {
6810  /* <07/09> <param-num> <param-size> <condition-type> <value> <num-sprites>
6811  *
6812  * B param-num
6813  * B param-size
6814  * B condition-type
6815  * V value
6816  * B num-sprites */
6817  uint32_t cond_val = 0;
6818  uint32_t mask = 0;
6819  bool result;
6820 
6821  uint8_t param = buf.ReadByte();
6822  uint8_t paramsize = buf.ReadByte();
6823  uint8_t condtype = buf.ReadByte();
6824 
6825  if (condtype < 2) {
6826  /* Always 1 for bit tests, the given value should be ignored. */
6827  paramsize = 1;
6828  }
6829 
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;
6835  default: break;
6836  }
6837 
6838  if (param < 0x80 && _cur.grffile->param_end <= param) {
6839  GrfMsg(7, "SkipIf: Param {} undefined, skipping test", param);
6840  return;
6841  }
6842 
6843  GrfMsg(7, "SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
6844 
6845  /* condtypes that do not use 'param' are always valid.
6846  * condtypes that use 'param' are either not valid for param 0x88, or they are only valid for param 0x88.
6847  */
6848  if (condtype >= 0x0B) {
6849  /* Tests that ignore 'param' */
6850  switch (condtype) {
6851  case 0x0B: result = !IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
6852  break;
6853  case 0x0C: result = IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
6854  break;
6855  case 0x0D: result = GetRailTypeByLabel(BSWAP32(cond_val)) == INVALID_RAILTYPE;
6856  break;
6857  case 0x0E: result = GetRailTypeByLabel(BSWAP32(cond_val)) != INVALID_RAILTYPE;
6858  break;
6859  case 0x0F: {
6860  RoadType rt = GetRoadTypeByLabel(BSWAP32(cond_val));
6861  result = rt == INVALID_ROADTYPE || !RoadTypeIsRoad(rt);
6862  break;
6863  }
6864  case 0x10: {
6865  RoadType rt = GetRoadTypeByLabel(BSWAP32(cond_val));
6866  result = rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt);
6867  break;
6868  }
6869  case 0x11: {
6870  RoadType rt = GetRoadTypeByLabel(BSWAP32(cond_val));
6871  result = rt == INVALID_ROADTYPE || !RoadTypeIsTram(rt);
6872  break;
6873  }
6874  case 0x12: {
6875  RoadType rt = GetRoadTypeByLabel(BSWAP32(cond_val));
6876  result = rt != INVALID_ROADTYPE && RoadTypeIsTram(rt);
6877  break;
6878  }
6879  default: GrfMsg(1, "SkipIf: Unsupported condition type {:02X}. Ignoring", condtype); return;
6880  }
6881  } else if (param == 0x88) {
6882  /* GRF ID checks */
6883 
6884  GRFConfig *c = GetGRFConfig(cond_val, mask);
6885 
6886  if (c != nullptr && HasBit(c->flags, GCF_STATIC) && !HasBit(_cur.grfconfig->flags, GCF_STATIC) && _networking) {
6888  c = nullptr;
6889  }
6890 
6891  if (condtype != 10 && c == nullptr) {
6892  GrfMsg(7, "SkipIf: GRFID 0x{:08X} unknown, skipping test", BSWAP32(cond_val));
6893  return;
6894  }
6895 
6896  switch (condtype) {
6897  /* Tests 0x06 to 0x0A are only for param 0x88, GRFID checks */
6898  case 0x06: // Is GRFID active?
6899  result = c->status == GCS_ACTIVATED;
6900  break;
6901 
6902  case 0x07: // Is GRFID non-active?
6903  result = c->status != GCS_ACTIVATED;
6904  break;
6905 
6906  case 0x08: // GRFID is not but will be active?
6907  result = c->status == GCS_INITIALISED;
6908  break;
6909 
6910  case 0x09: // GRFID is or will be active?
6911  result = c->status == GCS_ACTIVATED || c->status == GCS_INITIALISED;
6912  break;
6913 
6914  case 0x0A: // GRFID is not nor will be active
6915  /* This is the only condtype that doesn't get ignored if the GRFID is not found */
6916  result = c == nullptr || c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND;
6917  break;
6918 
6919  default: GrfMsg(1, "SkipIf: Unsupported GRF condition type {:02X}. Ignoring", condtype); return;
6920  }
6921  } else {
6922  /* Tests that use 'param' and are not GRF ID checks. */
6923  uint32_t param_val = GetParamVal(param, &cond_val); // cond_val is modified for param == 0x85
6924  switch (condtype) {
6925  case 0x00: result = !!(param_val & (1 << cond_val));
6926  break;
6927  case 0x01: result = !(param_val & (1 << cond_val));
6928  break;
6929  case 0x02: result = (param_val & mask) == cond_val;
6930  break;
6931  case 0x03: result = (param_val & mask) != cond_val;
6932  break;
6933  case 0x04: result = (param_val & mask) < cond_val;
6934  break;
6935  case 0x05: result = (param_val & mask) > cond_val;
6936  break;
6937  default: GrfMsg(1, "SkipIf: Unsupported condition type {:02X}. Ignoring", condtype); return;
6938  }
6939  }
6940 
6941  if (!result) {
6942  GrfMsg(2, "SkipIf: Not skipping sprites, test was false");
6943  return;
6944  }
6945 
6946  uint8_t numsprites = buf.ReadByte();
6947 
6948  /* numsprites can be a GOTO label if it has been defined in the GRF
6949  * file. The jump will always be the first matching label that follows
6950  * the current nfo_line. If no matching label is found, the first matching
6951  * label in the file is used. */
6952  const GRFLabel *choice = nullptr;
6953  for (const auto &label : _cur.grffile->labels) {
6954  if (label.label != numsprites) continue;
6955 
6956  /* Remember a goto before the current line */
6957  if (choice == nullptr) choice = &label;
6958  /* If we find a label here, this is definitely good */
6959  if (label.nfo_line > _cur.nfo_line) {
6960  choice = &label;
6961  break;
6962  }
6963  }
6964 
6965  if (choice != nullptr) {
6966  GrfMsg(2, "SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
6967  _cur.file->SeekTo(choice->pos, SEEK_SET);
6968  _cur.nfo_line = choice->nfo_line;
6969  return;
6970  }
6971 
6972  GrfMsg(2, "SkipIf: Skipping {} sprites, test was true", numsprites);
6973  _cur.skip_sprites = numsprites;
6974  if (_cur.skip_sprites == 0) {
6975  /* Zero means there are no sprites to skip, so
6976  * we use -1 to indicate that all further
6977  * sprites should be skipped. */
6978  _cur.skip_sprites = -1;
6979 
6980  /* If an action 8 hasn't been encountered yet, disable the grf. */
6981  if (_cur.grfconfig->status != (_cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED)) {
6982  DisableGrf();
6983  }
6984  }
6985 }
6986 
6987 
6988 /* Action 0x08 (GLS_FILESCAN) */
6989 static void ScanInfo(ByteReader &buf)
6990 {
6991  uint8_t grf_version = buf.ReadByte();
6992  uint32_t grfid = buf.ReadDWord();
6993  std::string_view name = buf.ReadString();
6994 
6995  _cur.grfconfig->ident.grfid = grfid;
6996 
6997  if (grf_version < 2 || grf_version > 8) {
6999  Debug(grf, 0, "{}: NewGRF \"{}\" (GRFID {:08X}) uses GRF version {}, which is incompatible with this version of OpenTTD.", _cur.grfconfig->filename, StrMakeValid(name), BSWAP32(grfid), grf_version);
7000  }
7001 
7002  /* GRF IDs starting with 0xFF are reserved for internal TTDPatch use */
7003  if (GB(grfid, 0, 8) == 0xFF) SetBit(_cur.grfconfig->flags, GCF_SYSTEM);
7004 
7005  AddGRFTextToList(_cur.grfconfig->name, 0x7F, grfid, false, name);
7006 
7007  if (buf.HasData()) {
7008  std::string_view info = buf.ReadString();
7009  AddGRFTextToList(_cur.grfconfig->info, 0x7F, grfid, true, info);
7010  }
7011 
7012  /* GLS_INFOSCAN only looks for the action 8, so we can skip the rest of the file */
7013  _cur.skip_sprites = -1;
7014 }
7015 
7016 /* Action 0x08 */
7017 static void GRFInfo(ByteReader &buf)
7018 {
7019  /* <08> <version> <grf-id> <name> <info>
7020  *
7021  * B version newgrf version, currently 06
7022  * 4*B grf-id globally unique ID of this .grf file
7023  * S name name of this .grf set
7024  * S info string describing the set, and e.g. author and copyright */
7025 
7026  uint8_t version = buf.ReadByte();
7027  uint32_t grfid = buf.ReadDWord();
7028  std::string_view name = buf.ReadString();
7029 
7030  if (_cur.stage < GLS_RESERVE && _cur.grfconfig->status != GCS_UNKNOWN) {
7031  DisableGrf(STR_NEWGRF_ERROR_MULTIPLE_ACTION_8);
7032  return;
7033  }
7034 
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));
7037  _cur.grffile->grfid = grfid;
7038  }
7039 
7040  _cur.grffile->grf_version = version;
7041  _cur.grfconfig->status = _cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED;
7042 
7043  /* Install the default cargo translation table. */
7044  if (_cur.stage < GLS_RESERVE && _cur.grffile->cargo_list.empty()) {
7045  auto default_table = GetDefaultCargoTranslationTable(version);
7046  _cur.grffile->cargo_list.assign(default_table.begin(), default_table.end());
7047  GrfMsg(3, "GRFInfo: Installing default GRFv{} translation table for {:08X}", version, BSWAP32(grfid));
7048  }
7049 
7050  /* Do swap the GRFID for displaying purposes since people expect that */
7051  Debug(grf, 1, "GRFInfo: Loaded GRFv{} set {:08X} - {} (palette: {}, version: {})", version, BSWAP32(grfid), StrMakeValid(name), (_cur.grfconfig->palette & GRFP_USE_MASK) ? "Windows" : "DOS", _cur.grfconfig->version);
7052 }
7053 
7060 static bool IsGRMReservedSprite(SpriteID first_sprite, uint16_t num_sprites)
7061 {
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;
7065  }
7066  return false;
7067 }
7068 
7069 /* Action 0x0A */
7070 static void SpriteReplace(ByteReader &buf)
7071 {
7072  /* <0A> <num-sets> <set1> [<set2> ...]
7073  * <set>: <num-sprites> <first-sprite>
7074  *
7075  * B num-sets How many sets of sprites to replace.
7076  * Each set:
7077  * B num-sprites How many sprites are in this set
7078  * W first-sprite First sprite number to replace */
7079 
7080  uint8_t num_sets = buf.ReadByte();
7081 
7082  for (uint i = 0; i < num_sets; i++) {
7083  uint8_t num_sprites = buf.ReadByte();
7084  uint16_t first_sprite = buf.ReadWord();
7085 
7086  GrfMsg(2, "SpriteReplace: [Set {}] Changing {} sprites, beginning with {}",
7087  i, num_sprites, first_sprite
7088  );
7089 
7090  if (first_sprite + num_sprites >= SPR_OPENTTD_BASE) {
7091  /* Outside allowed range, check for GRM sprite reservations. */
7092  if (!IsGRMReservedSprite(first_sprite, num_sprites)) {
7093  GrfMsg(0, "SpriteReplace: [Set {}] Changing {} sprites, beginning with {}, above limit of {} and not within reserved range, ignoring.",
7094  i, num_sprites, first_sprite, SPR_OPENTTD_BASE);
7095 
7096  /* Load the sprites at the current location so they will do nothing instead of appearing to work. */
7097  first_sprite = _cur.spriteid;
7098  _cur.spriteid += num_sprites;
7099  }
7100  }
7101 
7102  for (uint j = 0; j < num_sprites; j++) {
7103  SpriteID load_index = first_sprite + j;
7104  _cur.nfo_line++;
7105  LoadNextSprite(load_index, *_cur.file, _cur.nfo_line); // XXX
7106 
7107  /* Shore sprites now located at different addresses.
7108  * So detect when the old ones get replaced. */
7109  if (IsInsideMM(load_index, SPR_ORIGINALSHORE_START, SPR_ORIGINALSHORE_END + 1)) {
7111  }
7112  }
7113  }
7114 }
7115 
7116 /* Action 0x0A (SKIP) */
7117 static void SkipActA(ByteReader &buf)
7118 {
7119  uint8_t num_sets = buf.ReadByte();
7120 
7121  for (uint i = 0; i < num_sets; i++) {
7122  /* Skip the sprites this replaces */
7123  _cur.skip_sprites += buf.ReadByte();
7124  /* But ignore where they go */
7125  buf.ReadWord();
7126  }
7127 
7128  GrfMsg(3, "SkipActA: Skipping {} sprites", _cur.skip_sprites);
7129 }
7130 
7131 /* Action 0x0B */
7132 static void GRFLoadError(ByteReader &buf)
7133 {
7134  /* <0B> <severity> <language-id> <message-id> [<message...> 00] [<data...>] 00 [<parnum>]
7135  *
7136  * B severity 00: notice, continue loading grf file
7137  * 01: warning, continue loading grf file
7138  * 02: error, but continue loading grf file, and attempt
7139  * loading grf again when loading or starting next game
7140  * 03: error, abort loading and prevent loading again in
7141  * the future (only when restarting the patch)
7142  * B language-id see action 4, use 1F for built-in error messages
7143  * B message-id message to show, see below
7144  * S message for custom messages (message-id FF), text of the message
7145  * not present for built-in messages.
7146  * V data additional data for built-in (or custom) messages
7147  * B parnum parameter numbers to be shown in the message (maximum of 2) */
7148 
7149  static const StringID msgstr[] = {
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,
7157  };
7158 
7159  static const StringID sevstr[] = {
7160  STR_NEWGRF_ERROR_MSG_INFO,
7161  STR_NEWGRF_ERROR_MSG_WARNING,
7162  STR_NEWGRF_ERROR_MSG_ERROR,
7163  STR_NEWGRF_ERROR_MSG_FATAL
7164  };
7165 
7166  uint8_t severity = buf.ReadByte();
7167  uint8_t lang = buf.ReadByte();
7168  uint8_t message_id = buf.ReadByte();
7169 
7170  /* Skip the error if it isn't valid for the current language. */
7171  if (!CheckGrfLangID(lang, _cur.grffile->grf_version)) return;
7172 
7173  /* Skip the error until the activation stage unless bit 7 of the severity
7174  * is set. */
7175  if (!HasBit(severity, 7) && _cur.stage == GLS_INIT) {
7176  GrfMsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage {}", _cur.stage);
7177  return;
7178  }
7179  ClrBit(severity, 7);
7180 
7181  if (severity >= lengthof(sevstr)) {
7182  GrfMsg(7, "GRFLoadError: Invalid severity id {}. Setting to 2 (non-fatal error).", severity);
7183  severity = 2;
7184  } else if (severity == 3) {
7185  /* This is a fatal error, so make sure the GRF is deactivated and no
7186  * more of it gets loaded. */
7187  DisableGrf();
7188 
7189  /* Make sure we show fatal errors, instead of silly infos from before */
7190  _cur.grfconfig->error.reset();
7191  }
7192 
7193  if (message_id >= lengthof(msgstr) && message_id != 0xFF) {
7194  GrfMsg(7, "GRFLoadError: Invalid message id.");
7195  return;
7196  }
7197 
7198  if (buf.Remaining() <= 1) {
7199  GrfMsg(7, "GRFLoadError: No message data supplied.");
7200  return;
7201  }
7202 
7203  /* For now we can only show one message per newgrf file. */
7204  if (_cur.grfconfig->error.has_value()) return;
7205 
7206  _cur.grfconfig->error = {sevstr[severity]};
7207  GRFError *error = &_cur.grfconfig->error.value();
7208 
7209  if (message_id == 0xFF) {
7210  /* This is a custom error message. */
7211  if (buf.HasData()) {
7212  std::string_view message = buf.ReadString();
7213 
7214  error->custom_message = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER);
7215  } else {
7216  GrfMsg(7, "GRFLoadError: No custom message supplied.");
7217  error->custom_message.clear();
7218  }
7219  } else {
7220  error->message = msgstr[message_id];
7221  }
7222 
7223  if (buf.HasData()) {
7224  std::string_view data = buf.ReadString();
7225 
7226  error->data = TranslateTTDPatchCodes(_cur.grffile->grfid, lang, true, data);
7227  } else {
7228  GrfMsg(7, "GRFLoadError: No message data supplied.");
7229  error->data.clear();
7230  }
7231 
7232  /* Only two parameter numbers can be used in the string. */
7233  for (uint i = 0; i < error->param_value.size() && buf.HasData(); i++) {
7234  uint param_number = buf.ReadByte();
7235  error->param_value[i] = _cur.grffile->GetParam(param_number);
7236  }
7237 }
7238 
7239 /* Action 0x0C */
7240 static void GRFComment(ByteReader &buf)
7241 {
7242  /* <0C> [<ignored...>]
7243  *
7244  * V ignored Anything following the 0C is ignored */
7245 
7246  if (!buf.HasData()) return;
7247 
7248  std::string_view text = buf.ReadString();
7249  GrfMsg(2, "GRFComment: {}", StrMakeValid(text));
7250 }
7251 
7252 /* Action 0x0D (GLS_SAFETYSCAN) */
7253 static void SafeParamSet(ByteReader &buf)
7254 {
7255  uint8_t target = buf.ReadByte();
7256 
7257  /* Writing GRF parameters and some bits of 'misc GRF features' are safe. */
7258  if (target < 0x80 || target == 0x9E) return;
7259 
7260  /* GRM could be unsafe, but as here it can only happen after other GRFs
7261  * are loaded, it should be okay. If the GRF tried to use the slots it
7262  * reserved, it would be marked unsafe anyway. GRM for (e.g. bridge)
7263  * sprites is considered safe. */
7264 
7265  SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
7266 
7267  /* Skip remainder of GRF */
7268  _cur.skip_sprites = -1;
7269 }
7270 
7271 
7272 static uint32_t GetPatchVariable(uint8_t param)
7273 {
7274  switch (param) {
7275  /* start year - 1920 */
7277 
7278  /* freight trains weight factor */
7279  case 0x0E: return _settings_game.vehicle.freight_trains;
7280 
7281  /* empty wagon speed increase */
7282  case 0x0F: return 0;
7283 
7284  /* plane speed factor; our patch option is reversed from TTDPatch's,
7285  * the following is good for 1x, 2x and 4x (most common?) and...
7286  * well not really for 3x. */
7287  case 0x10:
7289  default:
7290  case 4: return 1;
7291  case 3: return 2;
7292  case 2: return 2;
7293  case 1: return 4;
7294  }
7295 
7296 
7297  /* 2CC colourmap base sprite */
7298  case 0x11: return SPR_2CCMAP_BASE;
7299 
7300  /* map size: format = -MABXYSS
7301  * M : the type of map
7302  * bit 0 : set : squared map. Bit 1 is now not relevant
7303  * clear : rectangle map. Bit 1 will indicate the bigger edge of the map
7304  * bit 1 : set : Y is the bigger edge. Bit 0 is clear
7305  * clear : X is the bigger edge.
7306  * A : minimum edge(log2) of the map
7307  * B : maximum edge(log2) of the map
7308  * XY : edges(log2) of each side of the map.
7309  * SS : combination of both X and Y, thus giving the size(log2) of the map
7310  */
7311  case 0x13: {
7312  uint8_t map_bits = 0;
7313  uint8_t log_X = Map::LogX() - 6; // subtraction is required to make the minimal size (64) zero based
7314  uint8_t log_Y = Map::LogY() - 6;
7315  uint8_t max_edge = std::max(log_X, log_Y);
7316 
7317  if (log_X == log_Y) { // we have a squared map, since both edges are identical
7318  SetBit(map_bits, 0);
7319  } else {
7320  if (max_edge == log_Y) SetBit(map_bits, 1); // edge Y been the biggest, mark it
7321  }
7322 
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);
7325  }
7326 
7327  /* The maximum height of the map. */
7328  case 0x14:
7330 
7331  /* Extra foundations base sprite */
7332  case 0x15:
7333  return SPR_SLOPES_BASE;
7334 
7335  /* Shore base sprite */
7336  case 0x16:
7337  return SPR_SHORE_BASE;
7338 
7339  /* Game map seed */
7340  case 0x17:
7342 
7343  default:
7344  GrfMsg(2, "ParamSet: Unknown Patch variable 0x{:02X}.", param);
7345  return 0;
7346  }
7347 }
7348 
7349 
7350 static uint32_t PerformGRM(uint32_t *grm, uint16_t num_ids, uint16_t count, uint8_t op, uint8_t target, const char *type)
7351 {
7352  uint start = 0;
7353  uint size = 0;
7354 
7355  if (op == 6) {
7356  /* Return GRFID of set that reserved ID */
7357  return grm[_cur.grffile->GetParam(target)];
7358  }
7359 
7360  /* With an operation of 2 or 3, we want to reserve a specific block of IDs */
7361  if (op == 2 || op == 3) start = _cur.grffile->GetParam(target);
7362 
7363  for (uint i = start; i < num_ids; i++) {
7364  if (grm[i] == 0) {
7365  size++;
7366  } else {
7367  if (op == 2 || op == 3) break;
7368  start = i + 1;
7369  size = 0;
7370  }
7371 
7372  if (size == count) break;
7373  }
7374 
7375  if (size == count) {
7376  /* Got the slot... */
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;
7380  }
7381  return start;
7382  }
7383 
7384  /* Unable to allocate */
7385  if (op != 4 && op != 5) {
7386  /* Deactivate GRF */
7387  GrfMsg(0, "ParamSet: GRM: Unable to allocate {} {}, deactivating", count, type);
7388  DisableGrf(STR_NEWGRF_ERROR_GRM_FAILED);
7389  return UINT_MAX;
7390  }
7391 
7392  GrfMsg(1, "ParamSet: GRM: Unable to allocate {} {}", count, type);
7393  return UINT_MAX;
7394 }
7395 
7396 
7398 static void ParamSet(ByteReader &buf)
7399 {
7400  /* <0D> <target> <operation> <source1> <source2> [<data>]
7401  *
7402  * B target parameter number where result is stored
7403  * B operation operation to perform, see below
7404  * B source1 first source operand
7405  * B source2 second source operand
7406  * D data data to use in the calculation, not necessary
7407  * if both source1 and source2 refer to actual parameters
7408  *
7409  * Operations
7410  * 00 Set parameter equal to source1
7411  * 01 Addition, source1 + source2
7412  * 02 Subtraction, source1 - source2
7413  * 03 Unsigned multiplication, source1 * source2 (both unsigned)
7414  * 04 Signed multiplication, source1 * source2 (both signed)
7415  * 05 Unsigned bit shift, source1 by source2 (source2 taken to be a
7416  * signed quantity; left shift if positive and right shift if
7417  * negative, source1 is unsigned)
7418  * 06 Signed bit shift, source1 by source2
7419  * (source2 like in 05, and source1 as well)
7420  */
7421 
7422  uint8_t target = buf.ReadByte();
7423  uint8_t oper = buf.ReadByte();
7424  uint32_t src1 = buf.ReadByte();
7425  uint32_t src2 = buf.ReadByte();
7426 
7427  uint32_t data = 0;
7428  if (buf.Remaining() >= 4) data = buf.ReadDWord();
7429 
7430  /* You can add 80 to the operation to make it apply only if the target
7431  * is not defined yet. In this respect, a parameter is taken to be
7432  * defined if any of the following applies:
7433  * - it has been set to any value in the newgrf(w).cfg parameter list
7434  * - it OR A PARAMETER WITH HIGHER NUMBER has been set to any value by
7435  * an earlier action D */
7436  if (HasBit(oper, 7)) {
7437  if (target < 0x80 && target < _cur.grffile->param_end) {
7438  GrfMsg(7, "ParamSet: Param {} already defined, skipping", target);
7439  return;
7440  }
7441 
7442  oper = GB(oper, 0, 7);
7443  }
7444 
7445  if (src2 == 0xFE) {
7446  if (GB(data, 0, 8) == 0xFF) {
7447  if (data == 0x0000FFFF) {
7448  /* Patch variables */
7449  src1 = GetPatchVariable(src1);
7450  } else {
7451  /* GRF Resource Management */
7452  uint8_t op = src1;
7453  uint8_t feature = GB(data, 8, 8);
7454  uint16_t count = GB(data, 16, 16);
7455 
7456  if (_cur.stage == GLS_RESERVE) {
7457  if (feature == 0x08) {
7458  /* General sprites */
7459  if (op == 0) {
7460  /* Check if the allocated sprites will fit below the original sprite limit */
7461  if (_cur.spriteid + count >= 16384) {
7462  GrfMsg(0, "ParamSet: GRM: Unable to allocate {} sprites; try changing NewGRF order", count);
7463  DisableGrf(STR_NEWGRF_ERROR_GRM_FAILED);
7464  return;
7465  }
7466 
7467  /* Reserve space at the current sprite ID */
7468  GrfMsg(4, "ParamSet: GRM: Allocated {} sprites at {}", count, _cur.spriteid);
7469  _grm_sprites[GRFLocation(_cur.grffile->grfid, _cur.nfo_line)] = std::make_pair(_cur.spriteid, count);
7470  _cur.spriteid += count;
7471  }
7472  }
7473  /* Ignore GRM result during reservation */
7474  src1 = 0;
7475  } else if (_cur.stage == GLS_ACTIVATION) {
7476  switch (feature) {
7477  case 0x00: // Trains
7478  case 0x01: // Road Vehicles
7479  case 0x02: // Ships
7480  case 0x03: // Aircraft
7482  src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles");
7483  if (_cur.skip_sprites == -1) return;
7484  } else {
7485  /* GRM does not apply for dynamic engine allocation. */
7486  switch (op) {
7487  case 2:
7488  case 3:
7489  src1 = _cur.grffile->GetParam(target);
7490  break;
7491 
7492  default:
7493  src1 = 0;
7494  break;
7495  }
7496  }
7497  break;
7498 
7499  case 0x08: // General sprites
7500  switch (op) {
7501  case 0:
7502  /* Return space reserved during reservation stage */
7503  src1 = _grm_sprites[GRFLocation(_cur.grffile->grfid, _cur.nfo_line)].first;
7504  GrfMsg(4, "ParamSet: GRM: Using pre-allocated sprites at {}", src1);
7505  break;
7506 
7507  case 1:
7508  src1 = _cur.spriteid;
7509  break;
7510 
7511  default:
7512  GrfMsg(1, "ParamSet: GRM: Unsupported operation {} for general sprites", op);
7513  return;
7514  }
7515  break;
7516 
7517  case 0x0B: // Cargo
7518  /* There are two ranges: one for cargo IDs and one for cargo bitmasks */
7519  src1 = PerformGRM(_grm_cargoes, NUM_CARGO * 2, count, op, target, "cargoes");
7520  if (_cur.skip_sprites == -1) return;
7521  break;
7522 
7523  default: GrfMsg(1, "ParamSet: GRM: Unsupported feature 0x{:X}", feature); return;
7524  }
7525  } else {
7526  /* Ignore GRM during initialization */
7527  src1 = 0;
7528  }
7529  }
7530  } else {
7531  /* Read another GRF File's parameter */
7532  const GRFFile *file = GetFileByGRFID(data);
7533  GRFConfig *c = GetGRFConfig(data);
7534  if (c != nullptr && HasBit(c->flags, GCF_STATIC) && !HasBit(_cur.grfconfig->flags, GCF_STATIC) && _networking) {
7535  /* Disable the read GRF if it is a static NewGRF. */
7537  src1 = 0;
7538  } else if (file == nullptr || c == nullptr || c->status == GCS_DISABLED) {
7539  src1 = 0;
7540  } else if (src1 == 0xFE) {
7541  src1 = c->version;
7542  } else {
7543  src1 = file->GetParam(src1);
7544  }
7545  }
7546  } else {
7547  /* The source1 and source2 operands refer to the grf parameter number
7548  * like in action 6 and 7. In addition, they can refer to the special
7549  * variables available in action 7, or they can be FF to use the value
7550  * of <data>. If referring to parameters that are undefined, a value
7551  * of 0 is used instead. */
7552  src1 = (src1 == 0xFF) ? data : GetParamVal(src1, nullptr);
7553  src2 = (src2 == 0xFF) ? data : GetParamVal(src2, nullptr);
7554  }
7555 
7556  uint32_t res;
7557  switch (oper) {
7558  case 0x00:
7559  res = src1;
7560  break;
7561 
7562  case 0x01:
7563  res = src1 + src2;
7564  break;
7565 
7566  case 0x02:
7567  res = src1 - src2;
7568  break;
7569 
7570  case 0x03:
7571  res = src1 * src2;
7572  break;
7573 
7574  case 0x04:
7575  res = (int32_t)src1 * (int32_t)src2;
7576  break;
7577 
7578  case 0x05:
7579  if ((int32_t)src2 < 0) {
7580  res = src1 >> -(int32_t)src2;
7581  } else {
7582  res = src1 << (src2 & 0x1F); // Same behaviour as in EvalAdjustT, mask 'value' to 5 bits, which should behave the same on all architectures.
7583  }
7584  break;
7585 
7586  case 0x06:
7587  if ((int32_t)src2 < 0) {
7588  res = (int32_t)src1 >> -(int32_t)src2;
7589  } else {
7590  res = (int32_t)src1 << (src2 & 0x1F); // Same behaviour as in EvalAdjustT, mask 'value' to 5 bits, which should behave the same on all architectures.
7591  }
7592  break;
7593 
7594  case 0x07: // Bitwise AND
7595  res = src1 & src2;
7596  break;
7597 
7598  case 0x08: // Bitwise OR
7599  res = src1 | src2;
7600  break;
7601 
7602  case 0x09: // Unsigned division
7603  if (src2 == 0) {
7604  res = src1;
7605  } else {
7606  res = src1 / src2;
7607  }
7608  break;
7609 
7610  case 0x0A: // Signed division
7611  if (src2 == 0) {
7612  res = src1;
7613  } else {
7614  res = (int32_t)src1 / (int32_t)src2;
7615  }
7616  break;
7617 
7618  case 0x0B: // Unsigned modulo
7619  if (src2 == 0) {
7620  res = src1;
7621  } else {
7622  res = src1 % src2;
7623  }
7624  break;
7625 
7626  case 0x0C: // Signed modulo
7627  if (src2 == 0) {
7628  res = src1;
7629  } else {
7630  res = (int32_t)src1 % (int32_t)src2;
7631  }
7632  break;
7633 
7634  default: GrfMsg(0, "ParamSet: Unknown operation {}, skipping", oper); return;
7635  }
7636 
7637  switch (target) {
7638  case 0x8E: // Y-Offset for train sprites
7639  _cur.grffile->traininfo_vehicle_pitch = res;
7640  break;
7641 
7642  case 0x8F: { // Rail track type cost factors
7643  extern RailTypeInfo _railtypes[RAILTYPE_END];
7644  _railtypes[RAILTYPE_RAIL].cost_multiplier = GB(res, 0, 8);
7646  _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 0, 8);
7647  _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 8, 8);
7648  } else {
7649  _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 8, 8);
7650  _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 16, 8);
7651  }
7652  _railtypes[RAILTYPE_MAGLEV].cost_multiplier = GB(res, 16, 8);
7653  break;
7654  }
7655 
7656  /* not implemented */
7657  case 0x93: // Tile refresh offset to left -- Intended to allow support for larger sprites, not necessary for OTTD
7658  case 0x94: // Tile refresh offset to right
7659  case 0x95: // Tile refresh offset upwards
7660  case 0x96: // Tile refresh offset downwards
7661  case 0x97: // Snow line height -- Better supported by feature 8 property 10h (snow line table) TODO: implement by filling the entire snow line table with the given value
7662  case 0x99: // Global ID offset -- Not necessary since IDs are remapped automatically
7663  GrfMsg(7, "ParamSet: Skipping unimplemented target 0x{:02X}", target);
7664  break;
7665 
7666  case 0x9E: // Miscellaneous GRF features
7667  /* Set train list engine width */
7668  _cur.grffile->traininfo_vehicle_width = HasBit(res, GMB_TRAIN_WIDTH_32_PIXELS) ? VEHICLEINFO_FULL_VEHICLE_WIDTH : TRAININFO_DEFAULT_VEHICLE_WIDTH;
7669  /* Remove the local flags from the global flags */
7671 
7672  /* Only copy safe bits for static grfs */
7673  if (HasBit(_cur.grfconfig->flags, GCF_STATIC)) {
7674  uint32_t safe_bits = 0;
7675  SetBit(safe_bits, GMB_SECOND_ROCKY_TILE_SET);
7676 
7677  _misc_grf_features = (_misc_grf_features & ~safe_bits) | (res & safe_bits);
7678  } else {
7679  _misc_grf_features = res;
7680  }
7681  break;
7682 
7683  case 0x9F: // locale-dependent settings
7684  GrfMsg(7, "ParamSet: Skipping unimplemented target 0x{:02X}", target);
7685  break;
7686 
7687  default:
7688  if (target < 0x80) {
7689  _cur.grffile->param[target] = res;
7690  /* param is zeroed by default */
7691  if (target + 1U > _cur.grffile->param_end) _cur.grffile->param_end = target + 1;
7692  } else {
7693  GrfMsg(7, "ParamSet: Skipping unknown target 0x{:02X}", target);
7694  }
7695  break;
7696  }
7697 }
7698 
7699 /* Action 0x0E (GLS_SAFETYSCAN) */
7700 static void SafeGRFInhibit(ByteReader &buf)
7701 {
7702  /* <0E> <num> <grfids...>
7703  *
7704  * B num Number of GRFIDs that follow
7705  * D grfids GRFIDs of the files to deactivate */
7706 
7707  uint8_t num = buf.ReadByte();
7708 
7709  for (uint i = 0; i < num; i++) {
7710  uint32_t grfid = buf.ReadDWord();
7711 
7712  /* GRF is unsafe it if tries to deactivate other GRFs */
7713  if (grfid != _cur.grfconfig->ident.grfid) {
7714  SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
7715 
7716  /* Skip remainder of GRF */
7717  _cur.skip_sprites = -1;
7718 
7719  return;
7720  }
7721  }
7722 }
7723 
7724 /* Action 0x0E */
7725 static void GRFInhibit(ByteReader &buf)
7726 {
7727  /* <0E> <num> <grfids...>
7728  *
7729  * B num Number of GRFIDs that follow
7730  * D grfids GRFIDs of the files to deactivate */
7731 
7732  uint8_t num = buf.ReadByte();
7733 
7734  for (uint i = 0; i < num; i++) {
7735  uint32_t grfid = buf.ReadDWord();
7736  GRFConfig *file = GetGRFConfig(grfid);
7737 
7738  /* Unset activation flag */
7739  if (file != nullptr && file != _cur.grfconfig) {
7740  GrfMsg(2, "GRFInhibit: Deactivating file '{}'", file->filename);
7741  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_FORCEFULLY_DISABLED, file);
7742  error->data = _cur.grfconfig->GetName();
7743  }
7744  }
7745 }
7746 
7748 static void FeatureTownName(ByteReader &buf)
7749 {
7750  /* <0F> <id> <style-name> <num-parts> <parts>
7751  *
7752  * B id ID of this definition in bottom 7 bits (final definition if bit 7 set)
7753  * V style-name Name of the style (only for final definition)
7754  * B num-parts Number of parts in this definition
7755  * V parts The parts */
7756 
7757  uint32_t grfid = _cur.grffile->grfid;
7758 
7759  GRFTownName *townname = AddGRFTownName(grfid);
7760 
7761  uint8_t id = buf.ReadByte();
7762  GrfMsg(6, "FeatureTownName: definition 0x{:02X}", id & 0x7F);
7763 
7764  if (HasBit(id, 7)) {
7765  /* Final definition */
7766  ClrBit(id, 7);
7767  bool new_scheme = _cur.grffile->grf_version >= 7;
7768 
7769  uint8_t lang = buf.ReadByte();
7770  StringID style = STR_UNDEFINED;
7771 
7772  do {
7773  ClrBit(lang, 7);
7774 
7775  std::string_view name = buf.ReadString();
7776 
7777  std::string lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
7778  GrfMsg(6, "FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name);
7779 
7780  style = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
7781 
7782  lang = buf.ReadByte();
7783  } while (lang != 0);
7784  townname->styles.emplace_back(style, id);
7785  }
7786 
7787  uint8_t parts = buf.ReadByte();
7788  GrfMsg(6, "FeatureTownName: {} parts", parts);
7789 
7790  townname->partlists[id].reserve(parts);
7791  for (uint partnum = 0; partnum < parts; partnum++) {
7792  NamePartList &partlist = townname->partlists[id].emplace_back();
7793  uint8_t texts = buf.ReadByte();
7794  partlist.bitstart = buf.ReadByte();
7795  partlist.bitcount = buf.ReadByte();
7796  partlist.maxprob = 0;
7797  GrfMsg(6, "FeatureTownName: part {} contains {} texts and will use GB(seed, {}, {})", partnum, texts, partlist.bitstart, partlist.bitcount);
7798 
7799  partlist.parts.reserve(texts);
7800  for (uint textnum = 0; textnum < texts; textnum++) {
7801  NamePart &part = partlist.parts.emplace_back();
7802  part.prob = buf.ReadByte();
7803 
7804  if (HasBit(part.prob, 7)) {
7805  uint8_t ref_id = buf.ReadByte();
7806  if (ref_id >= GRFTownName::MAX_LISTS || townname->partlists[ref_id].empty()) {
7807  GrfMsg(0, "FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
7808  DelGRFTownName(grfid);
7809  DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
7810  return;
7811  }
7812  part.id = ref_id;
7813  GrfMsg(6, "FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.prob & 0x7F);
7814  } else {
7815  std::string_view text = buf.ReadString();
7816  part.text = TranslateTTDPatchCodes(grfid, 0, false, text);
7817  GrfMsg(6, "FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.text, part.prob);
7818  }
7819  partlist.maxprob += GB(part.prob, 0, 7);
7820  }
7821  GrfMsg(6, "FeatureTownName: part {}, total probability {}", partnum, partlist.maxprob);
7822  }
7823 }
7824 
7826 static void DefineGotoLabel(ByteReader &buf)
7827 {
7828  /* <10> <label> [<comment>]
7829  *
7830  * B label The label to define
7831  * V comment Optional comment - ignored */
7832 
7833  uint8_t nfo_label = buf.ReadByte();
7834 
7835  _cur.grffile->labels.emplace_back(nfo_label, _cur.nfo_line, _cur.file->GetPos());
7836 
7837  GrfMsg(2, "DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
7838 }
7839 
7844 static void ImportGRFSound(SoundEntry *sound)
7845 {
7846  const GRFFile *file;
7847  uint32_t grfid = _cur.file->ReadDword();
7848  SoundID sound_id = _cur.file->ReadWord();
7849 
7850  file = GetFileByGRFID(grfid);
7851  if (file == nullptr || file->sound_offset == 0) {
7852  GrfMsg(1, "ImportGRFSound: Source file not available");
7853  return;
7854  }
7855 
7856  if (sound_id >= file->num_sounds) {
7857  GrfMsg(1, "ImportGRFSound: Sound effect {} is invalid", sound_id);
7858  return;
7859  }
7860 
7861  GrfMsg(2, "ImportGRFSound: Copying sound {} ({}) from file {:x}", sound_id, file->sound_offset + sound_id, grfid);
7862 
7863  *sound = *GetSound(file->sound_offset + sound_id);
7864 
7865  /* Reset volume and priority, which TTDPatch doesn't copy */
7866  sound->volume = SOUND_EFFECT_MAX_VOLUME;
7867  sound->priority = 0;
7868 }
7869 
7875 static void LoadGRFSound(size_t offs, SoundEntry *sound)
7876 {
7877  /* Set default volume and priority */
7878  sound->volume = SOUND_EFFECT_MAX_VOLUME;
7879  sound->priority = 0;
7880 
7881  if (offs != SIZE_MAX) {
7882  /* Sound is present in the NewGRF. */
7883  sound->file = _cur.file;
7884  sound->file_offset = offs;
7885  sound->grf_container_ver = _cur.file->GetContainerVersion();
7886  }
7887 }
7888 
7889 /* Action 0x11 */
7890 static void GRFSound(ByteReader &buf)
7891 {
7892  /* <11> <num>
7893  *
7894  * W num Number of sound files that follow */
7895 
7896  uint16_t num = buf.ReadWord();
7897  if (num == 0) return;
7898 
7899  SoundEntry *sound;
7900  if (_cur.grffile->sound_offset == 0) {
7901  _cur.grffile->sound_offset = GetNumSounds();
7902  _cur.grffile->num_sounds = num;
7903  sound = AllocateSound(num);
7904  } else {
7905  sound = GetSound(_cur.grffile->sound_offset);
7906  }
7907 
7908  SpriteFile &file = *_cur.file;
7909  uint8_t grf_container_version = file.GetContainerVersion();
7910  for (int i = 0; i < num; i++) {
7911  _cur.nfo_line++;
7912 
7913  /* Check whether the index is in range. This might happen if multiple action 11 are present.
7914  * While this is invalid, we do not check for this. But we should prevent it from causing bigger trouble */
7915  bool invalid = i >= _cur.grffile->num_sounds;
7916 
7917  size_t offs = file.GetPos();
7918 
7919  uint32_t len = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord();
7920  uint8_t type = file.ReadByte();
7921 
7922  if (grf_container_version >= 2 && type == 0xFD) {
7923  /* Reference to sprite section. */
7924  if (invalid) {
7925  GrfMsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
7926  file.SkipBytes(len);
7927  } else if (len != 4) {
7928  GrfMsg(1, "GRFSound: Invalid sprite section import");
7929  file.SkipBytes(len);
7930  } else {
7931  uint32_t id = file.ReadDword();
7932  if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i);
7933  }
7934  continue;
7935  }
7936 
7937  if (type != 0xFF) {
7938  GrfMsg(1, "GRFSound: Unexpected RealSprite found, skipping");
7939  file.SkipBytes(7);
7940  SkipSpriteData(*_cur.file, type, len - 8);
7941  continue;
7942  }
7943 
7944  if (invalid) {
7945  GrfMsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
7946  file.SkipBytes(len);
7947  }
7948 
7949  uint8_t action = file.ReadByte();
7950  switch (action) {
7951  case 0xFF:
7952  /* Allocate sound only in init stage. */
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");
7956  } else {
7957  LoadGRFSound(offs, sound + i);
7958  }
7959  }
7960  file.SkipBytes(len - 1); // already read <action>
7961  break;
7962 
7963  case 0xFE:
7964  if (_cur.stage == GLS_ACTIVATION) {
7965  /* XXX 'Action 0xFE' isn't really specified. It is only mentioned for
7966  * importing sounds, so this is probably all wrong... */
7967  if (file.ReadByte() != 0) GrfMsg(1, "GRFSound: Import type mismatch");
7968  ImportGRFSound(sound + i);
7969  } else {
7970  file.SkipBytes(len - 1); // already read <action>
7971  }
7972  break;
7973 
7974  default:
7975  GrfMsg(1, "GRFSound: Unexpected Action {:x} found, skipping", action);
7976  file.SkipBytes(len - 1); // already read <action>
7977  break;
7978  }
7979  }
7980 }
7981 
7982 /* Action 0x11 (SKIP) */
7983 static void SkipAct11(ByteReader &buf)
7984 {
7985  /* <11> <num>
7986  *
7987  * W num Number of sound files that follow */
7988 
7989  _cur.skip_sprites = buf.ReadWord();
7990 
7991  GrfMsg(3, "SkipAct11: Skipping {} sprites", _cur.skip_sprites);
7992 }
7993 
7995 static void LoadFontGlyph(ByteReader &buf)
7996 {
7997  /* <12> <num_def> <font_size> <num_char> <base_char>
7998  *
7999  * B num_def Number of definitions
8000  * B font_size Size of font (0 = normal, 1 = small, 2 = large, 3 = mono)
8001  * B num_char Number of consecutive glyphs
8002  * W base_char First character index */
8003 
8004  uint8_t num_def = buf.ReadByte();
8005 
8006  for (uint i = 0; i < num_def; i++) {
8007  FontSize size = (FontSize)buf.ReadByte();
8008  uint8_t num_char = buf.ReadByte();
8009  uint16_t base_char = buf.ReadWord();
8010 
8011  if (size >= FS_END) {
8012  GrfMsg(1, "LoadFontGlyph: Size {} is not supported, ignoring", size);
8013  }
8014 
8015  GrfMsg(7, "LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
8016 
8017  for (uint c = 0; c < num_char; c++) {
8018  if (size < FS_END) SetUnicodeGlyph(size, base_char + c, _cur.spriteid);
8019  _cur.nfo_line++;
8020  LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line);
8021  }
8022  }
8023 }
8024 
8026 static void SkipAct12(ByteReader &buf)
8027 {
8028  /* <12> <num_def> <font_size> <num_char> <base_char>
8029  *
8030  * B num_def Number of definitions
8031  * B font_size Size of font (0 = normal, 1 = small, 2 = large)
8032  * B num_char Number of consecutive glyphs
8033  * W base_char First character index */
8034 
8035  uint8_t num_def = buf.ReadByte();
8036 
8037  for (uint i = 0; i < num_def; i++) {
8038  /* Ignore 'size' byte */
8039  buf.ReadByte();
8040 
8041  /* Sum up number of characters */
8042  _cur.skip_sprites += buf.ReadByte();
8043 
8044  /* Ignore 'base_char' word */
8045  buf.ReadWord();
8046  }
8047 
8048  GrfMsg(3, "SkipAct12: Skipping {} sprites", _cur.skip_sprites);
8049 }
8050 
8053 {
8054  /* <13> <grfid> <num-ent> <offset> <text...>
8055  *
8056  * 4*B grfid The GRFID of the file whose texts are to be translated
8057  * B num-ent Number of strings
8058  * W offset First text ID
8059  * S text... Zero-terminated strings */
8060 
8061  uint32_t grfid = buf.ReadDWord();
8062  const GRFConfig *c = GetGRFConfig(grfid);
8063  if (c == nullptr || (c->status != GCS_INITIALISED && c->status != GCS_ACTIVATED)) {
8064  GrfMsg(7, "TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13", BSWAP32(grfid));
8065  return;
8066  }
8067 
8068  if (c->status == GCS_INITIALISED) {
8069  /* If the file is not active but will be activated later, give an error
8070  * and disable this file. */
8071  GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LOAD_AFTER);
8072 
8073  error->data = GetString(STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE);
8074 
8075  return;
8076  }
8077 
8078  /* Since no language id is supplied for with version 7 and lower NewGRFs, this string has
8079  * to be added as a generic string, thus the language id of 0x7F. For this to work
8080  * new_scheme has to be true as well, which will also be implicitly the case for version 8
8081  * and higher. A language id of 0x7F will be overridden by a non-generic id, so this will
8082  * not change anything if a string has been provided specifically for this language. */
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();
8086 
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);
8089  return;
8090  }
8091 
8092  for (uint i = 0; i < num_strings && buf.HasData(); i++) {
8093  std::string_view string = buf.ReadString();
8094 
8095  if (string.empty()) {
8096  GrfMsg(7, "TranslateGRFString: Ignoring empty string.");
8097  continue;
8098  }
8099 
8100  AddGRFString(grfid, first_id + i, language, true, true, string, STR_UNDEFINED);
8101  }
8102 }
8103 
8105 static bool ChangeGRFName(uint8_t langid, std::string_view str)
8106 {
8107  AddGRFTextToList(_cur.grfconfig->name, langid, _cur.grfconfig->ident.grfid, false, str);
8108  return true;
8109 }
8110 
8112 static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
8113 {
8114  AddGRFTextToList(_cur.grfconfig->info, langid, _cur.grfconfig->ident.grfid, true, str);
8115  return true;
8116 }
8117 
8119 static bool ChangeGRFURL(uint8_t langid, std::string_view str)
8120 {
8121  AddGRFTextToList(_cur.grfconfig->url, langid, _cur.grfconfig->ident.grfid, false, str);
8122  return true;
8123 }
8124 
8126 static bool ChangeGRFNumUsedParams(size_t len, ByteReader &buf)
8127 {
8128  if (len != 1) {
8129  GrfMsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'NPAR' but got {}, ignoring this field", len);
8130  buf.Skip(len);
8131  } else {
8132  _cur.grfconfig->num_valid_params = std::min(buf.ReadByte(), ClampTo<uint8_t>(_cur.grfconfig->param.size()));
8133  }
8134  return true;
8135 }
8136 
8138 static bool ChangeGRFPalette(size_t len, ByteReader &buf)
8139 {
8140  if (len != 1) {
8141  GrfMsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'PALS' but got {}, ignoring this field", len);
8142  buf.Skip(len);
8143  } else {
8144  char data = buf.ReadByte();
8145  GRFPalette pal = GRFP_GRF_UNSET;
8146  switch (data) {
8147  case '*':
8148  case 'A': pal = GRFP_GRF_ANY; break;
8149  case 'W': pal = GRFP_GRF_WINDOWS; break;
8150  case 'D': pal = GRFP_GRF_DOS; break;
8151  default:
8152  GrfMsg(2, "StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'PALS', ignoring this field", data);
8153  break;
8154  }
8155  if (pal != GRFP_GRF_UNSET) {
8156  _cur.grfconfig->palette &= ~GRFP_GRF_MASK;
8157  _cur.grfconfig->palette |= pal;
8158  }
8159  }
8160  return true;
8161 }
8162 
8164 static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
8165 {
8166  if (len != 1) {
8167  GrfMsg(2, "StaticGRFInfo: expected only 1 byte for 'INFO'->'BLTR' but got {}, ignoring this field", len);
8168  buf.Skip(len);
8169  } else {
8170  char data = buf.ReadByte();
8171  GRFPalette pal = GRFP_BLT_UNSET;
8172  switch (data) {
8173  case '8': pal = GRFP_BLT_UNSET; break;
8174  case '3': pal = GRFP_BLT_32BPP; break;
8175  default:
8176  GrfMsg(2, "StaticGRFInfo: unexpected value '{:02X}' for 'INFO'->'BLTR', ignoring this field", data);
8177  return true;
8178  }
8179  _cur.grfconfig->palette &= ~GRFP_BLT_MASK;
8180  _cur.grfconfig->palette |= pal;
8181  }
8182  return true;
8183 }
8184 
8186 static bool ChangeGRFVersion(size_t len, ByteReader &buf)
8187 {
8188  if (len != 4) {
8189  GrfMsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'VRSN' but got {}, ignoring this field", len);
8190  buf.Skip(len);
8191  } else {
8192  /* Set min_loadable_version as well (default to minimal compatibility) */
8193  _cur.grfconfig->version = _cur.grfconfig->min_loadable_version = buf.ReadDWord();
8194  }
8195  return true;
8196 }
8197 
8199 static bool ChangeGRFMinVersion(size_t len, ByteReader &buf)
8200 {
8201  if (len != 4) {
8202  GrfMsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'MINV' but got {}, ignoring this field", len);
8203  buf.Skip(len);
8204  } else {
8205  _cur.grfconfig->min_loadable_version = buf.ReadDWord();
8206  if (_cur.grfconfig->version == 0) {
8207  GrfMsg(2, "StaticGRFInfo: 'MINV' defined before 'VRSN' or 'VRSN' set to 0, ignoring this field");
8208  _cur.grfconfig->min_loadable_version = 0;
8209  }
8210  if (_cur.grfconfig->version < _cur.grfconfig->min_loadable_version) {
8211  GrfMsg(2, "StaticGRFInfo: 'MINV' defined as {}, limiting it to 'VRSN'", _cur.grfconfig->min_loadable_version);
8213  }
8214  }
8215  return true;
8216 }
8217 
8219 
8221 static bool ChangeGRFParamName(uint8_t langid, std::string_view str)
8222 {
8223  AddGRFTextToList(_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
8224  return true;
8225 }
8226 
8228 static bool ChangeGRFParamDescription(uint8_t langid, std::string_view str)
8229 {
8230  AddGRFTextToList(_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
8231  return true;
8232 }
8233 
8235 static bool ChangeGRFParamType(size_t len, ByteReader &buf)
8236 {
8237  if (len != 1) {
8238  GrfMsg(2, "StaticGRFInfo: expected 1 byte for 'INFO'->'PARA'->'TYPE' but got {}, ignoring this field", len);
8239  buf.Skip(len);
8240  } else {
8241  GRFParameterType type = (GRFParameterType)buf.ReadByte();
8242  if (type < PTYPE_END) {
8243  _cur_parameter->type = type;
8244  } else {
8245  GrfMsg(3, "StaticGRFInfo: unknown parameter type {}, ignoring this field", type);
8246  }
8247  }
8248  return true;
8249 }
8250 
8252 static bool ChangeGRFParamLimits(size_t len, ByteReader &buf)
8253 {
8255  GrfMsg(2, "StaticGRFInfo: 'INFO'->'PARA'->'LIMI' is only valid for parameters with type uint/enum, ignoring this field");
8256  buf.Skip(len);
8257  } else if (len != 8) {
8258  GrfMsg(2, "StaticGRFInfo: expected 8 bytes for 'INFO'->'PARA'->'LIMI' but got {}, ignoring this field", len);
8259  buf.Skip(len);
8260  } else {
8261  uint32_t min_value = buf.ReadDWord();
8262  uint32_t max_value = buf.ReadDWord();
8263  if (min_value <= max_value) {
8264  _cur_parameter->min_value = min_value;
8265  _cur_parameter->max_value = max_value;
8266  } else {
8267  GrfMsg(2, "StaticGRFInfo: 'INFO'->'PARA'->'LIMI' values are incoherent, ignoring this field");
8268  }
8269  }
8270  return true;
8271 }
8272 
8274 static bool ChangeGRFParamMask(size_t len, ByteReader &buf)
8275 {
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);
8278  buf.Skip(len);
8279  } else {
8280  uint8_t param_nr = buf.ReadByte();
8281  if (param_nr >= _cur.grfconfig->param.size()) {
8282  GrfMsg(2, "StaticGRFInfo: invalid parameter number in 'INFO'->'PARA'->'MASK', param {}, ignoring this field", param_nr);
8283  buf.Skip(len - 1);
8284  } else {
8285  _cur_parameter->param_nr = param_nr;
8286  if (len >= 2) _cur_parameter->first_bit = std::min<uint8_t>(buf.ReadByte(), 31);
8287  if (len >= 3) _cur_parameter->num_bit = std::min<uint8_t>(buf.ReadByte(), 32 - _cur_parameter->first_bit);
8288  }
8289  }
8290 
8291  return true;
8292 }
8293 
8295 static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
8296 {
8297  if (len != 4) {
8298  GrfMsg(2, "StaticGRFInfo: expected 4 bytes for 'INFO'->'PARA'->'DEFA' but got {}, ignoring this field", len);
8299  buf.Skip(len);
8300  } else {
8301  _cur_parameter->def_value = buf.ReadDWord();
8302  }
8303  _cur.grfconfig->has_param_defaults = true;
8304  return true;
8305 }
8306 
8307 typedef bool (*DataHandler)(size_t, ByteReader &);
8308 typedef bool (*TextHandler)(uint8_t, std::string_view str);
8309 typedef bool (*BranchHandler)(ByteReader &);
8310 
8321  id(0),
8322  type(0)
8323  {}
8324 
8330  AllowedSubtags(uint32_t id, DataHandler handler) :
8331  id(id),
8332  type('B')
8333  {
8334  this->handler.data = handler;
8335  }
8336 
8342  AllowedSubtags(uint32_t id, TextHandler handler) :
8343  id(id),
8344  type('T')
8345  {
8346  this->handler.text = handler;
8347  }
8348 
8354  AllowedSubtags(uint32_t id, BranchHandler handler) :
8355  id(id),
8356  type('C')
8357  {
8358  this->handler.call_handler = true;
8359  this->handler.u.branch = handler;
8360  }
8361 
8368  id(id),
8369  type('C')
8370  {
8371  this->handler.call_handler = false;
8372  this->handler.u.subtags = subtags;
8373  }
8374 
8375  uint32_t id;
8376  uint8_t type;
8377  union {
8380  struct {
8381  union {
8384  } u;
8386  };
8387  } handler;
8388 };
8389 
8390 static bool SkipUnknownInfo(ByteReader &buf, uint8_t type);
8391 static bool HandleNodes(ByteReader &buf, AllowedSubtags *tags);
8392 
8400 {
8401  uint8_t type = buf.ReadByte();
8402  while (type != 0) {
8403  uint32_t id = buf.ReadDWord();
8404  if (type != 'T' || id > _cur_parameter->max_value) {
8405  GrfMsg(2, "StaticGRFInfo: all child nodes of 'INFO'->'PARA'->param_num->'VALU' should have type 't' and the value/bit number as id");
8406  if (!SkipUnknownInfo(buf, type)) return false;
8407  type = buf.ReadByte();
8408  continue;
8409  }
8410 
8411  uint8_t langid = buf.ReadByte();
8412  std::string_view name_string = buf.ReadString();
8413 
8414  auto val_name = _cur_parameter->value_names.find(id);
8415  if (val_name != _cur_parameter->value_names.end()) {
8416  AddGRFTextToList(val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
8417  } else {
8418  GRFTextList list;
8419  AddGRFTextToList(list, langid, _cur.grfconfig->ident.grfid, false, name_string);
8420  _cur_parameter->value_names[id] = list;
8421  }
8422 
8423  type = buf.ReadByte();
8424  }
8425  return true;
8426 }
8427 
8437  AllowedSubtags()
8438 };
8439 
8447 {
8448  uint8_t type = buf.ReadByte();
8449  while (type != 0) {
8450  uint32_t id = buf.ReadDWord();
8451  if (type != 'C' || id >= _cur.grfconfig->num_valid_params) {
8452  GrfMsg(2, "StaticGRFInfo: all child nodes of 'INFO'->'PARA' should have type 'C' and their parameter number as id");
8453  if (!SkipUnknownInfo(buf, type)) return false;
8454  type = buf.ReadByte();
8455  continue;
8456  }
8457 
8458  if (id >= _cur.grfconfig->param_info.size()) {
8459  _cur.grfconfig->param_info.resize(id + 1);
8460  }
8461  if (!_cur.grfconfig->param_info[id].has_value()) {
8462  _cur.grfconfig->param_info[id] = GRFParameterInfo(id);
8463  }
8464  _cur_parameter = &_cur.grfconfig->param_info[id].value();
8465  /* Read all parameter-data and process each node. */
8466  if (!HandleNodes(buf, _tags_parameters)) return false;
8467  type = buf.ReadByte();
8468  }
8469  return true;
8470 }
8471 
8474  AllowedSubtags('NAME', ChangeGRFName),
8476  AllowedSubtags('URL_', ChangeGRFURL),
8483  AllowedSubtags()
8484 };
8485 
8488  AllowedSubtags('INFO', _tags_info),
8489  AllowedSubtags()
8490 };
8491 
8492 
8499 static bool SkipUnknownInfo(ByteReader &buf, uint8_t type)
8500 {
8501  /* type and id are already read */
8502  switch (type) {
8503  case 'C': {
8504  uint8_t new_type = buf.ReadByte();
8505  while (new_type != 0) {
8506  buf.ReadDWord(); // skip the id
8507  if (!SkipUnknownInfo(buf, new_type)) return false;
8508  new_type = buf.ReadByte();
8509  }
8510  break;
8511  }
8512 
8513  case 'T':
8514  buf.ReadByte(); // lang
8515  buf.ReadString(); // actual text
8516  break;
8517 
8518  case 'B': {
8519  uint16_t size = buf.ReadWord();
8520  buf.Skip(size);
8521  break;
8522  }
8523 
8524  default:
8525  return false;
8526  }
8527 
8528  return true;
8529 }
8530 
8539 static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, AllowedSubtags subtags[])
8540 {
8541  uint i = 0;
8542  AllowedSubtags *tag;
8543  while ((tag = &subtags[i++])->type != 0) {
8544  if (tag->id != BSWAP32(id) || tag->type != type) continue;
8545  switch (type) {
8546  default: NOT_REACHED();
8547 
8548  case 'T': {
8549  uint8_t langid = buf.ReadByte();
8550  return tag->handler.text(langid, buf.ReadString());
8551  }
8552 
8553  case 'B': {
8554  size_t len = buf.ReadWord();
8555  if (buf.Remaining() < len) return false;
8556  return tag->handler.data(len, buf);
8557  }
8558 
8559  case 'C': {
8560  if (tag->handler.call_handler) {
8561  return tag->handler.u.branch(buf);
8562  }
8563  return HandleNodes(buf, tag->handler.u.subtags);
8564  }
8565  }
8566  }
8567  GrfMsg(2, "StaticGRFInfo: unknown type/id combination found, type={:c}, id={:x}", type, id);
8568  return SkipUnknownInfo(buf, type);
8569 }
8570 
8577 static bool HandleNodes(ByteReader &buf, AllowedSubtags subtags[])
8578 {
8579  uint8_t type = buf.ReadByte();
8580  while (type != 0) {
8581  uint32_t id = buf.ReadDWord();
8582  if (!HandleNode(type, id, buf, subtags)) return false;
8583  type = buf.ReadByte();
8584  }
8585  return true;
8586 }
8587 
8592 static void StaticGRFInfo(ByteReader &buf)
8593 {
8594  /* <14> <type> <id> <text/data...> */
8595  HandleNodes(buf, _tags_root);
8596 }
8597 
8602 static void GRFUnsafe(ByteReader &)
8603 {
8604  SetBit(_cur.grfconfig->flags, GCF_UNSAFE);
8605 
8606  /* Skip remainder of GRF */
8607  _cur.skip_sprites = -1;
8608 }
8609 
8610 
8613 {
8614  _ttdpatch_flags[0] = ((_settings_game.station.never_expire_airports ? 1U : 0U) << 0x0C) // keepsmallairport
8615  | (1U << 0x0D) // newairports
8616  | (1U << 0x0E) // largestations
8617  | ((_settings_game.construction.max_bridge_length > 16 ? 1U : 0U) << 0x0F) // longbridges
8618  | (0U << 0x10) // loadtime
8619  | (1U << 0x12) // presignals
8620  | (1U << 0x13) // extpresignals
8621  | ((_settings_game.vehicle.never_expire_vehicles ? 1U : 0U) << 0x16) // enginespersist
8622  | (1U << 0x1B) // multihead
8623  | (1U << 0x1D) // lowmemory
8624  | (1U << 0x1E); // generalfixes
8625 
8626  _ttdpatch_flags[1] = ((_settings_game.economy.station_noise_level ? 1U : 0U) << 0x07) // moreairports - based on units of noise
8627  | (1U << 0x08) // mammothtrains
8628  | (1U << 0x09) // trainrefit
8629  | (0U << 0x0B) // subsidiaries
8630  | ((_settings_game.order.gradual_loading ? 1U : 0U) << 0x0C) // gradualloading
8631  | (1U << 0x12) // unifiedmaglevmode - set bit 0 mode. Not revelant to OTTD
8632  | (1U << 0x13) // unifiedmaglevmode - set bit 1 mode
8633  | (1U << 0x14) // bridgespeedlimits
8634  | (1U << 0x16) // eternalgame
8635  | (1U << 0x17) // newtrains
8636  | (1U << 0x18) // newrvs
8637  | (1U << 0x19) // newships
8638  | (1U << 0x1A) // newplanes
8639  | ((_settings_game.construction.train_signal_side == 1 ? 1U : 0U) << 0x1B) // signalsontrafficside
8640  | ((_settings_game.vehicle.disable_elrails ? 0U : 1U) << 0x1C); // electrifiedrailway
8641 
8642  _ttdpatch_flags[2] = (1U << 0x01) // loadallgraphics - obsolote
8643  | (1U << 0x03) // semaphores
8644  | (1U << 0x0A) // newobjects
8645  | (0U << 0x0B) // enhancedgui
8646  | (0U << 0x0C) // newagerating
8647  | ((_settings_game.construction.build_on_slopes ? 1U : 0U) << 0x0D) // buildonslopes
8648  | (1U << 0x0E) // fullloadany
8649  | (1U << 0x0F) // planespeed
8650  | (0U << 0x10) // moreindustriesperclimate - obsolete
8651  | (0U << 0x11) // moretoylandfeatures
8652  | (1U << 0x12) // newstations
8653  | (1U << 0x13) // tracktypecostdiff
8654  | (1U << 0x14) // manualconvert
8655  | ((_settings_game.construction.build_on_slopes ? 1U : 0U) << 0x15) // buildoncoasts
8656  | (1U << 0x16) // canals
8657  | (1U << 0x17) // newstartyear
8658  | ((_settings_game.vehicle.freight_trains > 1 ? 1U : 0U) << 0x18) // freighttrains
8659  | (1U << 0x19) // newhouses
8660  | (1U << 0x1A) // newbridges
8661  | (1U << 0x1B) // newtownnames
8662  | (1U << 0x1C) // moreanimation
8663  | ((_settings_game.vehicle.wagon_speed_limits ? 1U : 0U) << 0x1D) // wagonspeedlimits
8664  | (1U << 0x1E) // newshistory
8665  | (0U << 0x1F); // custombridgeheads
8666 
8667  _ttdpatch_flags[3] = (0U << 0x00) // newcargodistribution
8668  | (1U << 0x01) // windowsnap
8669  | ((_settings_game.economy.allow_town_roads || _generating_world ? 0U : 1U) << 0x02) // townbuildnoroad
8670  | (1U << 0x03) // pathbasedsignalling
8671  | (0U << 0x04) // aichoosechance
8672  | (1U << 0x05) // resolutionwidth
8673  | (1U << 0x06) // resolutionheight
8674  | (1U << 0x07) // newindustries
8675  | ((_settings_game.order.improved_load ? 1U : 0U) << 0x08) // fifoloading
8676  | (0U << 0x09) // townroadbranchprob
8677  | (0U << 0x0A) // tempsnowline
8678  | (1U << 0x0B) // newcargo
8679  | (1U << 0x0C) // enhancemultiplayer
8680  | (1U << 0x0D) // onewayroads
8681  | (1U << 0x0E) // irregularstations
8682  | (1U << 0x0F) // statistics
8683  | (1U << 0x10) // newsounds
8684  | (1U << 0x11) // autoreplace
8685  | (1U << 0x12) // autoslope
8686  | (0U << 0x13) // followvehicle
8687  | (1U << 0x14) // trams
8688  | (0U << 0x15) // enhancetunnels
8689  | (1U << 0x16) // shortrvs
8690  | (1U << 0x17) // articulatedrvs
8691  | ((_settings_game.vehicle.dynamic_engines ? 1U : 0U) << 0x18) // dynamic engines
8692  | (1U << 0x1E) // variablerunningcosts
8693  | (1U << 0x1F); // any switch is on
8694 
8695  _ttdpatch_flags[4] = (1U << 0x00) // larger persistent storage
8696  | ((_settings_game.economy.inflation ? 1U : 0U) << 0x01) // inflation is on
8697  | (1U << 0x02); // extended string range
8698 }
8699 
8701 static void ResetCustomStations()
8702 {
8703  for (GRFFile * const file : _grf_files) {
8704  file->stations.clear();
8705  }
8706 }
8707 
8709 static void ResetCustomHouses()
8710 {
8711  for (GRFFile * const file : _grf_files) {
8712  file->housespec.clear();
8713  }
8714 }
8715 
8717 static void ResetCustomAirports()
8718 {
8719  for (GRFFile * const file : _grf_files) {
8720  file->airportspec.clear();
8721  file->airtspec.clear();
8722  }
8723 }
8724 
8727 {
8728  for (GRFFile * const file : _grf_files) {
8729  file->industryspec.clear();
8730  file->indtspec.clear();
8731  }
8732 }
8733 
8735 static void ResetCustomObjects()
8736 {
8737  for (GRFFile * const file : _grf_files) {
8738  file->objectspec.clear();
8739  }
8740 }
8741 
8742 static void ResetCustomRoadStops()
8743 {
8744  for (auto file : _grf_files) {
8745  file->roadstops.clear();
8746  }
8747 }
8748 
8750 static void ResetNewGRF()
8751 {
8752  for (GRFFile * const file : _grf_files) {
8753  delete file;
8754  }
8755 
8756  _grf_files.clear();
8757  _cur.grffile = nullptr;
8758 }
8759 
8761 static void ResetNewGRFErrors()
8762 {
8763  for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
8764  c->error.reset();
8765  }
8766 }
8767 
8772 {
8773  CleanUpStrings();
8774  CleanUpGRFTownNames();
8775 
8776  /* Copy/reset original engine info data */
8777  SetupEngines();
8778 
8779  /* Copy/reset original bridge info data */
8780  ResetBridges();
8781 
8782  /* Reset rail type information */
8783  ResetRailTypes();
8784 
8785  /* Copy/reset original road type info data */
8786  ResetRoadTypes();
8787 
8788  /* Allocate temporary refit/cargo class data */
8789  _gted.resize(Engine::GetPoolSize());
8790 
8791  /* Fill rail type label temporary data for default trains */
8792  for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
8793  _gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
8794  }
8795 
8796  /* Reset GRM reservations */
8797  memset(&_grm_engines, 0, sizeof(_grm_engines));
8798  memset(&_grm_cargoes, 0, sizeof(_grm_cargoes));
8799 
8800  /* Reset generic feature callback lists */
8802 
8803  /* Reset price base data */
8805 
8806  /* Reset the curencies array */
8807  ResetCurrencies();
8808 
8809  /* Reset the house array */
8811  ResetHouses();
8812 
8813  /* Reset the industries structures*/
8815  ResetIndustries();
8816 
8817  /* Reset the objects. */
8820  ResetObjects();
8821 
8822  /* Reset station classes */
8825 
8826  /* Reset airport-related structures */
8831 
8832  /* Reset road stop classes */
8834  ResetCustomRoadStops();
8835 
8836  /* Reset canal sprite groups and flags */
8837  memset(_water_feature, 0, sizeof(_water_feature));
8838 
8839  /* Reset the snowline table. */
8840  ClearSnowLine();
8841 
8842  /* Reset NewGRF files */
8843  ResetNewGRF();
8844 
8845  /* Reset NewGRF errors. */
8847 
8848  /* Set up the default cargo types */
8850 
8851  /* Reset misc GRF features and train list display variables */
8852  _misc_grf_features = 0;
8853 
8855  _loaded_newgrf_features.used_liveries = 1 << LS_DEFAULT;
8858 
8859  /* Clear all GRF overrides */
8860  _grf_id_overrides.clear();
8861 
8862  InitializeSoundPool();
8863  _spritegroup_pool.CleanPool();
8864 }
8865 
8870 {
8871  /* Reset override managers */
8872  _engine_mngr.ResetToDefaultMapping();
8873  _house_mngr.ResetMapping();
8874  _industry_mngr.ResetMapping();
8875  _industile_mngr.ResetMapping();
8876  _airport_mngr.ResetMapping();
8877  _airporttile_mngr.ResetMapping();
8878 }
8879 
8885 {
8886  _cur.grffile->cargo_map.fill(UINT8_MAX);
8887 
8888  for (const CargoSpec *cs : CargoSpec::Iterate()) {
8889  if (!cs->IsValid()) continue;
8890 
8891  /* Check the translation table for this cargo's label */
8892  int idx = find_index(_cur.grffile->cargo_list, {cs->label});
8893  if (idx >= 0) _cur.grffile->cargo_map[cs->Index()] = idx;
8894  }
8895 }
8896 
8901 static void InitNewGRFFile(const GRFConfig *config)
8902 {
8903  GRFFile *newfile = GetFileByFilename(config->filename);
8904  if (newfile != nullptr) {
8905  /* We already loaded it once. */
8906  _cur.grffile = newfile;
8907  return;
8908  }
8909 
8910  newfile = new GRFFile(config);
8911  _grf_files.push_back(_cur.grffile = newfile);
8912 }
8913 
8919 {
8920  this->filename = config->filename;
8921  this->grfid = config->ident.grfid;
8922 
8923  /* Initialise local settings to defaults */
8924  this->traininfo_vehicle_pitch = 0;
8925  this->traininfo_vehicle_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
8926 
8927  /* Mark price_base_multipliers as 'not set' */
8928  for (Price i = PR_BEGIN; i < PR_END; i++) {
8929  this->price_base_multipliers[i] = INVALID_PRICE_MODIFIER;
8930  }
8931 
8932  /* Initialise rail type map with default rail types */
8933  std::fill(std::begin(this->railtype_map), std::end(this->railtype_map), INVALID_RAILTYPE);
8934  this->railtype_map[0] = RAILTYPE_RAIL;
8935  this->railtype_map[1] = RAILTYPE_ELECTRIC;
8936  this->railtype_map[2] = RAILTYPE_MONO;
8937  this->railtype_map[3] = RAILTYPE_MAGLEV;
8938 
8939  /* Initialise road type map with default road types */
8940  std::fill(std::begin(this->roadtype_map), std::end(this->roadtype_map), INVALID_ROADTYPE);
8941  this->roadtype_map[0] = ROADTYPE_ROAD;
8942 
8943  /* Initialise tram type map with default tram types */
8944  std::fill(std::begin(this->tramtype_map), std::end(this->tramtype_map), INVALID_ROADTYPE);
8945  this->tramtype_map[0] = ROADTYPE_TRAM;
8946 
8947  /* Copy the initial parameter list
8948  * 'Uninitialised' parameters are zeroed as that is their default value when dynamically creating them. */
8949  this->param = config->param;
8950  this->param_end = config->num_params;
8951 }
8952 
8958 static CargoLabel GetActiveCargoLabel(const std::initializer_list<CargoLabel> &labels)
8959 {
8960  for (const CargoLabel &label : labels) {
8961  CargoID cid = GetCargoIDByLabel(label);
8962  if (cid != INVALID_CARGO) return label;
8963  }
8964  return CT_INVALID;
8965 }
8966 
8972 static CargoLabel GetActiveCargoLabel(const std::variant<CargoLabel, MixedCargoType> &label)
8973 {
8974  struct visitor {
8975  CargoLabel operator()(const CargoLabel &label) { return label; }
8976  CargoLabel operator()(const MixedCargoType &mixed)
8977  {
8978  switch (mixed) {
8979  case MCT_LIVESTOCK_FRUIT: return GetActiveCargoLabel({CT_LIVESTOCK, CT_FRUIT});
8980  case MCT_GRAIN_WHEAT_MAIZE: return GetActiveCargoLabel({CT_GRAIN, CT_WHEAT, CT_MAIZE});
8981  case MCT_VALUABLES_GOLD_DIAMONDS: return GetActiveCargoLabel({CT_VALUABLES, CT_GOLD, CT_DIAMONDS});
8982  default: NOT_REACHED();
8983  }
8984  }
8985  };
8986 
8987  return std::visit(visitor{}, label);
8988 }
8989 
8993 static void CalculateRefitMasks()
8994 {
8995  CargoTypes original_known_cargoes = 0;
8996  for (CargoID cid = 0; cid != NUM_CARGO; ++cid) {
8997  if (IsDefaultCargo(cid)) SetBit(original_known_cargoes, cid);
8998  }
8999 
9000  for (Engine *e : Engine::Iterate()) {
9001  EngineID engine = e->index;
9002  EngineInfo *ei = &e->info;
9003  bool only_defaultcargo;
9004 
9005  /* Apply default cargo translation map if cargo type hasn't been set, either explicitly or by aircraft cargo handling. */
9006  if (!IsValidCargoID(e->info.cargo_type)) {
9007  e->info.cargo_type = GetCargoIDByLabel(GetActiveCargoLabel(e->info.cargo_label));
9008  }
9009 
9010  /* If the NewGRF did not set any cargo properties, we apply default values. */
9011  if (_gted[engine].defaultcargo_grf == nullptr) {
9012  /* If the vehicle has any capacity, apply the default refit masks */
9013  if (e->type != VEH_TRAIN || e->u.rail.capacity != 0) {
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 {
9019  uint8_t climate;
9020  CargoLabel cargo_label;
9021  CargoClasses cargo_allowed;
9022  CargoClasses cargo_disallowed;
9023  } _default_refit_masks[] = {
9024  {T | A | S | Y, CT_PASSENGERS, CC_PASSENGERS, 0},
9025  {T | A | S , CT_MAIL, CC_MAIL, 0},
9026  {T | A | S , CT_VALUABLES, CC_ARMOURED, CC_LIQUID},
9027  { Y, CT_MAIL, CC_MAIL | CC_ARMOURED, CC_LIQUID},
9028  {T | A , CT_COAL, CC_BULK, 0},
9029  { S , CT_COPPER_ORE, CC_BULK, 0},
9030  { Y, CT_SUGAR, CC_BULK, 0},
9031  {T | A | S , CT_OIL, CC_LIQUID, 0},
9032  { Y, CT_COLA, CC_LIQUID, 0},
9033  {T , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
9034  { A | S , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS | CC_REFRIGERATED},
9035  { A | S , CT_FOOD, CC_REFRIGERATED, 0},
9036  { Y, CT_CANDY, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
9037  };
9038 
9039  if (e->type == VEH_AIRCRAFT) {
9040  /* Aircraft default to "light" cargoes */
9041  _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS;
9042  _gted[engine].cargo_disallowed = CC_LIQUID;
9043  } else if (e->type == VEH_SHIP) {
9044  CargoLabel label = GetActiveCargoLabel(ei->cargo_label);
9045  switch (label.base()) {
9046  case CT_PASSENGERS.base():
9047  /* Ferries */
9048  _gted[engine].cargo_allowed = CC_PASSENGERS;
9049  _gted[engine].cargo_disallowed = 0;
9050  break;
9051  case CT_OIL.base():
9052  /* Tankers */
9053  _gted[engine].cargo_allowed = CC_LIQUID;
9054  _gted[engine].cargo_disallowed = 0;
9055  break;
9056  default:
9057  /* Cargo ships */
9058  if (_settings_game.game_creation.landscape == LT_TOYLAND) {
9059  /* No tanker in toyland :( */
9060  _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
9061  _gted[engine].cargo_disallowed = CC_PASSENGERS;
9062  } else {
9063  _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS;
9064  _gted[engine].cargo_disallowed = CC_LIQUID | CC_PASSENGERS;
9065  }
9066  break;
9067  }
9068  e->u.ship.old_refittable = true;
9069  } else if (e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON) {
9070  /* Train engines default to all cargoes, so you can build single-cargo consists with fast engines.
9071  * Trains loading multiple cargoes may start stations accepting unwanted cargoes. */
9072  _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
9073  _gted[engine].cargo_disallowed = 0;
9074  } else {
9075  /* Train wagons and road vehicles are classified by their default cargo type */
9076  CargoLabel label = GetActiveCargoLabel(ei->cargo_label);
9077  for (const auto &drm : _default_refit_masks) {
9078  if (!HasBit(drm.climate, _settings_game.game_creation.landscape)) continue;
9079  if (drm.cargo_label != label) continue;
9080 
9081  _gted[engine].cargo_allowed = drm.cargo_allowed;
9082  _gted[engine].cargo_disallowed = drm.cargo_disallowed;
9083  break;
9084  }
9085 
9086  /* All original cargoes have specialised vehicles, so exclude them */
9087  _gted[engine].ctt_exclude_mask = original_known_cargoes;
9088  }
9089  }
9090  _gted[engine].UpdateRefittability(_gted[engine].cargo_allowed != 0);
9091 
9092  if (IsValidCargoID(ei->cargo_type)) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
9093  }
9094 
9095  /* Compute refittability */
9096  {
9097  CargoTypes mask = 0;
9098  CargoTypes not_mask = 0;
9099  CargoTypes xor_mask = ei->refit_mask;
9100 
9101  /* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo.
9102  * Note: After applying the translations, the vehicle may end up carrying no defined cargo. It becomes unavailable in that case. */
9103  only_defaultcargo = _gted[engine].refittability != GRFTempEngineData::NONEMPTY;
9104 
9105  if (_gted[engine].cargo_allowed != 0) {
9106  /* Build up the list of cargo types from the set cargo classes. */
9107  for (const CargoSpec *cs : CargoSpec::Iterate()) {
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());
9110  }
9111  }
9112 
9113  ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) & _cargo_mask;
9114 
9115  /* Apply explicit refit includes/excludes. */
9116  ei->refit_mask |= _gted[engine].ctt_include_mask;
9117  ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
9118 
9119  /* Custom refit mask callback. */
9120  const GRFFile *file = _gted[e->index].defaultcargo_grf;
9121  if (file == nullptr) file = e->GetGRF();
9122  if (file != nullptr && HasBit(e->info.callback_mask, CBM_VEHICLE_CUSTOM_REFIT)) {
9123  for (const CargoSpec *cs : CargoSpec::Iterate()) {
9124  uint8_t local_slot = file->cargo_map[cs->Index()];
9125  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_CUSTOM_REFIT, cs->classes, local_slot, engine, nullptr);
9126  switch (callback) {
9127  case CALLBACK_FAILED:
9128  case 0:
9129  break; // Do nothing.
9130  case 1: SetBit(ei->refit_mask, cs->Index()); break;
9131  case 2: ClrBit(ei->refit_mask, cs->Index()); break;
9132 
9133  default: ErrorUnknownCallbackResult(file->grfid, CBID_VEHICLE_CUSTOM_REFIT, callback);
9134  }
9135  }
9136  }
9137  }
9138 
9139  /* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */
9140  if (IsValidCargoID(ei->cargo_type) && !HasBit(_cargo_mask, ei->cargo_type)) ei->cargo_type = INVALID_CARGO;
9141 
9142  /* Ensure that the vehicle is either not refittable, or that the default cargo is one of the refittable cargoes.
9143  * Note: Vehicles refittable to no cargo are handle differently to vehicle refittable to a single cargo. The latter might have subtypes. */
9144  if (!only_defaultcargo && (e->type != VEH_SHIP || e->u.ship.old_refittable) && IsValidCargoID(ei->cargo_type) && !HasBit(ei->refit_mask, ei->cargo_type)) {
9145  ei->cargo_type = INVALID_CARGO;
9146  }
9147 
9148  /* Check if this engine's cargo type is valid. If not, set to the first refittable
9149  * cargo type. Finally disable the vehicle, if there is still no cargo. */
9150  if (!IsValidCargoID(ei->cargo_type) && ei->refit_mask != 0) {
9151  /* Figure out which CTT to use for the default cargo, if it is 'first refittable'. */
9152  const GRFFile *file = _gted[engine].defaultcargo_grf;
9153  if (file == nullptr) file = e->GetGRF();
9154  if (file != nullptr && file->grf_version >= 8 && !file->cargo_list.empty()) {
9155  /* Use first refittable cargo from cargo translation table */
9156  uint8_t best_local_slot = UINT8_MAX;
9157  for (CargoID cargo_type : SetCargoBitIterator(ei->refit_mask)) {
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;
9162  }
9163  }
9164  }
9165 
9166  if (!IsValidCargoID(ei->cargo_type)) {
9167  /* Use first refittable cargo slot */
9168  ei->cargo_type = (CargoID)FindFirstBit(ei->refit_mask);
9169  }
9170  }
9171  if (!IsValidCargoID(ei->cargo_type) && e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON && e->u.rail.capacity == 0) {
9172  /* For train engines which do not carry cargo it does not matter if their cargo type is invalid.
9173  * Fallback to the first available instead, if the cargo type has not been changed (as indicated by
9174  * cargo_label not being CT_INVALID). */
9175  if (GetActiveCargoLabel(ei->cargo_label) != CT_INVALID) {
9176  ei->cargo_type = static_cast<CargoID>(FindFirstBit(_standard_cargo_mask));
9177  }
9178  }
9179  if (!IsValidCargoID(ei->cargo_type)) ei->climates = 0;
9180 
9181  /* Clear refit_mask for not refittable ships */
9182  if (e->type == VEH_SHIP && !e->u.ship.old_refittable) {
9183  ei->refit_mask = 0;
9184  }
9185  }
9186 }
9187 
9189 static void FinaliseCanals()
9190 {
9191  for (uint i = 0; i < CF_END; i++) {
9192  if (_water_feature[i].grffile != nullptr) {
9195  }
9196  }
9197 }
9198 
9200 static void FinaliseEngineArray()
9201 {
9202  for (Engine *e : Engine::Iterate()) {
9203  if (e->GetGRF() == nullptr) {
9204  const EngineIDMapping &eid = _engine_mngr[e->index];
9205  if (eid.grfid != INVALID_GRFID || eid.internal_id != eid.substitute_id) {
9206  e->info.string_id = STR_NEWGRF_INVALID_ENGINE;
9207  }
9208  }
9209 
9210  /* Do final mapping on variant engine ID. */
9211  if (e->info.variant_id != INVALID_ENGINE) {
9212  e->info.variant_id = GetNewEngineID(e->grf_prop.grffile, e->type, e->info.variant_id);
9213  }
9214 
9215  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
9216 
9217  /* Skip wagons, there livery is defined via the engine */
9218  if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
9221  /* Note: For ships and roadvehicles we assume that they cannot be refitted between passenger and freight */
9222 
9223  if (e->type == VEH_TRAIN) {
9224  SetBit(_loaded_newgrf_features.used_liveries, LS_FREIGHT_WAGON);
9225  switch (ls) {
9226  case LS_STEAM:
9227  case LS_DIESEL:
9228  case LS_ELECTRIC:
9229  case LS_MONORAIL:
9230  case LS_MAGLEV:
9231  SetBit(_loaded_newgrf_features.used_liveries, LS_PASSENGER_WAGON_STEAM + ls - LS_STEAM);
9232  break;
9233 
9234  case LS_DMU:
9235  case LS_EMU:
9236  SetBit(_loaded_newgrf_features.used_liveries, LS_PASSENGER_WAGON_DIESEL + ls - LS_DMU);
9237  break;
9238 
9239  default: NOT_REACHED();
9240  }
9241  }
9242  }
9243  }
9244 
9245  /* Check engine variants don't point back on themselves (either directly or via a loop) then set appropriate flags
9246  * on variant engine. This is performed separately as all variant engines need to have been resolved. */
9247  for (Engine *e : Engine::Iterate()) {
9248  EngineID parent = e->info.variant_id;
9249  while (parent != INVALID_ENGINE) {
9250  parent = Engine::Get(parent)->info.variant_id;
9251  if (parent != e->index) continue;
9252 
9253  /* Engine looped back on itself, so clear the variant. */
9254  e->info.variant_id = INVALID_ENGINE;
9255 
9256  GrfMsg(1, "FinaliseEngineArray: Variant of engine {:x} in '{}' loops back on itself", _engine_mngr[e->index].internal_id, e->GetGRF()->filename);
9257  break;
9258  }
9259 
9260  if (e->info.variant_id != INVALID_ENGINE) {
9262  }
9263  }
9264 }
9265 
9268 {
9269  for (CargoSpec &cs : CargoSpec::array) {
9270  if (cs.town_production_effect == INVALID_TPE) {
9271  /* Set default town production effect by cargo label. */
9272  switch (cs.label.base()) {
9273  case CT_PASSENGERS.base(): cs.town_production_effect = TPE_PASSENGERS; break;
9274  case CT_MAIL.base(): cs.town_production_effect = TPE_MAIL; break;
9275  default: cs.town_production_effect = TPE_NONE; break;
9276  }
9277  }
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;
9282  }
9283  }
9284 }
9285 
9297 static bool IsHouseSpecValid(HouseSpec *hs, const HouseSpec *next1, const HouseSpec *next2, const HouseSpec *next3, const std::string &filename)
9298 {
9299  if (((hs->building_flags & BUILDING_HAS_2_TILES) != 0 &&
9300  (next1 == nullptr || !next1->enabled || (next1->building_flags & BUILDING_HAS_1_TILE) != 0)) ||
9301  ((hs->building_flags & BUILDING_HAS_4_TILES) != 0 &&
9302  (next2 == nullptr || !next2->enabled || (next2->building_flags & BUILDING_HAS_1_TILE) != 0 ||
9303  next3 == nullptr || !next3->enabled || (next3->building_flags & BUILDING_HAS_1_TILE) != 0))) {
9304  hs->enabled = false;
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);
9306  return false;
9307  }
9308 
9309  /* Some places sum population by only counting north tiles. Other places use all tiles causing desyncs.
9310  * As the newgrf specs define population to be zero for non-north tiles, we just disable the offending house.
9311  * If you want to allow non-zero populations somewhen, make sure to sum the population of all tiles in all places. */
9312  if (((hs->building_flags & BUILDING_HAS_2_TILES) != 0 && next1->population != 0) ||
9313  ((hs->building_flags & BUILDING_HAS_4_TILES) != 0 && (next2->population != 0 || next3->population != 0))) {
9314  hs->enabled = false;
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);
9316  return false;
9317  }
9318 
9319  /* Substitute type is also used for override, and having an override with a different size causes crashes.
9320  * This check should only be done for NewGRF houses because grf_prop.subst_id is not set for original houses.*/
9321  if (!filename.empty() && (hs->building_flags & BUILDING_HAS_1_TILE) != (HouseSpec::Get(hs->grf_prop.subst_id)->building_flags & BUILDING_HAS_1_TILE)) {
9322  hs->enabled = false;
9323  Debug(grf, 1, "FinaliseHouseArray: {} defines house {} with different house size then it's substitute type. Disabling house.", filename, hs->grf_prop.local_id);
9324  return false;
9325  }
9326 
9327  /* Make sure that additional parts of multitile houses are not available. */
9328  if ((hs->building_flags & BUILDING_HAS_1_TILE) == 0 && (hs->building_availability & HZ_ZONALL) != 0 && (hs->building_availability & HZ_CLIMALL) != 0) {
9329  hs->enabled = false;
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);
9331  return false;
9332  }
9333 
9334  return true;
9335 }
9336 
9343 static void EnsureEarlyHouse(HouseZones bitmask)
9344 {
9346 
9347  for (const auto &hs : HouseSpec::Specs()) {
9348  if (!hs.enabled) continue;
9349  if ((hs.building_availability & bitmask) != bitmask) continue;
9350  if (hs.min_year < min_year) min_year = hs.min_year;
9351  }
9352 
9353  if (min_year == 0) return;
9354 
9355  for (auto &hs : HouseSpec::Specs()) {
9356  if (!hs.enabled) continue;
9357  if ((hs.building_availability & bitmask) != bitmask) continue;
9358  if (hs.min_year == min_year) hs.min_year = 0;
9359  }
9360 }
9361 
9368 static void FinaliseHouseArray()
9369 {
9370  /* If there are no houses with start dates before 1930, then all houses
9371  * with start dates of 1930 have them reset to 0. This is in order to be
9372  * compatible with TTDPatch, where if no houses have start dates before
9373  * 1930 and the date is before 1930, the game pretends that this is 1930.
9374  * If there have been any houses defined with start dates before 1930 then
9375  * the dates are left alone.
9376  * On the other hand, why 1930? Just 'fix' the houses with the lowest
9377  * minimum introduction date to 0.
9378  */
9379  for (GRFFile * const file : _grf_files) {
9380  if (file->housespec.empty()) continue;
9381 
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();
9385 
9386  if (hs == nullptr) continue;
9387 
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);
9391 
9392  if (!IsHouseSpecValid(hs, next1, next2, next3, file->filename)) continue;
9393 
9394  _house_mngr.SetEntitySpec(hs);
9395  }
9396  }
9397 
9398  for (size_t i = 0; i < HouseSpec::Specs().size(); i++) {
9399  HouseSpec *hs = HouseSpec::Get(i);
9400  const HouseSpec *next1 = (i + 1 < NUM_HOUSES ? HouseSpec::Get(i + 1) : nullptr);
9401  const HouseSpec *next2 = (i + 2 < NUM_HOUSES ? HouseSpec::Get(i + 2) : nullptr);
9402  const HouseSpec *next3 = (i + 3 < NUM_HOUSES ? HouseSpec::Get(i + 3) : nullptr);
9403 
9404  /* We need to check all houses again to we are sure that multitile houses
9405  * did get consecutive IDs and none of the parts are missing. */
9406  if (!IsHouseSpecValid(hs, next1, next2, next3, std::string{})) {
9407  /* GetHouseNorthPart checks 3 houses that are directly before
9408  * it in the house pool. If any of those houses have multi-tile
9409  * flags set it assumes it's part of a multitile house. Since
9410  * we can have invalid houses in the pool marked as disabled, we
9411  * don't want to have them influencing valid tiles. As such set
9412  * building_flags to zero here to make sure any house following
9413  * this one in the pool is properly handled as 1x1 house. */
9414  hs->building_flags = TILE_NO_FLAG;
9415  }
9416 
9417  /* Apply default cargo translation map for unset cargo slots */
9418  for (uint i = 0; i < lengthof(hs->accepts_cargo_label); ++i) {
9419  if (!IsValidCargoID(hs->accepts_cargo[i])) hs->accepts_cargo[i] = GetCargoIDByLabel(hs->accepts_cargo_label[i]);
9420  /* Disable acceptance if cargo type is invalid. */
9421  if (!IsValidCargoID(hs->accepts_cargo[i])) hs->cargo_acceptance[i] = 0;
9422  }
9423  }
9424 
9425  HouseZones climate_mask = (HouseZones)(1 << (_settings_game.game_creation.landscape + 12));
9426  EnsureEarlyHouse(HZ_ZON1 | climate_mask);
9427  EnsureEarlyHouse(HZ_ZON2 | climate_mask);
9428  EnsureEarlyHouse(HZ_ZON3 | climate_mask);
9429  EnsureEarlyHouse(HZ_ZON4 | climate_mask);
9430  EnsureEarlyHouse(HZ_ZON5 | climate_mask);
9431 
9432  if (_settings_game.game_creation.landscape == LT_ARCTIC) {
9438  }
9439 }
9440 
9447 {
9448  for (GRFFile * const file : _grf_files) {
9449  for (const auto &indsp : file->industryspec) {
9450  if (indsp == nullptr || !indsp->enabled) continue;
9451 
9452  StringID strid;
9453  /* process the conversion of text at the end, so to be sure everything will be fine
9454  * and available. Check if it does not return undefind marker, which is a very good sign of a
9455  * substitute industry who has not changed the string been examined, thus using it as such */
9456  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->name);
9457  if (strid != STR_UNDEFINED) indsp->name = strid;
9458 
9459  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->closure_text);
9460  if (strid != STR_UNDEFINED) indsp->closure_text = strid;
9461 
9462  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_up_text);
9463  if (strid != STR_UNDEFINED) indsp->production_up_text = strid;
9464 
9465  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_down_text);
9466  if (strid != STR_UNDEFINED) indsp->production_down_text = strid;
9467 
9468  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->new_industry_text);
9469  if (strid != STR_UNDEFINED) indsp->new_industry_text = strid;
9470 
9471  if (indsp->station_name != STR_NULL) {
9472  /* STR_NULL (0) can be set by grf. It has a meaning regarding assignation of the
9473  * station's name. Don't want to lose the value, therefore, do not process. */
9474  strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->station_name);
9475  if (strid != STR_UNDEFINED) indsp->station_name = strid;
9476  }
9477 
9478  _industry_mngr.SetEntitySpec(indsp.get());
9479  }
9480 
9481  for (const auto &indtsp : file->indtspec) {
9482  if (indtsp != nullptr) {
9483  _industile_mngr.SetEntitySpec(indtsp.get());
9484  }
9485  }
9486  }
9487 
9488  for (auto &indsp : _industry_specs) {
9489  if (indsp.enabled && indsp.grf_prop.grffile != nullptr) {
9490  for (auto &conflicting : indsp.conflicting) {
9491  conflicting = MapNewGRFIndustryType(conflicting, indsp.grf_prop.grffile->grfid);
9492  }
9493  }
9494  if (!indsp.enabled) {
9495  indsp.name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
9496  }
9497 
9498  /* Apply default cargo translation map for unset cargo slots */
9499  for (size_t i = 0; i < std::size(indsp.produced_cargo_label); ++i) {
9500  if (!IsValidCargoID(indsp.produced_cargo[i])) indsp.produced_cargo[i] = GetCargoIDByLabel(GetActiveCargoLabel(indsp.produced_cargo_label[i]));
9501  }
9502  for (size_t i = 0; i < std::size(indsp.accepts_cargo_label); ++i) {
9503  if (!IsValidCargoID(indsp.accepts_cargo[i])) indsp.accepts_cargo[i] = GetCargoIDByLabel(GetActiveCargoLabel(indsp.accepts_cargo_label[i]));
9504  }
9505  }
9506 
9507  for (auto &indtsp : _industry_tile_specs) {
9508  /* Apply default cargo translation map for unset cargo slots */
9509  for (size_t i = 0; i < std::size(indtsp.accepts_cargo_label); ++i) {
9510  if (!IsValidCargoID(indtsp.accepts_cargo[i])) indtsp.accepts_cargo[i] = GetCargoIDByLabel(GetActiveCargoLabel(indtsp.accepts_cargo_label[i]));
9511  }
9512  }
9513 }
9514 
9521 {
9522  for (GRFFile * const file : _grf_files) {
9523  for (auto &objectspec : file->objectspec) {
9524  if (objectspec != nullptr && objectspec->grf_prop.grffile != nullptr && objectspec->IsEnabled()) {
9525  _object_mngr.SetEntitySpec(objectspec.get());
9526  }
9527  }
9528  }
9529 
9531 }
9532 
9539 {
9540  for (GRFFile * const file : _grf_files) {
9541  for (auto &as : file->airportspec) {
9542  if (as != nullptr && as->enabled) {
9543  _airport_mngr.SetEntitySpec(as.get());
9544  }
9545  }
9546 
9547  for (auto &ats : file->airtspec) {
9548  if (ats != nullptr && ats->enabled) {
9549  _airporttile_mngr.SetEntitySpec(ats.get());
9550  }
9551  }
9552  }
9553 }
9554 
9555 /* Here we perform initial decoding of some special sprites (as are they
9556  * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
9557  * partial implementation yet).
9558  * XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
9559  * a crafted invalid GRF file. We should tell that to the user somehow, or
9560  * better make this more robust in the future. */
9561 static void DecodeSpecialSprite(uint8_t *buf, uint num, GrfLoadingStage stage)
9562 {
9563  /* XXX: There is a difference between staged loading in TTDPatch and
9564  * here. In TTDPatch, for some reason actions 1 and 2 are carried out
9565  * during stage 1, whilst action 3 is carried out during stage 2 (to
9566  * "resolve" cargo IDs... wtf). This is a little problem, because cargo
9567  * IDs are valid only within a given set (action 1) block, and may be
9568  * overwritten after action 3 associates them. But overwriting happens
9569  * in an earlier stage than associating, so... We just process actions
9570  * 1 and 2 in stage 2 now, let's hope that won't get us into problems.
9571  * --pasky
9572  * We need a pre-stage to set up GOTO labels of Action 0x10 because the grf
9573  * is not in memory and scanning the file every time would be too expensive.
9574  * In other stages we skip action 0x10 since it's already dealt with. */
9575  static const SpecialSpriteHandler handlers[][GLS_END] = {
9576  /* 0x00 */ { nullptr, SafeChangeInfo, nullptr, nullptr, ReserveChangeInfo, FeatureChangeInfo, },
9577  /* 0x01 */ { SkipAct1, SkipAct1, SkipAct1, SkipAct1, SkipAct1, NewSpriteSet, },
9578  /* 0x02 */ { nullptr, nullptr, nullptr, nullptr, nullptr, NewSpriteGroup, },
9579  /* 0x03 */ { nullptr, GRFUnsafe, nullptr, nullptr, nullptr, FeatureMapSpriteGroup, },
9580  /* 0x04 */ { nullptr, nullptr, nullptr, nullptr, nullptr, FeatureNewName, },
9581  /* 0x05 */ { SkipAct5, SkipAct5, SkipAct5, SkipAct5, SkipAct5, GraphicsNew, },
9582  /* 0x06 */ { nullptr, nullptr, nullptr, CfgApply, CfgApply, CfgApply, },
9583  /* 0x07 */ { nullptr, nullptr, nullptr, nullptr, SkipIf, SkipIf, },
9584  /* 0x08 */ { ScanInfo, nullptr, nullptr, GRFInfo, GRFInfo, GRFInfo, },
9585  /* 0x09 */ { nullptr, nullptr, nullptr, SkipIf, SkipIf, SkipIf, },
9586  /* 0x0A */ { SkipActA, SkipActA, SkipActA, SkipActA, SkipActA, SpriteReplace, },
9587  /* 0x0B */ { nullptr, nullptr, nullptr, GRFLoadError, GRFLoadError, GRFLoadError, },
9588  /* 0x0C */ { nullptr, nullptr, nullptr, GRFComment, nullptr, GRFComment, },
9589  /* 0x0D */ { nullptr, SafeParamSet, nullptr, ParamSet, ParamSet, ParamSet, },
9590  /* 0x0E */ { nullptr, SafeGRFInhibit, nullptr, GRFInhibit, GRFInhibit, GRFInhibit, },
9591  /* 0x0F */ { nullptr, GRFUnsafe, nullptr, FeatureTownName, nullptr, nullptr, },
9592  /* 0x10 */ { nullptr, nullptr, DefineGotoLabel, nullptr, nullptr, nullptr, },
9593  /* 0x11 */ { SkipAct11, GRFUnsafe, SkipAct11, GRFSound, SkipAct11, GRFSound, },
9595  /* 0x13 */ { nullptr, nullptr, nullptr, nullptr, nullptr, TranslateGRFStrings, },
9596  /* 0x14 */ { StaticGRFInfo, nullptr, nullptr, nullptr, nullptr, nullptr, },
9597  };
9598 
9599  GRFLocation location(_cur.grfconfig->ident.grfid, _cur.nfo_line);
9600 
9601  GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location);
9602  if (it == _grf_line_to_action6_sprite_override.end()) {
9603  /* No preloaded sprite to work with; read the
9604  * pseudo sprite content. */
9605  _cur.file->ReadBlock(buf, num);
9606  } else {
9607  /* Use the preloaded sprite data. */
9608  buf = _grf_line_to_action6_sprite_override[location].data();
9609  GrfMsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data");
9610 
9611  /* Skip the real (original) content of this action. */
9612  _cur.file->SeekTo(num, SEEK_CUR);
9613  }
9614 
9615  ByteReader br(buf, buf + num);
9616 
9617  try {
9618  uint8_t action = br.ReadByte();
9619 
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);
9628  } else {
9629  GrfMsg(7, "DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
9630  handlers[action][stage](br);
9631  }
9632  } catch (...) {
9633  GrfMsg(1, "DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
9634  DisableGrf(STR_NEWGRF_ERROR_READ_BOUNDS);
9635  }
9636 }
9637 
9644 static void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file)
9645 {
9646  _cur.file = &file;
9647  _cur.grfconfig = config;
9648 
9649  Debug(grf, 2, "LoadNewGRFFile: Reading NewGRF-file '{}'", config->filename);
9650 
9651  uint8_t grf_container_version = file.GetContainerVersion();
9652  if (grf_container_version == 0) {
9653  Debug(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
9654  return;
9655  }
9656 
9657  if (stage == GLS_INIT || stage == GLS_ACTIVATION) {
9658  /* We need the sprite offsets in the init stage for NewGRF sounds
9659  * and in the activation stage for real sprites. */
9660  ReadGRFSpriteOffsets(file);
9661  } else {
9662  /* Skip sprite section offset if present. */
9663  if (grf_container_version >= 2) file.ReadDword();
9664  }
9665 
9666  if (grf_container_version >= 2) {
9667  /* Read compression value. */
9668  uint8_t compression = file.ReadByte();
9669  if (compression != 0) {
9670  Debug(grf, 7, "LoadNewGRFFile: Unsupported compression format");
9671  return;
9672  }
9673  }
9674 
9675  /* Skip the first sprite; we don't care about how many sprites this
9676  * does contain; newest TTDPatches and George's longvehicles don't
9677  * neither, apparently. */
9678  uint32_t num = grf_container_version >= 2 ? file.ReadDword() : file.ReadWord();
9679  if (num == 4 && file.ReadByte() == 0xFF) {
9680  file.ReadDword();
9681  } else {
9682  Debug(grf, 7, "LoadNewGRFFile: Custom .grf has invalid format");
9683  return;
9684  }
9685 
9686  _cur.ClearDataForNextFile();
9687 
9689 
9690  while ((num = (grf_container_version >= 2 ? file.ReadDword() : file.ReadWord())) != 0) {
9691  uint8_t type = file.ReadByte();
9692  _cur.nfo_line++;
9693 
9694  if (type == 0xFF) {
9695  if (_cur.skip_sprites == 0) {
9696  DecodeSpecialSprite(buf.Allocate(num), num, stage);
9697 
9698  /* Stop all processing if we are to skip the remaining sprites */
9699  if (_cur.skip_sprites == -1) break;
9700 
9701  continue;
9702  } else {
9703  file.SkipBytes(num);
9704  }
9705  } else {
9706  if (_cur.skip_sprites == 0) {
9707  GrfMsg(0, "LoadNewGRFFile: Unexpected sprite, disabling");
9708  DisableGrf(STR_NEWGRF_ERROR_UNEXPECTED_SPRITE);
9709  break;
9710  }
9711 
9712  if (grf_container_version >= 2 && type == 0xFD) {
9713  /* Reference to data section. Container version >= 2 only. */
9714  file.SkipBytes(num);
9715  } else {
9716  file.SkipBytes(7);
9717  SkipSpriteData(file, type, num - 8);
9718  }
9719  }
9720 
9721  if (_cur.skip_sprites > 0) _cur.skip_sprites--;
9722  }
9723 }
9724 
9733 void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
9734 {
9735  const std::string &filename = config->filename;
9736 
9737  /* A .grf file is activated only if it was active when the game was
9738  * started. If a game is loaded, only its active .grfs will be
9739  * reactivated, unless "loadallgraphics on" is used. A .grf file is
9740  * considered active if its action 8 has been processed, i.e. its
9741  * action 8 hasn't been skipped using an action 7.
9742  *
9743  * During activation, only actions 0, 1, 2, 3, 4, 5, 7, 8, 9, 0A and 0B are
9744  * carried out. All others are ignored, because they only need to be
9745  * processed once at initialization. */
9746  if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
9747  _cur.grffile = GetFileByFilename(filename);
9748  if (_cur.grffile == nullptr) UserError("File '{}' lost in cache.\n", filename);
9749  if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
9750  if (stage == GLS_ACTIVATION && !HasBit(config->flags, GCF_RESERVED)) return;
9751  }
9752 
9753  bool needs_palette_remap = config->palette & GRFP_USE_MASK;
9754  if (temporary) {
9755  SpriteFile temporarySpriteFile(filename, subdir, needs_palette_remap);
9756  LoadNewGRFFileFromFile(config, stage, temporarySpriteFile);
9757  } else {
9758  LoadNewGRFFileFromFile(config, stage, OpenCachedSpriteFile(filename, subdir, needs_palette_remap));
9759  }
9760 }
9761 
9769 static void ActivateOldShore()
9770 {
9771  /* Use default graphics, if no shore sprites were loaded.
9772  * Should not happen, as the base set's extra grf should include some. */
9774 
9776  DupSprite(SPR_ORIGINALSHORE_START + 1, SPR_SHORE_BASE + 1); // SLOPE_W
9777  DupSprite(SPR_ORIGINALSHORE_START + 2, SPR_SHORE_BASE + 2); // SLOPE_S
9778  DupSprite(SPR_ORIGINALSHORE_START + 6, SPR_SHORE_BASE + 3); // SLOPE_SW
9779  DupSprite(SPR_ORIGINALSHORE_START + 0, SPR_SHORE_BASE + 4); // SLOPE_E
9780  DupSprite(SPR_ORIGINALSHORE_START + 4, SPR_SHORE_BASE + 6); // SLOPE_SE
9781  DupSprite(SPR_ORIGINALSHORE_START + 3, SPR_SHORE_BASE + 8); // SLOPE_N
9782  DupSprite(SPR_ORIGINALSHORE_START + 7, SPR_SHORE_BASE + 9); // SLOPE_NW
9783  DupSprite(SPR_ORIGINALSHORE_START + 5, SPR_SHORE_BASE + 12); // SLOPE_NE
9784  }
9785 
9787  DupSprite(SPR_FLAT_GRASS_TILE + 16, SPR_SHORE_BASE + 0); // SLOPE_STEEP_S
9788  DupSprite(SPR_FLAT_GRASS_TILE + 17, SPR_SHORE_BASE + 5); // SLOPE_STEEP_W
9789  DupSprite(SPR_FLAT_GRASS_TILE + 7, SPR_SHORE_BASE + 7); // SLOPE_WSE
9790  DupSprite(SPR_FLAT_GRASS_TILE + 15, SPR_SHORE_BASE + 10); // SLOPE_STEEP_N
9791  DupSprite(SPR_FLAT_GRASS_TILE + 11, SPR_SHORE_BASE + 11); // SLOPE_NWS
9792  DupSprite(SPR_FLAT_GRASS_TILE + 13, SPR_SHORE_BASE + 13); // SLOPE_ENW
9793  DupSprite(SPR_FLAT_GRASS_TILE + 14, SPR_SHORE_BASE + 14); // SLOPE_SEN
9794  DupSprite(SPR_FLAT_GRASS_TILE + 18, SPR_SHORE_BASE + 15); // SLOPE_STEEP_E
9795 
9796  /* XXX - SLOPE_EW, SLOPE_NS are currently not used.
9797  * If they would be used somewhen, then these grass tiles will most like not look as needed */
9798  DupSprite(SPR_FLAT_GRASS_TILE + 5, SPR_SHORE_BASE + 16); // SLOPE_EW
9799  DupSprite(SPR_FLAT_GRASS_TILE + 10, SPR_SHORE_BASE + 17); // SLOPE_NS
9800  }
9801 }
9802 
9807 {
9809  DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0); // use road depot graphics for "no tracks"
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); // use road depot graphics for "no tracks"
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);
9815  }
9816 }
9817 
9822 {
9823  extern const PriceBaseSpec _price_base_specs[];
9825  static const uint32_t override_features = (1 << GSF_TRAINS) | (1 << GSF_ROADVEHICLES) | (1 << GSF_SHIPS) | (1 << GSF_AIRCRAFT);
9826 
9827  /* Evaluate grf overrides */
9828  int num_grfs = (uint)_grf_files.size();
9829  std::vector<int> grf_overrides(num_grfs, -1);
9830  for (int i = 0; i < num_grfs; i++) {
9831  GRFFile *source = _grf_files[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;
9835 
9836  GRFFile *dest = GetFileByGRFID(override);
9837  if (dest == nullptr) continue;
9838 
9839  grf_overrides[i] = find_index(_grf_files, dest);
9840  assert(grf_overrides[i] >= 0);
9841  }
9842 
9843  /* Override features and price base multipliers of earlier loaded grfs */
9844  for (int i = 0; i < num_grfs; i++) {
9845  if (grf_overrides[i] < 0 || grf_overrides[i] >= i) continue;
9846  GRFFile *source = _grf_files[i];
9847  GRFFile *dest = _grf_files[grf_overrides[i]];
9848 
9849  uint32_t features = (source->grf_features | dest->grf_features) & override_features;
9850  source->grf_features |= features;
9851  dest->grf_features |= features;
9852 
9853  for (Price p = PR_BEGIN; p < PR_END; p++) {
9854  /* No price defined -> nothing to do */
9855  if (!HasBit(features, _price_base_specs[p].grf_feature) || source->price_base_multipliers[p] == INVALID_PRICE_MODIFIER) continue;
9856  Debug(grf, 3, "'{}' overrides price base multiplier {} of '{}'", source->filename, p, dest->filename);
9857  dest->price_base_multipliers[p] = source->price_base_multipliers[p];
9858  }
9859  }
9860 
9861  /* Propagate features and price base multipliers of afterwards loaded grfs, if none is present yet */
9862  for (int i = num_grfs - 1; i >= 0; i--) {
9863  if (grf_overrides[i] < 0 || grf_overrides[i] <= i) continue;
9864  GRFFile *source = _grf_files[i];
9865  GRFFile *dest = _grf_files[grf_overrides[i]];
9866 
9867  uint32_t features = (source->grf_features | dest->grf_features) & override_features;
9868  source->grf_features |= features;
9869  dest->grf_features |= features;
9870 
9871  for (Price p = PR_BEGIN; p < PR_END; p++) {
9872  /* Already a price defined -> nothing to do */
9873  if (!HasBit(features, _price_base_specs[p].grf_feature) || dest->price_base_multipliers[p] != INVALID_PRICE_MODIFIER) continue;
9874  Debug(grf, 3, "Price base multiplier {} from '{}' propagated to '{}'", p, source->filename, dest->filename);
9875  dest->price_base_multipliers[p] = source->price_base_multipliers[p];
9876  }
9877  }
9878 
9879  /* The 'master grf' now have the correct multipliers. Assign them to the 'addon grfs' to make everything consistent. */
9880  for (int i = 0; i < num_grfs; i++) {
9881  if (grf_overrides[i] < 0) continue;
9882  GRFFile *source = _grf_files[i];
9883  GRFFile *dest = _grf_files[grf_overrides[i]];
9884 
9885  uint32_t features = (source->grf_features | dest->grf_features) & override_features;
9886  source->grf_features |= features;
9887  dest->grf_features |= features;
9888 
9889  for (Price p = PR_BEGIN; p < PR_END; p++) {
9890  if (!HasBit(features, _price_base_specs[p].grf_feature)) continue;
9891  if (source->price_base_multipliers[p] != dest->price_base_multipliers[p]) {
9892  Debug(grf, 3, "Price base multiplier {} from '{}' propagated to '{}'", p, dest->filename, source->filename);
9893  }
9894  source->price_base_multipliers[p] = dest->price_base_multipliers[p];
9895  }
9896  }
9897 
9898  /* Apply fallback prices for grf version < 8 */
9899  for (GRFFile * const file : _grf_files) {
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++) {
9903  Price fallback_price = _price_base_specs[p].fallback_price;
9904  if (fallback_price != INVALID_PRICE && price_base_multipliers[p] == INVALID_PRICE_MODIFIER) {
9905  /* No price multiplier has been set.
9906  * So copy the multiplier from the fallback price, maybe a multiplier was set there. */
9907  price_base_multipliers[p] = price_base_multipliers[fallback_price];
9908  }
9909  }
9910  }
9911 
9912  /* Decide local/global scope of price base multipliers */
9913  for (GRFFile * const file : _grf_files) {
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) {
9917  /* No multiplier was set; set it to a neutral value */
9918  price_base_multipliers[p] = 0;
9919  } else {
9920  if (!HasBit(file->grf_features, _price_base_specs[p].grf_feature)) {
9921  /* The grf does not define any objects of the feature,
9922  * so it must be a difficulty setting. Apply it globally */
9923  Debug(grf, 3, "'{}' sets global price base multiplier {}", file->filename, p);
9924  SetPriceBaseMultiplier(p, price_base_multipliers[p]);
9925  price_base_multipliers[p] = 0;
9926  } else {
9927  Debug(grf, 3, "'{}' sets local price base multiplier {}", file->filename, p);
9928  }
9929  }
9930  }
9931  }
9932 }
9933 
9934 extern void InitGRFTownGeneratorNames();
9935 
9937 static void AfterLoadGRFs()
9938 {
9940  it.func(MapGRFStringID(it.grfid, it.source));
9941  }
9942  _string_to_grf_mapping.clear();
9943 
9944  /* Clear the action 6 override sprites. */
9945  _grf_line_to_action6_sprite_override.clear();
9946 
9947  /* Polish cargoes */
9949 
9950  /* Pre-calculate all refit masks after loading GRF files. */
9952 
9953  /* Polish engines */
9955 
9956  /* Set the actually used Canal properties */
9957  FinaliseCanals();
9958 
9959  /* Add all new houses to the house array. */
9961 
9962  /* Add all new industries to the industry array. */
9964 
9965  /* Add all new objects to the object array. */
9967 
9969 
9970  /* Sort the list of industry types. */
9972 
9973  /* Create dynamic list of industry legends for smallmap_gui.cpp */
9975 
9976  /* Build the routemap legend, based on the available cargos */
9978 
9979  /* Add all new airports to the airports array. */
9981  BindAirportSpecs();
9982 
9983  /* Update the townname generators list */
9985 
9986  /* Run all queued vehicle list order changes */
9988 
9989  /* Load old shore sprites in new position, if they were replaced by ActionA */
9990  ActivateOldShore();
9991 
9992  /* Load old tram depot sprites in new position, if no new ones are present */
9994 
9995  /* Set up custom rail types */
9996  InitRailTypes();
9997  InitRoadTypes();
9998 
9999  for (Engine *e : Engine::IterateType(VEH_ROAD)) {
10000  if (_gted[e->index].rv_max_speed != 0) {
10001  /* Set RV maximum speed from the mph/0.8 unit value */
10002  e->u.road.max_speed = _gted[e->index].rv_max_speed * 4;
10003  }
10004 
10005  RoadTramType rtt = HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? RTT_TRAM : RTT_ROAD;
10006 
10007  const GRFFile *file = e->GetGRF();
10008  if (file == nullptr || _gted[e->index].roadtramtype == 0) {
10009  e->u.road.roadtype = (rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
10010  continue;
10011  }
10012 
10013  /* Remove +1 offset. */
10014  _gted[e->index].roadtramtype--;
10015 
10016  const std::vector<RoadTypeLabel> *list = (rtt == RTT_TRAM) ? &file->tramtype_list : &file->roadtype_list;
10017  if (_gted[e->index].roadtramtype < list->size())
10018  {
10019  RoadTypeLabel rtl = (*list)[_gted[e->index].roadtramtype];
10020  RoadType rt = GetRoadTypeByLabel(rtl);
10021  if (rt != INVALID_ROADTYPE && GetRoadTramType(rt) == rtt) {
10022  e->u.road.roadtype = rt;
10023  continue;
10024  }
10025  }
10026 
10027  /* Road type is not available, so disable this engine */
10028  e->info.climates = 0;
10029  }
10030 
10031  for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
10032  RailType railtype = GetRailTypeByLabel(_gted[e->index].railtypelabel);
10033  if (railtype == INVALID_RAILTYPE) {
10034  /* Rail type is not available, so disable this engine */
10035  e->info.climates = 0;
10036  } else {
10037  e->u.rail.railtype = railtype;
10038  e->u.rail.intended_railtype = railtype;
10039  }
10040  }
10041 
10043 
10045 
10046  /* Deallocate temporary loading data */
10047  _gted.clear();
10048  _grm_sprites.clear();
10049 }
10050 
10056 void LoadNewGRF(SpriteID load_index, uint num_baseset)
10057 {
10058  /* In case of networking we need to "sync" the start values
10059  * so all NewGRFs are loaded equally. For this we use the
10060  * start date of the game and we set the counters, etc. to
10061  * 0 so they're the same too. */
10062  TimerGameCalendar::Date date = TimerGameCalendar::date;
10065 
10066  TimerGameEconomy::Date economy_date = TimerGameEconomy::date;
10067  TimerGameEconomy::Year economy_year = TimerGameEconomy::year;
10069 
10070  uint64_t tick_counter = TimerGameTick::counter;
10071  uint8_t display_opt = _display_opt;
10072 
10073  if (_networking) {
10077 
10081 
10083  _display_opt = 0;
10084  }
10085 
10087 
10088  ResetNewGRFData();
10089 
10090  /*
10091  * Reset the status of all files, so we can 'retry' to load them.
10092  * This is needed when one for example rearranges the NewGRFs in-game
10093  * and a previously disabled NewGRF becomes usable. If it would not
10094  * be reset, the NewGRF would remain disabled even though it should
10095  * have been enabled.
10096  */
10097  for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
10098  if (c->status != GCS_NOT_FOUND) c->status = GCS_UNKNOWN;
10099  }
10100 
10101  _cur.spriteid = load_index;
10102 
10103  /* Load newgrf sprites
10104  * in each loading stage, (try to) open each file specified in the config
10105  * and load information from it. */
10106  for (GrfLoadingStage stage = GLS_LABELSCAN; stage <= GLS_ACTIVATION; stage++) {
10107  /* Set activated grfs back to will-be-activated between reservation- and activation-stage.
10108  * This ensures that action7/9 conditions 0x06 - 0x0A work correctly. */
10109  for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
10110  if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
10111  }
10112 
10113  if (stage == GLS_RESERVE) {
10114  static const std::pair<uint32_t, uint32_t> default_grf_overrides[] = {
10115  { BSWAP32(0x44442202), BSWAP32(0x44440111) }, // UKRS addons modifies UKRS
10116  { BSWAP32(0x6D620402), BSWAP32(0x6D620401) }, // DBSetXL ECS extension modifies DBSetXL
10117  { BSWAP32(0x4D656f20), BSWAP32(0x4D656F17) }, // LV4cut modifies LV4
10118  };
10119  for (const auto &grf_override : default_grf_overrides) {
10120  SetNewGRFOverride(grf_override.first, grf_override.second);
10121  }
10122  }
10123 
10124  uint num_grfs = 0;
10125  uint num_non_static = 0;
10126 
10127  _cur.stage = stage;
10128  for (GRFConfig *c = _grfconfig; c != nullptr; c = c->next) {
10129  if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
10130  if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue;
10131 
10132  Subdirectory subdir = num_grfs < num_baseset ? BASESET_DIR : NEWGRF_DIR;
10133  if (!FioCheckFileExists(c->filename, subdir)) {
10134  Debug(grf, 0, "NewGRF file is missing '{}'; disabling", c->filename);
10135  c->status = GCS_NOT_FOUND;
10136  continue;
10137  }
10138 
10139  if (stage == GLS_LABELSCAN) InitNewGRFFile(c);
10140 
10141  if (!HasBit(c->flags, GCF_STATIC) && !HasBit(c->flags, GCF_SYSTEM)) {
10142  if (num_non_static == NETWORK_MAX_GRF_COUNT) {
10143  Debug(grf, 0, "'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->filename);
10144  c->status = GCS_DISABLED;
10145  c->error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED};
10146  continue;
10147  }
10148  num_non_static++;
10149  }
10150 
10151  num_grfs++;
10152 
10153  LoadNewGRFFile(c, stage, subdir, false);
10154  if (stage == GLS_RESERVE) {
10155  SetBit(c->flags, GCF_RESERVED);
10156  } else if (stage == GLS_ACTIVATION) {
10157  ClrBit(c->flags, GCF_RESERVED);
10158  assert(GetFileByGRFID(c->ident.grfid) == _cur.grffile);
10161  Debug(sprite, 2, "LoadNewGRF: Currently {} sprites are loaded", _cur.spriteid);
10162  } else if (stage == GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) {
10163  /* We're not going to activate this, so free whatever data we allocated */
10165  }
10166  }
10167  }
10168 
10169  /* Pseudo sprite processing is finished; free temporary stuff */
10170  _cur.ClearDataForNextFile();
10171 
10172  /* Call any functions that should be run after GRFs have been loaded. */
10173  AfterLoadGRFs();
10174 
10175  /* Now revert back to the original situation */
10176  TimerGameCalendar::year = year;
10177  TimerGameCalendar::date = date;
10178  TimerGameCalendar::date_fract = date_fract;
10179 
10180  TimerGameEconomy::year = economy_year;
10181  TimerGameEconomy::date = economy_date;
10182  TimerGameEconomy::date_fract = economy_date_fract;
10183 
10184  TimerGameTick::counter = tick_counter;
10185  _display_opt = display_opt;
10186 }
static const uint INVALID_AIRPORTTILE
id for an invalid airport tile
Definition: airport.h:25
static const uint NEW_AIRPORTTILE_OFFSET
offset of first newgrf airport tile
Definition: airport.h:24
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
Definition: airport.h:39
@ NUM_AIRPORTS_PER_GRF
Maximal number of airports per NewGRF.
Definition: airport.h:40
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...
Definition: airport.h:21
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.
Header file for bridges.
static const uint MAX_BRIDGES
Maximal number of available bridge specs.
Definition: bridge.h:35
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.
Definition: cargo_type.h:71
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
static constexpr CargoLabel CT_PASSENGERS
Available types of cargo Labels may be re-used between different climates.
Definition: cargo_type.h:30
StrongType::Typedef< uint32_t, struct CargoLabelTag, StrongType::Compare > CargoLabel
Globally unique label of a cargo type.
Definition: cargo_type.h:17
MixedCargoType
Mixed cargo types for definitions with cargo that can vary depending on climate.
Definition: cargo_type.h:83
@ MCT_GRAIN_WHEAT_MAIZE
Cargo can be grain, wheat or maize.
Definition: cargo_type.h:85
@ MCT_LIVESTOCK_FRUIT
Cargo can be livestock or fruit.
Definition: cargo_type.h:84
@ MCT_VALUABLES_GOLD_DIAMONDS
Cargo can be valuables, gold or diamonds.
Definition: cargo_type.h:86
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
Definition: cargo_type.h:74
bool IsDefaultCargo(CargoID cid)
Test if a cargo is a default cargo type.
Definition: cargotype.cpp:143
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.
Definition: cargotype.cpp:114
CargoTypes _standard_cargo_mask
Bitmask of real cargo types available.
Definition: cargotype.cpp:36
void BuildCargoLabelMap()
Build cargo label map.
Definition: cargotype.cpp:125
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
Definition: cargotype.cpp:216
void SetupCargoForClimate(LandscapeID l)
Set up the default cargo types for the given landscape type.
Definition: cargotype.cpp:62
CargoTypes _cargo_mask
Bitmask of cargo types available.
Definition: cargotype.cpp:31
@ CC_MAIL
Mail.
Definition: cargotype.h:51
@ CC_REFRIGERATED
Refrigerated cargo (Food, Fruit)
Definition: cargotype.h:57
@ CC_ARMOURED
Armoured cargo (Valuables, Gold, Diamonds)
Definition: cargotype.h:53
@ CC_BULK
Bulk cargo (Coal, Grain etc., Ores, Fruit)
Definition: cargotype.h:54
@ CC_EXPRESS
Express cargo (Goods, Food, Candy, but also possible for passengers)
Definition: cargotype.h:52
@ CC_LIQUID
Liquids (Oil, Water, Rubber)
Definition: cargotype.h:56
@ CC_PIECE_GOODS
Piece goods (Livestock, Wood, Steel, Paper)
Definition: cargotype.h:55
@ CC_PASSENGERS
Passengers.
Definition: cargotype.h:50
@ INVALID_TPE
Invalid town production effect.
Definition: cargotype.h:44
@ TPE_NONE
Town will not produce this cargo type.
Definition: cargotype.h:35
@ TPE_PASSENGERS
Cargo behaves passenger-like for production.
Definition: cargotype.h:36
@ TPE_MAIL
Cargo behaves mail-like for production.
Definition: cargotype.h:37
uint16_t CargoClasses
Bitmask of cargo classes.
Definition: cargotype.h:64
@ TAE_GOODS
Cargo behaves goods/candy-like.
Definition: cargotype.h:26
@ TAE_NONE
Cargo has no effect.
Definition: cargotype.h:23
@ TAE_PASSENGERS
Cargo behaves passenger-like.
Definition: cargotype.h:24
@ TAE_MAIL
Cargo behaves mail-like.
Definition: cargotype.h:25
@ TAE_FOOD
Cargo behaves food/fizzy-drinks-like.
Definition: cargotype.h:28
@ TAE_WATER
Cargo behaves water-like.
Definition: cargotype.h:27
Class to read from a NewGRF file.
Definition: newgrf.cpp:216
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.
Definition: newgrf_class.h:49
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.
Definition: rail.h:127
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:231
TimerGameCalendar::Date introduction_date
Introduction date.
Definition: rail.h:255
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
Definition: rail.h:188
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
Definition: rail.h:266
RailTypes introduction_required_railtypes
Bitmask of railtypes that are required for this railtype to be introduced at a given introduction_dat...
Definition: rail.h:261
uint8_t sorting_order
The sorting order of this railtype for the toolbar dropdown.
Definition: rail.h:271
RailTypeLabel label
Unique 32 bit rail type identifier.
Definition: rail.h:236
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this rail type.
Definition: rail.h:221
const SpriteGroup * group[RTSG_END]
Sprite groups for resolving sprites.
Definition: rail.h:281
uint8_t map_colour
Colour on mini-map.
Definition: rail.h:246
StringID menu_text
Name of this rail type in the main toolbar dropdown.
Definition: rail.h:178
StringID name
Name of this rail type.
Definition: rail.h:176
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel
Definition: rail.h:191
uint8_t fallback_railtype
Original railtype number to use when drawing non-newgrf railtypes, or when drawing stations.
Definition: rail.h:201
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
Definition: rail.h:177
RailTypeFlags flags
Bit mask of rail type flags.
Definition: rail.h:211
uint8_t curve_speed
Multiplier for curve maximum speed advantage.
Definition: rail.h:206
uint16_t cost_multiplier
Cost multiplier for building this rail type.
Definition: rail.h:216
StringID replace_text
Text used in the autoreplace GUI.
Definition: rail.h:180
RailTypeLabelList alternate_labels
Rail type labels this type provides in addition to the main label.
Definition: rail.h:241
StringID build_caption
Caption of the build vehicle GUI for this rail type.
Definition: rail.h:179
StringID new_loco
Name of an engine for this type of rail in the engine preview GUI.
Definition: rail.h:181
const GRFFile * grffile[RTSG_END]
NewGRF providing the Action3 for the railtype.
Definition: rail.h:276
uint8_t acceleration_type
Acceleration type of this rail type.
Definition: rail.h:226
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.
Definition: alloc_type.hpp:42
StringID menu_text
Name of this rail type in the main toolbar dropdown.
Definition: road.h:105
StringID replace_text
Text used in the autoreplace GUI.
Definition: road.h:107
RoadTypeLabelList alternate_labels
Road type labels this type provides in addition to the main label.
Definition: road.h:152
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
Definition: road.h:122
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition: road.h:177
TimerGameCalendar::Date introduction_date
Introduction date.
Definition: road.h:166
const SpriteGroup * group[ROTSG_END]
Sprite groups for resolving sprites.
Definition: road.h:192
uint8_t sorting_order
The sorting order of this roadtype for the toolbar dropdown.
Definition: road.h:182
uint16_t maintenance_multiplier
Cost multiplier for maintenance of this road type.
Definition: road.h:137
RoadTypeFlags flags
Bit mask of road type flags.
Definition: road.h:127
struct RoadTypeInfo::@29 strings
Strings associated with the rail type.
uint8_t map_colour
Colour on mini-map.
Definition: road.h:157
const GRFFile * grffile[ROTSG_END]
NewGRF providing the Action3 for the roadtype.
Definition: road.h:187
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition: road.h:142
StringID name
Name of this rail type.
Definition: road.h:103
StringID toolbar_caption
Caption in the construction toolbar GUI for this rail type.
Definition: road.h:104
StringID new_engine
Name of an engine for this type of road in the engine preview GUI.
Definition: road.h:108
RoadTypes introduction_required_roadtypes
Bitmask of roadtypes that are required for this roadtype to be introduced at a given introduction_dat...
Definition: road.h:172
uint16_t cost_multiplier
Cost multiplier for building this road type.
Definition: road.h:132
StringID build_caption
Caption of the build vehicle GUI for this rail type.
Definition: road.h:106
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.
Definition: config.h:90
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...
Definition: currency.cpp:160
uint8_t GetNewgrfCurrencyIdConverted(uint8_t grfcurr_id)
Will return the ottd's index correspondence to the ttdpatch's id.
Definition: currency.cpp:116
std::array< CurrencySpec, CURRENCY_END > _currency_specs
Array of currencies used by the system.
Definition: currency.cpp:77
Functions to handle different currencies.
@ CURRENCY_END
always the last item
Definition: currency.h:71
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
Direction
Defines the 8 directions on the map.
@ DIR_W
West.
@ DIR_E
East.
void SetPriceBaseMultiplier(Price price, int factor)
Change a price base by the given factor.
Definition: economy.cpp:902
void ResetPriceBaseMultipliers()
Reset changes to the price base multipliers.
Definition: economy.cpp:890
Price
Enumeration of all base prices for use with Prices.
Definition: economy_type.h:89
void SetYearEngineAgingStops()
Compute the value for _year_engine_aging_stops.
Definition: engine.cpp:657
const uint8_t _engine_counts[4]
Number of engines of each vehicle type in original engine data.
Definition: engine.cpp:53
void SetupEngines()
Initialise the engine pool with the data from the original vehicles.
Definition: engine.cpp:565
const uint8_t _engine_offsets[4]
Offset of the first engine of each vehicle type in original engine data.
Definition: engine.cpp:61
Base class for engines.
@ 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.
Definition: engine_type.h:33
@ EC_DIESEL
Diesel rail engine.
Definition: engine_type.h:35
@ EC_STEAM
Steam rail engine.
Definition: engine_type.h:34
@ EC_MAGLEV
Maglev engine.
Definition: engine_type.h:38
@ EC_ELECTRIC
Electric rail engine.
Definition: engine_type.h:36
@ EC_MONORAIL
Mono rail engine.
Definition: engine_type.h:37
@ RAILVEH_SINGLEHEAD
indicates a "standalone" locomotive
Definition: engine_type.h:27
@ RAILVEH_WAGON
simple wagon, not motorized
Definition: engine_type.h:29
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
Definition: engine_type.h:28
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
Definition: engine_type.h:206
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
ExtraEngineFlags
Definition: engine_type.h:131
@ EF_USES_2CC
Vehicle uses two company colours.
Definition: engine_type.h:170
@ EF_ROAD_TRAM
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:169
Functions related to errors.
Error reporting related functions.
bool FioCheckFileExists(const std::string &filename, Subdirectory subdir)
Check whether the given file exists.
Definition: fileio.cpp:121
Functions for Standard In/Out file operations.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition: fileio_type.h:115
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
Definition: fileio_type.h:124
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:123
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.
Definition: fontcache.h:152
bool _generating_world
Whether we are generating the map or not.
Definition: genworld.cpp:67
Functions related to world/map generation.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
FontSize
Available font sizes.
Definition: gfx_type.h:208
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
void SetSnowLine(uint8_t table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
Set a variable snow line, as loaded from a newgrf file.
Definition: landscape.cpp:590
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition: landscape.cpp:609
bool IsSnowLineSet()
Has a snow line table already been loaded.
Definition: landscape.cpp:580
void ClearSnowLine()
Clear the variable snow line table and free the memory.
Definition: landscape.cpp:641
static const HouseID NUM_HOUSES
Total number of houses.
Definition: house.h:29
static const HouseID NEW_HOUSE_OFFSET
Offset for new houses.
Definition: house.h:28
static const HouseID NUM_HOUSES_PER_GRF
Number of supported houses per NewGRF; limited to 255 to allow extending Action3 with an extended byt...
Definition: house.h:25
static const uint HOUSE_ORIGINAL_NUM_ACCEPTS
Original number of accepted cargo types.
Definition: house.h:33
HouseZones
Definition: house.h:66
@ HZ_ZONALL
1F This is just to englobe all above types at once
Definition: house.h:73
@ HZ_CLIMALL
Bitmask of all climate bits.
Definition: house.h:79
@ HZ_ZON5
center of town
Definition: house.h:72
@ HZ_SUBARTC_ABOVE
11 800 can appear in sub-arctic climate above the snow line
Definition: house.h:74
@ HZ_ZON1
0..4 1,2,4,8,10 which town zones the building can be built in, Zone1 been the further suburb
Definition: house.h:68
HouseExtraFlags
Definition: house.h:83
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
Definition: industry_map.h:54
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
Definition: industry_type.h:32
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
Definition: industry_type.h:31
static const IndustryType NEW_INDUSTRYOFFSET
original number of industry types
Definition: industry_type.h:25
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
Definition: industry_type.h:40
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF; limited to 255 to allow extending Action3 with an extend...
Definition: industry_type.h:29
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
Definition: industry_type.h:34
static const int INDUSTRY_ORIGINAL_NUM_OUTPUTS
Original number of produced cargo types.
Definition: industry_type.h:41
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...
Definition: industry_type.h:23
Industry type specs.
IndustryLifeType
Available types of industry lifetimes.
Definition: industrytype.h:22
@ CHECK_NOTHING
Always succeeds.
Definition: industrytype.h:34
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
Definition: industrytype.h:96
IndustryBehaviour
Various industry behaviours mostly to represent original TTD specialities.
Definition: industrytype.h:55
IndustryTileSpecialFlags
Flags for miscellaneous industry tile specialities.
Definition: industrytype.h:82
Functions related to OTTD's landscape.
static const uint SNOW_LINE_DAYS
Number of days in each month in the snow line table.
Definition: landscape.h:17
static const uint SNOW_LINE_MONTHS
Number of months in the snow line table.
Definition: landscape.h:16
Information about languages and their files.
const LanguageMetadata * GetLanguage(uint8_t newgrflangid)
Get the language with the given NewGRF language ID.
Definition: strings.cpp:2046
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
Definition: language.h:20
static const uint8_t MAX_NUM_CASES
Maximum number of supported cases.
Definition: language.h:21
LiveryScheme
List of different livery schemes.
Definition: livery.h:21
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:79
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
void MemSetT(T *ptr, uint8_t value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:49
static constexpr CargoID SG_DEFAULT
Default type used when no more-specific cargo matches.
Definition: newgrf_cargo.h:23
static constexpr CargoID SG_PURCHASE
Used in purchase lists before an item exists.
Definition: newgrf_cargo.h:24
static constexpr CargoID SG_DEFAULT_NA
Used only by stations and roads when no more-specific cargo matches.
Definition: newgrf_cargo.h:25
bool _networking
are we in networking mode?
Definition: network.cpp:65
static void FinaliseObjectsArray()
Add all new objects to the object array.
Definition: newgrf.cpp:9520
static void FinalisePriceBaseMultipliers()
Decide whether price base multipliers of grfs shall apply globally or only to the grf specifying them...
Definition: newgrf.cpp:9821
static void ResetCustomStations()
Reset and clear all NewGRF stations.
Definition: newgrf.cpp:8701
static void SkipAct12(ByteReader &buf)
Action 0x12 (SKIP)
Definition: newgrf.cpp:8026
static std::vector< GRFTempEngineData > _gted
Temporary engine data used during NewGRF loading.
Definition: newgrf.cpp:348
static CargoLabel GetActiveCargoLabel(const std::initializer_list< CargoLabel > &labels)
Find first cargo label that exists and is active from a list of cargo labels.
Definition: newgrf.cpp:8958
bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
Reads a variable common to VarAction2 and Action7/9/D.
Definition: newgrf.cpp:6522
static bool ChangeGRFParamType(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'TYPE' to set the typeof a parameter.
Definition: newgrf.cpp:8235
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader &buf, std::vector< T > &translation_table, const char *name)
Load a cargo- or railtype-translation table.
Definition: newgrf.cpp:2701
bool(* BranchHandler)(ByteReader &)
Type of callback function for branch nodes.
Definition: newgrf.cpp:8309
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 ...
Definition: newgrf.cpp:560
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.
Definition: newgrf.cpp:6349
static void FinaliseIndustriesArray()
Add all new industries to the industry array.
Definition: newgrf.cpp:9446
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.
Definition: newgrf.cpp:8252
static void AddStringForMapping(StringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
Definition: newgrf.cpp:473
static bool ChangeGRFNumUsedParams(size_t len, ByteReader &buf)
Callback function for 'INFO'->'NPAR' to set the number of valid parameters.
Definition: newgrf.cpp:8126
void ResetPersistentNewGRFData()
Reset NewGRF data which is stored persistently in savegames.
Definition: newgrf.cpp:8869
static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, ByteReader &buf)
Define properties for stations.
Definition: newgrf.cpp:1926
static uint32_t _grm_cargoes[NUM_CARGO *2]
Contains the GRF ID of the owner of a cargo if it has been reserved.
Definition: newgrf.cpp:357
static bool ChangeGRFURL(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'URL_' to set the newgrf url.
Definition: newgrf.cpp:8119
static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for road vehicles.
Definition: newgrf.cpp:1361
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.
Definition: newgrf.cpp:5159
bool(* DataHandler)(size_t, ByteReader &)
Type of callback function for binary nodes.
Definition: newgrf.cpp:8307
static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, ByteReader &buf)
Define properties common to all vehicles.
Definition: newgrf.cpp:1010
static void FinaliseAirportsArray()
Add all new airports to the airport array.
Definition: newgrf.cpp:9538
std::span< const Action5Type > GetAction5Types()
Get list of all action 5 types.
Definition: newgrf.cpp:6405
static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, ByteReader &buf)
Define properties for airports.
Definition: newgrf.cpp:3916
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.
Definition: newgrf.cpp:8228
static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for water features.
Definition: newgrf.cpp:2206
static void InitNewGRFFile(const GRFConfig *config)
Prepare loading a NewGRF file with its config.
Definition: newgrf.cpp:8901
static bool ChangeGRFMinVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'MINV' to the minimum compatible version of the NewGRF.
Definition: newgrf.cpp:8199
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.
Definition: newgrf.cpp:9297
static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, ByteReader &buf)
Define properties for global variables.
Definition: newgrf.cpp:2738
static GRFError * DisableGrf(StringID message=STR_NULL, GRFConfig *config=nullptr)
Disable a GRF.
Definition: newgrf.cpp:433
AllowedSubtags _tags_root[]
Action14 root tags.
Definition: newgrf.cpp:8487
static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, ByteReader &buf)
Define properties for cargoes.
Definition: newgrf.cpp:3033
static bool ChangeGRFParamDefault(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'DFLT' to set the default value.
Definition: newgrf.cpp:8295
static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteReader &buf)
Define properties for bridges.
Definition: newgrf.cpp:2244
static void TranslateGRFStrings(ByteReader &buf)
Action 0x13.
Definition: newgrf.cpp:8052
static void GRFUnsafe(ByteReader &)
Set the current NewGRF as unsafe for static use.
Definition: newgrf.cpp:8602
static void DefineGotoLabel(ByteReader &buf)
Action 0x10 - Define goto label.
Definition: newgrf.cpp:7826
static void ActivateOldShore()
Relocates the old shore sprites at new positions.
Definition: newgrf.cpp:9769
static void EnsureEarlyHouse(HouseZones bitmask)
Make sure there is at least one house available in the year 0 for the given climate / housezone combi...
Definition: newgrf.cpp:9343
static const uint NUM_STATIONS_PER_GRF
The maximum amount of stations a single GRF is allowed to add.
Definition: newgrf.cpp:312
static void ParamSet(ByteReader &buf)
Action 0x0D: Set parameter.
Definition: newgrf.cpp:7398
static bool ChangeGRFParamValueNames(ByteReader &buf)
Callback function for 'INFO'->'PARA'->param_num->'VALU' to set the names of some parameter values (ty...
Definition: newgrf.cpp:8399
static void LoadNewGRFFileFromFile(GRFConfig *config, GrfLoadingStage stage, SpriteFile &file)
Load a particular NewGRF from a SpriteFile.
Definition: newgrf.cpp:9644
static void FinaliseEngineArray()
Check for invalid engines.
Definition: newgrf.cpp:9200
static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader &buf)
Define properties for industry tiles.
Definition: newgrf.cpp:3286
static bool HandleParameterInfo(ByteReader &buf)
Callback function for 'INFO'->'PARA' to set extra information about the parameters.
Definition: newgrf.cpp:8446
static void ReadSpriteLayoutRegisters(ByteReader &buf, TileLayoutFlags flags, bool is_parent, NewGRFSpriteLayout *dts, uint index)
Preprocess the TileLayoutFlags and read register modifiers from the GRF.
Definition: newgrf.cpp:810
static GRFParameterInfo * _cur_parameter
The parameter which info is currently changed by the newgrf.
Definition: newgrf.cpp:8218
static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for aircraft.
Definition: newgrf.cpp:1757
static uint32_t _grm_engines[256]
Contains the GRF ID of the owner of a vehicle if it has been reserved.
Definition: newgrf.cpp:354
static bool HandleNode(uint8_t type, uint32_t id, ByteReader &buf, AllowedSubtags subtags[])
Handle the nodes of an Action14.
Definition: newgrf.cpp:8539
static void ResetNewGRFErrors()
Clear all NewGRF errors.
Definition: newgrf.cpp:8761
uint8_t _misc_grf_features
Miscellaneous GRF features, set by Action 0x0D, parameter 0x9E.
Definition: newgrf.cpp:78
AllowedSubtags _tags_info[]
Action14 tags for the INFO node.
Definition: newgrf.cpp:8473
static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for ships.
Definition: newgrf.cpp:1566
static void SetNewGRFOverride(uint32_t source_grfid, uint32_t target_grfid)
Set the override for a NewGRF.
Definition: newgrf.cpp:594
static bool ChangeGRFName(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'NAME' to add a translation to the newgrf name.
Definition: newgrf.cpp:8105
static std::vector< StringIDMapping > _string_to_grf_mapping
Strings to be mapped during load.
Definition: newgrf.cpp:466
static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf, RoadTramType rtt)
Define properties for roadtypes.
Definition: newgrf.cpp:4463
static void LoadGRFSound(size_t offs, SoundEntry *sound)
Load a sound from a file.
Definition: newgrf.cpp:7875
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...
Definition: newgrf.cpp:496
bool(* TextHandler)(uint8_t, std::string_view str)
Type of callback function for text nodes.
Definition: newgrf.cpp:8308
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition: newgrf.cpp:84
static const uint MAX_SPRITEGROUP
Maximum GRF-local ID for a spritegroup.
Definition: newgrf.cpp:86
void LoadNewGRF(SpriteID load_index, uint num_baseset)
Load all the NewGRFs.
Definition: newgrf.cpp:10056
static void InitializeGRFSpecial()
Initialize the TTDPatch flags.
Definition: newgrf.cpp:8612
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.
Definition: newgrf.cpp:2723
static void ClearTemporaryNewGRFData(GRFFile *gf)
Reset all NewGRFData that was used only while processing data.
Definition: newgrf.cpp:422
static void FinaliseCanals()
Set to use the correct action0 properties for each canal feature.
Definition: newgrf.cpp:9189
AllowedSubtags _tags_parameters[]
Action14 parameter tags.
Definition: newgrf.cpp:8429
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.
Definition: newgrf.cpp:613
static bool IsValidNewGRFImageIndex(uint8_t image_index)
Helper to check whether an image index is valid for a particular NewGRF vehicle.
Definition: newgrf.cpp:208
static ChangeInfoResult RailTypeChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for railtypes.
Definition: newgrf.cpp:4245
void LoadNewGRFFile(GRFConfig *config, GrfLoadingStage stage, Subdirectory subdir, bool temporary)
Load a particular NewGRF.
Definition: newgrf.cpp:9733
static ChangeInfoResult IgnoreObjectProperty(uint prop, ByteReader &buf)
Ignore properties for objects.
Definition: newgrf.cpp:4068
void ResetNewGRFData()
Reset all NewGRF loaded data.
Definition: newgrf.cpp:8771
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.
Definition: newgrf.cpp:7060
static void CalculateRefitMasks()
Precalculate refit masks from cargo classes for all vehicles.
Definition: newgrf.cpp:8993
void FinaliseCargoArray()
Check for invalid cargoes.
Definition: newgrf.cpp:9267
static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop, ByteReader &buf)
Define properties for rail vehicles.
Definition: newgrf.cpp:1053
static CargoTypes TranslateRefitMask(uint32_t refit_mask)
Translate the refit mask.
Definition: newgrf.cpp:956
static void StaticGRFInfo(ByteReader &buf)
Handle Action 0x14.
Definition: newgrf.cpp:8592
static ChangeInfoResult IgnoreRoadStopProperty(uint prop, ByteReader &buf)
Ignore properties for roadstops.
Definition: newgrf.cpp:4771
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader &buf)
Ignore an industry property.
Definition: newgrf.cpp:3420
static void BuildCargoTranslationMap()
Construct the Cargo Mapping.
Definition: newgrf.cpp:8884
static bool ChangeGRFParamMask(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PARAM'->param_num->'MASK' to set the parameter and bits to use.
Definition: newgrf.cpp:8274
static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, ByteReader &buf)
Define properties for industries.
Definition: newgrf.cpp:3543
static void ImportGRFSound(SoundEntry *sound)
Process a sound import from another GRF file.
Definition: newgrf.cpp:7844
static bool SkipUnknownInfo(ByteReader &buf, uint8_t type)
Try to skip the current node and all subnodes (if it's a branch node).
Definition: newgrf.cpp:8499
static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader &buf)
Ignore a house property.
Definition: newgrf.cpp:2355
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.
Definition: newgrf.cpp:863
void GrfMsgI(int severity, const std::string &msg)
Debug() function dedicated to newGRF debugging messages Function is essentially the same as Debug(grf...
Definition: newgrf.cpp:390
static void ResetCustomHouses()
Reset and clear all NewGRF houses.
Definition: newgrf.cpp:8709
EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal_id)
Return the ID of a new engine.
Definition: newgrf.cpp:704
static bool ChangeGRFDescription(uint8_t langid, std::string_view str)
Callback function for 'INFO'->'DESC' to add a translation to the newgrf description.
Definition: newgrf.cpp:8112
static bool HandleNodes(ByteReader &buf, AllowedSubtags subtags[])
Handle the contents of a 'C' choice of an Action14.
Definition: newgrf.cpp:8577
static GRFFile * GetFileByGRFID(uint32_t grfid)
Obtain a NewGRF file by its grfID.
Definition: newgrf.cpp:400
static void LoadFontGlyph(ByteReader &buf)
Action 0x12.
Definition: newgrf.cpp:7995
static void ResetCustomIndustries()
Reset and clear all NewGRF industries.
Definition: newgrf.cpp:8726
static std::vector< GRFFile * > _grf_files
List of all loaded GRF files.
Definition: newgrf.cpp:70
static void ResetCustomObjects()
Reset and clear all NewObjects.
Definition: newgrf.cpp:8735
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....
Definition: newgrf.cpp:973
static void FinaliseHouseArray()
Add all new houses to the house array.
Definition: newgrf.cpp:9368
static bool ChangeGRFPalette(size_t len, ByteReader &buf)
Callback function for 'INFO'->'PALS' to set the number of valid parameters.
Definition: newgrf.cpp:8138
static constexpr auto _action5_types
The information about action 5 types.
Definition: newgrf.cpp:6371
static bool ChangeGRFVersion(size_t len, ByteReader &buf)
Callback function for 'INFO'->'VRSN' to the version of the NewGRF.
Definition: newgrf.cpp:8186
ChangeInfoResult
Possible return values for the FeatureChangeInfo functions.
Definition: newgrf.cpp:993
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
Definition: newgrf.cpp:998
@ CIR_DISABLED
GRF was disabled due to error.
Definition: newgrf.cpp:995
@ CIR_UNKNOWN
Variable is unknown.
Definition: newgrf.cpp:997
@ CIR_UNHANDLED
Variable was parsed but unread.
Definition: newgrf.cpp:996
@ CIR_SUCCESS
Variable was parsed and read.
Definition: newgrf.cpp:994
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
Validate the industry layout; e.g.
Definition: newgrf.cpp:3510
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.
Definition: newgrf.cpp:752
static void DisableStaticNewGRFInfluencingNonStaticNewGRFs(GRFConfig *c)
Disable a static NewGRF when it is influencing another (non-static) NewGRF as this could cause desync...
Definition: newgrf.cpp:6800
static void ActivateOldTramDepot()
Replocate the old tram depot sprites to the new position, if no new ones were loaded.
Definition: newgrf.cpp:9806
static uint32_t _ttdpatch_flags[8]
32 * 8 = 256 flags.
Definition: newgrf.cpp:81
static GRFFile * GetFileByFilename(const std::string &filename)
Obtain a NewGRF file by its filename.
Definition: newgrf.cpp:413
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
Definition: newgrf.cpp:3246
static void MapSpriteMappingRecolour(PalSpriteID *grf_sprite)
Map the colour modifiers of TTDPatch to those that Open is using.
Definition: newgrf.cpp:721
static void AfterLoadGRFs()
Finish loading NewGRFs and execute needed post-processing.
Definition: newgrf.cpp:9937
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.
Definition: newgrf.cpp:8221
static void ResetNewGRF()
Reset and clear all NewGRFs.
Definition: newgrf.cpp:8750
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.
Definition: newgrf.cpp:3191
static bool ChangeGRFBlitter(size_t len, ByteReader &buf)
Callback function for 'INFO'->'BLTR' to set the blitter info.
Definition: newgrf.cpp:8164
static void FeatureTownName(ByteReader &buf)
Action 0x0F - Define Town names.
Definition: newgrf.cpp:7748
static void ResetCustomAirports()
Reset and clear all NewGRF airports.
Definition: newgrf.cpp:8717
static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, ByteReader &buf)
Define properties for objects.
Definition: newgrf.cpp:4115
static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader &buf)
Define properties for houses.
Definition: newgrf.cpp:2422
@ GMB_TRAIN_WIDTH_32_PIXELS
Use 32 pixels per train vehicle in depot gui and vehicle details. Never set in the global variable;.
Definition: newgrf.h:61
@ TRAMWAY_REPLACE_DEPOT_WITH_TRACK
Electrified depot graphics with tram track were loaded.
Definition: newgrf.h:173
@ TRAMWAY_REPLACE_DEPOT_NO_TRACK
Electrified depot graphics without tram track were loaded.
Definition: newgrf.h:174
@ TRAMWAY_REPLACE_DEPOT_NONE
No tram depot graphics were loaded.
Definition: newgrf.h:172
@ SHORE_REPLACE_ACTION_A
Shore sprites were replaced by ActionA (using grass tiles for the corner-shores).
Definition: newgrf.h:167
@ SHORE_REPLACE_NONE
No shore sprites were replaced.
Definition: newgrf.h:165
@ SHORE_REPLACE_ONLY_NEW
Only corner-shores were loaded by Action5 (openttd(w/d).grf only).
Definition: newgrf.h:168
@ SHORE_REPLACE_ACTION_5
Shore sprites were replaced by Action5.
Definition: newgrf.h:166
Information about NewGRF Action 5.
@ A5BLOCK_ALLOW_OFFSET
Allow replacing any subset by specifiing an offset.
Definition: newgrf_act5.h:16
@ A5BLOCK_INVALID
unknown/not-implemented type
Definition: newgrf_act5.h:17
@ A5BLOCK_FIXED
Only allow replacing a whole block of sprites. (TTDP compatible)
Definition: newgrf_act5.h:15
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.
Definition: newgrf_config.h:58
@ GRFP_GRF_UNSET
The NewGRF provided no information.
Definition: newgrf_config.h:69
@ GRFP_BLT_UNSET
The NewGRF provided no information or doesn't care about a 32 bpp blitter.
Definition: newgrf_config.h:75
@ GRFP_GRF_WINDOWS
The NewGRF says the Windows palette can be used.
Definition: newgrf_config.h:71
@ GRFP_GRF_DOS
The NewGRF says the DOS palette can be used.
Definition: newgrf_config.h:70
@ GRFP_GRF_ANY
The NewGRF says any palette can be used.
Definition: newgrf_config.h:72
@ GRFP_BLT_MASK
Bitmask to only get the blitter information.
Definition: newgrf_config.h:77
@ GRFP_BLT_32BPP
The NewGRF prefers a 32 bpp blitter.
Definition: newgrf_config.h:76
@ GRFP_USE_MASK
Bitmask to get only the use palette use states.
Definition: newgrf_config.h:67
@ GRFP_GRF_MASK
Bitmask to get only the NewGRF supplied information.
Definition: newgrf_config.h:73
@ GCF_INIT_ONLY
GRF file is processed up to GLS_INIT.
Definition: newgrf_config.h:27
@ GCF_INVALID
GRF is unusable with this version of OpenTTD.
Definition: newgrf_config.h:29
@ GCF_STATIC
GRF file is used statically (can be used in any MP game)
Definition: newgrf_config.h:24
@ GCF_UNSAFE
GRF file is unsafe for static usage.
Definition: newgrf_config.h:23
@ GCF_RESERVED
GRF file passed GLS_RESERVE stage.
Definition: newgrf_config.h:28
@ GCF_SYSTEM
GRF file is an openttd-internal system grf.
Definition: newgrf_config.h:22
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.
Definition: newgrf_config.h:37
@ GCS_DISABLED
GRF file is disabled.
Definition: newgrf_config.h:35
@ GCS_NOT_FOUND
GRF file was not found in the local cache.
Definition: newgrf_config.h:36
@ GCS_UNKNOWN
The status of this grf file is unknown.
Definition: newgrf_config.h:34
@ GCS_ACTIVATED
GRF file has been activated.
Definition: newgrf_config.h:38
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,...
Definition: newgrf_object.h:43
ObjectFlags
Various object behaviours.
Definition: newgrf_object.h:24
@ OBJECT_FLAG_2CC_COLOUR
Object wants 2CC colour mapping.
Definition: newgrf_object.h:34
@ 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
@ DSGA_OP_ADD
a + b
@ 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.
StationClassID
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.
Definition: object_type.h:24
RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
Get the rail type for a given label.
Definition: rail.cpp:311
RailType AllocateRailType(RailTypeLabel label)
Allocate a new rail type label.
Definition: rail_cmd.cpp:150
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:307
void InitRailTypes()
Resolve sprites of custom rail types.
Definition: rail_cmd.cpp:130
void ResetRailTypes()
Reset all rail type information to its default values.
Definition: rail_cmd.cpp:65
RailTypeFlags
Railtype flags.
Definition: rail.h:35
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
@ RAILTYPE_END
Used for iterations.
Definition: rail_type.h:33
@ RAILTYPE_MONO
Monorail.
Definition: rail_type.h:31
@ INVALID_RAILTYPE
Flag for invalid railtype.
Definition: rail_type.h:34
@ RAILTYPE_ELECTRIC
Electric rails.
Definition: rail_type.h:30
@ RAILTYPE_RAIL
Standard non-electric rails.
Definition: rail_type.h:29
@ RAILTYPE_MAGLEV
Maglev.
Definition: rail_type.h:32
declaration of OTTD revision dependent variables
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
Get the road type for a given label.
Definition: road.cpp:254
Road specific functions.
void ResetRoadTypes()
Reset all road type information to its default values.
Definition: road_cmd.cpp:67
void InitRoadTypes()
Resolve sprites of custom road types.
Definition: road_cmd.cpp:114
RoadTypeFlags
Roadtype flags.
Definition: road.h:46
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
Allocate a new road type label.
Definition: road_cmd.cpp:134
RoadType
The different roadtypes we support.
Definition: road_type.h:25
@ INVALID_ROADTYPE
flag for invalid roadtype
Definition: road_type.h:30
@ ROADTYPE_TRAM
Trams.
Definition: road_type.h:28
@ ROADTYPE_ROAD
Basic road type.
Definition: road_type.h:27
@ ROADTYPE_END
Used for iterations.
Definition: road_type.h:29
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
@ SP_CUSTOM
No profile, special "custom" highscore.
Definition: settings_type.h:46
Slope
Enumeration for the slope-type.
Definition: slope_type.h:48
void BuildLinkStatsLegend()
Populate legend table for the link stat view.
void BuildIndustriesLegend()
Fills an array for the industries legends.
Smallmap GUI functions.
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
Definition: sound_type.h:116
SpriteFile & OpenCachedSpriteFile(const std::string &filename, Subdirectory subdir, bool palette_remap)
Open/get the SpriteFile that is cached for use in the sprite cache.
Definition: spritecache.cpp:93
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.
Definition: sprites.h:1546
static const SpriteID SPR_AQUEDUCT_BASE
Sprites for the Aqueduct.
Definition: sprites.h:186
static const SpriteID SPR_OPENTTD_BASE
Extra graphic spritenumbers.
Definition: sprites.h:56
static const SpriteID SPR_TRACKS_FOR_SLOPES_BASE
Sprites for 'highlighting' tracks on sloped land.
Definition: sprites.h:198
static const SpriteID SPR_ROAD_WAYPOINTS_BASE
Road waypoint sprites.
Definition: sprites.h:311
static constexpr uint8_t PALETTE_MODIFIER_TRANSPARENT
when a sprite is to be displayed transparently, this bit needs to be set.
Definition: sprites.h:1547
static const SpriteID SPR_RAILTYPE_TUNNEL_BASE
Tunnel sprites with grass only for custom railtype tunnel.
Definition: sprites.h:299
static const SpriteID SPR_TRAMWAY_BASE
Tramway sprites.
Definition: sprites.h:272
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
Definition: sprites.h:1545
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
Definition: sprites.h:1535
static const SpriteID SPR_AIRPORT_PREVIEW_BASE
Airport preview sprites.
Definition: sprites.h:248
static constexpr uint8_t PALETTE_MODIFIER_COLOUR
this bit is set when a recolouring process is in action
Definition: sprites.h:1548
static const SpriteID SPR_ONEWAY_BASE
One way road sprites.
Definition: sprites.h:293
static const SpriteID SPR_SHORE_BASE
shore tiles - action 05-0D
Definition: sprites.h:224
static constexpr uint MAX_CATCHMENT
Maximum catchment for airports with "modified catchment" enabled.
Definition: station_type.h:85
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition: stdafx.h:280
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.
Definition: string.cpp:107
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Definition: string.cpp:419
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.
Definition: string_func.h:69
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition: strings.cpp:319
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
static const uint MAX_LANG
Maximum number of languages supported by the game, and the NewGRF specs.
Definition: strings_type.h:19
Information about a single action 5 type.
Definition: newgrf_act5.h:21
Action5BlockType block_type
How is this Action5 type processed?
Definition: newgrf_act5.h:22
uint16_t max_sprites
If the Action5 contains more sprites, only the first max_sprites sprites will be used.
Definition: newgrf_act5.h:25
uint16_t min_sprites
If the Action5 contains less sprites, the whole block will be ignored.
Definition: newgrf_act5.h:24
SpriteID sprite_base
Load the sprites starting from this sprite.
Definition: newgrf_act5.h:23
const std::string_view name
Name for error messages.
Definition: newgrf_act5.h:26
Information about a aircraft vehicle.
Definition: engine_type.h:100
uint16_t max_speed
Maximum speed (1 unit = 8 mph = 12.8 km-ish/h)
Definition: engine_type.h:107
uint8_t mail_capacity
Mail capacity (bags).
Definition: engine_type.h:108
uint8_t subtype
Type of aircraft.
Definition: engine_type.h:104
uint16_t passenger_capacity
Passenger capacity (persons).
Definition: engine_type.h:109
uint16_t max_range
Maximum range of this aircraft.
Definition: engine_type.h:110
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.
Data structure to store the allowed id/type combinations for action 14.
Definition: newgrf.cpp:8318
AllowedSubtags * subtags
Pointer to a list of subtags, only valid if type == 'C' && !call_handler.
Definition: newgrf.cpp:8383
uint32_t id
The identifier for this node.
Definition: newgrf.cpp:8375
AllowedSubtags(uint32_t id, BranchHandler handler)
Create a branch node with a callback handler.
Definition: newgrf.cpp:8354
uint8_t type
The type of the node, must be one of 'C', 'B' or 'T'.
Definition: newgrf.cpp:8376
AllowedSubtags(uint32_t id, DataHandler handler)
Create a binary leaf node.
Definition: newgrf.cpp:8330
TextHandler text
Callback function for a text node, only valid if type == 'T'.
Definition: newgrf.cpp:8379
AllowedSubtags()
Create empty subtags object used to identify the end of a list.
Definition: newgrf.cpp:8320
AllowedSubtags(uint32_t id, AllowedSubtags *subtags)
Create a branch node with a list of sub-nodes.
Definition: newgrf.cpp:8367
bool call_handler
True if there is a callback function for this node, false if there is a list of subnodes.
Definition: newgrf.cpp:8385
DataHandler data
Callback function for a binary node, only valid if type == 'B'.
Definition: newgrf.cpp:8378
AllowedSubtags(uint32_t id, TextHandler handler)
Create a text leaf node.
Definition: newgrf.cpp:8342
BranchHandler branch
Callback function for a branch node, only valid if type == 'C' && call_handler.
Definition: newgrf.cpp:8382
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.
Definition: bridge.h:42
uint16_t price
the price multiplier
Definition: bridge.h:46
uint8_t min_length
the minimum length (not counting start and end tile)
Definition: bridge.h:44
StringID material
the string that contains the bridge description
Definition: bridge.h:50
TimerGameCalendar::Year avail_year
the year where it becomes available
Definition: bridge.h:43
PalSpriteID ** sprite_table
table of sprites for drawing the bridge
Definition: bridge.h:52
StringID transport_name[2]
description of the bridge, when built for road or rail
Definition: bridge.h:51
uint8_t flags
bit 0 set: disable drawing of far pillars.
Definition: bridge.h:53
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: bridge.h:47
uint16_t max_length
the maximum length (not counting start and end tile)
Definition: bridge.h:45
Canal properties local to the NewGRF.
Definition: newgrf.h:40
uint8_t callback_mask
Bitmask of canal callbacks that have to be called.
Definition: newgrf.h:41
uint8_t flags
Flags controlling display.
Definition: newgrf.h:42
Specification of a cargo type.
Definition: cargotype.h:71
int32_t initial_payment
Initial payment rate before inflation is applied.
Definition: cargotype.h:79
CargoClasses classes
Classes of this cargo type.
Definition: cargotype.h:78
uint16_t multiplier
Capacity multiplier for vehicles. (8 fractional bits)
Definition: cargotype.h:77
StringID units_volume
Name of a single unit of cargo of this type.
Definition: cargotype.h:90
StringID abbrev
Two letter abbreviation for this cargo type.
Definition: cargotype.h:92
uint8_t bitnum
Cargo bit number, is INVALID_CARGO_BITNUM for a non-used spec.
Definition: cargotype.h:73
StringID quantifier
Text for multiple units of cargo of this type.
Definition: cargotype.h:91
SpriteID sprite
Icon to display this cargo type, may be 0xFFF (which means to resolve an action123 chain).
Definition: cargotype.h:94
bool is_freight
Cargo type is considered to be freight (affects train freight multiplier).
Definition: cargotype.h:82
uint8_t weight
Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
Definition: cargotype.h:76
CargoLabel label
Unique label of the cargo type.
Definition: cargotype.h:72
const struct GRFFile * grffile
NewGRF where #group belongs to.
Definition: cargotype.h:96
static IterateWrapper Iterate(size_t from=0)
Returns an iterable ensemble of all valid CargoSpec.
Definition: cargotype.h:190
static CargoSpec array[NUM_CARGO]
Array holding all CargoSpecs.
Definition: cargotype.h:196
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:134
uint8_t callback_mask
Bitmask of cargo callbacks that have to be called.
Definition: cargotype.h:86
StringID name
Name of this type of cargo.
Definition: cargotype.h:88
TownProductionEffect town_production_effect
The effect on town cargo production.
Definition: cargotype.h:84
TownAcceptanceEffect town_acceptance_effect
The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
Definition: cargotype.h:83
uint16_t town_production_multiplier
Town production multipler, if commanded by TownProductionEffect.
Definition: cargotype.h:85
bool IsValid() const
Tests for validity of this cargospec.
Definition: cargotype.h:115
StringID name_single
Name of a single entity of this type of cargo.
Definition: cargotype.h:89
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.
Definition: sprite.h:25
int8_t delta_z
0x80 identifies child sprites
Definition: sprite.h:28
bool IsParentSprite() const
Check whether this is a parent sprite with a boundingbox.
Definition: sprite.h:47
bool IsTerminator() const
Check whether this is a sequence terminator.
Definition: sprite.h:41
int8_t delta_x
0x80 is sequence terminator
Definition: sprite.h:26
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:58
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition: sprite.h:60
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:59
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.
Definition: engine_base.h:193
uint8_t substitute_id
The (original) entity ID to use if this GRF is not available (currently not used)
Definition: engine_base.h:196
uint16_t internal_id
The internal ID within the GRF file.
Definition: engine_base.h:194
Information about a vehicle.
Definition: engine_type.h:144
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
Definition: engine_type.h:159
TimerGameCalendar::Year base_life
Basic duration of engine availability (without random parts). 0xFF means infinite life.
Definition: engine_type.h:147
EngineID variant_id
Engine variant ID. If set, will be treated specially in purchase lists.
Definition: engine_type.h:160
uint8_t misc_flags
Miscellaneous flags.
Definition: engine_type.h:155
StringID string_id
Default name of engine.
Definition: engine_type.h:158
uint8_t climates
Climates supported by the engine.
Definition: engine_type.h:150
TimerGameCalendar::Date base_intro
Basic date of engine introduction (without random parts).
Definition: engine_type.h:145
uint16_t callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition: engine_type.h:156
int8_t retire_early
Number of years early to retire vehicle.
Definition: engine_type.h:157
TimerGameCalendar::Year lifelength
Lifetime of a single vehicle.
Definition: engine_type.h:146
void ResetToDefaultMapping()
Initializes the EngineOverrideManager with the default engines.
Definition: engine.cpp:509
EngineID GetID(VehicleType type, uint16_t grf_local_id, uint32_t grfid)
Looks up an EngineID in the EngineOverrideManager.
Definition: engine.cpp:532
GRFFilePropsBase< NUM_CARGO+2 > grf_prop
Properties related the the grf file.
Definition: engine_base.h:77
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition: engine_base.h:56
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:167
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition: engine_base.h:186
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.
Definition: newgrf.h:108
uint param_end
one more than the highest set parameter
Definition: newgrf.h:126
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoID -> local ID)
Definition: newgrf.h:131
std::vector< RailTypeLabel > railtype_list
Railtype translation table.
Definition: newgrf.h:133
uint32_t GetParam(uint number) const
Get GRF Parameter with range checking.
Definition: newgrf.h:155
CanalProperties canal_local_properties[CF_END]
Canal properties as set by this NewGRF.
Definition: newgrf.h:142
std::vector< RoadTypeLabel > roadtype_list
Roadtype translation table (road)
Definition: newgrf.h:136
uint32_t grf_features
Bitset of GrfSpecFeature the grf uses.
Definition: newgrf.h:149
GRFFile(const struct GRFConfig *config)
Constructor for GRFFile.
Definition: newgrf.cpp:8918
std::vector< RoadTypeLabel > tramtype_list
Roadtype translation table (tram)
Definition: newgrf.h:139
std::vector< CargoLabel > cargo_list
Cargo translation table (local ID -> label)
Definition: newgrf.h:130
uint traininfo_vehicle_width
Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details.
Definition: newgrf.h:147
int traininfo_vehicle_pitch
Vertical offset for drawing train images in depot GUI and vehicle details.
Definition: newgrf.h:146
std::unordered_map< uint8_t, LanguageMap > language_map
Mappings related to the languages.
Definition: newgrf.h:144
std::vector< GRFLabel > labels
List of labels.
Definition: newgrf.h:128
PriceMultipliers price_base_multipliers
Price base multipliers as set by the grf.
Definition: newgrf.h:150
uint32_t grfid
GRF ID (defined by Action 0x08)
Definition: newgrf_config.h:83
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition: newgrf.h:178
ShoreReplacement shore
In which way shore sprites were replaced.
Definition: newgrf.h:180
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition: newgrf.h:179
TramReplacement tram
In which way tram depots were replaced.
Definition: newgrf.h:181
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.
Definition: newgrf.cpp:315
CargoTypes ctt_exclude_mask
Cargo types always excluded from the refit mask.
Definition: newgrf.cpp:332
Refittability refittability
Did the newgrf set any refittability property? If not, default refittability will be applied.
Definition: newgrf.cpp:329
CargoClasses cargo_disallowed
Bitmask of cargo classes that are disallowed as a refit.
Definition: newgrf.cpp:325
CargoTypes ctt_include_mask
Cargo types always included in the refit mask.
Definition: newgrf.cpp:331
Refittability
Summary state of refittability properties.
Definition: newgrf.cpp:317
@ UNSET
No properties assigned. Default refit masks shall be activated.
Definition: newgrf.cpp:318
@ EMPTY
GRF defined vehicle as not-refittable. The vehicle shall only carry the default cargo.
Definition: newgrf.cpp:319
@ NONEMPTY
GRF defined the vehicle as refittable. If the refitmask is empty after translation (cargotypes not av...
Definition: newgrf.cpp:320
uint8_t rv_max_speed
Temporary storage of RV prop 15, maximum speed in mph/0.8.
Definition: newgrf.cpp:330
CargoClasses cargo_allowed
Bitmask of cargo classes that are allowed as a refit.
Definition: newgrf.cpp:323
void UpdateRefittability(bool non_empty)
Update the summary refittability on setting a refittability property.
Definition: newgrf.cpp:338
CargoClasses cargo_allowed_required
Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
Definition: newgrf.cpp:324
const GRFFile * defaultcargo_grf
GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
Definition: newgrf.cpp:328
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.
Definition: newgrf.cpp:92
uint num_sprites
Number of sprites in the set.
Definition: newgrf.cpp:94
SpriteID sprite
SpriteID of the first sprite of the set.
Definition: newgrf.cpp:93
Temporary data during loading of GRFs.
Definition: newgrf.cpp:89
SpriteFile * file
File of currently processed GRF file.
Definition: newgrf.cpp:106
GRFFile * grffile
Currently processed GRF file.
Definition: newgrf.cpp:107
void AddSpriteSets(uint8_t feature, SpriteID first_sprite, uint first_set, uint numsets, uint numents)
Records new spritesets.
Definition: newgrf.cpp:138
uint32_t nfo_line
Currently processed pseudo sprite number in the GRF.
Definition: newgrf.cpp:109
SpriteID spriteid
First available SpriteID for loading realsprites.
Definition: newgrf.cpp:103
GRFConfig * grfconfig
Config of the currently processed GRF file.
Definition: newgrf.cpp:108
SpriteID GetSprite(uint8_t feature, uint set) const
Returns the first sprite of a spriteset.
Definition: newgrf.cpp:179
bool IsValidSpriteSet(uint8_t feature, uint set) const
Check whether a specific set is defined.
Definition: newgrf.cpp:167
uint GetNumEnts(uint8_t feature, uint set) const
Returns the number of sprites in a spriteset.
Definition: newgrf.cpp:191
bool HasValidSpriteSets(uint8_t feature) const
Check whether there are any valid spritesets for a feature.
Definition: newgrf.cpp:154
std::map< uint, SpriteSet > spritesets[GSF_END]
Currently referenceable spritesets.
Definition: newgrf.cpp:98
void ClearDataForNextFile()
Clear temporary data before processing the next file in the current loading stage.
Definition: newgrf.cpp:118
GrfLoadingStage stage
Current loading stage.
Definition: newgrf.cpp:102
int skip_sprites
Number of pseudo sprites to skip before processing the next one. (-1 to skip to end of file)
Definition: newgrf.cpp:112
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]
input cargo slots
Definition: house.h:103
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
Definition: house.h:106
CargoLabel accepts_cargo_label[HOUSE_ORIGINAL_NUM_ACCEPTS]
input landscape cargo slots
Definition: house.h:120
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...)
Definition: house.h:104
uint8_t population
population (Zero on other tiles in multi tile house.)
Definition: house.h:97
uint8_t cargo_acceptance[HOUSE_NUM_ACCEPTS]
acceptance level for the cargo slots
Definition: house.h:102
TimerGameCalendar::Year min_year
introduction year of the house
Definition: house.h:95
GRFFileProps grf_prop
Properties related the the grf file.
Definition: house.h:109
HouseZones building_availability
where can it be built (climates, zones)
Definition: house.h:105
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.
Definition: industrytype.h:101
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
16 accepted cargoes.
Definition: industrytype.h:115
StringID production_up_text
Message appearing when the industry's production is increasing.
Definition: industrytype.h:124
StringID name
Displayed name of the industry.
Definition: industrytype.h:121
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industries.
Definition: industrytype.h:136
IndustryType conflicting[3]
Industries this industry cannot be close to.
Definition: industrytype.h:106
GRFFileProps grf_prop
properties related to the grf file
Definition: industrytype.h:132
StringID production_down_text
Message appearing when the industry's production is decreasing.
Definition: industrytype.h:125
StringID station_name
Default name for nearby station.
Definition: industrytype.h:126
StringID closure_text
Message appearing when the industry closes.
Definition: industrytype.h:123
StringID new_industry_text
Message appearing when the industry is built.
Definition: industrytype.h:122
bool enabled
entity still available (by default true).newgrf can disable it, though
Definition: industrytype.h:131
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_OUTPUTS > produced_cargo_label
Cargo labels of produced cargo for default industries.
Definition: industrytype.h:135
Definition of one tile in an industry tile layout.
Definition: industrytype.h:90
Defines the data structure of each individual tile of an industry.
Definition: industrytype.h:149
std::array< CargoID, INDUSTRY_NUM_INPUTS > accepts_cargo
Cargo accepted by this tile.
Definition: industrytype.h:150
GRFFileProps grf_prop
properties related to the grf file
Definition: industrytype.h:165
std::array< std::variant< CargoLabel, MixedCargoType >, INDUSTRY_ORIGINAL_NUM_INPUTS > accepts_cargo_label
Cargo labels of accepted cargo for default industry tiles.
Definition: industrytype.h:167
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.
Definition: newgrf.cpp:2679
Make sure the size is right.
Definition: language.h:93
uint8_t GetGenderIndex(const char *gender_str) const
Get the index for the given gender.
Definition: language.h:68
uint8_t GetCaseIndex(const char *case_str) const
Get the index for the given case.
Definition: language.h:81
static debug_inline uint LogX()
Logarithm of the map size along the X side.
Definition: map_func.h:251
static uint LogY()
Logarithm of the map size along the y side.
Definition: map_func.h:261
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.
Definition: newgrf_object.h:60
GRFFilePropsBase< 2 > grf_prop
Properties related the the grf file.
Definition: newgrf_object.h:62
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.
Definition: gfx_type.h:23
SpriteID sprite
The 'real' sprite.
Definition: gfx_type.h:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:25
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:360
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
void CleanPool() override
Virtual method that deletes all items in the pool.
Describes properties of price bases.
Definition: economy_type.h:207
Price fallback_price
Fallback price multiplier for new prices but old grfs.
Definition: economy_type.h:211
uint grf_feature
GRF Feature that decides whether price multipliers apply locally or globally, #GSF_END if none.
Definition: economy_type.h:210
Information about a rail vehicle.
Definition: engine_type.h:42
uint16_t power
Power of engine (hp); For multiheaded engines the sum of both engine powers.
Definition: engine_type.h:49
uint8_t user_def_data
Property 0x25: "User-defined bit mask" Used only for (very few) NewGRF vehicles.
Definition: engine_type.h:62
uint8_t running_cost
Running cost of engine; For multiheaded engines the sum of both running costs.
Definition: engine_type.h:51
uint8_t cost_factor
Purchase cost factor; For multiheaded engines the sum of both engine prices.
Definition: engine_type.h:45
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
Definition: engine_type.h:59
RailType intended_railtype
Intended railtype, regardless of elrail being enabled or disabled.
Definition: engine_type.h:47
uint16_t pow_wag_power
Extra power applied to consist if wagon should be powered.
Definition: engine_type.h:56
uint16_t max_speed
Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: engine_type.h:48
int16_t curve_speed_mod
Modifier to maximum speed in curves (fixed-point binary with 8 fractional bits)
Definition: engine_type.h:63
uint16_t weight
Weight of vehicle (tons); For multiheaded engines the weight of each single engine.
Definition: engine_type.h:50
uint8_t capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
Definition: engine_type.h:54
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:58
uint8_t air_drag
Coefficient of air drag.
Definition: engine_type.h:61
EngineClass engclass
Class of engine for this vehicle.
Definition: engine_type.h:53
uint8_t ai_passenger_only
Bit value to tell AI that this engine is for passenger use only.
Definition: engine_type.h:55
RailType railtype
Railtype, mangled if elrail is disabled.
Definition: engine_type.h:46
uint8_t tractive_effort
Tractive effort coefficient.
Definition: engine_type.h:60
uint8_t pow_wag_weight
Extra weight applied to consist if wagon should be powered.
Definition: engine_type.h:57
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)
Road stop specification.
GRFFilePropsBase< NUM_CARGO+3 > grf_prop
Properties related the the grf file.
Information about a road vehicle.
Definition: engine_type.h:114
uint8_t tractive_effort
Coefficient of tractive effort.
Definition: engine_type.h:124
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
Definition: engine_type.h:120
uint8_t air_drag
Coefficient of air drag.
Definition: engine_type.h:125
uint8_t power
Power in 10hp units.
Definition: engine_type.h:123
RoadType roadtype
Road type.
Definition: engine_type.h:128
uint8_t weight
Weight in 1/4t units.
Definition: engine_type.h:122
uint8_t shorten_factor
length on main map for this type is 8 - shorten_factor
Definition: engine_type.h:127
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:126
Iterable ensemble of each set bit in a value.
Information about a ship vehicle.
Definition: engine_type.h:67
bool old_refittable
Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask.
Definition: engine_type.h:75
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
Definition: engine_type.h:77
uint8_t visual_effect
Bitstuffed NewGRF visual effect data.
Definition: engine_type.h:76
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h)
Definition: engine_type.h:71
uint8_t acceleration
Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick)
Definition: engine_type.h:70
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
Definition: engine_type.h:78
uint8_t grf_container_ver
NewGRF container version if the sound is from a NewGRF.
Definition: sound_type.h:22
bool never_expire_airports
never expire airports
Station specification.
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.
Definition: newgrf.cpp:457
uint32_t grfid
Source NewGRF.
Definition: newgrf.cpp:458
StringID source
Source StringID (GRF local).
Definition: newgrf.cpp:459
std::function< void(StringID)> func
Function for mapping result.
Definition: newgrf.cpp:460
Templated helper to make a type-safe 'typedef' representing a single POD value.
int16_t x
The x value of the coordinate.
Definition: map_type.h:32
int16_t y
The y value of the coordinate.
Definition: map_type.h:33
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.
Definition: newgrf_canal.h:25
const SpriteGroup * group
Sprite group to start resolving.
Definition: newgrf_canal.h:23
const GRFFile * grffile
NewGRF where 'group' belongs to.
Definition: newgrf_canal.h:24
uint8_t flags
Flags controlling display.
Definition: newgrf_canal.h:26
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_BASE.
Definition: tile_type.h:18
Definition of the game-calendar-timer.
Definition of the tick-based game-timer.
Base of the town class.
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.
Definition: vehicle.cpp:1970
Base class for all vehicles.
@ VE_TYPE_COUNT
Number of bits used for the effect type.
Definition: vehicle_base.h:87
@ VE_TYPE_START
First bit used for the type of effect.
Definition: vehicle_base.h:86
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
Definition: vehicle_base.h:93
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
Definition: vehicle_base.h:97
Functions related to vehicles.
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24