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