src/newgrf.cpp
branchNewGRF_ports
changeset 6720 35756db7e577
parent 6719 4cc327ad39d5
child 6722 72f280229ee1
--- a/src/newgrf.cpp	Sat Jun 02 19:59:29 2007 +0000
+++ b/src/newgrf.cpp	Sat Jul 14 19:42:58 2007 +0000
@@ -18,6 +18,7 @@
 #include "newgrf.h"
 #include "variables.h"
 #include "string.h"
+#include "strings.h"
 #include "table/strings.h"
 #include "bridge.h"
 #include "town.h"
@@ -40,7 +41,10 @@
 #include "cargotype.h"
 #include "industry.h"
 #include "newgrf_canal.h"
+#include "table/build_industry.h"
 #include "newgrf_commons.h"
+#include "newgrf_townname.h"
+#include "newgrf_industries.h"
 
 /* TTDPatch extended GRF format codec
  * (c) Petr Baudis 2004 (GPL'd)
@@ -75,7 +79,7 @@
 static byte *_preload_sprite = NULL;
 
 /* Indicates which are the newgrf features currently loaded ingame */
-uint8 _loaded_newgrf_features;
+GRFLoadedFeatures _loaded_newgrf_features;
 
 enum GrfDataType {
 	GDT_SOUND,
@@ -283,8 +287,6 @@
 
 typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
 
-#define FOR_EACH_OBJECT for (i = 0; i < numinfo; i++)
-
 static void dewagonize(int condition, int engine)
 {
 	EngineInfo *ei = &_engine_info[engine];
@@ -302,153 +304,138 @@
 
 static bool RailVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
 {
-	EngineInfo *ei = &_engine_info[engine];
-	RailVehicleInfo *rvi = &_rail_vehicle_info[engine];
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	switch (prop) {
-		case 0x05: // Track type
-			FOR_EACH_OBJECT {
+	for (int i = 0; i < numinfo; i++) {
+		EngineInfo *ei       = &_engine_info[engine + i];
+		RailVehicleInfo *rvi = &_rail_vehicle_info[engine + i];
+
+		switch (prop) {
+			case 0x05: { // Track type
 				uint8 tracktype = grf_load_byte(&buf);
 
 				switch (tracktype) {
-					case 0: rvi[i].railtype = rvi[i].engclass >= 2 ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; break;
-					case 1: rvi[i].railtype = RAILTYPE_MONO; break;
-					case 2: rvi[i].railtype = RAILTYPE_MAGLEV; break;
+					case 0: rvi->railtype = rvi->engclass >= 2 ? RAILTYPE_ELECTRIC : RAILTYPE_RAIL; break;
+					case 1: rvi->railtype = RAILTYPE_MONO; break;
+					case 2: rvi->railtype = RAILTYPE_MAGLEV; break;
 					default:
 						grfmsg(1, "RailVehicleChangeInfo: Invalid track type %d specified, ignoring", tracktype);
 						break;
 				}
-			}
-			break;
-
-		case 0x08: // AI passenger service
-			/* @todo missing feature */
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		case 0x09: // Speed (1 unit is 1 kmh)
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x08: // AI passenger service
+				/** @todo Tells the AI that this engine is designed for
+				 * passenger services and shouldn't be used for freight. */
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			case 0x09: { // Speed (1 unit is 1 kmh)
 				uint16 speed = grf_load_word(&buf);
 				if (speed == 0xFFFF) speed = 0;
 
-				rvi[i].max_speed = speed;
-			}
-			break;
-
-		case 0x0B: // Power
-			FOR_EACH_OBJECT {
+				rvi->max_speed = speed;
+			} break;
+
+			case 0x0B: { // Power
 				uint16 power = grf_load_word(&buf);
 
-				if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) power /= 2;
-
-				rvi[i].power = power;
+				if (rvi->railveh_type == RAILVEH_MULTIHEAD) power /= 2;
+
+				rvi->power = power;
 				dewagonize(power, engine + i);
-			}
-			break;
-
-		case 0x0D: // Running cost factor
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0D: { // Running cost factor
 				uint8 runcostfact = grf_load_byte(&buf);
 
-				if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) runcostfact /= 2;
-
-				rvi[i].running_cost_base = runcostfact;
-			}
-			break;
-
-		case 0x0E: // Running cost base
-			FOR_EACH_OBJECT {
+				if (rvi->railveh_type == RAILVEH_MULTIHEAD) runcostfact /= 2;
+
+				rvi->running_cost_base = runcostfact;
+			} break;
+
+			case 0x0E: { // Running cost base
 				uint32 base = grf_load_dword(&buf);
 
 				switch (base) {
-					case 0x4C30: rvi[i].running_cost_class = 0; break;
-					case 0x4C36: rvi[i].running_cost_class = 1; break;
-					case 0x4C3C: rvi[i].running_cost_class = 2; break;
+					case 0x4C30: rvi->running_cost_class = 0; break;
+					case 0x4C36: rvi->running_cost_class = 1; break;
+					case 0x4C3C: rvi->running_cost_class = 2; break;
 					case 0: break; // Used by wagons
 					default:
 						grfmsg(1, "RailVehicleChangeInfo: Unsupported running cost base 0x%04X, ignoring", base);
 						break;
 				}
-			}
-			break;
-
-		case 0x12: // Sprite ID
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x12: { // Sprite ID
 				uint8 spriteid = grf_load_byte(&buf);
 
 				/* TTD sprite IDs point to a location in a 16bit array, but we use it
 				 * as an array index, so we need it to be half the original value. */
 				if (spriteid < 0xFD) spriteid >>= 1;
 
-				rvi[i].image_index = spriteid;
-			}
-			break;
-
-		case 0x13: // Dual-headed
-			FOR_EACH_OBJECT {
+				rvi->image_index = spriteid;
+			} break;
+
+			case 0x13: { // Dual-headed
 				uint8 dual = grf_load_byte(&buf);
 
 				if (dual != 0) {
-					if (rvi[i].railveh_type != RAILVEH_MULTIHEAD) {
+					if (rvi->railveh_type != RAILVEH_MULTIHEAD) {
 						// adjust power and running cost if needed
-						rvi[i].power /= 2;
-						rvi[i].running_cost_base /= 2;
+						rvi->power /= 2;
+						rvi->running_cost_base /= 2;
 					}
-					rvi[i].railveh_type = RAILVEH_MULTIHEAD;
+					rvi->railveh_type = RAILVEH_MULTIHEAD;
 				} else {
-					if (rvi[i].railveh_type == RAILVEH_MULTIHEAD) {
+					if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
 						// adjust power and running cost if needed
-						rvi[i].power *= 2;
-						rvi[i].running_cost_base *= 2;
+						rvi->power *= 2;
+						rvi->running_cost_base *= 2;
 					}
-					rvi[i].railveh_type = rvi[i].power == 0 ?
+					rvi->railveh_type = rvi->power == 0 ?
 						RAILVEH_WAGON : RAILVEH_SINGLEHEAD;
 				}
-			}
-			break;
-
-		case 0x14: // Cargo capacity
-			FOR_EACH_OBJECT rvi[i].capacity = grf_load_byte(&buf);
-			break;
-
-		case 0x15: // Cargo type
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x14: // Cargo capacity
+				rvi->capacity = grf_load_byte(&buf);
+				break;
+
+			case 0x15: { // Cargo type
 				uint8 ctype = grf_load_byte(&buf);
 
 				if (ctype < NUM_CARGO && HASBIT(_cargo_mask, ctype)) {
-					rvi[i].cargo_type = ctype;
+					rvi->cargo_type = ctype;
 				} else {
-					rvi[i].cargo_type = CT_INVALID;
+					rvi->cargo_type = CT_INVALID;
 					grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
 				}
-			}
-			break;
-
-		case 0x16: // Weight
-			FOR_EACH_OBJECT SB(rvi[i].weight, 0, 8, grf_load_byte(&buf));
-			break;
-
-		case 0x17: // Cost factor
-			FOR_EACH_OBJECT rvi[i].base_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x18: // AI rank
-			FOR_EACH_OBJECT rvi[i].ai_rank = grf_load_byte(&buf);
-			break;
-
-		case 0x19: // Engine traction type
-			/* What do the individual numbers mean?
-			 * 0x00 .. 0x07: Steam
-			 * 0x08 .. 0x27: Diesel
-			 * 0x28 .. 0x31: Electric
-			 * 0x32 .. 0x37: Monorail
-			 * 0x38 .. 0x41: Maglev
-			 */
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x16: // Weight
+				SB(rvi->weight, 0, 8, grf_load_byte(&buf));
+				break;
+
+			case 0x17: // Cost factor
+				rvi->base_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x18: // AI rank
+				rvi->ai_rank = grf_load_byte(&buf);
+				break;
+
+			case 0x19: { // Engine traction type
+				/* What do the individual numbers mean?
+				 * 0x00 .. 0x07: Steam
+				 * 0x08 .. 0x27: Diesel
+				 * 0x28 .. 0x31: Electric
+				 * 0x32 .. 0x37: Monorail
+				 * 0x38 .. 0x41: Maglev
+				 */
 				uint8 traction = grf_load_byte(&buf);
 				EngineClass engclass;
 
@@ -465,15 +452,13 @@
 				} else {
 					break;
 				}
-				if (rvi[i].railtype == RAILTYPE_RAIL     && engclass >= EC_ELECTRIC) rvi[i].railtype = RAILTYPE_ELECTRIC;
-				if (rvi[i].railtype == RAILTYPE_ELECTRIC && engclass  < EC_ELECTRIC) rvi[i].railtype = RAILTYPE_RAIL;
-
-				rvi[i].engclass = engclass;
-			}
-			break;
-
-		case 0x1A: // Alter purchase list sort order
-			FOR_EACH_OBJECT {
+				if (rvi->railtype == RAILTYPE_RAIL     && engclass >= EC_ELECTRIC) rvi->railtype = RAILTYPE_ELECTRIC;
+				if (rvi->railtype == RAILTYPE_ELECTRIC && engclass  < EC_ELECTRIC) rvi->railtype = RAILTYPE_RAIL;
+
+				rvi->engclass = engclass;
+			} break;
+
+			case 0x1A: { // Alter purchase list sort order
 				EngineID pos = grf_load_byte(&buf);
 
 				if (pos < NUM_TRAIN_ENGINES) {
@@ -481,122 +466,118 @@
 				} else {
 					grfmsg(2, "RailVehicleChangeInfo: Invalid train engine ID %d, ignoring", pos);
 				}
-			}
-			break;
-
-		case 0x1B: // Powered wagons power bonus
-			FOR_EACH_OBJECT rvi[i].pow_wag_power = grf_load_word(&buf);
-			break;
-
-		case 0x1C: // Refit cost
-			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x1D: // Refit cargo
-			FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
-			break;
-
-		case 0x1E: // Callback
-			FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x1F: // Tractive effort coefficient
-			FOR_EACH_OBJECT rvi[i].tractive_effort = grf_load_byte(&buf);
-			break;
-
-		case 0x21: // Shorter vehicle
-			FOR_EACH_OBJECT rvi[i].shorten_factor = grf_load_byte(&buf);
-			break;
-
-		case 0x22: // Visual effect
-			/* see note in engine.h about rvi->visual_effect */
-			FOR_EACH_OBJECT rvi[i].visual_effect = grf_load_byte(&buf);
-			break;
-
-		case 0x23: // Powered wagons weight bonus
-			FOR_EACH_OBJECT rvi[i].pow_wag_weight = grf_load_byte(&buf);
-			break;
-
-		case 0x24: // High byte of vehicle weight
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x1B: // Powered wagons power bonus
+				rvi->pow_wag_power = grf_load_word(&buf);
+				break;
+
+			case 0x1C: // Refit cost
+				ei->refit_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x1D: // Refit cargo
+				ei->refit_mask = grf_load_dword(&buf);
+				break;
+
+			case 0x1E: // Callback
+				ei->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x1F: // Tractive effort coefficient
+				rvi->tractive_effort = grf_load_byte(&buf);
+				break;
+
+			case 0x21: // Shorter vehicle
+				rvi->shorten_factor = grf_load_byte(&buf);
+				break;
+
+			case 0x22: // Visual effect
+				/** @see note in engine.h about rvi->visual_effect */
+				rvi->visual_effect = grf_load_byte(&buf);
+				break;
+
+			case 0x23: // Powered wagons weight bonus
+				rvi->pow_wag_weight = grf_load_byte(&buf);
+				break;
+
+			case 0x24: { // High byte of vehicle weight
 				byte weight = grf_load_byte(&buf);
 
 				if (weight > 4) {
 					grfmsg(2, "RailVehicleChangeInfo: Nonsensical weight of %d tons, ignoring", weight << 8);
 				} else {
-					SB(rvi[i].weight, 8, 8, weight);
+					SB(rvi->weight, 8, 8, weight);
 				}
-			}
-			break;
-
-		case 0x25: // User-defined bit mask to set when checking veh. var. 42
-			FOR_EACH_OBJECT rvi[i].user_def_data = grf_load_byte(&buf);
-			break;
-
-		case 0x26: // Retire vehicle early
-			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
-			break;
-
-		case 0x27: // Miscellaneous flags
-			FOR_EACH_OBJECT {
-				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
-			}
-			break;
-
-		case 0x28: // Cargo classes allowed
-			FOR_EACH_OBJECT cargo_allowed[engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x29: // Cargo classes disallowed
-			FOR_EACH_OBJECT cargo_disallowed[engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x2A: // Long format introduction date (days since year 0)
-			FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
-			break;
-
-		/* @todo air drag and retire vehicle early
-		 * Fall-through for unimplemented one byte long properties. */
-		case 0x20: // Air drag
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x25: // User-defined bit mask to set when checking veh. var. 42
+				rvi->user_def_data = grf_load_byte(&buf);
+				break;
+
+			case 0x26: // Retire vehicle early
+				ei->retire_early = grf_load_byte(&buf);
+				break;
+
+			case 0x27: // Miscellaneous flags
+				ei->misc_flags = grf_load_byte(&buf);
+				_loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+				break;
+
+			case 0x28: // Cargo classes allowed
+				cargo_allowed[engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x29: // Cargo classes disallowed
+				cargo_disallowed[engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x2A: // Long format introduction date (days since year 0)
+				ei->base_intro = grf_load_dword(&buf);
+				break;
+
+			case 0x20: // Air drag
+				/** @todo Air drag for trains. */
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
+
 	*bufp = buf;
 	return ret;
 }
 
 static bool RoadVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
 {
-	EngineInfo *ei = &_engine_info[ROAD_ENGINES_INDEX + engine];
-	RoadVehicleInfo *rvi = &_road_vehicle_info[engine];
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	switch (prop) {
-		case 0x08: // Speed (1 unit is 0.5 kmh)
-			FOR_EACH_OBJECT rvi[i].max_speed = grf_load_byte(&buf);
-			break;
-
-		case 0x09: // Running cost factor
-			FOR_EACH_OBJECT rvi[i].running_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x0A: // Running cost base
-			/* @todo : I have no idea. --pasky
-			 * I THINK it is used for overriding the base cost of all road vehicle (_price.roadveh_base) --belugas */
-			FOR_EACH_OBJECT grf_load_dword(&buf);
-			ret = true;
-			break;
-
-		case 0x0E: // Sprite ID
-			FOR_EACH_OBJECT {
+	for (int i = 0; i < numinfo; i++) {
+		EngineInfo *ei       = &_engine_info[ROAD_ENGINES_INDEX + engine + i];
+		RoadVehicleInfo *rvi = &_road_vehicle_info[engine + i];
+
+		switch (prop) {
+			case 0x08: // Speed (1 unit is 0.5 kmh)
+				rvi->max_speed = grf_load_byte(&buf);
+				break;
+
+			case 0x09: // Running cost factor
+				rvi->running_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x0A: // Running cost base
+				/** @todo : I have no idea. --pasky
+				 * I THINK it is used for overriding the base cost of all road vehicle (_price.roadveh_base) --belugas */
+				grf_load_dword(&buf);
+				ret = true;
+				break;
+
+			case 0x0E: { // Sprite ID
 				uint8 spriteid = grf_load_byte(&buf);
 
 				/* cars have different custom id in the GRF file */
@@ -604,90 +585,86 @@
 
 				if (spriteid < 0xFD) spriteid >>= 1;
 
-				rvi[i].image_index = spriteid;
-			}
-			break;
-
-		case 0x0F: // Cargo capacity
-			FOR_EACH_OBJECT rvi[i].capacity = grf_load_byte(&buf);
-			break;
-
-		case 0x10: // Cargo type
-			FOR_EACH_OBJECT {
+				rvi->image_index = spriteid;
+			} break;
+
+			case 0x0F: // Cargo capacity
+				rvi->capacity = grf_load_byte(&buf);
+				break;
+
+			case 0x10: { // Cargo type
 				uint8 cargo = grf_load_byte(&buf);
 
 				if (cargo < NUM_CARGO && HASBIT(_cargo_mask, cargo)) {
-					rvi[i].cargo_type = cargo;
+					rvi->cargo_type = cargo;
 				} else {
-					rvi[i].cargo_type = CT_INVALID;
+					rvi->cargo_type = CT_INVALID;
 					grfmsg(2, "RoadVehicleChangeInfo: Invalid cargo type %d, using first refittable", cargo);
 				}
-			}
-			break;
-
-		case 0x11: // Cost factor
-			FOR_EACH_OBJECT rvi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
-			break;
-
-		case 0x12: // SFX
-			FOR_EACH_OBJECT rvi[i].sfx = (SoundFx)grf_load_byte(&buf);
-			break;
-
-		case 0x13: // Power in 10hp
-		case 0x14: // Weight in 1/4 tons
-		case 0x15: // Speed in mph*0.8
-			/* TODO: Support for road vehicles realistic power
-			 * computations (called rvpower in TTDPatch) is just
-			 * missing in OTTD yet. --pasky */
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		case 0x16: // Cargos available for refitting
-			FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
-			break;
-
-		case 0x17: // Callback mask
-			FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x1A: // Refit cost
-			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x1B: // Retire vehicle early
-			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
-			break;
-
-		case 0x1C: // Miscellaneous flags
-			FOR_EACH_OBJECT {
-				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
-			}
-			break;
-
-		case 0x1D: // Cargo classes allowed
-			FOR_EACH_OBJECT cargo_allowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x1E: // Cargo classes disallowed
-			FOR_EACH_OBJECT cargo_disallowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x1F: // Long format introduction date (days since year 0)
-			FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
-			break;
-
-		case 0x18: // Tractive effort
-		case 0x19: // Air drag
-			/* @todo */
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x11: // Cost factor
+				rvi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+				break;
+
+			case 0x12: // SFX
+				rvi->sfx = (SoundFx)grf_load_byte(&buf);
+				break;
+
+			case 0x13: // Power in 10hp
+			case 0x14: // Weight in 1/4 tons
+			case 0x15: // Speed in mph*0.8
+				/** @todo Support for road vehicles realistic power
+				 * computations (called rvpower in TTDPatch) is just
+				 * missing in OTTD yet. --pasky */
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			case 0x16: // Cargos available for refitting
+				ei->refit_mask = grf_load_dword(&buf);
+				break;
+
+			case 0x17: // Callback mask
+				ei->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x1A: // Refit cost
+				ei->refit_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x1B: // Retire vehicle early
+				ei->retire_early = grf_load_byte(&buf);
+				break;
+
+			case 0x1C: // Miscellaneous flags
+				ei->misc_flags = grf_load_byte(&buf);
+				_loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+				break;
+
+			case 0x1D: // Cargo classes allowed
+				cargo_allowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x1E: // Cargo classes disallowed
+				cargo_disallowed[ROAD_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x1F: // Long format introduction date (days since year 0)
+				ei->base_intro = grf_load_dword(&buf);
+				break;
+
+			case 0x18: // Tractive effort
+			case 0x19: // Air drag
+				/** @todo Tractive effort and air drag for road vehicles. */
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -696,16 +673,15 @@
 
 static bool ShipVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
 {
-	EngineInfo *ei = &_engine_info[SHIP_ENGINES_INDEX + engine];
-	ShipVehicleInfo *svi = &_ship_vehicle_info[engine];
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	//printf("e %x prop %x?\n", engine, prop);
-	switch (prop) {
-		case 0x08: // Sprite ID
-			FOR_EACH_OBJECT {
+	for (int i = 0; i < numinfo; i++) {
+		EngineInfo *ei       = &_engine_info[SHIP_ENGINES_INDEX + engine + i];
+		ShipVehicleInfo *svi = &_ship_vehicle_info[engine + i];
+
+		switch (prop) {
+			case 0x08: { // Sprite ID
 				uint8 spriteid = grf_load_byte(&buf);
 
 				/* ships have different custom id in the GRF file */
@@ -713,92 +689,88 @@
 
 				if (spriteid < 0xFD) spriteid >>= 1;
 
-				svi[i].image_index = spriteid;
-			}
-			break;
-
-		case 0x09: // Refittable
-			FOR_EACH_OBJECT svi[i].refittable = (grf_load_byte(&buf) != 0);
-			break;
-
-		case 0x0A: // Cost factor
-			FOR_EACH_OBJECT svi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
-			break;
-
-		case 0x0B: // Speed (1 unit is 0.5 kmh)
-			FOR_EACH_OBJECT svi[i].max_speed = grf_load_byte(&buf);
-			break;
-
-		case 0x0C: // Cargo type
-			FOR_EACH_OBJECT {
+				svi->image_index = spriteid;
+			} break;
+
+			case 0x09: // Refittable
+				svi->refittable = (grf_load_byte(&buf) != 0);
+				break;
+
+			case 0x0A: // Cost factor
+				svi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+				break;
+
+			case 0x0B: // Speed (1 unit is 0.5 kmh)
+				svi->max_speed = grf_load_byte(&buf);
+				break;
+
+			case 0x0C: { // Cargo type
 				uint8 cargo = grf_load_byte(&buf);
 
 				if (cargo < NUM_CARGO && HASBIT(_cargo_mask, cargo)) {
-					svi[i].cargo_type = cargo;
+					svi->cargo_type = cargo;
 				} else {
-					svi[i].cargo_type = CT_INVALID;
+					svi->cargo_type = CT_INVALID;
 					grfmsg(2, "ShipVehicleChangeInfo: Invalid cargo type %d, using first refittable", cargo);
 				}
-			}
-			break;
-
-		case 0x0D: // Cargo capacity
-			FOR_EACH_OBJECT svi[i].capacity = grf_load_word(&buf);
-			break;
-
-		case 0x0F: // Running cost factor
-			FOR_EACH_OBJECT svi[i].running_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x10: // SFX
-			FOR_EACH_OBJECT svi[i].sfx = (SoundFx)grf_load_byte(&buf);
-			break;
-
-		case 0x11: // Cargos available for refitting
-			FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
-			break;
-
-		case 0x12: // Callback mask
-			FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x13: // Refit cost
-			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x16: // Retire vehicle early
-			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
-			break;
-
-		case 0x17: // Miscellaneous flags
-			FOR_EACH_OBJECT {
-				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
-			}
-			break;
-
-		case 0x18: // Cargo classes allowed
-			FOR_EACH_OBJECT cargo_allowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x19: // Cargo classes disallowed
-			FOR_EACH_OBJECT cargo_disallowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x1A: // Long format introduction date (days since year 0)
-			FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
-			break;
-
-		case 0x14: // Ocean speed fraction
-		case 0x15: // Canal speed fraction
-			/* @todo */
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x0D: // Cargo capacity
+				svi->capacity = grf_load_word(&buf);
+				break;
+
+			case 0x0F: // Running cost factor
+				svi->running_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x10: // SFX
+				svi->sfx = (SoundFx)grf_load_byte(&buf);
+				break;
+
+			case 0x11: // Cargos available for refitting
+				ei->refit_mask = grf_load_dword(&buf);
+				break;
+
+			case 0x12: // Callback mask
+				ei->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x13: // Refit cost
+				ei->refit_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x16: // Retire vehicle early
+				ei->retire_early = grf_load_byte(&buf);
+				break;
+
+			case 0x17: // Miscellaneous flags
+				ei->misc_flags = grf_load_byte(&buf);
+				_loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+				break;
+
+			case 0x18: // Cargo classes allowed
+				cargo_allowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x19: // Cargo classes disallowed
+				cargo_disallowed[SHIP_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x1A: // Long format introduction date (days since year 0)
+				ei->base_intro = grf_load_dword(&buf);
+				break;
+
+			case 0x14: // Ocean speed fraction
+			case 0x15: // Canal speed fraction
+				/** @todo Speed fractions for ships on oceans and canals */
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -807,16 +779,15 @@
 
 static bool AircraftVehicleChangeInfo(uint engine, int numinfo, int prop, byte **bufp, int len)
 {
-	EngineInfo *ei = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine];
-	AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine];
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	//printf("e %x prop %x?\n", engine, prop);
-	switch (prop) {
-		case 0x08: // Sprite ID
-			FOR_EACH_OBJECT {
+	for (int i = 0; i < numinfo; i++) {
+		EngineInfo *ei           = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine + i];
+		AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine + i];
+
+		switch (prop) {
+			case 0x08: { // Sprite ID
 				uint8 spriteid = grf_load_byte(&buf);
 
 				/* aircraft have different custom id in the GRF file */
@@ -824,90 +795,86 @@
 
 				if (spriteid < 0xFD) spriteid >>= 1;
 
-				avi[i].image_index = spriteid;
-			}
-			break;
-
-		case 0x09: // Helicopter
-			FOR_EACH_OBJECT {
+				avi->image_index = spriteid;
+			} break;
+
+			case 0x09: // Helicopter
 				if (grf_load_byte(&buf) == 0) {
-					avi[i].subtype = AIR_HELI;
+					avi->subtype = AIR_HELI;
 				} else {
-					SB(avi[i].subtype, 0, 1, 1); // AIR_CTOL
+					SB(avi->subtype, 0, 1, 1); // AIR_CTOL
 				}
-			}
-			break;
-
-		case 0x0A: // Large
-			FOR_EACH_OBJECT SB(avi[i].subtype, 1, 1, (grf_load_byte(&buf) != 0 ? 1 : 0)); // AIR_FAST
-			break;
-
-		case 0x0B: // Cost factor
-			FOR_EACH_OBJECT avi[i].base_cost = grf_load_byte(&buf); // ?? is it base_cost?
-			break;
-
-		case 0x0C: // Speed (1 unit is 8 mph, we translate to 1 unit is 1 km/h)
-			FOR_EACH_OBJECT avi[i].max_speed = (grf_load_byte(&buf) * 129) / 10;
-			break;
-
-		case 0x0D: // Acceleration
-			FOR_EACH_OBJECT avi[i].acceleration = (grf_load_byte(&buf) * 129) / 10;
-			break;
-
-		case 0x0E: // Running cost factor
-			FOR_EACH_OBJECT avi[i].running_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x0F: // Passenger capacity
-			FOR_EACH_OBJECT avi[i].passenger_capacity = grf_load_word(&buf);
-			break;
-
-		case 0x11: // Mail capacity
-			FOR_EACH_OBJECT avi[i].mail_capacity = grf_load_byte(&buf);
-			break;
-
-		case 0x12: // SFX
-			FOR_EACH_OBJECT avi[i].sfx = (SoundFx)grf_load_byte(&buf);
-			break;
-
-		case 0x13: // Cargos available for refitting
-			FOR_EACH_OBJECT ei[i].refit_mask = grf_load_dword(&buf);
-			break;
-
-		case 0x14: // Callback mask
-			FOR_EACH_OBJECT ei[i].callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x15: // Refit cost
-			FOR_EACH_OBJECT ei[i].refit_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x16: // Retire vehicle early
-			FOR_EACH_OBJECT ei[i].retire_early = grf_load_byte(&buf);
-			break;
-
-		case 0x17: // Miscellaneous flags
-			FOR_EACH_OBJECT {
-				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
-			}
-			break;
-
-		case 0x18: // Cargo classes allowed
-			FOR_EACH_OBJECT cargo_allowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x19: // Cargo classes disallowed
-			FOR_EACH_OBJECT cargo_disallowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
-			break;
-
-		case 0x1A: // Long format introduction date (days since year 0)
-			FOR_EACH_OBJECT ei[i].base_intro = grf_load_dword(&buf);
-			break;
-
-		default:
-			ret = true;
-			break;
+				break;
+
+			case 0x0A: // Large
+				SB(avi->subtype, 1, 1, (grf_load_byte(&buf) != 0 ? 1 : 0)); // AIR_FAST
+				break;
+
+			case 0x0B: // Cost factor
+				avi->base_cost = grf_load_byte(&buf); // ?? is it base_cost?
+				break;
+
+			case 0x0C: // Speed (1 unit is 8 mph, we translate to 1 unit is 1 km/h)
+				avi->max_speed = (grf_load_byte(&buf) * 129) / 10;
+				break;
+
+			case 0x0D: // Acceleration
+				avi->acceleration = (grf_load_byte(&buf) * 129) / 10;
+				break;
+
+			case 0x0E: // Running cost factor
+				avi->running_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x0F: // Passenger capacity
+				avi->passenger_capacity = grf_load_word(&buf);
+				break;
+
+			case 0x11: // Mail capacity
+				avi->mail_capacity = grf_load_byte(&buf);
+				break;
+
+			case 0x12: // SFX
+				avi->sfx = (SoundFx)grf_load_byte(&buf);
+				break;
+
+			case 0x13: // Cargos available for refitting
+				ei->refit_mask = grf_load_dword(&buf);
+				break;
+
+			case 0x14: // Callback mask
+				ei->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x15: // Refit cost
+				ei->refit_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x16: // Retire vehicle early
+				ei->retire_early = grf_load_byte(&buf);
+				break;
+
+			case 0x17: // Miscellaneous flags
+				ei->misc_flags = grf_load_byte(&buf);
+				_loaded_newgrf_features.has_2CC |= HASBIT(ei->misc_flags, EF_USES_2CC);
+				break;
+
+			case 0x18: // Cargo classes allowed
+				cargo_allowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x19: // Cargo classes disallowed
+				cargo_disallowed[AIRCRAFT_ENGINES_INDEX + engine + i] = grf_load_word(&buf);
+				break;
+
+			case 0x1A: // Long format introduction date (days since year 0)
+				ei->base_intro = grf_load_dword(&buf);
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -916,9 +883,7 @@
 
 static bool StationChangeInfo(uint stid, int numinfo, int prop, byte **bufp, int len)
 {
-	StationSpec **statspec;
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
 	if (stid + numinfo > MAX_STATIONS) {
@@ -929,34 +894,28 @@
 	/* Allocate station specs if necessary */
 	if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
 
-	statspec = &_cur_grffile->stations[stid];
-
-	if (prop != 0x08) {
-		/* Check that all stations we are modifying are defined. */
-		FOR_EACH_OBJECT {
-			if (statspec[i] == NULL) {
-				grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
-				return false;
-			}
+	for (int i = 0; i < numinfo; i++) {
+		StationSpec *statspec = _cur_grffile->stations[stid + i];
+
+		/* Check that the station we are modifying is defined. */
+		if (statspec == NULL && prop != 0x08) {
+			grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
+			continue;
 		}
-	}
-
-	switch (prop) {
-		case 0x08: // Class ID
-			FOR_EACH_OBJECT {
+
+		switch (prop) {
+			case 0x08: { // Class ID
+				StationSpec **spec = &_cur_grffile->stations[stid + i];
+
 				/* Property 0x08 is special; it is where the station is allocated */
-				if (statspec[i] == NULL) statspec[i] = CallocT<StationSpec>(1);
+				if (*spec == NULL) *spec = CallocT<StationSpec>(1);
 
 				/* Swap classid because we read it in BE meaning WAYP or DFLT */
 				uint32 classid = grf_load_dword(&buf);
-				statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
-			}
-			break;
-
-		case 0x09: // Define sprite layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+				(*spec)->sclass = AllocateStationClass(BSWAP32(classid));
+			} break;
+
+			case 0x09: // Define sprite layout
 				statspec->tiles = grf_load_extended(&buf);
 				statspec->renderdata = CallocT<DrawTileSprites>(statspec->tiles);
 				statspec->copied_renderdata = false;
@@ -1007,37 +966,30 @@
 						}
 					}
 				}
-			}
-			break;
-
-		case 0x0A: // Copy sprite layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
+				break;
+
+			case 0x0A: { // Copy sprite layout
 				byte srcid = grf_load_byte(&buf);
 				const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
 
 				statspec->tiles = srcstatspec->tiles;
 				statspec->renderdata = srcstatspec->renderdata;
 				statspec->copied_renderdata = true;
-			}
-			break;
-
-		case 0x0B: // Callback mask
-			FOR_EACH_OBJECT statspec[i]->callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x0C: // Disallowed number of platforms
-			FOR_EACH_OBJECT statspec[i]->disallowed_platforms = grf_load_byte(&buf);
-			break;
-
-		case 0x0D: // Disallowed platform lengths
-			FOR_EACH_OBJECT statspec[i]->disallowed_lengths = grf_load_byte(&buf);
-			break;
-
-		case 0x0E: // Define custom layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+			} break;
+
+			case 0x0B: // Callback mask
+				statspec->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x0C: // Disallowed number of platforms
+				statspec->disallowed_platforms = grf_load_byte(&buf);
+				break;
+
+			case 0x0D: // Disallowed platform lengths
+				statspec->disallowed_lengths = grf_load_byte(&buf);
+				break;
+
+			case 0x0E: // Define custom layout
 				statspec->copied_layouts = false;
 
 				while (buf < *bufp + len) {
@@ -1084,12 +1036,9 @@
 					free(statspec->layouts[l][p]);
 					statspec->layouts[l][p] = layout;
 				}
-			}
-			break;
-
-		case 0x0F: // Copy custom layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
+				break;
+
+			case 0x0F: { // Copy custom layout
 				byte srcid = grf_load_byte(&buf);
 				const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
 
@@ -1097,51 +1046,51 @@
 				statspec->platforms = srcstatspec->platforms;
 				statspec->layouts   = srcstatspec->layouts;
 				statspec->copied_layouts = true;
-			}
-			break;
-
-		case 0x10: // Little/lots cargo threshold
-			FOR_EACH_OBJECT statspec[i]->cargo_threshold = grf_load_word(&buf);
-			break;
-
-		case 0x11: // Pylon placement
-			FOR_EACH_OBJECT statspec[i]->pylons = grf_load_byte(&buf);
-			break;
-
-		case 0x12: // Cargo types for random triggers
-			FOR_EACH_OBJECT statspec[i]->cargo_triggers = grf_load_dword(&buf);
-			break;
-
-		case 0x13: // General flags
-			FOR_EACH_OBJECT statspec[i]->flags = grf_load_byte(&buf);
-			break;
-
-		case 0x14: // Overhead wire placement
-			FOR_EACH_OBJECT statspec[i]->wires = grf_load_byte(&buf);
-			break;
-
-		case 0x15: // Blocked tiles
-			FOR_EACH_OBJECT statspec[i]->blocked = grf_load_byte(&buf);
-			break;
-
-		case 0x16: // @todo Animation info
-			FOR_EACH_OBJECT grf_load_word(&buf);
-			ret = true;
-			break;
-
-		case 0x17: // @todo Animation speed
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		case 0x18: // @todo Animation triggers
-			FOR_EACH_OBJECT grf_load_word(&buf);
-			ret = true;
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x10: // Little/lots cargo threshold
+				statspec->cargo_threshold = grf_load_word(&buf);
+				break;
+
+			case 0x11: // Pylon placement
+				statspec->pylons = grf_load_byte(&buf);
+				break;
+
+			case 0x12: // Cargo types for random triggers
+				statspec->cargo_triggers = grf_load_dword(&buf);
+				break;
+
+			case 0x13: // General flags
+				statspec->flags = grf_load_byte(&buf);
+				break;
+
+			case 0x14: // Overhead wire placement
+				statspec->wires = grf_load_byte(&buf);
+				break;
+
+			case 0x15: // Blocked tiles
+				statspec->blocked = grf_load_byte(&buf);
+				break;
+
+			case 0x16: // @todo Animation info
+				grf_load_word(&buf);
+				ret = true;
+				break;
+
+			case 0x17: // @todo Animation speed
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			case 0x18: // @todo Animation triggers
+				grf_load_word(&buf);
+				ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1151,33 +1100,38 @@
 static bool BridgeChangeInfo(uint brid, int numinfo, int prop, byte **bufp, int len)
 {
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	switch (prop) {
-		case 0x08: // Year of availability
-			FOR_EACH_OBJECT _bridge[brid + i].avail_year = ORIGINAL_BASE_YEAR + grf_load_byte(&buf);
-			break;
-
-		case 0x09: // Minimum length
-			FOR_EACH_OBJECT _bridge[brid + i].min_length = grf_load_byte(&buf);
-			break;
-
-		case 0x0A: // Maximum length
-			FOR_EACH_OBJECT _bridge[brid + i].max_length = grf_load_byte(&buf);
-			break;
-
-		case 0x0B: // Cost factor
-			FOR_EACH_OBJECT _bridge[brid + i].price = grf_load_byte(&buf);
-			break;
-
-		case 0x0C: // Maximum speed
-			FOR_EACH_OBJECT _bridge[brid + i].speed = grf_load_word(&buf);
-			break;
-
-		case 0x0D: // Bridge sprite tables
-			FOR_EACH_OBJECT {
-				Bridge *bridge = &_bridge[brid + i];
+	if (brid + numinfo > MAX_BRIDGES) {
+		grfmsg(1, "BridgeChangeInfo: Bridge %u is invalid, max %u, ignoring", brid + numinfo, MAX_BRIDGES);
+		return false;
+	}
+
+	for (int i = 0; i < numinfo; i++) {
+		Bridge *bridge = &_bridge[brid + i];
+
+		switch (prop) {
+			case 0x08: // Year of availability
+				bridge->avail_year = ORIGINAL_BASE_YEAR + grf_load_byte(&buf);
+				break;
+
+			case 0x09: // Minimum length
+				bridge->min_length = grf_load_byte(&buf);
+				break;
+
+			case 0x0A: // Maximum length
+				bridge->max_length = grf_load_byte(&buf);
+				break;
+
+			case 0x0B: // Cost factor
+				bridge->price = grf_load_byte(&buf);
+				break;
+
+			case 0x0C: // Maximum speed
+				bridge->speed = grf_load_word(&buf);
+				break;
+
+			case 0x0D: { // Bridge sprite tables
 				byte tableid = grf_load_byte(&buf);
 				byte numtables = grf_load_byte(&buf);
 
@@ -1212,19 +1166,20 @@
 						bridge->sprite_table[tableid][sprite].pal    = pal;
 					}
 				}
-			}
-			break;
-
-		case 0x0E: // Flags; bit 0 - disable far pillars
-			FOR_EACH_OBJECT _bridge[brid + i].flags = grf_load_byte(&buf);
-			break;
-
-		case 0x0F: // Long format year of availability (year since year 0)
-			FOR_EACH_OBJECT _bridge[brid + i].avail_year = clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
-			break;
-
-		default:
-			ret = true;
+			} break;
+
+			case 0x0E: // Flags; bit 0 - disable far pillars
+				bridge->flags = grf_load_byte(&buf);
+				break;
+
+			case 0x0F: // Long format year of availability (year since year 0)
+				bridge->avail_year = clamp(grf_load_dword(&buf), MIN_YEAR, MAX_YEAR);
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1233,13 +1188,11 @@
 
 static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
 {
-	HouseSpec **housespec;
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	if (hid + numinfo >= HOUSE_MAX) {
-		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX-1);
+	if (hid + numinfo > HOUSE_MAX) {
+		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX);
 		return false;
 	}
 
@@ -1251,21 +1204,17 @@
 		_house_mngr.ResetOverride();
 	}
 
-	housespec = &_cur_grffile->housespec[hid];
-
-	if (prop != 0x08) {
-		/* Check that all the houses being modified have been defined. */
-		FOR_EACH_OBJECT {
-			if (housespec[i] == NULL) {
-				grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
-				return false;
-			}
+	for (int i = 0; i < numinfo; i++) {
+		HouseSpec *housespec = _cur_grffile->housespec[hid + i];
+
+		if (prop != 0x08 && housespec == NULL) {
+			grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
+			continue;
 		}
-	}
-
-	switch (prop) {
-		case 0x08: // Substitute building type, and definition of a new house
-			FOR_EACH_OBJECT {
+
+		switch (prop) {
+			case 0x08: { // Substitute building type, and definition of a new house
+				HouseSpec **house = &_cur_grffile->housespec[hid + i];
 				byte subs_id = grf_load_byte(&buf);
 
 				if (subs_id == 0xFF) {
@@ -1280,144 +1229,130 @@
 				}
 
 				/* Allocate space for this house. */
-				if (housespec[i] == NULL) housespec[i] = CallocT<HouseSpec>(1);
-
-				memcpy(housespec[i], &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
-
-				housespec[i]->enabled = true;
-				housespec[i]->local_id = hid + i;
-				housespec[i]->substitute_id = subs_id;
-				housespec[i]->grffile = _cur_grffile;
-				housespec[i]->random_colour[0] = 0x04;  // those 4 random colours are the base colour
-				housespec[i]->random_colour[1] = 0x08;  // for all new houses
-				housespec[i]->random_colour[2] = 0x0C;  // they stand for red, blue, orange and green
-				housespec[i]->random_colour[3] = 0x06;
-
-				/* New houses do not (currently) expect to have a default start
-				 * date before 1930, as this breaks the build date stuff. See
-				 * FinaliseHouseArray() for more details. */
-				if (housespec[i]->min_date < 1930) housespec[i]->min_date = 1930;
-			}
-			SETBIT(_loaded_newgrf_features, GRFLOADED_NEWHOUSES);
-			break;
-
-		case 0x09: // Building flags
-			FOR_EACH_OBJECT {
-				byte state = grf_load_byte(&buf);
-				housespec[i]->building_flags = (BuildingFlags)state;
-			}
-			break;
-
-		case 0x0A: // Availability years
-			FOR_EACH_OBJECT {
+				if (*house == NULL) *house = CallocT<HouseSpec>(1);
+
+				housespec = *house;
+
+				memcpy(housespec, &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
+
+				housespec->enabled = true;
+				housespec->local_id = hid + i;
+				housespec->substitute_id = subs_id;
+				housespec->grffile = _cur_grffile;
+				housespec->random_colour[0] = 0x04;  // those 4 random colours are the base colour
+				housespec->random_colour[1] = 0x08;  // for all new houses
+				housespec->random_colour[2] = 0x0C;  // they stand for red, blue, orange and green
+				housespec->random_colour[3] = 0x06;
+
+				/**
+				 * New houses do not (currently) expect to have a default start
+				 * date before 1930, as this breaks the build date stuff.
+				 * @see FinaliseHouseArray() for more details.
+				 */
+				if (housespec->min_date < 1930) housespec->min_date = 1930;
+
+				_loaded_newgrf_features.has_newhouses = true;
+			} break;
+
+			case 0x09: // Building flags
+				housespec->building_flags = (BuildingFlags)grf_load_byte(&buf);
+				break;
+
+			case 0x0A: { // Availability years
 				uint16 years = grf_load_word(&buf);
-				housespec[i]->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
-				housespec[i]->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
-			}
-			break;
-
-		case 0x0B: // Population
-			FOR_EACH_OBJECT housespec[i]->population = grf_load_byte(&buf);
-			break;
-
-		case 0x0C: // Mail generation multiplier
-			FOR_EACH_OBJECT housespec[i]->mail_generation = grf_load_byte(&buf);
-			break;
-
-		case 0x0D: // Passenger acceptance
-		case 0x0E: // Mail acceptance
-			FOR_EACH_OBJECT housespec[i]->cargo_acceptance[prop - 0x0D] = grf_load_byte(&buf);
-			break;
-		case 0x0F: // Goods/candy, food/fizzy drinks acceptance
-			FOR_EACH_OBJECT {
+				housespec->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
+				housespec->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
+			} break;
+
+			case 0x0B: // Population
+				housespec->population = grf_load_byte(&buf);
+				break;
+
+			case 0x0C: // Mail generation multiplier
+				housespec->mail_generation = grf_load_byte(&buf);
+				break;
+
+			case 0x0D: // Passenger acceptance
+			case 0x0E: // Mail acceptance
+				housespec->cargo_acceptance[prop - 0x0D] = grf_load_byte(&buf);
+				break;
+
+			case 0x0F: { // Goods/candy, food/fizzy drinks acceptance
 				int8 goods = grf_load_byte(&buf);
 
 				/* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
 				 * Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
-				housespec[i]->accepts_cargo[2] = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
+				housespec->accepts_cargo[2] = (goods >= 0) ? ((_opt.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
 						((_opt.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
 
-				housespec[i]->cargo_acceptance[2] = abs(goods); // but we do need positive value here
-			}
-			break;
-
-		case 0x10: // Local authority rating decrease on removal
-			FOR_EACH_OBJECT housespec[i]->remove_rating_decrease = grf_load_word(&buf);
-			break;
-
-		case 0x11: // Removal cost multiplier
-			FOR_EACH_OBJECT housespec[i]->removal_cost = grf_load_byte(&buf);
-			break;
-
-		case 0x12: // Building name ID
-			FOR_EACH_OBJECT housespec[i]->building_name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
-			break;
-
-		case 0x13: // Building availability mask
-			FOR_EACH_OBJECT {
-				uint16 avail = grf_load_word(&buf);
-				housespec[i]->building_availability = (HouseZones)avail;
-			}
-			break;
-
-		case 0x14: // House callback flags
-			FOR_EACH_OBJECT housespec[i]->callback_mask = grf_load_byte(&buf);
-			break;
-
-		case 0x15: // House override byte
-			FOR_EACH_OBJECT {
+				housespec->cargo_acceptance[2] = abs(goods); // but we do need positive value here
+			} break;
+
+			case 0x10: // Local authority rating decrease on removal
+				housespec->remove_rating_decrease = grf_load_word(&buf);
+				break;
+
+			case 0x11: // Removal cost multiplier
+				housespec->removal_cost = grf_load_byte(&buf);
+				break;
+
+			case 0x12: // Building name ID
+				housespec->building_name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x13: // Building availability mask
+				housespec->building_availability = (HouseZones)grf_load_word(&buf);
+				break;
+
+			case 0x14: // House callback flags
+				housespec->callback_mask = grf_load_byte(&buf);
+				break;
+
+			case 0x15: { // House override byte
 				byte override = grf_load_byte(&buf);
 
 				/* The house being overridden must be an original house. */
 				if (override >= NEW_HOUSE_OFFSET) {
-					grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid);
-					return false;
+					grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid + i);
+					continue;
 				}
 
-				_house_mngr.Add(hid, override);
-			}
-			break;
-
-		case 0x16: // Periodic refresh multiplier
-			FOR_EACH_OBJECT housespec[i]->processing_time = grf_load_byte(&buf);
-			break;
-
-		case 0x17: // Four random colours to use
-			FOR_EACH_OBJECT {
-				uint j;
-				for (j = 0; j < 4; j++) housespec[i]->random_colour[j] = grf_load_byte(&buf);
-			}
-			break;
-
-		case 0x18: // Relative probability of appearing
-			FOR_EACH_OBJECT housespec[i]->probability = grf_load_byte(&buf);
-			break;
-
-		case 0x19: // Extra flags
-			FOR_EACH_OBJECT {
-				byte flags = grf_load_byte(&buf);
-				housespec[i]->extra_flags = (HouseExtraFlags)flags;
-			}
-			break;
-
-		case 0x1A: // Animation frames
-			FOR_EACH_OBJECT housespec[i]->animation_frames = grf_load_byte(&buf);
-			break;
-
-		case 0x1B: // Animation speed
-			FOR_EACH_OBJECT housespec[i]->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
-			break;
-
-		case 0x1C: // Class of the building type
-			FOR_EACH_OBJECT housespec[i]->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
-			break;
-
-		case 0x1D: // Callback flags 2
-			FOR_EACH_OBJECT housespec[i]->callback_mask |= (grf_load_byte(&buf) << 8);
-			break;
-
-		case 0x1E: // Accepted cargo types
-			FOR_EACH_OBJECT {
+				_house_mngr.Add(hid + i, override);
+			} break;
+
+			case 0x16: // Periodic refresh multiplier
+				housespec->processing_time = grf_load_byte(&buf);
+				break;
+
+			case 0x17: // Four random colours to use
+				for (uint j = 0; j < 4; j++) housespec->random_colour[j] = grf_load_byte(&buf);
+				break;
+
+			case 0x18: // Relative probability of appearing
+				housespec->probability = grf_load_byte(&buf);
+				break;
+
+			case 0x19: // Extra flags
+				housespec->extra_flags = (HouseExtraFlags)grf_load_byte(&buf);
+				break;
+
+			case 0x1A: // Animation frames
+				housespec->animation_frames = grf_load_byte(&buf);
+				break;
+
+			case 0x1B: // Animation speed
+				housespec->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
+				break;
+
+			case 0x1C: // Class of the building type
+				housespec->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
+				break;
+
+			case 0x1D: // Callback flags 2
+				housespec->callback_mask |= (grf_load_byte(&buf) << 8);
+				break;
+
+			case 0x1E: { // Accepted cargo types
 				uint32 cargotypes = grf_load_dword(&buf);
 
 				/* Check if the cargo types should not be changed */
@@ -1430,21 +1365,21 @@
 
 					if (cargo == CT_INVALID) {
 						/* Disable acceptance of invalid cargo type */
-						housespec[i]->cargo_acceptance[j] = 0;
+						housespec->cargo_acceptance[j] = 0;
 					} else {
-						housespec[i]->accepts_cargo[j] = cargo;
+						housespec->accepts_cargo[j] = cargo;
 					}
 				}
-			}
-			break;
-
-		case 0x1F: // Minimum life span
-			FOR_EACH_OBJECT housespec[i]->minimum_life = grf_load_byte(&buf);
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x1F: // Minimum life span
+				housespec->minimum_life = grf_load_byte(&buf);
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1454,12 +1389,11 @@
 static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
 {
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
-	switch (prop) {
-		case 0x08: /* Cost base factor */
-			FOR_EACH_OBJECT {
+	for (int i = 0; i < numinfo; i++) {
+		switch (prop) {
+			case 0x08: { // Cost base factor
 				byte factor = grf_load_byte(&buf);
 				uint price = gvid + i;
 
@@ -1468,28 +1402,24 @@
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Price %d out of range, ignoring", price);
 				}
-			}
-			break;
-
-		case 0x09: /* Cargo translation table */
-			/* This is loaded during the initialisation stage, so just skip it here. */
-			/* Each entry is 4 bytes. */
-			buf += numinfo * 4;
-			break;
-
-		case 0x0A: // Currency display names
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x09: // Cargo translation table
+				/* This is loaded during the initialisation stage, so just skip it here. */
+				/* Each entry is 4 bytes. */
+				buf += 4;
+				break;
+
+			case 0x0A: { // Currency display names
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				StringID newone = GetGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
 
 				if ((newone != STR_UNDEFINED) && (curidx < NUM_CURRENCY)) {
 					_currency_specs[curidx].name = newone;
 				}
-			}
-			break;
-
-		case 0x0B: // Currency multipliers
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0B: { // Currency multipliers
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				uint32 rate = grf_load_dword(&buf);
 
@@ -1501,11 +1431,9 @@
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Currency multipliers %d out of range, ignoring", curidx);
 				}
-			}
-			break;
-
-		case 0x0C: // Currency options
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0C: { // Currency options
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				uint16 options = grf_load_word(&buf);
 
@@ -1517,25 +1445,21 @@
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Currency option %d out of range, ignoring", curidx);
 				}
-			}
-			break;
-
-		case 0x0D: // Currency prefix symbol
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0D: { // Currency prefix symbol
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				uint32 tempfix = grf_load_dword(&buf);
 
 				if (curidx < NUM_CURRENCY) {
-					memcpy(_currency_specs[curidx].prefix,&tempfix,4);
+					memcpy(_currency_specs[curidx].prefix, &tempfix, 4);
 					_currency_specs[curidx].prefix[4] = 0;
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
 				}
-			}
-			break;
-
-		case 0x0E: // Currency suffix symbol
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0E: { // Currency suffix symbol
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				uint32 tempfix = grf_load_dword(&buf);
 
@@ -1545,11 +1469,9 @@
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Currency symbol %d out of range, ignoring", curidx);
 				}
-			}
-			break;
-
-		case 0x0F: //  Euro introduction dates
-			FOR_EACH_OBJECT {
+			} break;
+
+			case 0x0F: { //  Euro introduction dates
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
 				Year year_euro = grf_load_word(&buf);
 
@@ -1558,28 +1480,29 @@
 				} else {
 					grfmsg(1, "GlobalVarChangeInfo: Euro intro date %d out of range, ignoring", curidx);
 				}
-			}
-			break;
-
-		case 0x10: // 12 * 32 * B Snow line height table
-			if (numinfo > 1 || IsSnowLineSet()) {
-				grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
-			} else if (len < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
-				grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (%d)", len);
-			} else {
-				byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
-
-				for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
-					for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
-						table[i][j] = grf_load_byte(&buf);
+			} break;
+
+			case 0x10: // Snow line height table
+				if (numinfo > 1 || IsSnowLineSet()) {
+					grfmsg(1, "GlobalVarChangeInfo: The snowline can only be set once (%d)", numinfo);
+				} else if (len < SNOW_LINE_MONTHS * SNOW_LINE_DAYS) {
+					grfmsg(1, "GlobalVarChangeInfo: Not enough entries set in the snowline table (%d)", len);
+				} else {
+					byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS];
+
+					for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
+						for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
+							table[i][j] = grf_load_byte(&buf);
+						}
 					}
+					SetSnowLine(table);
 				}
-				SetSnowLine(table);
-			}
-			break;
-
-		default:
-			ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1588,120 +1511,118 @@
 
 static bool CargoChangeInfo(uint cid, int numinfo, int prop, byte **bufp, int len)
 {
+	byte *buf = *bufp;
+	bool ret = false;
+
 	if (cid + numinfo > NUM_CARGO) {
 		grfmsg(2, "CargoChangeInfo: Cargo type %d out of range (max %d)", cid + numinfo, NUM_CARGO - 1);
 		return false;
 	}
 
-	CargoSpec *cs = &_cargo[cid];
-	byte *buf = *bufp;
-	int i;
-	bool ret = false;
-
-	switch (prop) {
-		case 0x08: /* Bit number of cargo */
-			FOR_EACH_OBJECT {
-				cs[i].bitnum = grf_load_byte(&buf);
-				cs[i].grfid = _cur_grffile->grfid;
+	for (int i = 0; i < numinfo; i++) {
+		CargoSpec *cs = &_cargo[cid + i];
+
+		switch (prop) {
+			case 0x08: /* Bit number of cargo */
+				cs->bitnum = grf_load_byte(&buf);
+				cs->grfid = _cur_grffile->grfid;
 				if (cs->IsValid()) {
 					SETBIT(_cargo_mask, cid + i);
 				} else {
 					CLRBIT(_cargo_mask, cid + i);
 				}
-			}
-			break;
-
-		case 0x09: /* String ID for cargo type name */
-			FOR_EACH_OBJECT cs[i].name = grf_load_word(&buf);
-			break;
-
-		case 0x0A: /* String for cargo name, plural */
-			FOR_EACH_OBJECT cs[i].name_plural = grf_load_word(&buf);
-			break;
-
-		case 0x0B:
-			/* String for units of cargo. This is different in OpenTTD to TTDPatch
-			 * (e.g. 10 tonnes of coal) */
-			FOR_EACH_OBJECT cs[i].units_volume = grf_load_word(&buf);
-			break;
-
-		case 0x0C: /* String for quantity of cargo (e.g. 10 tonnes of coal) */
-			FOR_EACH_OBJECT cs[i].quantifier = grf_load_word(&buf);
-			break;
-
-		case 0x0D: /* String for two letter cargo abbreviation */
-			FOR_EACH_OBJECT cs[i].abbrev = grf_load_word(&buf);
-			break;
-
-		case 0x0E: /* Sprite ID for cargo icon */
-			FOR_EACH_OBJECT cs[i].sprite = grf_load_word(&buf);
-			break;
-
-		case 0x0F: /* Weight of one unit of cargo */
-			FOR_EACH_OBJECT cs[i].weight = grf_load_byte(&buf);
-			break;
-
-		case 0x10: /* Used for payment calculation */
-			FOR_EACH_OBJECT cs[i].transit_days[0] = grf_load_byte(&buf);
-			break;
-
-		case 0x11: /* Used for payment calculation */
-			FOR_EACH_OBJECT cs[i].transit_days[1] = grf_load_byte(&buf);
-			break;
-
-		case 0x12: /* Base cargo price */
-			FOR_EACH_OBJECT cs[i].initial_payment = grf_load_dword(&buf);
-			break;
-
-		case 0x13: /* Colour for station rating bars */
-			FOR_EACH_OBJECT cs[i].rating_colour = MapDOSColour(grf_load_byte(&buf));
-			break;
-
-		case 0x14: /* Colour for cargo graph */
-			FOR_EACH_OBJECT cs[i].legend_colour = MapDOSColour(grf_load_byte(&buf));
-			break;
-
-		case 0x15: /* Freight status */
-			FOR_EACH_OBJECT cs[i].is_freight = grf_load_byte(&buf) != 0;
-			break;
-
-		case 0x16: /* Cargo classes */
-			FOR_EACH_OBJECT cs[i].classes = grf_load_word(&buf);
-			break;
-
-		case 0x17: /* Cargo label */
-			FOR_EACH_OBJECT {
-				cs[i].label = grf_load_dword(&buf);
-				cs[i].label = BSWAP32(cs[i].label);
-			}
-			break;
-
-		case 0x18: /* Town growth substitute type */
-			FOR_EACH_OBJECT {
+				break;
+
+			case 0x09: /* String ID for cargo type name */
+				cs->name = grf_load_word(&buf);
+				break;
+
+			case 0x0A: /* String for cargo name, plural */
+				cs->name_plural = grf_load_word(&buf);
+				break;
+
+			case 0x0B:
+				/* String for units of cargo. This is different in OpenTTD to TTDPatch
+				 * (e.g. 10 tonnes of coal) */
+				cs->units_volume = grf_load_word(&buf);
+				break;
+
+			case 0x0C: /* String for quantity of cargo (e.g. 10 tonnes of coal) */
+				cs->quantifier = grf_load_word(&buf);
+				break;
+
+			case 0x0D: /* String for two letter cargo abbreviation */
+				cs->abbrev = grf_load_word(&buf);
+				break;
+
+			case 0x0E: /* Sprite ID for cargo icon */
+				cs->sprite = grf_load_word(&buf);
+				break;
+
+			case 0x0F: /* Weight of one unit of cargo */
+				cs->weight = grf_load_byte(&buf);
+				break;
+
+			case 0x10: /* Used for payment calculation */
+				cs->transit_days[0] = grf_load_byte(&buf);
+				break;
+
+			case 0x11: /* Used for payment calculation */
+				cs->transit_days[1] = grf_load_byte(&buf);
+				break;
+
+			case 0x12: /* Base cargo price */
+				cs->initial_payment = grf_load_dword(&buf);
+				break;
+
+			case 0x13: /* Colour for station rating bars */
+				cs->rating_colour = MapDOSColour(grf_load_byte(&buf));
+				break;
+
+			case 0x14: /* Colour for cargo graph */
+				cs->legend_colour = MapDOSColour(grf_load_byte(&buf));
+				break;
+
+			case 0x15: /* Freight status */
+				cs->is_freight = (grf_load_byte(&buf) != 0);
+				break;
+
+			case 0x16: /* Cargo classes */
+				cs->classes = grf_load_word(&buf);
+				break;
+
+			case 0x17: /* Cargo label */
+				cs->label = grf_load_dword(&buf);
+				cs->label = BSWAP32(cs->label);
+				break;
+
+			case 0x18: { /* Town growth substitute type */
 				uint8 substitute_type = grf_load_byte(&buf);
+
 				switch (substitute_type) {
-					case 0x00: cs[i].town_effect = TE_PASSENGERS; break;
-					case 0x02: cs[i].town_effect = TE_MAIL; break;
-					case 0x05: cs[i].town_effect = TE_GOODS; break;
-					case 0x09: cs[i].town_effect = TE_WATER; break;
-					case 0x0B: cs[i].town_effect = TE_FOOD; break;
+					case 0x00: cs->town_effect = TE_PASSENGERS; break;
+					case 0x02: cs->town_effect = TE_MAIL; break;
+					case 0x05: cs->town_effect = TE_GOODS; break;
+					case 0x09: cs->town_effect = TE_WATER; break;
+					case 0x0B: cs->town_effect = TE_FOOD; break;
 					default:
 						grfmsg(1, "CargoChangeInfo: Unknown town growth substitute value %d, setting to none.", substitute_type);
-					case 0xFF: cs[i].town_effect = TE_NONE; break;
+					case 0xFF: cs->town_effect = TE_NONE; break;
 				}
-			}
-			break;
-
-		case 0x19: /* Town growth coefficient */
-			FOR_EACH_OBJECT cs[i].multipliertowngrowth = grf_load_word(&buf);
-			break;
-
-		case 0x1A: /* Bitmask of callbacks to use */
-			FOR_EACH_OBJECT cs[i].callback_mask = grf_load_byte(&buf);
-			break;
-
-		default:
-			ret = true;
+			} break;
+
+			case 0x19: /* Town growth coefficient */
+				cs->multipliertowngrowth = grf_load_word(&buf);
+				break;
+
+			case 0x1A: /* Bitmask of callbacks to use */
+				cs->callback_mask = grf_load_byte(&buf);
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1712,7 +1633,6 @@
 static bool SoundEffectChangeInfo(uint sid, int numinfo, int prop, byte **bufp, int len)
 {
 	byte *buf = *bufp;
-	int i;
 	bool ret = false;
 
 	if (_cur_grffile->sound_offset == 0) {
@@ -1720,38 +1640,28 @@
 		return false;
 	}
 
-	switch (prop) {
-		case 0x08: // Relative volume
-			FOR_EACH_OBJECT {
-				uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
-
-				if (sound >= GetNumSounds()) {
-					grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
-				} else {
-					GetSound(sound)->volume = grf_load_byte(&buf);
-				}
-			}
-			break;
-
-		case 0x09: // Priority
-			FOR_EACH_OBJECT {
-				uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
-
-				if (sound >= GetNumSounds()) {
-					grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
-				} else {
-					GetSound(sound)->priority = grf_load_byte(&buf);
-				}
-			}
-			break;
-
-		case 0x0A: // Override old sound
-			FOR_EACH_OBJECT {
-				uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
+	for (int i = 0; i < numinfo; i++) {
+		uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds();
+
+		if (sound >= GetNumSounds()) {
+			grfmsg(1, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds());
+			continue;
+		}
+
+		switch (prop) {
+			case 0x08: // Relative volume
+				GetSound(sound)->volume = grf_load_byte(&buf);
+				break;
+
+			case 0x09: // Priority
+				GetSound(sound)->priority = grf_load_byte(&buf);
+				break;
+
+			case 0x0A: { // Override old sound
 				uint orig_sound = grf_load_byte(&buf);
 
-				if (sound >= GetNumSounds() || orig_sound >= GetNumSounds()) {
-					grfmsg(1, "SoundEffectChangeInfo: Sound %d or %d not defined (max %d)", sound, orig_sound, GetNumSounds());
+				if (orig_sound >= GetNumSounds()) {
+					grfmsg(1, "SoundEffectChangeInfo: Original sound %d not defined (max %d)", orig_sound, GetNumSounds());
 				} else {
 					FileEntry *newfe = GetSound(sound);
 					FileEntry *oldfe = GetSound(orig_sound);
@@ -1759,11 +1669,373 @@
 					/* Literally copy the data of the new sound over the original */
 					*oldfe = *newfe;
 				}
-			}
-			break;
-
-		default:
-			ret = true;
+			} break;
+
+			default:
+				ret = true;
+				break;
+		}
+	}
+
+	*bufp = buf;
+	return ret;
+}
+
+static bool IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, byte **bufp, int len)
+{
+	if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true;
+
+	byte *buf = *bufp;
+	bool ret = false;
+
+	if (indtid + numinfo > NUM_INDUSTRYTILES) {
+		grfmsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded (%u), max (%u). Ignoring.", indtid + numinfo, NUM_INDUSTRYTILES);
+		return false;
+	}
+
+	/* Allocate industry tile specs if they haven't been allocated already. */
+	if (_cur_grffile->indtspec == NULL) {
+		_cur_grffile->indtspec = CallocT<IndustryTileSpec*>(NUM_INDUSTRYTILES);
+
+		/* Reset any overrides that have been set. */
+		_industile_mngr.ResetOverride();
+	}
+
+	for (int i = 0; i < numinfo; i++) {
+		IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i];
+
+		if (prop != 0x08 && tsp == NULL) {
+			grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i);
+			continue;
+		}
+
+		switch (prop) {
+			case 0x08: { // Substitute industry tile type
+				IndustryTileSpec **tilespec = &_cur_grffile->indtspec[indtid + i];
+				byte subs_id = grf_load_byte(&buf);
+
+				if (subs_id == 0xFF) {
+					/* Instead of defining a new industry, a substitute industry id
+					 * of 0xFF disables the old industry with the current id. */
+					tsp->enabled = false;
+					continue;
+				} else if (subs_id >= NEW_INDUSTRYTILEOFFSET) {
+					/* The substitute id must be one of the original industry tile. */
+					grfmsg(2, "IndustryTilesChangeInfo: Attempt to use new industry tile %u as substitute industry tile for %u. Ignoring.", subs_id, indtid + i);
+					return false;
+				}
+
+				/* Allocate space for this industry. */
+				if (*tilespec == NULL) {
+					int tempid;
+					*tilespec = CallocT<IndustryTileSpec>(1);
+					tsp = *tilespec;
+
+					memcpy(tsp, &_industry_tile_specs[subs_id], sizeof(_industry_tile_specs[subs_id]));
+					tsp->enabled = true;
+					tsp->grf_prop.local_id = indtid + i;
+					tsp->grf_prop.subst_id = subs_id;
+					tsp->grf_prop.grffile = _cur_grffile;
+					tempid = _industile_mngr.AddEntityID(indtid + i, _cur_grffile->grfid, subs_id); // pre-reserve the tile slot
+				}
+			} break;
+
+			case 0x09: { // Industry tile override
+				byte ovrid = grf_load_byte(&buf);
+
+				/* The industry being overridden must be an original industry. */
+				if (ovrid >= NEW_INDUSTRYTILEOFFSET) {
+					grfmsg(2, "IndustryTilesChangeInfo: Attempt to override new industry tile %u with industry tile id %u. Ignoring.", ovrid, indtid + i);
+					return false;
+				}
+
+				tsp->grf_prop.override = ovrid;
+				_industile_mngr.Add(indtid + i, ovrid);
+			} break;
+
+			case 0x0A: // Tile acceptance
+			case 0x0B:
+			case 0x0C: {
+				uint16 acctp = grf_load_word(&buf);
+				tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur_grffile);
+				tsp->acceptance[prop - 0x0A] = GetCargoTranslation(GB(acctp, 8, 8), _cur_grffile);
+			} break;
+
+			case 0x0D: // Land shape flags
+				tsp->slopes_refused = (Slope)grf_load_byte(&buf);
+				break;
+
+			case 0x0E: // Callback flags
+				tsp->callback_flags = grf_load_byte(&buf);
+				break;
+
+			case 0x0F: // Animation information
+				tsp->animation_info = grf_load_word(&buf);
+				break;
+
+			case 0x10: // Animation speed
+				tsp->animation_speed = grf_load_byte(&buf);
+				break;
+
+			case 0x11: // Triggers for callback 25
+				tsp->animation_triggers = grf_load_byte(&buf);
+				break;
+
+			case 0x12: // Special flags
+				tsp->animation_special_flags = grf_load_byte(&buf);
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
+	}
+
+	*bufp = buf;
+	return ret;
+}
+
+static bool IndustriesChangeInfo(uint indid, int numinfo, int prop, byte **bufp, int len)
+{
+	if (!HASBIT(_ttdpatch_flags[3], 0x07)) return true;
+
+	byte *buf = *bufp;
+	bool ret = false;
+
+	if (indid + numinfo > NUM_INDUSTRYTYPES) {
+		grfmsg(1, "IndustriesChangeInfo: Too many industries loaded (%u), max (%u). Ignoring.", indid + numinfo, NUM_INDUSTRYTYPES);
+		return false;
+	}
+
+	grfmsg(1, "IndustriesChangeInfo: newid %u", indid);
+
+	/* Allocate industry specs if they haven't been allocated already. */
+	if (_cur_grffile->industryspec == NULL) {
+		_cur_grffile->industryspec = CallocT<IndustrySpec*>(NUM_INDUSTRYTYPES);
+
+		/* Reset any overrides that have been set. */
+		_industry_mngr.ResetOverride();
+	}
+
+	for (int i = 0; i < numinfo; i++) {
+		IndustrySpec *indsp = _cur_grffile->industryspec[indid + i];
+
+		if (prop != 0x08 && indsp == NULL) {
+			grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i);
+			continue;
+		}
+
+		switch (prop) {
+			case 0x08: { // Substitute industry type
+				IndustrySpec **indspec = &_cur_grffile->industryspec[indid + i];
+				byte subs_id = grf_load_byte(&buf);
+
+				if (subs_id == 0xFF) {
+					/* Instead of defining a new industry, a substitute industry id
+					 * of 0xFF disables the old industry with the current id. */
+					_industry_specs[indid + i].enabled = false;
+					continue;
+				} else if (subs_id >= NEW_INDUSTRYOFFSET) {
+					/* The substitute id must be one of the original industry. */
+					grfmsg(2, "_industry_specs: Attempt to use new industry %u as substitute industry for %u. Ignoring.", subs_id, indid + i);
+					return false;
+				}
+
+				/* Allocate space for this industry.
+				 * Only need to do it once. If ever it is called again, it should not
+				 * do anything */
+				if (*indspec == NULL) {
+					*indspec = CallocT<IndustrySpec>(1);
+					indsp = *indspec;
+
+					memcpy(indsp, &_origin_industry_specs[subs_id], sizeof(_industry_specs[subs_id]));
+					indsp->enabled = true;
+					indsp->grf_prop.local_id = indid + i;
+					indsp->grf_prop.subst_id = subs_id;
+					indsp->grf_prop.grffile = _cur_grffile;
+				}
+			} break;
+
+			case 0x09: { // Industry type override
+				byte ovrid = grf_load_byte(&buf);
+
+				/* The industry being overridden must be an original industry. */
+				if (ovrid >= NEW_INDUSTRYOFFSET) {
+					grfmsg(2, "IndustriesChangeInfo: Attempt to override new industry %u with industry id %u. Ignoring.", ovrid, indid + i);
+					return false;
+				}
+				indsp->grf_prop.override = ovrid;
+				_industry_mngr.Add(indid + i, ovrid);
+			} break;
+
+			case 0x0A: { // Set industry layout(s)
+				indsp->num_table = grf_load_byte(&buf); // Number of layaouts
+				uint32 defsize = grf_load_dword(&buf);  // Total size of the definition
+				IndustryTileTable **tile_table = CallocT<IndustryTileTable*>(indsp->num_table); // Table with tiles to compose an industry
+				IndustryTileTable *itt = CallocT<IndustryTileTable>(defsize); // Temporary array to read the tile layouts from the GRF
+				int size;
+				IndustryTileTable *copy_from;
+
+				for (byte j = 0; j < indsp->num_table; j++) {
+					for (int k = 0;; k++) {
+						itt[k].ti.x = grf_load_byte(&buf); // Offsets from northermost tile
+
+						if (itt[k].ti.x == 0xFE && k == 0) {
+							/* This means we have to borrow the layout from an old industry */
+							IndustryType type = grf_load_byte(&buf);  //industry holding required layout
+							byte laynbr = grf_load_byte(&buf);        //layout number to borrow
+
+							copy_from = (IndustryTileTable*)_origin_industry_specs[type].table[laynbr];
+							for (size = 1;; size++) {
+								if (_origin_industry_specs[type].table[laynbr + (size - 1)]->ti.x == -0x80 &&
+										_origin_industry_specs[type].table[laynbr + (size - 1)]->ti.y == 0) break;
+							}
+							break;
+						}
+
+						itt[k].ti.y = grf_load_byte(&buf); // Or table definition finalisation
+
+						if (itt[k].ti.x == 0 && itt[k].ti.y == 0x80) {
+							/*  Not the same terminator.  The one we are using is rather
+							 x= -80, y = x .  So, adjust it. */
+							itt[k].ti.x = -0x80;
+							itt[k].ti.y =  0;
+							itt[k].gfx  =  0;
+
+							size = k + 1;
+							copy_from = itt;
+							break;
+						}
+
+						itt[k].gfx = grf_load_byte(&buf);
+
+						if (itt[k].gfx == 0xFE) {
+							/* Use a new tile from this GRF */
+							int local_tile_id = grf_load_word(&buf);
+
+							/* Read the ID from the _industile_mngr. */
+							int tempid = _industile_mngr.GetID(local_tile_id, _cur_grffile->grfid);
+
+							if (tempid == INVALID_INDUSTRYTILE) {
+								grfmsg(2, "IndustriesChangeInfo: Attempt to use industry tile %u with industry id %u, not yet defined. Ignoring.", local_tile_id, indid);
+							} else {
+								/* Declared as been valid, can be used */
+								itt[k].gfx = tempid;
+								size = k + 1;
+								copy_from = itt;
+							}
+						}
+					}
+					tile_table[j] = CallocT<IndustryTileTable>(size);
+					memcpy(tile_table[j], copy_from, sizeof(*copy_from) * size);
+				}
+				/* Install final layout construction in the industry spec */
+				indsp->table = tile_table;
+				SETBIT(indsp->cleanup_flag, 1);
+				free(itt);
+			} break;
+
+			case 0x0B: // Industry production flags
+				indsp->life_type = (IndustryLifeType)grf_load_byte(&buf);
+				break;
+
+			case 0x0C: // Industry closure message
+				indsp->closure_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x0D: // Production increase message
+				indsp->production_up_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x0E: // Production decrease message
+				indsp->production_down_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x0F: // Fund cost multiplier
+				indsp->cost_multiplier = grf_load_byte(&buf);
+				break;
+
+			case 0x10: // Production cargo types
+				for (byte j = 0; j < 2; j++) {
+					indsp->produced_cargo[j] = GetCargoTranslation(grf_load_byte(&buf), _cur_grffile);
+				}
+				break;
+
+			case 0x11: // Acceptance cargo types
+				for (byte j = 0; j < 3; j++) {
+					indsp->accepts_cargo[j] = GetCargoTranslation(grf_load_byte(&buf), _cur_grffile);
+				}
+				grf_load_byte(&buf); // Unnused, eat it up
+				break;
+
+			case 0x12: // Production multipliers
+			case 0x13:
+				indsp->production_rate[prop - 0x12] = grf_load_byte(&buf);
+				break;
+
+			case 0x14: // Minimal amount of cargo distributed
+				indsp->minimal_cargo = grf_load_byte(&buf);
+				break;
+
+			case 0x15: { // Random sound effects
+				indsp->number_of_sounds = grf_load_byte(&buf);
+				uint8 *sounds = MallocT<uint8>(indsp->number_of_sounds);
+
+				for (uint8 j = 0; j < indsp->number_of_sounds; j++) sounds[j] = grf_load_byte(&buf);
+				indsp->random_sounds = sounds;
+				SETBIT(indsp->cleanup_flag, 0);
+			} break;
+
+			case 0x16: // Conflicting industry types
+				for (byte j = 0; j < 3; j++) indsp->conflicting[j] = grf_load_byte(&buf);
+				break;
+
+			case 0x17: // Probability in random game
+				indsp->appear_ingame[_opt.landscape] = grf_load_byte(&buf);
+				break;
+
+			case 0x18: // Probability during gameplay
+				indsp->appear_creation[_opt.landscape] = grf_load_byte(&buf);
+				break;
+
+			case 0x19: // Map color
+				indsp->map_colour = MapDOSColour(grf_load_byte(&buf));
+				break;
+
+			case 0x1A: // Special industry flags to define special behavior
+				indsp->behaviour = (IndustyBehaviour)grf_load_dword(&buf);
+				break;
+
+			case 0x1B: // New industry text ID
+				indsp->new_industry_text = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x1C: // Input cargo multipliers for the three input cargo types
+			case 0x1D:
+			case 0x1E: {
+					uint32 multiples = grf_load_dword(&buf);
+					indsp->input_cargo_multiplier[prop - 0x1C][0] = GB(multiples, 0,15);
+					indsp->input_cargo_multiplier[prop - 0x1C][1] = GB(multiples, 15,15);
+				} break;
+
+			case 0x1F: // Industry name
+				indsp->name = MapGRFStringID(_cur_grffile->grfid, grf_load_word(&buf));
+				break;
+
+			case 0x20: // Prospecting success chance
+				indsp->prospecting_chance = grf_load_dword(&buf);
+				break;
+
+			case 0x21:   // Callback flags
+			case 0x22: { // Callback additional flags
+				byte aflag = grf_load_byte(&buf);
+				SB(indsp->callback_flags, (prop - 0x21) * 8, 8, aflag);
+			} break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -1783,36 +2055,30 @@
 	}
 
 	/* Allocate station specs if necessary */
-	if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_FSM_PORTS);
-
-	statspec = &_cur_grffile->stations[stid];
-
-	if (prop != 0x08) {
-		/* Check that all stations we are modifying are defined. */
-		FOR_EACH_OBJECT {
-			if (statspec[i] == NULL) {
-				grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
-				return false;
-			}
+	if (_cur_grffile->stations == NULL) _cur_grffile->stations = CallocT<StationSpec*>(MAX_STATIONS);
+
+	for (int i = 0; i < numinfo; i++) {
+		StationSpec *statspec = _cur_grffile->stations[stid + i];
+
+		/* Check that the station we are modifying is defined. */
+		if (statspec == NULL && prop != 0x08) {
+			grfmsg(2, "StationChangeInfo: Attempt to modify undefined station %u, ignoring", stid + i);
+			continue;
 		}
-	}
-
-	switch (prop) {
-		case 0x08: // Class ID
-			FOR_EACH_OBJECT {
+
+		switch (prop) {
+			case 0x08: { // Class ID
+				StationSpec **spec = &_cur_grffile->stations[stid + i];
+
 				/* Property 0x08 is special; it is where the station is allocated */
-				if (statspec[i] == NULL) statspec[i] = CallocT<StationSpec>(1);
+				if (*spec == NULL) *spec = CallocT<StationSpec>(1);
 
 				/* Swap classid because we read it in BE meaning WAYP or DFLT */
 				uint32 classid = grf_load_dword(&buf);
-				statspec[i]->sclass = AllocateStationClass(BSWAP32(classid));
-			}
-			break;
-
-		case 0x09: // Define sprite layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+				(*spec)->sclass = AllocateStationClass(BSWAP32(classid));
+			} break;
+
+			case 0x09: // Define sprite layout
 				statspec->tiles = grf_load_extended(&buf);
 				statspec->renderdata = CallocT<DrawTileSprites>(statspec->tiles);
 				statspec->copied_renderdata = false;
@@ -1863,37 +2129,30 @@
 						}
 					}
 				}
-			}
-			break;
-
-		case 0x0A: // Copy sprite layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
+				break;
+
+			case 0x0A: { // Copy sprite layout
 				byte srcid = grf_load_byte(&buf);
 				const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
 
 				statspec->tiles = srcstatspec->tiles;
 				statspec->renderdata = srcstatspec->renderdata;
 				statspec->copied_renderdata = true;
-			}
-			break;
-
-		case 0x0B: // Callback mask
-			FOR_EACH_OBJECT statspec[i]->callbackmask = grf_load_byte(&buf);
-			break;
-
-		case 0x0C: // Disallowed number of platforms
-			FOR_EACH_OBJECT statspec[i]->disallowed_platforms = grf_load_byte(&buf);
-			break;
-
-		case 0x0D: // Disallowed platform lengths
-			FOR_EACH_OBJECT statspec[i]->disallowed_lengths = grf_load_byte(&buf);
-			break;
-
-		case 0x0E: // Define custom layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
-
+			} break;
+
+			case 0x0B: // Callback mask
+				statspec->callbackmask = grf_load_byte(&buf);
+				break;
+
+			case 0x0C: // Disallowed number of platforms
+				statspec->disallowed_platforms = grf_load_byte(&buf);
+				break;
+
+			case 0x0D: // Disallowed platform lengths
+				statspec->disallowed_lengths = grf_load_byte(&buf);
+				break;
+
+			case 0x0E: // Define custom layout
 				statspec->copied_layouts = false;
 
 				while (buf < *bufp + len) {
@@ -1940,12 +2199,9 @@
 					free(statspec->layouts[l][p]);
 					statspec->layouts[l][p] = layout;
 				}
-			}
-			break;
-
-		case 0x0F: // Copy custom layout
-			FOR_EACH_OBJECT {
-				StationSpec *statspec = _cur_grffile->stations[stid + i];
+				break;
+
+			case 0x0F: { // Copy custom layout
 				byte srcid = grf_load_byte(&buf);
 				const StationSpec *srcstatspec = _cur_grffile->stations[srcid];
 
@@ -1953,51 +2209,51 @@
 				statspec->platforms = srcstatspec->platforms;
 				statspec->layouts   = srcstatspec->layouts;
 				statspec->copied_layouts = true;
-			}
-			break;
-
-		case 0x10: // Little/lots cargo threshold
-			FOR_EACH_OBJECT statspec[i]->cargo_threshold = grf_load_word(&buf);
-			break;
-
-		case 0x11: // Pylon placement
-			FOR_EACH_OBJECT statspec[i]->pylons = grf_load_byte(&buf);
-			break;
-
-		case 0x12: // Cargo types for random triggers
-			FOR_EACH_OBJECT statspec[i]->cargo_triggers = grf_load_dword(&buf);
-			break;
-
-		case 0x13: // General flags
-			FOR_EACH_OBJECT statspec[i]->flags = grf_load_byte(&buf);
-			break;
-
-		case 0x14: // Overhead wire placement
-			FOR_EACH_OBJECT statspec[i]->wires = grf_load_byte(&buf);
-			break;
-
-		case 0x15: // Blocked tiles
-			FOR_EACH_OBJECT statspec[i]->blocked = grf_load_byte(&buf);
-			break;
-
-		case 0x16: // @todo Animation info
-			FOR_EACH_OBJECT grf_load_word(&buf);
-			ret = true;
-			break;
-
-		case 0x17: // @todo Animation speed
-			FOR_EACH_OBJECT grf_load_byte(&buf);
-			ret = true;
-			break;
-
-		case 0x18: // @todo Animation triggers
-			FOR_EACH_OBJECT grf_load_word(&buf);
-			ret = true;
-			break;
-
-		default:
-			ret = true;
-			break;
+			} break;
+
+			case 0x10: // Little/lots cargo threshold
+				statspec->cargo_threshold = grf_load_word(&buf);
+				break;
+
+			case 0x11: // Pylon placement
+				statspec->pylons = grf_load_byte(&buf);
+				break;
+
+			case 0x12: // Cargo types for random triggers
+				statspec->cargo_triggers = grf_load_dword(&buf);
+				break;
+
+			case 0x13: // General flags
+				statspec->flags = grf_load_byte(&buf);
+				break;
+
+			case 0x14: // Overhead wire placement
+				statspec->wires = grf_load_byte(&buf);
+				break;
+
+			case 0x15: // Blocked tiles
+				statspec->blocked = grf_load_byte(&buf);
+				break;
+
+			case 0x16: // @todo Animation info
+				grf_load_word(&buf);
+				ret = true;
+				break;
+
+			case 0x17: // @todo Animation speed
+				grf_load_byte(&buf);
+				ret = true;
+				break;
+
+			case 0x18: // @todo Animation triggers
+				grf_load_word(&buf);
+				ret = true;
+				break;
+
+			default:
+				ret = true;
+				break;
+		}
 	}
 
 	*bufp = buf;
@@ -2008,7 +2264,6 @@
 static void FeatureChangeInfo(byte *buf, int len)
 {
 	byte *bufend = buf + len;
-	uint i;
 
 	/* <00> <feature> <num-props> <num-info> <id> (<property <new-info>)...
 	 *
@@ -2033,15 +2288,13 @@
 		/* GSF_BRIDGE */       BridgeChangeInfo,
 		/* GSF_TOWNHOUSE */    TownHouseChangeInfo,
 		/* GSF_GLOBALVAR */    GlobalVarChangeInfo,
-		/* GSF_INDUSTRYTILES */NULL,
-		/* GSF_INDUSTRIES */   NULL,
+		/* GSF_INDUSTRYTILES */IndustrytilesChangeInfo,
+		/* GSF_INDUSTRIES */   IndustriesChangeInfo,
 		/* GSF_CARGOS */       NULL, /* Cargo is handled during reservation */
 		/* GSF_SOUNDFX */      SoundEffectChangeInfo,
 		/* GSF_FSMPORTS */     FSMPortChangeInfo,
 	};
 
-	EngineInfo *ei = NULL;
-
 	if (!check_length(len, 6, "FeatureChangeInfo")) return;
 	buf++;
 	uint8 feature  = grf_load_byte(&buf);
@@ -2062,7 +2315,6 @@
 			grfmsg(0, "FeatureChangeInfo: Last engine ID %d out of bounds (max %d), skipping", engine + numinfo, _vehcounts[feature]);
 			return;
 		}
-		ei = &_engine_info[engine + _vehshifts[feature]];
 	}
 
 	while (numprops-- && buf < bufend) {
@@ -2073,43 +2325,49 @@
 			case GSF_TRAIN:
 			case GSF_ROAD:
 			case GSF_SHIP:
-			case GSF_AIRCRAFT:
-				/* Common properties for vehicles */
-				switch (prop) {
-					case 0x00: // Introduction date
-						FOR_EACH_OBJECT ei[i].base_intro = grf_load_word(&buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
-						break;
-
-					case 0x02: // Decay speed
-						FOR_EACH_OBJECT SB(ei[i].unk2, 0, 7, grf_load_byte(&buf) & 0x7F);
-						break;
-
-					case 0x03: // Vehicle life
-						FOR_EACH_OBJECT ei[i].lifelength = grf_load_byte(&buf);
-						break;
-
-					case 0x04: // Model life
-						FOR_EACH_OBJECT ei[i].base_life = grf_load_byte(&buf);
-						break;
-
-					case 0x06: // Climates available
-						FOR_EACH_OBJECT ei[i].climates = grf_load_byte(&buf);
-						break;
-
-					case 0x07: // Loading speed
-						/* Hyronymus explained me what does
-						 * this mean and insists on having a
-						 * credit ;-). --pasky */
-						FOR_EACH_OBJECT ei[i].load_amount = grf_load_byte(&buf);
-						break;
-
-					default:
-						if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) {
-							ignoring = true;
-						}
-						break;
+			case GSF_AIRCRAFT: {
+				bool handled = true;
+
+				for (uint i = 0; i < numinfo; i++) {
+					EngineInfo *ei = &_engine_info[engine + _vehshifts[feature] + i];
+
+					/* Common properties for vehicles */
+					switch (prop) {
+						case 0x00: // Introduction date
+							ei->base_intro = grf_load_word(&buf) + DAYS_TILL_ORIGINAL_BASE_YEAR;
+							break;
+
+						case 0x02: // Decay speed
+							SB(ei->unk2, 0, 7, grf_load_byte(&buf) & 0x7F);
+							break;
+
+						case 0x03: // Vehicle life
+							ei->lifelength = grf_load_byte(&buf);
+							break;
+
+						case 0x04: // Model life
+							ei->base_life = grf_load_byte(&buf);
+							break;
+
+						case 0x06: // Climates available
+							ei->climates = grf_load_byte(&buf);
+							break;
+
+						case 0x07: // Loading speed
+							/* Hyronymus explained me what does
+							 * this mean and insists on having a
+							 * credit ;-). --pasky */
+							ei->load_amount = grf_load_byte(&buf);
+							break;
+
+						default:
+							handled = false;
+							break;
+					}
 				}
-				break;
+
+				if (handled) break;
+			} /* FALL THROUGH */
 
 			default:
 				if (handler[feature](engine, numinfo, prop, &buf, bufend - buf)) {
@@ -2173,8 +2431,7 @@
 						_cur_grffile->cargo_max = numinfo;
 						_cur_grffile->cargo_list = MallocT<CargoLabel>(numinfo);
 
-						int i;
-						FOR_EACH_OBJECT {
+						for (uint i = 0; i < numinfo; i++) {
 							CargoLabel cl = grf_load_dword(&buf);
 							_cur_grffile->cargo_list[i] = BSWAP32(cl);
 						}
@@ -2209,8 +2466,6 @@
 	}
 }
 
-#undef FOR_EACH_OBJECT
-
 /**
  * Creates a spritegroup representing a callback result
  * @param value The value that was used to represent this callback result
@@ -2281,7 +2536,7 @@
 	);
 
 	for (uint16 i = 0; i < num_sets * num_ents; i++) {
-		LoadNextSprite(_cur_spriteid++, _file_index);
+		LoadNextSprite(_cur_spriteid++, _file_index, _nfo_line);
 		_nfo_line++;
 	}
 }
@@ -2337,6 +2592,7 @@
 
 	if (feature != _cur_grffile->spriteset_feature) {
 		grfmsg(1, "CreateGroupFromGroupID(0x%02X:0x%02X): Sprite set feature 0x%02X does not match action feature 0x%02X, skipping",
+				setid, type,
 				_cur_grffile->spriteset_feature, feature);
 		return NULL;
 	}
@@ -2535,7 +2791,8 @@
 					break;
 				}
 
-				case GSF_TOWNHOUSE: {
+				case GSF_TOWNHOUSE:
+				case GSF_INDUSTRYTILES: {
 					byte sprites     = _cur_grffile->spriteset_numents;
 					byte num_sprites = max((uint8)1, type);
 					uint i;
@@ -2615,6 +2872,35 @@
 					break;
 				}
 
+				case GSF_INDUSTRIES: {
+					if (type > 1) {
+						grfmsg(1, "NewSpriteGroup: Unsupported industry production version %d, skipping", type);
+						break;
+					}
+
+					group = AllocateSpriteGroup();
+					group->type = SGT_INDUSTRY_PRODUCTION;
+					group->g.indprod.version = type;
+					if (type == 0) {
+						for (uint i = 0; i < 3; i++) {
+							group->g.indprod.substract_input[i] = grf_load_word(&buf);
+						}
+						for (uint i = 0; i < 2; i++) {
+							group->g.indprod.add_output[i] = grf_load_word(&buf);
+						}
+						group->g.indprod.again = grf_load_byte(&buf);
+					} else {
+						for (uint i = 0; i < 3; i++) {
+							group->g.indprod.substract_input[i] = grf_load_byte(&buf);
+						}
+						for (uint i = 0; i < 2; i++) {
+							group->g.indprod.add_output[i] = grf_load_byte(&buf);
+						}
+						group->g.indprod.again = grf_load_byte(&buf);
+					}
+					break;
+				}
+
 				/* Loading of Tile Layout and Production Callback groups would happen here */
 				default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
 			}
@@ -2741,7 +3027,7 @@
 
 			/* Don't tell me you don't love duplicated code! */
 			if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-				grfmsg(1, "FeatureMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
+				grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
 				       groupid, _cur_grffile->spritegroups_count);
 				continue;
 			}
@@ -2860,6 +3146,57 @@
 	}
 }
 
+static void IndustryMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+{
+	if (!HASBIT(_ttdpatch_flags[3], 0x07)) return;
+
+	byte *bp = &buf[4 + idcount + cidcount * 3];
+	uint16 groupid = grf_load_word(&bp);
+
+	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+		grfmsg(1, "IndustryMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
+		       groupid, _cur_grffile->spritegroups_count);
+		return;
+	}
+
+	for (uint i = 0; i < idcount; i++) {
+		uint8 id = buf[3 + i];
+		IndustrySpec *indsp = _cur_grffile->industryspec[id];
+
+		if (indsp == NULL) {
+			grfmsg(1, "IndustryMapSpriteGroup: Too many industries defined, skipping");
+			return;
+		}
+
+		indsp->grf_prop.spritegroup = _cur_grffile->spritegroups[groupid];
+	}
+}
+
+static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+{
+	if (!HASBIT(_ttdpatch_flags[3], 0x07)) return;
+
+	byte *bp = &buf[4 + idcount + cidcount * 3];
+	uint16 groupid = grf_load_word(&bp);
+
+	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+		grfmsg(1, "IndustrytileMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
+		       groupid, _cur_grffile->spritegroups_count);
+		return;
+	}
+
+	for (uint i = 0; i < idcount; i++) {
+		uint8 id = buf[3 + i];
+		IndustryTileSpec *indtsp = _cur_grffile->indtspec[id];
+
+		if (indtsp == NULL) {
+			grfmsg(1, "IndustrytileMapSpriteGroup: Too many industry tiles defined, skipping");
+			return;
+		}
+
+		indtsp->grf_prop.spritegroup = _cur_grffile->spritegroups[groupid];
+	}
+}
 
 static void CargoMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
 {
@@ -2949,6 +3286,14 @@
 			TownHouseMapSpriteGroup(buf, idcount, cidcount);
 			return;
 
+		case GSF_INDUSTRIES:
+			IndustryMapSpriteGroup(buf, idcount, cidcount);
+			return;
+
+		case GSF_INDUSTRYTILES:
+			IndustrytileMapSpriteGroup(buf, idcount, cidcount);
+			return;
+
 		case GSF_CARGOS:
 			CargoMapSpriteGroup(buf, idcount, cidcount);
 			return;
@@ -3021,6 +3366,11 @@
 				}
 				break;
 
+			case GSF_INDUSTRIES: {
+				AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+				break;
+			}
+
 			case GSF_TOWNHOUSE:
 			default:
 				switch (GB(id, 8, 8)) {
@@ -3071,10 +3421,6 @@
 					}
 					break;
 
-				case GSF_INDUSTRIES :
-				case 0x48 :   // for generic strings
-					AddGRFString(_cur_spriteid, id, lang, name);
-					break;
 				default :
 					grfmsg(7, "FeatureNewName: Unsupported feature (0x%02X)", feature);
 					break;
@@ -3151,7 +3497,7 @@
 
 		case 0x0B: // tramways
 			if (num != 113) {
-				grfmsg(1, "GraphicsNews: Tramway graphics sprite count must be 113, skipping");
+				grfmsg(1, "GraphicsNew: Tramway graphics sprite count must be 113, skipping");
 				return;
 			}
 			replace = SPR_TRAMWAY_BASE;
@@ -3184,6 +3530,7 @@
 		default:
 			grfmsg(2, "GraphicsNew: Custom graphics (type 0x%02X) sprite block of length %u (unimplemented, ignoring)",
 					type, num);
+			_skip_sprites = num;
 			return;
 	}
 
@@ -3194,7 +3541,7 @@
 	}
 
 	for (; num > 0; num--) {
-		LoadNextSprite(replace == 0 ? _cur_spriteid++ : replace++, _file_index);
+		LoadNextSprite(replace == 0 ? _cur_spriteid++ : replace++, _file_index, _nfo_line);
 		_nfo_line++;
 	}
 }
@@ -3223,8 +3570,14 @@
 		case 0x83: // current climate, 0=temp, 1=arctic, 2=trop, 3=toyland
 			return _opt.landscape;
 
-		case 0x84: // GRF loading stage
-			return (_cur_stage > GLS_INIT) | ((_cur_stage == GLS_ACTIVATION) << 9);
+		case 0x84: { // GRF loading stage
+			uint32 res = 0;
+
+			if (_cur_stage > GLS_INIT) SETBIT(res, 0);
+			if (_cur_stage == GLS_RESERVE) SETBIT(res, 8);
+			if (_cur_stage == GLS_ACTIVATION) SETBIT(res, 9);
+			return res;
+		}
 
 		case 0x85: // TTDPatch flags, only for bit tests
 			if (cond_val == NULL) {
@@ -3507,7 +3860,9 @@
 		_skip_sprites = -1;
 
 		/* If an action 8 hasn't been encountered yet, disable the grf. */
-		if (_cur_stage != GLS_RESERVE && _cur_grfconfig->status != GCS_ACTIVATED) _cur_grfconfig->status = GCS_DISABLED;
+		if (_cur_grfconfig->status != GCS_ACTIVATED && _cur_grfconfig->status != GCS_INITIALISED) {
+			_cur_grfconfig->status = GCS_DISABLED;
+		}
 	}
 }
 
@@ -3557,7 +3912,7 @@
 
 	_cur_grffile->grfid = grfid;
 	_cur_grffile->grf_version = version;
-	_cur_grfconfig->status = _cur_stage < GLS_ACTIVATION ? GCS_INITIALISED : GCS_ACTIVATED;
+	_cur_grfconfig->status = _cur_stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED;
 
 	/* Do swap the GRFID for displaying purposes since people expect that */
 	DEBUG(grf, 1, "GRFInfo: Loaded GRFv%d set %08lX - %s", version, BSWAP32(grfid), name);
@@ -3586,7 +3941,7 @@
 		);
 
 		for (uint j = 0; j < num_sprites; j++) {
-			LoadNextSprite(first_sprite + j, _file_index); // XXX
+			LoadNextSprite(first_sprite + j, _file_index, _nfo_line); // XXX
 			_nfo_line++;
 		}
 	}
@@ -3642,15 +3997,6 @@
 		STR_NEWGRF_ERROR_MSG_FATAL
 	};
 
-	/* AddGRFString expects the string to be referred to by an id in the newgrf
-	 * file. Errors messages are never referred to however, so invent ids that
-	 * are unlikely to be reached in a newgrf file so they don't overwrite
-	 * anything else. */
-	enum {
-		MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1,
-		MESSAGE_DATA_ID   = MAX_UVALUE(StringID)
-	};
-
 	if (!check_length(len, 6, "GRFLoadError")) return;
 
 	/* For now we can only show one message per newgrf file. */
@@ -3662,10 +4008,13 @@
 	byte message_id = grf_load_byte(&buf);
 	len -= 4;
 
+	/* Skip the error if it isn't valid for the current language. */
+	if (!CheckGrfLangID(lang, _cur_grffile->grf_version)) return;
+
 	/* Skip the error until the activation stage unless bit 7 of the severity
 	 * is set. */
-	if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) {
-		grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage 1");
+	if (!HASBIT(severity, 7) && _cur_stage == GLS_INIT) {
+		grfmsg(7, "GRFLoadError: Skipping non-fatal GRFLoadError in stage %d", _cur_stage);
 		return;
 	}
 	CLRBIT(severity, 7);
@@ -3691,7 +4040,6 @@
 		return;
 	}
 
-	bool new_scheme = _cur_grffile->grf_version >= 7;
 	GRFError *error = CallocT<GRFError>(1);
 
 	error->severity = sevstr[severity];
@@ -3701,7 +4049,7 @@
 		const char *message = grf_load_string(&buf, len);
 		len -= (strlen(message) + 1);
 
-		error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED);
+		error->custom_message = TranslateTTDPatchCodes(message);
 	} else {
 		error->message = msgstr[message_id];
 	}
@@ -3710,7 +4058,7 @@
 		const char *data = grf_load_string(&buf, len);
 		len -= (strlen(data) + 1);
 
-		error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED);
+		error->data = TranslateTTDPatchCodes(data);
 	}
 
 	/* Only two parameter numbers can be used in the string. */
@@ -4131,6 +4479,106 @@
 	}
 }
 
+/* Action 0x0F */
+static void FeatureTownName(byte *buf, int len)
+{
+	/* <0F> <id> <style-name> <num-parts> <parts>
+	 *
+	 * B id          ID of this definition in bottom 7 bits (final definition if bit 7 set)
+	 * V style-name  Name of the style (only for final definition)
+	 * B num-parts   Number of parts in this definition
+	 * V parts       The parts */
+
+	if (!check_length(len, 1, "FeatureTownName: definition ID")) return;
+	buf++; len--;
+
+	uint32 grfid = _cur_grffile->grfid;
+
+	GRFTownName *townname = AddGRFTownName(grfid);
+
+	byte id = grf_load_byte(&buf);
+	len--;
+	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;
+
+		if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
+		byte lang = grf_load_byte(&buf);
+		len--;
+
+		byte nb_gen = townname->nb_gen;
+		do {
+			CLRBIT(lang, 7);
+
+			if (!check_length(len, 1, "FeatureTownName: style name")) return;
+			const char *name = grf_load_string(&buf, len);
+			len -= strlen(name) + 1;
+			grfmsg(6, "FeatureTownName: lang 0x%X -> '%s'", lang, TranslateTTDPatchCodes(name));
+
+			townname->name[nb_gen] = AddGRFString(grfid, id, lang, new_scheme, name, STR_UNDEFINED);
+
+			if (!check_length(len, 1, "FeatureTownName: lang_id")) return;
+			lang = grf_load_byte(&buf);
+			len--;
+		} while (lang != 0);
+		townname->id[nb_gen] = id;
+		townname->nb_gen++;
+	}
+
+	if (!check_length(len, 1, "FeatureTownName: number of parts")) return;
+	byte nb = grf_load_byte(&buf);
+	len--;
+	grfmsg(6, "FeatureTownName: %d parts", nb, nb);
+
+	townname->nbparts[id] = nb;
+	townname->partlist[id] = CallocT<NamePartList>(nb);
+
+	for (int i = 0; i < nb; i++) {
+		if (!check_length(len, 3, "FeatureTownName: parts header")) return;
+		byte nbtext =  grf_load_byte(&buf);
+		townname->partlist[id][i].bitstart  = grf_load_byte(&buf);
+		townname->partlist[id][i].bitcount  = grf_load_byte(&buf);
+		townname->partlist[id][i].maxprob   = 0;
+		townname->partlist[id][i].partcount = nbtext;
+		townname->partlist[id][i].parts     = CallocT<NamePart>(nbtext);
+		len -= 3;
+		grfmsg(6, "FeatureTownName: part %d contains %d texts and will use GB(seed, %d, %d)", i, nbtext, townname->partlist[id][i].bitstart, townname->partlist[id][i].bitcount);
+
+		for (int j = 0; j < nbtext; j++) {
+			if (!check_length(len, 2, "FeatureTownName: part")) return;
+			byte prob = grf_load_byte(&buf);
+			len--;
+
+			if (HASBIT(prob, 7)) {
+				byte ref_id = grf_load_byte(&buf);
+				len--;
+
+				if (townname->nbparts[ref_id] == 0) {
+					grfmsg(0, "FeatureTownName: definition 0x%02X doesn't exist, deactivating", ref_id);
+					DelGRFTownName(grfid);
+					_cur_grfconfig->status = GCS_DISABLED;
+					_skip_sprites = -1;
+					return;
+				}
+
+				grfmsg(6, "FeatureTownName: part %d, text %d, uses intermediate definition 0x%02X (with probability %d)", i, j, ref_id, prob & 0x7F);
+				townname->partlist[id][i].parts[j].data.id = ref_id;
+			} else {
+				const char *text = grf_load_string(&buf, len);
+				len -= strlen(text) + 1;
+				townname->partlist[id][i].parts[j].data.text = TranslateTTDPatchCodes(text);
+				grfmsg(6, "FeatureTownName: part %d, text %d, '%s' (with probability %d)", i, j, townname->partlist[id][i].parts[j].data.text, prob);
+			}
+			townname->partlist[id][i].parts[j].prob = prob;
+			townname->partlist[id][i].maxprob += GB(prob, 0, 7);
+		}
+		grfmsg(6, "FeatureTownName: part %d, total probability %d", i, townname->partlist[id][i].maxprob);
+	}
+}
+
 /* Action 0x10 */
 static void DefineGotoLabel(byte *buf, int len)
 {
@@ -4316,7 +4764,7 @@
 
 		for (uint c = 0; c < num_char; c++) {
 			SetUnicodeGlyph(size, base_char + c, _cur_spriteid);
-			LoadNextSprite(_cur_spriteid++, _file_index);
+			LoadNextSprite(_cur_spriteid++, _file_index, _nfo_line);
 			_nfo_line++;
 		}
 	}
