File diff r27123:c9e33a591e8d → r27124:237b340de564
src/newgrf.cpp
Show inline comments
 
@@ -582,13 +582,13 @@ static std::map<uint32, uint32> _grf_id_
 
 * @param source_grfid The grfID which wants to override another NewGRF.
 
 * @param target_grfid The grfID which is being overridden.
 
 */
 
static void SetNewGRFOverride(uint32 source_grfid, uint32 target_grfid)
 
{
 
	_grf_id_overrides[source_grfid] = target_grfid;
 
	GrfMsg(5, "SetNewGRFOverride: Added override of {:#X} to {:#X}", BSWAP32(source_grfid), BSWAP32(target_grfid));
 
	GrfMsg(5, "SetNewGRFOverride: Added override of 0x{:X} to 0x{:X}", BSWAP32(source_grfid), BSWAP32(target_grfid));
 
}
 

	
 
/**
 
 * Returns the engine associated to a certain internal_id, resp. allocates it.
 
 * @param file NewGRF that wants to change the engine.
 
 * @param type Vehicle type.
 
@@ -859,13 +859,13 @@ static bool ReadSpriteLayout(ByteReader 
 

	
 
	/* Groundsprite */
 
	TileLayoutFlags flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &dts->ground, max_sprite_offset.data(), max_palette_offset.data());
 
	if (_cur.skip_sprites < 0) return true;
 

	
 
	if (flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS)) {
 
		GrfMsg(1, "ReadSpriteLayout: Spritelayout uses invalid flag {:#X} for ground sprite", flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS));
 
		GrfMsg(1, "ReadSpriteLayout: Spritelayout uses invalid flag 0x{:X} for ground sprite", flags & ~(valid_flags & ~TLF_NON_GROUND_FLAGS));
 
		DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
 
		return true;
 
	}
 

	
 
	ReadSpriteLayoutRegisters(buf, flags, false, dts, 0);
 
	if (_cur.skip_sprites < 0) return true;
 
@@ -874,13 +874,13 @@ static bool ReadSpriteLayout(ByteReader 
 
		DrawTileSeqStruct *seq = const_cast<DrawTileSeqStruct*>(&dts->seq[i]);
 

	
 
		flags = ReadSpriteLayoutSprite(buf, has_flags, false, use_cur_spritesets, feature, &seq->image, max_sprite_offset.data() + i + 1, max_palette_offset.data() + i + 1);
 
		if (_cur.skip_sprites < 0) return true;
 

	
 
		if (flags & ~valid_flags) {
 
			GrfMsg(1, "ReadSpriteLayout: Spritelayout uses unknown flag {:#X}", flags & ~valid_flags);
 
			GrfMsg(1, "ReadSpriteLayout: Spritelayout uses unknown flag 0x{:X}", flags & ~valid_flags);
 
			DisableGrf(STR_NEWGRF_ERROR_INVALID_SPRITE_LAYOUT);
 
			return true;
 
		}
 

	
 
		seq->delta_x = buf->ReadByte();
 
		seq->delta_y = buf->ReadByte();
 
@@ -965,13 +965,13 @@ static void ConvertTTDBasePrice(uint32 b
 
	}
 

	
 
	static const uint32 start = 0x4B34; ///< Position of first base price
 
	static const uint32 size  = 6;      ///< Size of each base price record
 

	
 
	if (base_pointer < start || (base_pointer - start) % size != 0 || (base_pointer - start) / size >= PR_END) {
 
		GrfMsg(1, "{}: Unsupported running cost base {:#04X}, ignoring", error_location, base_pointer);
 
		GrfMsg(1, "{}: Unsupported running cost base 0x{:04X}, ignoring", error_location, base_pointer);
 
		return;
 
	}
 

	
 
	*index = (Price)((base_pointer - start) / size);
 
}
 

	
 
@@ -2133,13 +2133,13 @@ static ChangeInfoResult StationChangeInf
 
 */
 
static ChangeInfoResult CanalChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
 