@@ -4346,8 +4794,12 @@
 		/* If the file is not active but will be activated later, give an error
 		 * and disable this file. */
 		GRFError *error = CallocT<GRFError>(1);
+
+		char tmp[256];
+		GetString(tmp, STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE, lastof(tmp));
+		error->data = strdup(tmp);
+
 		error->message  = STR_NEWGRF_ERROR_LOAD_AFTER;
-		error->data     = STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE;
 		error->severity = STR_NEWGRF_ERROR_MSG_FATAL;
 
 		if (_cur_grfconfig->error != NULL) free(_cur_grfconfig->error);
@@ -4458,7 +4910,7 @@
 	                   |                                        (0 << 0x0C)  // newagerating
 	                   |       ((_patches.build_on_slopes ? 1 : 0) << 0x0D)  // buildonslopes
 	                   |         ((_patches.full_load_any ? 1 : 0) << 0x0E)  // fullloadany
-	                   |                                        (0 << 0x0F)  // planespeed
+	                   |                                        (1 << 0x0F)  // planespeed - TODO depends on patch when implemented
 	                   |                                        (0 << 0x10)  // moreindustriesperclimate - obsolete
 	                   |                                        (0 << 0x11)  // moretoylandfeatures
 	                   |                                        (1 << 0x12)  // newstations
@@ -4470,7 +4922,7 @@
 	                   |    ((_patches.freight_trains > 1 ? 1 : 0) << 0x18)  // freighttrains
 	                   |                                        (1 << 0x19)  // newhouses
 	                   |                                        (1 << 0x1A)  // newbridges
-	                   |                                        (0 << 0x1B)  // newtownnames
+	                   |                                        (1 << 0x1B)  // newtownnames
 	                   |                                        (0 << 0x1C)  // moreanimations
 	                   |    ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D)  // wagonspeedlimits
 	                   |                                        (1 << 0x1E)  // newshistory
@@ -4498,8 +4950,8 @@
 	                   |                                        (0 << 0x13)  // followvehicle
 	                   |                                        (1 << 0x14)  // trams
 	                   |                                        (0 << 0x15)  // enhancetunnels
-	                   |                                        (0 << 0x16)  // shortrvs
-	                   |                                        (0 << 0x17)  // articulatedrvs
+	                   |                                        (1 << 0x16)  // shortrvs
+	                   |                                        (1 << 0x17)  // articulatedrvs
 	                   |                                        (1 << 0x1E); // variablerunningcosts
 }
 
@@ -4548,7 +5000,9 @@
 
 	for (file = _first_grffile; file != NULL; file = file->next) {
 		if (file->housespec == NULL) continue;
-		for (i = 0; i < HOUSE_MAX; i++) free(file->housespec[i]);
+		for (i = 0; i < HOUSE_MAX; i++) {
+			free(file->housespec[i]);
+		}
 
 		free(file->housespec);
 		file->housespec = NULL;
@@ -4626,6 +5080,18 @@
 	_cur_grffile   = NULL;
 }
 