{
 
	ChangeInfoResult ret = CIR_SUCCESS;
 

	
 
	if (id + numinfo > CF_END) {
 
		GrfMsg(1, "CanalChangeInfo: Canal feature {:#02X} is invalid, max {}, ignoring", id + numinfo, CF_END);
 
		GrfMsg(1, "CanalChangeInfo: Canal feature 0x{:02X} is invalid, max {}, ignoring", id + numinfo, CF_END);
 
		return CIR_INVALID_ID;
 
	}
 

	
 
	for (int i = 0; i < numinfo; i++) {
 
		CanalProperties *cp = &_cur.grffile->canal_local_properties[id + i];
 

	
 
@@ -4114,13 +4114,13 @@ static ChangeInfoResult ObjectChangeInfo
 
				spec->climate = buf->ReadByte();
 
				break;
 

	
 
			case 0x0C: // Size
 
				spec->size = buf->ReadByte();
 
				if (GB(spec->size, 0, 4) == 0 || GB(spec->size, 4, 4) == 0) {
 
					GrfMsg(0, "ObjectChangeInfo: Invalid object size requested ({:#X}) for object id {}. Ignoring.", spec->size, id + i);
 
					GrfMsg(0, "ObjectChangeInfo: Invalid object size requested (0x{:X}) for object id {}. Ignoring.", spec->size, id + i);
 
					spec->size = OBJECT_SIZE_1X1;
 
				}
 
				break;
 

	
 
			case 0x0D: // Build cost multipler
 
				spec->build_cost_multiplier = buf->ReadByte();
 
@@ -4848,17 +4848,17 @@ static bool HandleChangeInfoResult(const
 
			return true;
 

	
 
		case CIR_SUCCESS:
 
			return false;
 

	
 
		case CIR_UNHANDLED:
 
			GrfMsg(1, "{}: Ignoring property {:#02X} of feature {:#02X} (not implemented)", caller, property, feature);
 
			GrfMsg(1, "{}: Ignoring property 0x{:02X} of feature 0x{:02X} (not implemented)", caller, property, feature);
 
			return false;
 

	
 
		case CIR_UNKNOWN:
 
			GrfMsg(0, "{}: Unknown property {:#02X} of feature {:#02X}, disabling", caller, property, feature);
 
			GrfMsg(0, "{}: Unknown property 0x{:02X} of feature 0x{:02X}, disabling", caller, property, feature);
 
			FALLTHROUGH;
 

	
 
		case CIR_INVALID_ID: {
 
			/* No debug message for an invalid ID, as it has already been output */
 
			GRFError *error = DisableGrf(cir == CIR_INVALID_ID ? STR_NEWGRF_ERROR_INVALID_ID : STR_NEWGRF_ERROR_UNKNOWN_PROPERTY);
 
			if (cir != CIR_INVALID_ID) error->param_value[1] = property;
 
@@ -4909,21 +4909,21 @@ static void FeatureChangeInfo(ByteReader
 
	uint8 feature  = buf->ReadByte();
 
	uint8 numprops = buf->ReadByte();
 
	uint numinfo  = buf->ReadByte();
 
	uint engine   = buf->ReadExtendedByte();
 

	
 
	if (feature >= GSF_END) {
 
		GrfMsg(1, "FeatureChangeInfo: Unsupported feature {:#02X}, skipping", feature);
 
		GrfMsg(1, "FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
 
		return;
 
	}
 

	
 
	GrfMsg(6, "FeatureChangeInfo: Feature {:#02X}, {} properties, to apply to {}+{}",
 
	GrfMsg(6, "FeatureChangeInfo: Feature 0x{:02X}, {} properties, to apply to {}+{}",
 
	               feature, numprops, engine, numinfo);
 

	
 
	if (handler[feature] == nullptr) {
 
		if (feature != GSF_CARGOES) GrfMsg(1, "FeatureChangeInfo: Unsupported feature {:#02X}, skipping", feature);
 
		if (feature != GSF_CARGOES) GrfMsg(1, "FeatureChangeInfo: Unsupported feature 0x{:02X}, skipping", feature);
 
		return;
 
	}
 

	
 
	/* Mark the feature as used by the grf */
 
	SetBit(_cur.grffile->grf_features, feature);
 

	
 
@@ -5042,19 +5042,19 @@ static void NewSpriteSet(ByteReader *buf
 
		num_sets = buf->ReadExtendedByte();
 
	}
 
	uint16 num_ents = buf->ReadExtendedByte();
 

	
 
	if (feature >= GSF_END) {
 
		_cur.skip_sprites = num_sets * num_ents;
 
		GrfMsg(1, "NewSpriteSet: Unsupported feature {:#02X}, skipping {} sprites", feature, _cur.skip_sprites);
 
		GrfMsg(1, "NewSpriteSet: Unsupported feature 0x{:02X}, skipping {} sprites", feature, _cur.skip_sprites);
 
		return;
 
	}
 

	
 
	_cur.AddSpriteSets(feature, _cur.spriteid, first_set, num_sets, num_ents);
 

	
 
	GrfMsg(7, "New sprite set at {} of feature {:#02X}, consisting of {} sets with {} views each (total {})",
 
	GrfMsg(7, "New sprite set at {} of feature 0x{:02X}, consisting of {} sets with {} views each (total {})",
 
		_cur.spriteid, feature, num_sets, num_ents, num_sets * num_ents
 
	);
 

	
 
	for (int i = 0; i < num_sets * num_ents; i++) {
 
		_cur.nfo_line++;
 
		LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line);
 
@@ -5087,13 +5087,13 @@ static const SpriteGroup *GetGroupFromGr
 
	if (HasBit(groupid, 15)) {
 
		assert(CallbackResultSpriteGroup::CanAllocateItem());
 
		return new CallbackResultSpriteGroup(groupid, _cur.grffile->grf_version >= 8);
 
	}
 

	
 
	if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
 
		GrfMsg(1, "GetGroupFromGroupID({:#02X}:{:#02X}): Groupid {:#04X} does not exist, leaving empty", setid, type, groupid);
 
		GrfMsg(1, "GetGroupFromGroupID(0x{:02X}:0x{:02X}): Groupid 0x{:04X} does not exist, leaving empty", setid, type, groupid);
 
		return nullptr;
 
	}
 

	
 
	return _cur.spritegroups[groupid];
 
}
 

	
 
@@ -5110,13 +5110,13 @@ static const SpriteGroup *CreateGroupFro
 
	if (HasBit(spriteid, 15)) {
 
		assert(CallbackResultSpriteGroup::CanAllocateItem());
 
		return new CallbackResultSpriteGroup(spriteid, _cur.grffile->grf_version >= 8);
 
	}
 

	
 
	if (!_cur.IsValidSpriteSet(feature, spriteid)) {
 
		GrfMsg(1, "CreateGroupFromGroupID({:#02X}:{:#02X}): Sprite set {} invalid", setid, type, spriteid);
 
		GrfMsg(1, "CreateGroupFromGroupID(0x{:02X}:0x{:02X}): Sprite set {} invalid", setid, type, spriteid);
 
		return nullptr;
 
	}
 

	
 
	SpriteID spriteset_start = _cur.GetSprite(feature, spriteid);
 
	uint num_sprites = _cur.GetNumEnts(feature, spriteid);
 

	
 
@@ -5141,13 +5141,13 @@ static void NewSpriteGroup(ByteReader *b
 
	 *                 meaning depends on the feature
 
	 * V feature-specific-data (huge mess, don't even look it up --pasky) */
 
	const SpriteGroup *act_group = nullptr;
 

	
 
	uint8 feature = buf->ReadByte();
 
	if (feature >= GSF_END) {
 
		GrfMsg(1, "NewSpriteGroup: Unsupported feature {:#02X}, skipping", feature);
 
		GrfMsg(1, "NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
 
		return;
 
	}
 

	
 
	uint8 setid   = buf->ReadByte();
 
	uint8 type    = buf->ReadByte();
 

	
 
@@ -5318,13 +5318,13 @@ static void NewSpriteGroup(ByteReader *b
 

	
 
					if (!_cur.HasValidSpriteSets(feature)) {
 
						GrfMsg(0, "NewSpriteGroup: No sprite set to work on! Skipping");
 
						return;
 
					}
 

	
 
					GrfMsg(6, "NewSpriteGroup: New SpriteGroup {:#02X}, {} loaded, {} loading",
 
					GrfMsg(6, "NewSpriteGroup: New SpriteGroup 0x{:02X}, {} loaded, {} loading",
 
							setid, num_loaded, num_loading);
 

	
 
					if (num_loaded + num_loading == 0) {
 
						GrfMsg(1, "NewSpriteGroup: no result, skipping invalid RealSpriteGroup");
 
						break;
 
					}
 
@@ -5474,13 +5474,13 @@ static void NewSpriteGroup(ByteReader *b
 
						NOT_REACHED();
 
					}
 
					break;
 
				}
 

	
 
				/* Loading of Tile Layout and Production Callback groups would happen here */
 
				default: GrfMsg(1, "NewSpriteGroup: Unsupported feature {:#02X}, skipping", feature);
 
				default: GrfMsg(1, "NewSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
 
			}
 
		}
 
	}
 

	
 
	_cur.spritegroups[setid] = act_group;
 
}
 
@@ -5542,13 +5542,13 @@ static CargoID TranslateCargo(uint8 feat
 
}
 

	
 

	
 
static bool IsValidGroupID(uint16 groupid, const char *function)
 
{
 
	if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
 
		GrfMsg(1, "{}: Spritegroup {:#04X} out of range or empty, skipping.", function, groupid);
 
		GrfMsg(1, "{}: Spritegroup 0x{:04X} out of range or empty, skipping.", function, groupid);
 
		return false;
 
	}
 

	
 
	return true;
 
}
 

	
 
@@ -5596,13 +5596,13 @@ static void VehicleMapSpriteGroup(ByteRe
 
	uint8 cidcount = buf->ReadByte();
 
	for (uint c = 0; c < cidcount; c++) {
 
		uint8 ctype = buf->ReadByte();
 
		uint16 groupid = buf->ReadWord();
 
		if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) continue;
 

	
 
		GrfMsg(8, "VehicleMapSpriteGroup: * [{}] Cargo type {:#X}, group id {:#02X}", c, ctype, groupid);
 
		GrfMsg(8, "VehicleMapSpriteGroup: * [{}] Cargo type 0x{:X}, group id 0x{:02X}", c, ctype, groupid);
 

	
 
		ctype = TranslateCargo(feature, ctype);
 
		if (ctype == CT_INVALID) continue;
 

	
 
		for (uint i = 0; i < idcount; i++) {
 
			EngineID engine = engines[i];
 
@@ -5617,13 +5617,13 @@ static void VehicleMapSpriteGroup(ByteRe
 
		}
 
	}
 

	
 
	uint16 groupid = buf->ReadWord();
 
	if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
 

	
 
	GrfMsg(8, "-- Default group id {:#04X}", groupid);
 
	GrfMsg(8, "-- Default group id 0x{:04X}", groupid);
 

	
 
	for (uint i = 0; i < idcount; i++) {
 
		EngineID engine = engines[i];
 

	
 
		if (wagover) {
 
			SetWagonOverrideSprites(engine, CT_DEFAULT, _cur.spritegroups[groupid], last_engines, last_engines_count);
 
@@ -5684,13 +5684,13 @@ static void StationMapSpriteGroup(ByteRe
 
		if (ctype == CT_INVALID) continue;
 

	
 
		for (auto &station : stations) {
 
			StationSpec *statspec = station >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[station].get();
 

	
 
			if (statspec == nullptr) {
 
				GrfMsg(1, "StationMapSpriteGroup: Station with ID {:#02X} does not exist, skipping", station);
 
				GrfMsg(1, "StationMapSpriteGroup: Station with ID 0x{:02X} does not exist, skipping", station);
 
				continue;
 
			}
 

	
 
			statspec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
 
		}
 
	}
 
@@ -5699,18 +5699,18 @@ static void StationMapSpriteGroup(ByteRe
 
	if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) return;
 

	
 
	for (auto &station : stations) {
 
		StationSpec *statspec = station >= _cur.grffile->stations.size() ? nullptr : _cur.grffile->stations[station].get();
 

	
 
		if (statspec == nullptr) {
 
			GrfMsg(1, "StationMapSpriteGroup: Station with ID {:#02X} does not exist, skipping", station);
 
			GrfMsg(1, "StationMapSpriteGroup: Station with ID 0x{:02X} does not exist, skipping", station);
 
			continue;
 
		}
 

	
 
		if (statspec->grf_prop.grffile != nullptr) {
 
			GrfMsg(1, "StationMapSpriteGroup: Station with ID {:#02X} mapped multiple times, skipping", station);
 
			GrfMsg(1, "StationMapSpriteGroup: Station with ID 0x{:02X} mapped multiple times, skipping", station);
 
			continue;
 
		}
 

	
 
		statspec->grf_prop.spritegroup[CT_DEFAULT] = _cur.spritegroups[groupid];
 
		statspec->grf_prop.grffile = _cur.grffile;
 
		statspec->grf_prop.local_id = station;
 
@@ -5865,13 +5865,13 @@ static void ObjectMapSpriteGroup(ByteRea
 
		if (ctype == CT_INVALID) continue;
 

	
 
		for (auto &object : objects) {
 
			ObjectSpec *spec = object >= _cur.grffile->objectspec.size() ? nullptr : _cur.grffile->objectspec[object].get();
 

	
 
			if (spec == nullptr) {
 
				GrfMsg(1, "ObjectMapSpriteGroup: Object with ID {:#02X} undefined, skipping", object);
 
				GrfMsg(1, "ObjectMapSpriteGroup: Object with ID 0x{:02X} undefined, skipping", object);
 
				continue;
 
			}
 

	
 
			spec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
 
		}
 
	}
 
@@ -5880,18 +5880,18 @@ static void ObjectMapSpriteGroup(ByteRea
 
	if (!IsValidGroupID(groupid, "ObjectMapSpriteGroup")) return;
 

	
 
	for (auto &object : objects) {
 
		ObjectSpec *spec = object >= _cur.grffile->objectspec.size() ? nullptr : _cur.grffile->objectspec[object].get();
 

	
 
		if (spec == nullptr) {
 
			GrfMsg(1, "ObjectMapSpriteGroup: Object with ID {:#02X} undefined, skipping", object);
 
			GrfMsg(1, "ObjectMapSpriteGroup: Object with ID 0x{:02X} undefined, skipping", object);
 
			continue;
 
		}
 

	
 
		if (spec->grf_prop.grffile != nullptr) {
 
			GrfMsg(1, "ObjectMapSpriteGroup: Object with ID {:#02X} mapped multiple times, skipping", object);
 
			GrfMsg(1, "ObjectMapSpriteGroup: Object with ID 0x{:02X} mapped multiple times, skipping", object);
 
			continue;
 
		}
 

	
 
		spec->grf_prop.spritegroup[0] = _cur.spritegroups[groupid];
 
		spec->grf_prop.grffile        = _cur.grffile;
 
		spec->grf_prop.local_id       = object;
 
@@ -6051,13 +6051,13 @@ static void RoadStopMapSpriteGroup(ByteR
 
		if (ctype == CT_INVALID) continue;
 

	
 
		for (auto &roadstop : roadstops) {
 
			RoadStopSpec *roadstopspec = roadstop >= _cur.grffile->roadstops.size() ? nullptr : _cur.grffile->roadstops[roadstop].get();
 

	
 
			if (roadstopspec == nullptr) {
 
				GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID {:#02X} does not exist, skipping", roadstop);
 
				GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x{:02X} does not exist, skipping", roadstop);
 
				continue;
 
			}
 

	
 
			roadstopspec->grf_prop.spritegroup[ctype] = _cur.spritegroups[groupid];
 
		}
 
	}
 
@@ -6066,18 +6066,18 @@ static void RoadStopMapSpriteGroup(ByteR
 
	if (!IsValidGroupID(groupid, "RoadStopMapSpriteGroup")) return;
 

	
 
	for (auto &roadstop : roadstops) {
 
		RoadStopSpec *roadstopspec = roadstop >= _cur.grffile->roadstops.size() ? nullptr : _cur.grffile->roadstops[roadstop].get();
 

	
 
		if (roadstopspec == nullptr) {
 
			GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID {:#02X} does not exist, skipping.", roadstop);
 
			GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x{:02X} does not exist, skipping.", roadstop);
 
			continue;
 
		}
 

	
 
		if (roadstopspec->grf_prop.grffile != nullptr) {
 
			GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID {:#02X} mapped multiple times, skipping", roadstop);
 
			GrfMsg(1, "RoadStopMapSpriteGroup: Road stop with ID 0x{:02X} mapped multiple times, skipping", roadstop);
 
			continue;
 
		}
 

	
 
		roadstopspec->grf_prop.spritegroup[CT_DEFAULT] = _cur.spritegroups[groupid];
 
		roadstopspec->grf_prop.grffile = _cur.grffile;
 
		roadstopspec->grf_prop.local_id = roadstop;
 
@@ -6103,33 +6103,33 @@ static void FeatureMapSpriteGroup(ByteRe
 
	 * W def-cid       default cargo ID (sprite group ID) */
 

	
 
	uint8 feature = buf->ReadByte();
 
	uint8 idcount = buf->ReadByte();
 

	
 
	if (feature >= GSF_END) {
 
		GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature {:#02X}, skipping", feature);
 
		GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
 
		return;
 
	}
 

	
 
	/* If idcount is zero, this is a feature callback */
 
	if (idcount == 0) {
 
		/* Skip number of cargo ids? */
 
		buf->ReadByte();
 
		uint16 groupid = buf->ReadWord();
 
		if (!IsValidGroupID(groupid, "FeatureMapSpriteGroup")) return;
 

	
 
		GrfMsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature {:#02X}", feature);
 
		GrfMsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature 0x{:02X}", feature);
 

	
 
		AddGenericCallback(feature, _cur.grffile, _cur.spritegroups[groupid]);
 
		return;
 
	}
 

	
 
	/* Mark the feature as used by the grf (generic callbacks do not count) */
 
	SetBit(_cur.grffile->grf_features, feature);
 

	
 
	GrfMsg(6, "FeatureMapSpriteGroup: Feature {:#02X}, {} ids", feature, idcount);
 
	GrfMsg(6, "FeatureMapSpriteGroup: Feature 0x{:02X}, {} ids", feature, idcount);
 

	
 
	switch (feature) {
 
		case GSF_TRAINS:
 
		case GSF_ROADVEHICLES:
 
		case GSF_SHIPS:
 
		case GSF_AIRCRAFT:
 
@@ -6186,13 +6186,13 @@ static void FeatureMapSpriteGroup(ByteRe
 

	
 
		case GSF_ROADSTOPS:
 
			RoadStopMapSpriteGroup(buf, idcount);
 
			return;
 

	
 
		default:
 
			GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature {:#02X}, skipping", feature);
 
			GrfMsg(1, "FeatureMapSpriteGroup: Unsupported feature 0x{:02X}, skipping", feature);
 
			return;
 
	}
 
}
 

	
 
/* Action 0x04 */
 
static void FeatureNewName(ByteReader *buf)
 
@@ -6214,13 +6214,13 @@ static void FeatureNewName(ByteReader *b
 
	 *                 which the next name begins. */
 

	
 
	bool new_scheme = _cur.grffile->grf_version >= 7;
 

	
 
	uint8 feature  = buf->ReadByte();
 
	if (feature >= GSF_END && feature != 0x48) {
 
		GrfMsg(1, "FeatureNewName: Unsupported feature {:#02X}, skipping", feature);
 
		GrfMsg(1, "FeatureNewName: Unsupported feature 0x{:02X}, skipping", feature);
 
		return;
 
	}
 

	
 
	uint8 lang     = buf->ReadByte();
 
	uint8 num      = buf->ReadByte();
 
	bool generic   = HasBit(lang, 7);
 
@@ -6234,18 +6234,18 @@ static void FeatureNewName(ByteReader *b
 
	}
 

	
 
	ClrBit(lang, 7);
 

	
 
	uint16 endid = id + num;
 

	
 
	GrfMsg(6, "FeatureNewName: About to rename engines {}..{} (feature {:#02X}) in language {:#02X}",
 
	GrfMsg(6, "FeatureNewName: About to rename engines {}..{} (feature 0x{:02X}) in language 0x{:02X}",
 
	               id, endid, feature, lang);
 

	
 
	for (; id < endid && buf->HasData(); id++) {
 
		const char *name = buf->ReadString();
 
		GrfMsg(8, "FeatureNewName: {:#04X} <- {}", id, name);
 
		GrfMsg(8, "FeatureNewName: 0x{:04X} <- {}", id, name);
 

	
 
		switch (feature) {
 
			case GSF_TRAINS:
 
			case GSF_ROADVEHICLES:
 
			case GSF_SHIPS:
 
			case GSF_AIRCRAFT:
 
@@ -6265,45 +6265,45 @@ static void FeatureNewName(ByteReader *b
 
					break;
 
				}
 

	
 
				switch (GB(id, 8, 8)) {
 
					case 0xC4: // Station class name
 
						if (GB(id, 0, 8) >= _cur.grffile->stations.size() || _cur.grffile->stations[GB(id, 0, 8)] == nullptr) {
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined station {:#X}, ignoring", GB(id, 0, 8));
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring", GB(id, 0, 8));
 
						} else {
 
							StationClassID cls_id = _cur.grffile->stations[GB(id, 0, 8)]->cls_id;
 
							StationClass::Get(cls_id)->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
 
						}
 
						break;
 

	
 
					case 0xC5: // Station name
 
						if (GB(id, 0, 8) >= _cur.grffile->stations.size() || _cur.grffile->stations[GB(id, 0, 8)] == nullptr) {
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined station {:#X}, ignoring", GB(id, 0, 8));
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined station 0x{:X}, ignoring", GB(id, 0, 8));
 
						} else {
 
							_cur.grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
 
						}
 
						break;
 

	
 
					case 0xC7: // Airporttile name
 
						if (GB(id, 0, 8) >= _cur.grffile->airtspec.size() || _cur.grffile->airtspec[GB(id, 0, 8)] == nullptr) {
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined airport tile {:#X}, ignoring", GB(id, 0, 8));
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined airport tile 0x{:X}, ignoring", GB(id, 0, 8));
 
						} else {
 
							_cur.grffile->airtspec[GB(id, 0, 8)]->name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
 
						}
 
						break;
 

	
 
					case 0xC9: // House name
 
						if (GB(id, 0, 8) >= _cur.grffile->housespec.size() || _cur.grffile->housespec[GB(id, 0, 8)] == nullptr) {
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined house {:#X}, ignoring.", GB(id, 0, 8));
 
							GrfMsg(1, "FeatureNewName: Attempt to name undefined house 0x{:X}, ignoring.", GB(id, 0, 8));
 
						} else {
 
							_cur.grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur.grffile->grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
 
						}
 
						break;
 

	
 
					default:
 
						GrfMsg(7, "FeatureNewName: Unsupported ID ({:#04X})", id);
 
						GrfMsg(7, "FeatureNewName: Unsupported ID (0x{:04X})", id);
 
						break;
 
				}
 
				break;
 
		}
 
	}
 
}
 
@@ -6413,41 +6413,41 @@ static void GraphicsNew(ByteReader *buf)
 
		if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ONLY_NEW;
 
		return;
 
	}
 

	
 
	/* Supported type? */
 
	if ((type >= lengthof(_action5_types)) || (_action5_types[type].block_type == A5BLOCK_INVALID)) {
 
		GrfMsg(2, "GraphicsNew: Custom graphics (type {:#02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
 
		GrfMsg(2, "GraphicsNew: Custom graphics (type 0x{:02X}) sprite block of length {} (unimplemented, ignoring)", type, num);
 
		_cur.skip_sprites = num;
 
		return;
 
	}
 

	
 
	const Action5Type *action5_type = &_action5_types[type];
 

	
 
	/* Contrary to TTDP we allow always to specify too few sprites as we allow always an offset,
 
	 * except for the long version of the shore type:
 
	 * Ignore offset if not allowed */
 
	if ((action5_type->block_type != A5BLOCK_ALLOW_OFFSET) && (offset != 0)) {
 
		GrfMsg(1, "GraphicsNew: {} (type {:#02X}) do not allow an <offset> field. Ignoring offset.", action5_type->name, type);
 
		GrfMsg(1, "GraphicsNew: {} (type 0x{:02X}) do not allow an <offset> field. Ignoring offset.", action5_type->name, type);
 
		offset = 0;
 
	}
 

	
 
	/* Ignore action5 if too few sprites are specified. (for TTDP compatibility)
 
	 * This does not make sense, if <offset> is allowed */
 
	if ((action5_type->block_type == A5BLOCK_FIXED) && (num < action5_type->min_sprites)) {
 
		GrfMsg(1, "GraphicsNew: {} (type {:#02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->name, type, action5_type->min_sprites, num);
 
		GrfMsg(1, "GraphicsNew: {} (type 0x{:02X}) count must be at least {}. Only {} were specified. Skipping.", action5_type->name, type, action5_type->min_sprites, num);
 
		_cur.skip_sprites = num;
 
		return;
 
	}
 

	
 
	/* Load at most max_sprites sprites. Skip remaining sprites. (for compatibility with TTDP and future extensions) */
 
	uint16 skip_num = SanitizeSpriteOffset(num, offset, action5_type->max_sprites, action5_type->name);
 
	SpriteID replace = action5_type->sprite_base + offset;
 

	
 
	/* Load <num> sprites starting from <replace>, then skip <skip_num> sprites. */
 
	GrfMsg(2, "GraphicsNew: Replacing sprites {} to {} of {} (type {:#02X}) at SpriteID {:#04X}", offset, offset + num - 1, action5_type->name, type, replace);
 
	GrfMsg(2, "GraphicsNew: Replacing sprites {} to {} of {} (type 0x{:02X}) at SpriteID 0x{:04X}", offset, offset + num - 1, action5_type->name, type, replace);
 

	
 
	if (type == 0x0D) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_5;
 

	
 
	if (type == 0x0B) {
 
		static const SpriteID depot_with_track_offset = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_TRAMWAY_BASE;
 
		static const SpriteID depot_no_track_offset = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_TRAMWAY_BASE;
 
@@ -6661,13 +6661,13 @@ static uint32 GetParamVal(byte param, ui
 

	
 
		default:
 
			/* GRF Parameter */
 
			if (param < 0x80) return _cur.grffile->GetParam(param);
 

	
 
			/* In-game variable. */
 
			GrfMsg(1, "Unsupported in-game variable {:#02X}", param);
 
			GrfMsg(1, "Unsupported in-game variable 0x{:02X}", param);
 
			return UINT_MAX;
 
	}
 
}
 

	
 
/* Action 0x06 */
 
static void CfgApply(ByteReader *buf)
 
@@ -6743,13 +6743,13 @@ static void CfgApply(ByteReader *buf)
 
		 * if it (and all further sequential parameters) has been defined. */
 
		if (param_num < 0x80 && (param_num + (param_size - 1) / 4) >= _cur.grffile->param_end) {
 
			GrfMsg(2, "CfgApply: Ignoring (param {} not set)", (param_num + (param_size - 1) / 4));
 
			break;
 
		}
 

	
 
		GrfMsg(8, "CfgApply: Applying {} bytes from parameter {:#02X} at offset {:#04X}", param_size, param_num, offset);
 
		GrfMsg(8, "CfgApply: Applying {} bytes from parameter 0x{:02X} at offset 0x{:04X}", param_size, param_num, offset);
 

	
 
		bool carry = false;
 
		for (i = 0; i < param_size && offset + i < num; i++) {
 
			uint32 value = GetParamVal(param_num + i / 4, nullptr);
 
			/* Reset carry flag for each iteration of the variable (only really
 
			 * matters if param_size is greater than 4) */
 
@@ -6816,13 +6816,13 @@ static void SkipIf(ByteReader *buf)
 

	
 
	if (param < 0x80 && _cur.grffile->param_end <= param) {
 
		GrfMsg(7, "SkipIf: Param {} undefined, skipping test", param);
 
		return;
 
	}
 

	
 
	GrfMsg(7, "SkipIf: Test condtype {}, param {:#02X}, condval {:#08X}", condtype, param, cond_val);
 
	GrfMsg(7, "SkipIf: Test condtype {}, param 0x{:02X}, condval 0x{:08X}", condtype, param, cond_val);
 

	
 
	/* condtypes that do not use 'param' are always valid.
 
	 * condtypes that use 'param' are either not valid for param 0x88, or they are only valid for param 0x88.
 
	 */
 
	if (condtype >= 0x0B) {
 
		/* Tests that ignore 'param' */
 
@@ -6865,13 +6865,13 @@ static void SkipIf(ByteReader *buf)
 
		if (c != nullptr && HasBit(c->flags, GCF_STATIC) && !HasBit(_cur.grfconfig->flags, GCF_STATIC) && _networking) {
 
			DisableStaticNewGRFInfluencingNonStaticNewGRFs(c);
 
			c = nullptr;
 
		}
 

	
 
		if (condtype != 10 && c == nullptr) {
 
			GrfMsg(7, "SkipIf: GRFID {:#08X} unknown, skipping test", BSWAP32(cond_val));
 
			GrfMsg(7, "SkipIf: GRFID 0x{:08X} unknown, skipping test", BSWAP32(cond_val));
 
			return;
 
		}
 

	
 
		switch (condtype) {
 
			/* Tests 0x06 to 0x0A are only for param 0x88, GRFID checks */
 
			case 0x06: // Is GRFID active?
 
@@ -6939,13 +6939,13 @@ static void SkipIf(ByteReader *buf)
 
			choice = &label;
 
			break;
 
		}
 
	}
 

	
 
	if (choice != nullptr) {
 
		GrfMsg(2, "SkipIf: Jumping to label {:#X} at line {}, test was true", choice->label, choice->nfo_line);
 
		GrfMsg(2, "SkipIf: Jumping to label 0x{:X} at line {}, test was true", choice->label, choice->nfo_line);
 
		_cur.file->SeekTo(choice->pos, SEEK_SET);
 
		_cur.nfo_line = choice->nfo_line;
 
		return;
 
	}
 

	
 
	GrfMsg(2, "SkipIf: Skipping {} sprites, test was true", numsprites);
 
@@ -7285,13 +7285,13 @@ static uint32 GetPatchVariable(uint8 par
 

	
 
		/* Game map seed */
 
		case 0x17:
 
			return _settings_game.game_creation.generation_seed;
 

	
 
		default:
 
			GrfMsg(2, "ParamSet: Unknown Patch variable {:#02X}.", param);
 
			GrfMsg(2, "ParamSet: Unknown Patch variable 0x{:02X}.", param);
 
			return 0;
 
	}
 
}
 

	
 

	
 
static uint32 PerformGRM(uint32 *grm, uint16 num_ids, uint16 count, uint8 op, uint8 target, const char *type)
 
@@ -7464,13 +7464,13 @@ static void ParamSet(ByteReader *buf)
 
						case 0x0B: // Cargo
 
							/* There are two ranges: one for cargo IDs and one for cargo bitmasks */
 
							src1 = PerformGRM(_grm_cargoes, NUM_CARGO * 2, count, op, target, "cargoes");
 
							if (_cur.skip_sprites == -1) return;
 
							break;
 

	
 
						default: GrfMsg(1, "ParamSet: GRM: Unsupported feature {:#X}", feature); return;
 
						default: GrfMsg(1, "ParamSet: GRM: Unsupported feature 0x{:X}", feature); return;
 
					}
 
				} else {
 
					/* Ignore GRM during initialization */
 
					src1 = 0;
 
				}
 
			}
 
@@ -7604,13 +7604,13 @@ static void ParamSet(ByteReader *buf)
 
		case 0x93: // Tile refresh offset to left -- Intended to allow support for larger sprites, not necessary for OTTD
 
		case 0x94: // Tile refresh offset to right
 
		case 0x95: // Tile refresh offset upwards
 
		case 0x96: // Tile refresh offset downwards
 
		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
 
		case 0x99: // Global ID offset -- Not necessary since IDs are remapped automatically
 
			GrfMsg(7, "ParamSet: Skipping unimplemented target {:#02X}", target);
 
			GrfMsg(7, "ParamSet: Skipping unimplemented target 0x{:02X}", target);
 
			break;
 

	
 
		case 0x9E: // Miscellaneous GRF features
 
			/* Set train list engine width */
 
			_cur.grffile->traininfo_vehicle_width = HasBit(res, GMB_TRAIN_WIDTH_32_PIXELS) ? VEHICLEINFO_FULL_VEHICLE_WIDTH : TRAININFO_DEFAULT_VEHICLE_WIDTH;
 
			/* Remove the local flags from the global flags */
 
@@ -7625,22 +7625,22 @@ static void ParamSet(ByteReader *buf)
 
			} else {
 
				_misc_grf_features = res;
 
			}
 
			break;
 

	
 
		case 0x9F: // locale-dependent settings
 
			GrfMsg(7, "ParamSet: Skipping unimplemented target {:#02X}", target);
 
			GrfMsg(7, "ParamSet: Skipping unimplemented target 0x{:02X}", target);
 
			break;
 

	
 
		default:
 
			if (target < 0x80) {
 
				_cur.grffile->param[target] = res;
 
				/* param is zeroed by default */
 
				if (target + 1U > _cur.grffile->param_end) _cur.grffile->param_end = target + 1;
 
			} else {
 
				GrfMsg(7, "ParamSet: Skipping unknown target {:#02X}", target);
 
				GrfMsg(7, "ParamSet: Skipping unknown target 0x{:02X}", target);
 
			}
 
			break;
 
	}
 
}
 

	
 
/* Action 0x0E (GLS_SAFETYSCAN) */
 
@@ -7703,13 +7703,13 @@ static void FeatureTownName(ByteReader *
 

	
 
	uint32 grfid = _cur.grffile->grfid;
 

	
 
	GRFTownName *townname = AddGRFTownName(grfid);
 

	
 
	byte id = buf->ReadByte();
 
	GrfMsg(6, "FeatureTownName: definition {:#02X}", id & 0x7F);
 
	GrfMsg(6, "FeatureTownName: definition 0x{:02X}", id & 0x7F);
 

	
 
	if (HasBit(id, 7)) {
 
		/* Final definition */
 
		ClrBit(id, 7);
 
		bool new_scheme = _cur.grffile->grf_version >= 7;
 

	
 
@@ -7719,13 +7719,13 @@ static void FeatureTownName(ByteReader *
 
		do {
 
			ClrBit(lang, 7);
 

	
 
			const char *name = buf->ReadString();
 

	
 
			std::string lang_name = TranslateTTDPatchCodes(grfid, lang, false, name);
 
			GrfMsg(6, "FeatureTownName: lang {:#X} -> '{}'", lang, lang_name.c_str());
 
			GrfMsg(6, "FeatureTownName: lang 0x{:X} -> '{}'", lang, lang_name.c_str());
 

	
 
			style = AddGRFString(grfid, id, lang, new_scheme, false, name, STR_UNDEFINED);
 

	
 
			lang = buf->ReadByte();
 
		} while (lang != 0);
 
		townname->styles.emplace_back(style, id);
 
@@ -7748,19 +7748,19 @@ static void FeatureTownName(ByteReader *
 
			NamePart &part = partlist.parts.emplace_back();
 
			part.prob = buf->ReadByte();
 

	
 
			if (HasBit(part.prob, 7)) {
 
				byte ref_id = buf->ReadByte();
 
				if (ref_id >= GRFTownName::MAX_LISTS || townname->partlists[ref_id].empty()) {
 
					GrfMsg(0, "FeatureTownName: definition {:#02X} doesn't exist, deactivating", ref_id);
 
					GrfMsg(0, "FeatureTownName: definition 0x{:02X} doesn't exist, deactivating", ref_id);
 
					DelGRFTownName(grfid);
 
					DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
 
					return;
 
				}
 
				part.id = ref_id;
 
				GrfMsg(6, "FeatureTownName: part {}, text {}, uses intermediate definition {:#02X} (with probability {})", partnum, textnum, ref_id, part.prob & 0x7F);
 
				GrfMsg(6, "FeatureTownName: part {}, text {}, uses intermediate definition 0x{:02X} (with probability {})", partnum, textnum, ref_id, part.prob & 0x7F);
 
			} else {
 
				const char *text = buf->ReadString();
 
				part.text = TranslateTTDPatchCodes(grfid, 0, false, text);
 
				GrfMsg(6, "FeatureTownName: part {}, text {}, '{}' (with probability {})", partnum, textnum, part.text.c_str(), part.prob);
 
			}
 
			partlist.maxprob += GB(part.prob, 0, 7);
 
@@ -7778,13 +7778,13 @@ static void DefineGotoLabel(ByteReader *
 
	 * V comment    Optional comment - ignored */
 

	
 
	byte nfo_label = buf->ReadByte();
 

	
 
	_cur.grffile->labels.emplace_back(nfo_label, _cur.nfo_line, _cur.file->GetPos());
 

	
 
	GrfMsg(2, "DefineGotoLabel: GOTO target with label {:#02X}", nfo_label);
 
	GrfMsg(2, "DefineGotoLabel: GOTO target with label 0x{:02X}", nfo_label);
 
}
 

	
 
/**
 
 * Process a sound import from another GRF file.
 
 * @param sound Destination for sound.
 
 */
 
@@ -7956,13 +7956,13 @@ static void LoadFontGlyph(ByteReader *bu
 
		uint16 base_char = buf->ReadWord();
 

	
 
		if (size >= FS_END) {
 
			GrfMsg(1, "LoadFontGlyph: Size {} is not supported, ignoring", size);
 
		}
 

	
 
		GrfMsg(7, "LoadFontGlyph: Loading {} glyph(s) at {:#04X} for size {}", num_char, base_char, size);
 
		GrfMsg(7, "LoadFontGlyph: Loading {} glyph(s) at 0x{:04X} for size {}", num_char, base_char, size);
 

	
 
		for (uint c = 0; c < num_char; c++) {
 
			if (size < FS_END) SetUnicodeGlyph(size, base_char + c, _cur.spriteid);
 
			_cur.nfo_line++;
 
			LoadNextSprite(_cur.spriteid++, *_cur.file, _cur.nfo_line);
 
		}
 
@@ -8005,13 +8005,13 @@ static void TranslateGRFStrings(ByteRead
 
	 * W   offset    First text ID
 
	 * S   text...   Zero-terminated strings */
 

	
 
	uint32 grfid = buf->ReadDWord();
 
	const GRFConfig *c = GetGRFConfig(grfid);
 
	if (c == nullptr || (c->status != GCS_INITIALISED && c->status != GCS_ACTIVATED)) {
 
		GrfMsg(7, "TranslateGRFStrings: GRFID {:#08X} unknown, skipping action 13", BSWAP32(grfid));
 
		GrfMsg(7, "TranslateGRFStrings: GRFID 0x{:08X} unknown, skipping action 13", BSWAP32(grfid));
 
		return;
 
	}
 

	
 
	if (c->status == GCS_INITIALISED) {
 
		/* If the file is not active but will be activated later, give an error
 
		 * and disable this file. */
 
@@ -8029,13 +8029,13 @@ static void TranslateGRFStrings(ByteRead
 
	 * not change anything if a string has been provided specifically for this language. */
 
	byte language = _cur.grffile->grf_version >= 8 ? buf->ReadByte() : 0x7F;
 
	byte num_strings = buf->ReadByte();
 
	uint16 first_id  = buf->ReadWord();
 

	
 
	if (!((first_id >= 0xD000 && first_id + num_strings <= 0xD400) || (first_id >= 0xD800 && first_id + num_strings <= 0xE000))) {
 
		GrfMsg(7, "TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: {:#04X}, number: {:#02X})", first_id, num_strings);
 
		GrfMsg(7, "TranslateGRFStrings: Attempting to set out-of-range string IDs in action 13 (first: 0x{:04X}, number: 0x{:02X})", first_id, num_strings);
 
		return;
 
	}
 

	
 
	for (uint i = 0; i < num_strings && buf->HasData(); i++) {
 
		const char *string = buf->ReadString();
 

	
 
@@ -9497,17 +9497,17 @@ static void DecodeSpecialSprite(byte *bu
 

	
 
		if (action == 0xFF) {
 
			GrfMsg(2, "DecodeSpecialSprite: Unexpected data block, skipping");
 
		} else if (action == 0xFE) {
 
			GrfMsg(2, "DecodeSpecialSprite: Unexpected import block, skipping");
 
		} else if (action >= lengthof(handlers)) {
 
			GrfMsg(7, "DecodeSpecialSprite: Skipping unknown action {:#02X}", action);
 
			GrfMsg(7, "DecodeSpecialSprite: Skipping unknown action 0x{:02X}", action);
 
		} else if (handlers[action][stage] == nullptr) {
 
			GrfMsg(7, "DecodeSpecialSprite: Skipping action {:#02X} in stage {}", action, stage);
 
			GrfMsg(7, "DecodeSpecialSprite: Skipping action 0x{:02X} in stage {}", action, stage);
 
		} else {
 
			GrfMsg(7, "DecodeSpecialSprite: Handling action {:#02X} in stage {}", action, stage);
 
			GrfMsg(7, "DecodeSpecialSprite: Handling action 0x{:02X} in stage {}", action, stage);
 
			handlers[action][stage](bufp);
 
		}
 
	} catch (...) {
 
		GrfMsg(1, "DecodeSpecialSprite: Tried to read past end of pseudo-sprite data");
 
		DisableGrf(STR_NEWGRF_ERROR_READ_BOUNDS);
 
	}