+static void ResetNewGRFErrors()
+{
+	for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
+		if (!HASBIT(c->flags, GCF_COPY) && c->error != NULL) {
+			free(c->error->custom_message);
+			free(c->error->data);
+			free(c->error);
+			c->error = NULL;
+		}
+	}
+}
+
 /**
  * Reset all NewGRF loaded data
  * TODO
@@ -4633,6 +5099,7 @@
 static void ResetNewGRFData()
 {
 	CleanUpStrings();
+	CleanUpGRFTownNames();
 
 	/* Copy/reset original engine info data */
 	memcpy(&_engine_info, &orig_engine_info, sizeof(orig_engine_info));
@@ -4693,6 +5160,9 @@
 	/* Reset NewGRF files */
 	ResetNewGRF();
 
+	/* Reset NewGRF errors. */
+	ResetNewGRFErrors();
+
 	/* Add engine type to engine data. This is needed for the refit precalculation. */
 	AddTypeToEngines();
 
@@ -4704,7 +5174,9 @@
 	_traininfo_vehicle_pitch = 0;
 	_traininfo_vehicle_width = 29;
 
-	_loaded_newgrf_features = 0;
+	_loaded_newgrf_features.has_2CC           = false;
+	_loaded_newgrf_features.has_newhouses     = false;
+	_loaded_newgrf_features.has_newindustries = false,
 
 	_signal_base = 0;
 	_coast_base = 0;
@@ -4767,7 +5239,7 @@
 
 	if (newfile == NULL) error ("Out of memory");
 
-	newfile->filename = strdup(config->full_path);
+	newfile->filename = strdup(config->filename);
 	newfile->sprite_offset = sprite_offset;
 
 	/* Copy the initial parameter list */
@@ -4941,6 +5413,61 @@
 	}
 }
 
+/** Add all new industries to the industry array. Industry properties can be set at any
+ * time in the GRF file, so we can only add a industry spec to the industry array
+ * after the file has finished loading. */
+static void FinaliseIndustriesArray()
+{
+	for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
+		if (file->industryspec != NULL) {
+			for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
+				IndustrySpec *indsp = file->industryspec[i];
+
+				if (indsp != NULL && indsp->enabled) {
+					StringID strid;
+					/* process the conversion of text at the end, so to be sure everything will be fine
+					 * and available.  Check if it does not return undefind marker, which is a very good sign of a
+					 * substitute industry who has not changed the string been examined, thus using it as such */
+					strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->name);
+					if (strid != STR_UNDEFINED) indsp->name = strid;
+
+					strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->closure_text);
+					if (strid != STR_UNDEFINED) indsp->closure_text = strid;
+
+					strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_up_text);
+					if (strid != STR_UNDEFINED) indsp->production_up_text = strid;
+
+					strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->production_down_text);
+					if (strid != STR_UNDEFINED) indsp->production_down_text = strid;
+
+					strid = GetGRFStringID(indsp->grf_prop.grffile->grfid, indsp->new_industry_text);
+					if (strid != STR_UNDEFINED) indsp->new_industry_text = strid;
+
+					_industry_mngr.SetEntitySpec(indsp);
+					_loaded_newgrf_features.has_newindustries = true;
+				}
+			}
+		}
+
+		if (file->indtspec != NULL) {
+			for (int i = 0; i < NUM_INDUSTRYTILES; i++) {
+				IndustryTileSpec *indtsp = file->indtspec[i];
+				if (indtsp != NULL) {
+					_industile_mngr.SetEntitySpec(indtsp);
+				}
+			}
+		}
+	}
+
+	for (uint j = 0; j < NUM_INDUSTRYTYPES; j++) {
+		IndustrySpec *indsp = &_industry_specs[j];
+		if (indsp->enabled && indsp->grf_prop.grffile != NULL) {
+			for (uint i = 0; i < 3; i++) {
+				indsp->conflicting[i] = MapNewGRFIndustryType(indsp->conflicting[i], indsp->grf_prop.grffile->grfid);
+			}
+		}
+	}
+}
 
 /** Each cargo string needs to be mapped from TTDPatch to OpenTTD string IDs.
  * This is done after loading so that strings from Action 4 will be mapped
@@ -4990,14 +5517,14 @@
 		/* 0x05 */ { SkipAct5, SkipAct5,  SkipAct5,        SkipAct5,       SkipAct5,          GraphicsNew, },
 		/* 0x06 */ { NULL,     NULL,      NULL,            CfgApply,       CfgApply,          CfgApply, },
 		/* 0x07 */ { NULL,     NULL,      NULL,            NULL,           SkipIf,            SkipIf, },
-		/* 0x08 */ { ScanInfo, NULL,      NULL,            GRFInfo,        NULL,              GRFInfo, },
+		/* 0x08 */ { ScanInfo, NULL,      NULL,            GRFInfo,        GRFInfo,           GRFInfo, },
 		/* 0x09 */ { NULL,     NULL,      NULL,            SkipIf,         SkipIf,            SkipIf, },
 		/* 0x0A */ { SkipActA, SkipActA,  SkipActA,        SkipActA,       SkipActA,          SpriteReplace, },
 		/* 0x0B */ { NULL,     NULL,      NULL,            GRFLoadError,   GRFLoadError,      GRFLoadError, },
 		/* 0x0C */ { NULL,     NULL,      NULL,            GRFComment,     NULL,              GRFComment, },
 		/* 0x0D */ { NULL,     SafeParamSet, NULL,         ParamSet,       ParamSet,          ParamSet, },
 		/* 0x0E */ { NULL,     SafeGRFInhibit, NULL,       GRFInhibit,     GRFInhibit,        GRFInhibit, },
-		/* 0x0F */ { NULL,     NULL,      NULL,            NULL,           NULL,              NULL, },
+		/* 0x0F */ { NULL,     GRFUnsafe, NULL,            FeatureTownName, NULL,             NULL, },
 		/* 0x10 */ { NULL,     NULL,      DefineGotoLabel, NULL,           NULL,              NULL, },
 		/* 0x11 */ { NULL,     GRFUnsafe, NULL,            NULL,           NULL,              GRFSound, },
 		/* 0x12 */ { NULL,     NULL,      NULL,            NULL,           NULL,              LoadFontGlyph, },
@@ -5044,7 +5571,7 @@
 
 void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage)
 {
-	const char *filename = config->full_path;
+	const char *filename = config->filename;
 	uint16 num;
 
 	/* A .grf file is activated only if it was active when the game was
@@ -5059,6 +5586,7 @@
 	if (stage != GLS_FILESCAN && stage != GLS_SAFETYSCAN && stage != GLS_LABELSCAN) {
 		_cur_grffile = GetFileByFilename(filename);
 		if (_cur_grffile == NULL) error("File '%s' lost in cache.\n", filename);
+		if (stage == GLS_RESERVE && config->status != GCS_INITIALISED) return;
 		if (stage == GLS_ACTIVATION && config->status != GCS_INITIALISED) return;
 	}
 
@@ -5126,6 +5654,8 @@
 
 void InitDepotWindowBlockSizes();
 
+extern void SortTownGeneratorNames();
+
 static void AfterLoadGRFs()
 {
 	/* Update the bitmasks for the vehicle lists */
@@ -5144,12 +5674,18 @@
 	/* Add all new houses to the house array. */
 	FinaliseHouseArray();
 
+	/* Add all new industries to the industry array. */
+	FinaliseIndustriesArray();
+
 	/* Create dynamic list of industry legends for smallmap_gui.cpp */
 	BuildIndustriesLegend();
 
 	/* Map cargo strings. This is a separate step because cargos are
 	 * loaded before strings... */
 	MapNewCargoStrings();
+
+	/* Update the townname generators list */
+	SortTownGeneratorNames();
 }
 
 void LoadNewGRF(uint load_index, uint file_index)
@@ -5168,13 +5704,16 @@
 		_cur_spriteid = load_index;
 		for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 			if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
+			if (stage > GLS_INIT && HASBIT(c->flags, GCF_INIT_ONLY)) continue;
 
 			/* @todo usererror() */
-			if (!FileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename);
+			if (!FioCheckFileExists(c->filename)) error("NewGRF file is missing '%s'", c->filename);
 
 			if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid);
 			LoadNewGRFFile(c, slot++, stage);
-			if (stage == GLS_ACTIVATION) {
+			if (stage == GLS_RESERVE) {
+				if (c->status == GCS_ACTIVATED) c->status = GCS_INITIALISED;
+			} else if (stage == GLS_ACTIVATION) {
 				ClearTemporaryNewGRFData();
 				BuildCargoTranslationMap();
 				DEBUG(sprite, 2, "LoadNewGRF: Currently %i sprites are loaded", _cur_spriteid);