(svn r12924) -Feature: Introducing the so called 'engine pool' which primarily removes the fixed engine type limits and also happens to allow (with the patch option 'dynamic_engines') multiple NewGRF vehicle sets to coexist.
authorpeter1138
Tue, 29 Apr 2008 21:31:29 +0000
changeset 10382 d1d4452acbfc
parent 10380 b36a754e4c21
child 10387 b452b4949cca
(svn r12924) -Feature: Introducing the so called 'engine pool' which primarily removes the fixed engine type limits and also happens to allow (with the patch option 'dynamic_engines') multiple NewGRF vehicle sets to coexist.
bin/data/openttdd.grf
bin/data/openttdw.grf
projects/openttd_vs80.vcproj
projects/openttd_vs90.vcproj
source.list
src/ai/default/default.cpp
src/ai/trolly/build.cpp
src/ai/trolly/trolly.cpp
src/aircraft.h
src/aircraft_cmd.cpp
src/articulated_vehicles.cpp
src/autoreplace_gui.cpp
src/build_vehicle_gui.cpp
src/depot_gui.cpp
src/elrail.cpp
src/engine.cpp
src/engine_base.h
src/engine_func.h
src/engine_gui.cpp
src/engine_type.h
src/group.h
src/group_cmd.cpp
src/lang/english.txt
src/newgrf.cpp
src/newgrf_engine.cpp
src/newgrf_engine.h
src/newgrf_sound.cpp
src/oldloader.cpp
src/openttd.cpp
src/player_base.h
src/players.cpp
src/rail.cpp
src/rail_cmd.cpp
src/road.cpp
src/roadveh.h
src/roadveh_cmd.cpp
src/saveload.cpp
src/settings.cpp
src/settings_gui.cpp
src/settings_type.h
src/ship.h
src/ship_cmd.cpp
src/strings.cpp
src/table/engines.h
src/table/files.h
src/train_cmd.cpp
src/train_gui.cpp
src/tunnelbridge_cmd.cpp
src/vehicle.cpp
Binary file bin/data/openttdd.grf has changed
Binary file bin/data/openttdw.grf has changed
--- a/projects/openttd_vs80.vcproj	Tue Apr 29 18:19:29 2008 +0000
+++ b/projects/openttd_vs80.vcproj	Tue Apr 29 21:31:29 2008 +0000
@@ -988,6 +988,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\engine_base.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\engine_func.h"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj	Tue Apr 29 18:19:29 2008 +0000
+++ b/projects/openttd_vs90.vcproj	Tue Apr 29 21:31:29 2008 +0000
@@ -985,6 +985,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\engine_base.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\engine_func.h"
 				>
 			</File>
--- a/source.list	Tue Apr 29 18:19:29 2008 +0000
+++ b/source.list	Tue Apr 29 21:31:29 2008 +0000
@@ -168,6 +168,7 @@
 effectvehicle_func.h
 effectvehicle_base.h
 core/endian_func.hpp
+engine_base.h
 engine_func.h
 engine_type.h
 core/enum_type.hpp
--- a/src/ai/default/default.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/ai/default/default.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -137,11 +137,11 @@
 {
 	EngineID best_veh_index = INVALID_ENGINE;
 	byte best_veh_score = 0;
-	EngineID i;
-
-	FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_TRAIN) {
-		const RailVehicleInfo *rvi = RailVehInfo(i);
-		const Engine* e = GetEngine(i);
+	const Engine *e;
+
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+		EngineID i = e->index;
+		const RailVehicleInfo *rvi = &e->u.rail;
 
 		if (!IsCompatibleRail(rvi->railtype, railtype) ||
 				rvi->railveh_type == RAILVEH_WAGON ||
@@ -168,11 +168,11 @@
 {
 	EngineID best_veh_index = INVALID_ENGINE;
 	int32 best_veh_rating = 0;
-	EngineID i;
-
-	FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
-		const RoadVehicleInfo *rvi = RoadVehInfo(i);
-		const Engine* e = GetEngine(i);
+	const Engine *e;
+
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+		EngineID i = e->index;
+		const RoadVehicleInfo *rvi = &e->u.road;
 
 		if (!HasBit(e->player_avail, _current_player) || e->reliability < 0x8A3D) {
 			continue;
@@ -209,16 +209,17 @@
 {
 	EngineID best_veh_index = INVALID_ENGINE;
 	Money best_veh_cost = 0;
-	EngineID i;
-
-	FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_AIRCRAFT) {
-		const Engine* e = GetEngine(i);
+	const Engine *e;
+
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_AIRCRAFT) {
+		EngineID i = e->index;
+		const AircraftVehicleInfo *avi = &e->u.air;
 
 		if (!HasBit(e->player_avail, _current_player) || e->reliability < 0x8A3D) {
 			continue;
 		}
 
-		if ((AircraftVehInfo(i)->subtype & forbidden) != 0) continue;
+		if ((avi->subtype & forbidden) != 0) continue;
 
 		CommandCost ret = DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT);
 		if (CmdSucceeded(ret) && ret.GetCost() <= money && ret.GetCost() >= best_veh_cost) {
@@ -2445,14 +2446,14 @@
 static EngineID AiFindBestWagon(CargoID cargo, RailType railtype)
 {
 	EngineID best_veh_index = INVALID_ENGINE;
-	EngineID i;
 	uint16 best_capacity = 0;
 	uint16 best_speed    = 0;
 	uint speed;
-
-	FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_TRAIN) {
-		const RailVehicleInfo *rvi = RailVehInfo(i);
-		const Engine* e = GetEngine(i);
+	const Engine *e;
+
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+		EngineID i = e->index;
+		const RailVehicleInfo *rvi = &e->u.rail;
 
 		if (!IsCompatibleRail(rvi->railtype, railtype) ||
 				rvi->railveh_type != RAILVEH_WAGON ||
--- a/src/ai/trolly/build.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/ai/trolly/build.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -7,6 +7,7 @@
 #include "../../command_func.h"
 #include "trolly.h"
 #include "../../engine_func.h"
+#include "../../engine_base.h"
 #include "../../variables.h"
 #include "../../bridge.h"
 #include "../../vehicle_func.h"
@@ -235,12 +236,12 @@
 	} else {
 		EngineID best_veh_index = INVALID_ENGINE;
 		int32 best_veh_rating = 0;
-		EngineID i;
+		const Engine *e;
 
 		/* Loop through all road vehicles */
-		FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
-			const RoadVehicleInfo *rvi = RoadVehInfo(i);
-			const Engine* e = GetEngine(i);
+		FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+			EngineID i = e->index;
+			const RoadVehicleInfo *rvi = &e->u.road;
 
 			/* Skip vehicles which can't take our cargo type */
 			if (rvi->cargo_type != _players_ainew[p->index].cargo && !CanRefitTo(i, _players_ainew[p->index].cargo)) continue;
--- a/src/ai/trolly/trolly.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/ai/trolly/trolly.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -29,6 +29,7 @@
 #include "../../industry.h"
 #include "../../station_base.h"
 #include "../../engine_func.h"
+#include "../../engine_base.h"
 #include "../../gui.h"
 #include "../../depot_base.h"
 #include "../../vehicle_base.h"
--- a/src/aircraft.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/aircraft.h	Tue Apr 29 21:31:29 2008 +0000
@@ -9,6 +9,7 @@
 #include "station_base.h"
 #include "vehicle_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 
 /** An aircraft can be one ot those types */
 enum AircraftSubType {
--- a/src/aircraft_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/aircraft_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -168,7 +168,7 @@
 		SpriteID sprite = GetCustomVehicleSprite(this, direction);
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_aircraft_vehicle_info[this->engine_type - AIRCRAFT_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(this->engine_type)->image_index;
 	}
 
 	return direction + _aircraft_sprite[spritenum];
@@ -196,7 +196,7 @@
 		SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W);
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_aircraft_vehicle_info[engine - AIRCRAFT_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(engine)->image_index;
 	}
 
 	return 6 + _aircraft_sprite[spritenum];
--- a/src/articulated_vehicles.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/articulated_vehicles.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -11,6 +11,19 @@
 #include "newgrf_engine.h"
 #include "vehicle_func.h"
 
+static EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16 internal_id)
+{
+	const Engine *e = NULL;
+	FOR_ALL_ENGINES(e) {
+		if (e->grffile != file) continue;
+		if (e->type != type) continue;
+		if (e->internal_id != internal_id) continue;
+
+		return e->index;
+	}
+
+	return INVALID_ENGINE;
+}
 
 uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
 {
@@ -54,7 +67,7 @@
 		uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine, NULL);
 		if (callback == CALLBACK_FAILED || GB(callback, 0, 8) == 0xFF) break;
 
-		EngineID artic_engine = GetFirstEngineOfType(type) + GB(callback, 0, 7);
+		EngineID artic_engine = GetNewEngineID(GetEngineGRF(engine), type, GB(callback, 0, 7));
 
 		if (type == VEH_TRAIN) {
 			const RailVehicleInfo *rvi = RailVehInfo(artic_engine);
@@ -88,7 +101,7 @@
 		Vehicle *previous = u;
 		u = u->Next();
 
-		EngineID engine_type = GetFirstEngineOfType(type) + GB(callback, 0, 7);
+		EngineID engine_type = GetNewEngineID(GetEngineGRF(v->engine_type), type, GB(callback, 0, 7));
 		bool flip_image = HasBit(callback, 7);
 
 		/* get common values from first engine */
--- a/src/autoreplace_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/autoreplace_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -20,6 +20,7 @@
 #include "player_func.h"
 #include "widgets/dropdown_func.h"
 #include "engine_func.h"
+#include "engine_base.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -198,8 +199,9 @@
 	EngineList *list = &WP(w, replaceveh_d).list[i];
 	EngList_RemoveAll(list);
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, type) {
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, type) {
+		EngineID eid = e->index;
 		if (type == VEH_TRAIN && !GenerateReplaceRailList(eid, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains
 
 		if (draw_left) {
@@ -214,7 +216,7 @@
 			if (!EnginesGotCargoInCommon(eid, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo
 
 			/* Road vehicles can't be replaced by trams and vice-versa */
-			if (type == VEH_ROAD && HasBit(EngInfo(WP(w, replaceveh_d).sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM)) continue;
+			if (type == VEH_ROAD && HasBit(EngInfo(WP(w, replaceveh_d).sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
 			if (eid == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
 		}
 
--- a/src/build_vehicle_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/build_vehicle_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -800,9 +800,10 @@
 	 * Also check to see if the previously selected engine is still available,
 	 * and if not, reset selection to INVALID_ENGINE. This could be the case
 	 * when engines become obsolete and are removed */
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_TRAIN) {
-		const RailVehicleInfo *rvi = RailVehInfo(eid);
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+		EngineID eid = e->index;
+		const RailVehicleInfo *rvi = &e->u.rail;
 
 		if (bv->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, bv->filter.railtype)) continue;
 		if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue;
@@ -839,8 +840,9 @@
 
 	EngList_RemoveAll(&bv->eng_list);
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_ROAD) {
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+		EngineID eid = e->index;
 		if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
 		if (!HasBit(bv->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
 		EngList_Add(&bv->eng_list, eid);
@@ -858,8 +860,9 @@
 
 	EngList_RemoveAll(&bv->eng_list);
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_SHIP) {
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) {
+		EngineID eid = e->index;
 		if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue;
 		EngList_Add(&bv->eng_list, eid);
 
@@ -880,8 +883,9 @@
 	 * Also check to see if the previously selected plane is still available,
 	 * and if not, reset selection to INVALID_ENGINE. This could be the case
 	 * when planes become obsolete and are removed */
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_AIRCRAFT) {
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_AIRCRAFT) {
+		EngineID eid = e->index;
 		if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue;
 		/* First VEH_END window_numbers are fake to allow a window open for all different types at once */
 		if (w->window_number > VEH_END && !CanAircraftUseStation(eid, w->window_number)) continue;
--- a/src/depot_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/depot_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -656,8 +656,9 @@
 	uint max_width  = 0;
 	uint max_height = 0;
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, type) {
+	const Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, type) {
+		EngineID eid = e->index;
 		uint x, y;
 
 		switch (type) {
--- a/src/elrail.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/elrail.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -66,6 +66,7 @@
 #include "player_base.h"
 #include "tunnelbridge.h"
 #include "engine_func.h"
+#include "engine_base.h"
 
 #include "table/sprites.h"
 #include "table/elrail_data.h"
@@ -480,9 +481,9 @@
 	const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
 
 	/* walk through all train engines */
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_TRAIN) {
-		RailVehicleInfo *rv_info = &_rail_vehicle_info[eid];
+	Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+		RailVehicleInfo *rv_info = &e->u.rail;
 		/* if it is an electric rail engine and its railtype is the wrong one */
 		if (rv_info->engclass == 2 && rv_info->railtype == old_railtype) {
 			/* change it to the proper one */
--- a/src/engine.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/engine.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -14,6 +14,7 @@
 #include "train.h"
 #include "aircraft.h"
 #include "newgrf_cargo.h"
+#include "newgrf_engine.h"
 #include "group.h"
 #include "strings_func.h"
 #include "gfx_func.h"
@@ -25,43 +26,103 @@
 #include "string_func.h"
 #include "settings_type.h"
 #include "oldpool_func.h"
+#include "core/alloc_func.hpp"
+#include "map"
 
 #include "table/strings.h"
 #include "table/engines.h"
 
-Engine _engines[TOTAL_NUM_ENGINES];
-EngineInfo _engine_info[TOTAL_NUM_ENGINES];
-RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
-ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES];
-AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
-RoadVehicleInfo _road_vehicle_info[NUM_ROAD_ENGINES];
+DEFINE_OLD_POOL_GENERIC(Engine, Engine)
 
 enum {
 	YEAR_ENGINE_AGING_STOPS = 2050,
 };
 
 
+/** Number of engines of each vehicle type in original engine data */
+const uint8 _engine_counts[4] = {
+	lengthof(_orig_rail_vehicle_info),
+	lengthof(_orig_road_vehicle_info),
+	lengthof(_orig_ship_vehicle_info),
+	lengthof(_orig_aircraft_vehicle_info),
+};
+
+/** Offset of the first engine of each vehicle type in original engine data */
+const uint8 _engine_offsets[4] = {
+	0,
+	lengthof(_orig_rail_vehicle_info),
+	lengthof(_orig_rail_vehicle_info) + lengthof(_orig_road_vehicle_info),
+	lengthof(_orig_rail_vehicle_info) + lengthof(_orig_road_vehicle_info) + lengthof(_orig_ship_vehicle_info),
+};
+
+Engine::Engine() :
+	name(NULL),
+	overrides_count(0),
+	overrides(NULL)
+{
+}
+
+Engine::Engine(VehicleType type, EngineID base)
+{
+	this->type = type;
+	this->internal_id = base;
+	this->list_position = base;
+
+	/* Check if this base engine is within the original engine data range */
+	if (base >= _engine_counts[type]) {
+		/* Mark engine as valid anyway */
+		this->info.climates = 0x80;
+		return;
+	}
+
+	/* Copy the original engine info for this slot */
+	this->info = _orig_engine_info[_engine_offsets[type] + base];
+
+	/* Copy the original engine data for this slot */
+	switch (type) {
+		default: NOT_REACHED();
+
+		case VEH_TRAIN:
+			this->u.rail = _orig_rail_vehicle_info[base];
+			this->image_index = this->u.rail.image_index;
+			this->info.string_id = STR_8000_KIRBY_PAUL_TANK_STEAM + base;
+			break;
+
+		case VEH_ROAD:
+			this->u.road = _orig_road_vehicle_info[base];
+			this->image_index = this->u.road.image_index;
+			this->info.string_id = STR_8074_MPS_REGAL_BUS + base;
+			break;
+
+		case VEH_SHIP:
+			this->u.ship = _orig_ship_vehicle_info[base];
+			this->image_index = this->u.ship.image_index;
+			this->info.string_id = STR_80CC_MPS_OIL_TANKER + base;
+			break;
+
+		case VEH_AIRCRAFT:
+			this->u.air = _orig_aircraft_vehicle_info[base];
+			this->image_index = this->u.air.image_index;
+			this->info.string_id = STR_80D7_SAMPSON_U52 + base;
+			break;
+	}
+}
+
+Engine::~Engine()
+{
+	UnloadWagonOverrides(this);
+	free(this->name);
+}
+
 void SetupEngines()
 {
-	/* Copy original static engine data */
-	memcpy(&_engine_info, &_orig_engine_info, sizeof(_orig_engine_info));
-	memcpy(&_rail_vehicle_info, &_orig_rail_vehicle_info, sizeof(_orig_rail_vehicle_info));
-	memcpy(&_ship_vehicle_info, &_orig_ship_vehicle_info, sizeof(_orig_ship_vehicle_info));
-	memcpy(&_aircraft_vehicle_info, &_orig_aircraft_vehicle_info, sizeof(_orig_aircraft_vehicle_info));
-	memcpy(&_road_vehicle_info, &_orig_road_vehicle_info, sizeof(_orig_road_vehicle_info));
+	_Engine_pool.CleanPool();
+	_Engine_pool.AddBlockToPool();
 
-	/* Add type to engines */
-	Engine* e = _engines;
-	do e->type = VEH_TRAIN;    while (++e < &_engines[ROAD_ENGINES_INDEX]);
-	do e->type = VEH_ROAD;     while (++e < &_engines[SHIP_ENGINES_INDEX]);
-	do e->type = VEH_SHIP;     while (++e < &_engines[AIRCRAFT_ENGINES_INDEX]);
-	do e->type = VEH_AIRCRAFT; while (++e < &_engines[TOTAL_NUM_ENGINES]);
-
-	/* Set up default engine names */
-	for (EngineID engine = 0; engine < TOTAL_NUM_ENGINES; engine++) {
-		EngineInfo *ei = &_engine_info[engine];
-		ei->string_id = STR_8000_KIRBY_PAUL_TANK_STEAM + engine;
-	}
+	for (uint i = 0; i < lengthof(_orig_rail_vehicle_info); i++) new Engine(VEH_TRAIN, i);
+	for (uint i = 0; i < lengthof(_orig_road_vehicle_info); i++) new Engine(VEH_ROAD, i);
+	for (uint i = 0; i < lengthof(_orig_ship_vehicle_info); i++) new Engine(VEH_SHIP, i);
+	for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++) new Engine(VEH_AIRCRAFT, i);
 }
 
 
@@ -90,7 +151,7 @@
 
 	/* Check for early retirement */
 	if (e->player_avail != 0 && !_patches.never_expire_vehicles) {
-		int retire_early = EngInfo(e - _engines)->retire_early;
+		int retire_early = e->info.retire_early;
 		uint retire_early_max_age = max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12);
 		if (retire_early != 0 && age >= retire_early_max_age) {
 			/* Early retirement is enabled and we're past the date... */
@@ -124,11 +185,11 @@
 void StartupEngines()
 {
 	Engine *e;
-	const EngineInfo *ei;
 	/* Aging of vehicles stops, so account for that when starting late */
 	const Date aging_date = min(_date, ConvertYMDToDate(YEAR_ENGINE_AGING_STOPS, 0, 1));
 
-	for (e = _engines, ei = _engine_info; e != endof(_engines); e++, ei++) {
+	FOR_ALL_ENGINES(e) {
+		const EngineInfo *ei = &e->info;
 		uint32 r;
 
 		e->age = 0;
@@ -224,13 +285,11 @@
 
 void EnginesDailyLoop()
 {
-	EngineID i;
-
 	if (_cur_year >= YEAR_ENGINE_AGING_STOPS) return;
 
-	for (i = 0; i != lengthof(_engines); i++) {
-		Engine *e = &_engines[i];
-
+	Engine *e;
+	FOR_ALL_ENGINES(e) {
+		EngineID i = e->index;
 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) {
 			if (e->flags & ENGINE_OFFER_WINDOW_OPEN) {
 				if (e->preview_player_rank != 0xFF && !--e->preview_wait) {
@@ -282,14 +341,15 @@
 /* Determine if an engine type is a wagon (and not a loco) */
 static bool IsWagon(EngineID index)
 {
-	return index < NUM_TRAIN_ENGINES && RailVehInfo(index)->railveh_type == RAILVEH_WAGON;
+	const Engine *e = GetEngine(index);
+	return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON;
 }
 
 static void NewVehicleAvailable(Engine *e)
 {
 	Vehicle *v;
 	Player *p;
-	EngineID index = e - _engines;
+	EngineID index = e->index;
 
 	/* In case the player didn't build the vehicle during the intro period,
 	 * prevent that player from getting future intro periods for a while. */
@@ -326,7 +386,7 @@
 
 	if (e->type == VEH_TRAIN) {
 		/* maybe make another rail type available */
-		RailType railtype = RailVehInfo(index)->railtype;
+		RailType railtype = e->u.rail.railtype;
 		assert(railtype < RAILTYPE_END);
 		FOR_ALL_PLAYERS(p) {
 			if (p->is_active) SetBit(p->avail_railtypes, railtype);
@@ -334,7 +394,7 @@
 	} else if (e->type == VEH_ROAD) {
 		/* maybe make another road type available */
 		FOR_ALL_PLAYERS(p) {
-			if (p->is_active) SetBit(p->avail_roadtypes, HasBit(EngInfo(index)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
+			if (p->is_active) SetBit(p->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
 		}
 	}
 	AddNewsItem(index, NM_CALLBACK, NF_NONE, NT_NEW_VEHICLES, DNC_VEHICLEAVAIL, 0, 0);
@@ -359,7 +419,7 @@
 				e->flags |= ENGINE_EXCLUSIVE_PREVIEW;
 
 				/* Do not introduce new rail wagons */
-				if (!IsWagon(e - _engines))
+				if (!IsWagon(e->index))
 					e->preview_player_rank = 1; // Give to the player with the highest rating.
 			}
 		}
@@ -370,8 +430,9 @@
 {
 	char buf[512];
 
-	for (EngineID i = 0; i < TOTAL_NUM_ENGINES; i++) {
-		SetDParam(0, i);
+	const Engine *e;
+	FOR_ALL_ENGINES(e) {
+		SetDParam(0, e->index);
 		GetString(buf, STR_ENGINE_NAME, lastof(buf));
 		if (strcmp(buf, name) == 0) return false;
 	}
@@ -620,32 +681,77 @@
 	SLE_END()
 };
 
+static std::map<EngineID, Engine> _temp_engine;
+
+Engine *GetTempDataEngine(EngineID index)
+{
+	return &_temp_engine[index];
+}
+
 static void Save_ENGN()
 {
-	uint i;
-
-	for (i = 0; i != lengthof(_engines); i++) {
-		SlSetArrayIndex(i);
-		SlObject(&_engines[i], _engine_desc);
+	Engine *e;
+	FOR_ALL_ENGINES(e) {
+		SlSetArrayIndex(e->index);
+		SlObject(e, _engine_desc);
 	}
 }
 
 static void Load_ENGN()
 {
+	/* As engine data is loaded before engines are initialized we need to load
+	 * this information into a temporary array. This is then copied into the
+	 * engine pool after processing NewGRFs by CopyTempEngineData(). */
 	int index;
 	while ((index = SlIterateArray()) != -1) {
-		SlObject(GetEngine(index), _engine_desc);
+		Engine *e = GetTempDataEngine(index);
+		SlObject(e, _engine_desc);
 	}
 }
 
+/**
+ * Copy data from temporary engine array into the real engine pool.
+ */
+void CopyTempEngineData()
+{
+	Engine *e;
+	FOR_ALL_ENGINES(e) {
+		if (e->index >= _temp_engine.size()) break;
+
+		const Engine *se = GetTempDataEngine(e->index);
+		e->intro_date          = se->intro_date;
+		e->age                 = se->age;
+		e->reliability         = se->reliability;
+		e->reliability_spd_dec = se->reliability_spd_dec;
+		e->reliability_start   = se->reliability_start;
+		e->reliability_max     = se->reliability_max;
+		e->reliability_final   = se->reliability_final;
+		e->duration_phase_1    = se->duration_phase_1;
+		e->duration_phase_2    = se->duration_phase_2;
+		e->duration_phase_3    = se->duration_phase_3;
+		e->lifelength          = se->lifelength;
+		e->flags               = se->flags;
+		e->preview_player_rank = se->preview_player_rank;
+		e->preview_wait        = se->preview_wait;
+		e->player_avail        = se->player_avail;
+		if (se->name != NULL) e->name = strdup(se->name);
+	}
+
+	/* Get rid of temporary data */
+	_temp_engine.clear();
+}
+
 static void Load_ENGS()
 {
-	StringID names[TOTAL_NUM_ENGINES];
+	/* Load old separate String ID list into a temporary array. This
+	 * was always 256 entries. */
+	StringID names[256];
 
 	SlArray(names, lengthof(names), SLE_STRINGID);
 
+	/* Copy each string into the temporary engine array. */
 	for (EngineID engine = 0; engine < lengthof(names); engine++) {
-		Engine *e = GetEngine(engine);
+		Engine *e = GetTempDataEngine(engine);
 		e->name = CopyFromOldName(names[engine]);
 	}
 }
@@ -661,10 +767,4 @@
 	/* Clean the engine renew pool and create 1 block in it */
 	_EngineRenew_pool.CleanPool();
 	_EngineRenew_pool.AddBlockToPool();
-
-	Engine *e;
-	FOR_ALL_ENGINES(e) {
-		free(e->name);
-		e->name = NULL;
-	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/engine_base.h	Tue Apr 29 21:31:29 2008 +0000
@@ -0,0 +1,88 @@
+/* $Id$ */
+
+/** @file engine_base.h Base class for engines. */
+
+#ifndef ENGINE_BASE_H
+#define ENGINE_BASE_H
+
+#include "engine_type.h"
+#include "oldpool.h"
+
+DECLARE_OLD_POOL(Engine, Engine, 6, 10000)
+
+struct Engine : PoolItem<Engine, EngineID, &_Engine_pool> {
+	char *name;         ///< Custom name of engine
+	Date intro_date;
+	Date age;
+	uint16 reliability;
+	uint16 reliability_spd_dec;
+	uint16 reliability_start, reliability_max, reliability_final;
+	uint16 duration_phase_1, duration_phase_2, duration_phase_3;
+	byte lifelength;
+	byte flags;
+	uint8 preview_player_rank;
+	byte preview_wait;
+	byte player_avail;
+	uint8 image_index; ///< Original vehicle image index
+	VehicleType type; ///< type, ie VEH_ROAD, VEH_TRAIN, etc.
+
+	EngineInfo info;
+
+	union {
+		RailVehicleInfo rail;
+		RoadVehicleInfo road;
+		ShipVehicleInfo ship;
+		AircraftVehicleInfo air;
+	} u;
+
+	/* NewGRF related data */
+	const struct GRFFile *grffile;
+	const struct SpriteGroup *group[NUM_CARGO + 2];
+	uint16 internal_id;                             ///< ID within the GRF file
+	uint16 overrides_count;
+	struct WagonOverride *overrides;
+	uint16 list_position;
+
+	Engine();
+	Engine(VehicleType type, EngineID base);
+	~Engine();
+
+	inline bool IsValid() const { return this->info.climates != 0; }
+};
+
+static inline bool IsEngineIndex(uint index)
+{
+	return index < GetEnginePoolSize();
+}
+
+#define FOR_ALL_ENGINES_FROM(e, start) for (e = GetEngine(start); e != NULL; e = (e->index + 1U < GetEnginePoolSize()) ? GetEngine(e->index + 1U) : NULL) if (e->IsValid())
+#define FOR_ALL_ENGINES(e) FOR_ALL_ENGINES_FROM(e, 0)
+
+#define FOR_ALL_ENGINES_OF_TYPE(e, engine_type) FOR_ALL_ENGINES(e) if (e->type == engine_type)
+
+static inline const EngineInfo *EngInfo(EngineID e)
+{
+	return &GetEngine(e)->info;
+}
+
+static inline const RailVehicleInfo *RailVehInfo(EngineID e)
+{
+	return &GetEngine(e)->u.rail;
+}
+
+static inline const RoadVehicleInfo *RoadVehInfo(EngineID e)
+{
+	return &GetEngine(e)->u.road;
+}
+
+static inline const ShipVehicleInfo *ShipVehInfo(EngineID e)
+{
+	return &GetEngine(e)->u.ship;
+}
+
+static inline const AircraftVehicleInfo *AircraftVehInfo(EngineID e)
+{
+	return &GetEngine(e)->u.air;
+}
+
+#endif /* ENGINE_TYPE_H */
--- a/src/engine_func.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/engine_func.h	Tue Apr 29 21:31:29 2008 +0000
@@ -10,6 +10,12 @@
 void SetupEngines();
 void StartupEngines();
 
+Engine *GetTempDataEngine(EngineID index);
+void CopyTempEngineData();
+
+/* Original engine data counts and offsets */
+extern const uint8 _engine_counts[4];
+extern const uint8 _engine_offsets[4];
 
 void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal);
 void DrawRoadVehEngine(int x, int y, EngineID engine, SpriteID pal);
@@ -22,83 +28,6 @@
 bool IsEngineBuildable(EngineID engine, VehicleType type, PlayerID player);
 CargoID GetEngineCargoType(EngineID engine);
 
-static inline EngineID GetFirstEngineOfType(VehicleType type)
-{
-	const EngineID start[] = {0, ROAD_ENGINES_INDEX, SHIP_ENGINES_INDEX, AIRCRAFT_ENGINES_INDEX};
-
-	return start[type];
-}
-
-static inline EngineID GetLastEngineOfType(VehicleType type)
-{
-	const EngineID end[] = {
-		NUM_TRAIN_ENGINES,
-		ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES,
-		SHIP_ENGINES_INDEX + NUM_SHIP_ENGINES,
-		AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES};
-
-	return end[type];
-}
-
-extern Engine _engines[TOTAL_NUM_ENGINES];
-#define FOR_ALL_ENGINES(e) for (e = _engines; e != endof(_engines); e++)
-#define FOR_ALL_ENGINEIDS_OF_TYPE(e, type) for (e = GetFirstEngineOfType(type); e != GetLastEngineOfType(type); e++)
-
-
-static inline Engine* GetEngine(EngineID i)
-{
-	assert(i < lengthof(_engines));
-	return &_engines[i];
-}
-
-static inline bool IsEngineIndex(uint index)
-{
-	return index < TOTAL_NUM_ENGINES;
-}
-
-/* Access Vehicle Data */
-extern const EngineInfo _orig_engine_info[TOTAL_NUM_ENGINES];
-extern const RailVehicleInfo _orig_rail_vehicle_info[NUM_TRAIN_ENGINES];
-extern const ShipVehicleInfo _orig_ship_vehicle_info[NUM_SHIP_ENGINES];
-extern const AircraftVehicleInfo _orig_aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
-extern const RoadVehicleInfo _orig_road_vehicle_info[NUM_ROAD_ENGINES];
-
-extern EngineInfo _engine_info[TOTAL_NUM_ENGINES];
-extern RailVehicleInfo _rail_vehicle_info[NUM_TRAIN_ENGINES];
-extern ShipVehicleInfo _ship_vehicle_info[NUM_SHIP_ENGINES];
-extern AircraftVehicleInfo _aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES];
-extern RoadVehicleInfo _road_vehicle_info[NUM_ROAD_ENGINES];
-
-static inline const EngineInfo *EngInfo(EngineID e)
-{
-	assert(e < lengthof(_engine_info));
-	return &_engine_info[e];
-}
-
-static inline const RailVehicleInfo* RailVehInfo(EngineID e)
-{
-	assert(e < lengthof(_rail_vehicle_info));
-	return &_rail_vehicle_info[e];
-}
-
-static inline const ShipVehicleInfo* ShipVehInfo(EngineID e)
-{
-	assert(e >= SHIP_ENGINES_INDEX && e < SHIP_ENGINES_INDEX + lengthof(_ship_vehicle_info));
-	return &_ship_vehicle_info[e - SHIP_ENGINES_INDEX];
-}
-
-static inline const AircraftVehicleInfo* AircraftVehInfo(EngineID e)
-{
-	assert(e >= AIRCRAFT_ENGINES_INDEX && e < AIRCRAFT_ENGINES_INDEX + lengthof(_aircraft_vehicle_info));
-	return &_aircraft_vehicle_info[e - AIRCRAFT_ENGINES_INDEX];
-}
-
-static inline const RoadVehicleInfo* RoadVehInfo(EngineID e)
-{
-	assert(e >= ROAD_ENGINES_INDEX && e < ROAD_ENGINES_INDEX + lengthof(_road_vehicle_info));
-	return &_road_vehicle_info[e - ROAD_ENGINES_INDEX];
-}
-
 /* Engine list manipulators - current implementation is only C wrapper of CBlobT<EngineID> class (helpers.cpp) */
 void EngList_Create(EngineList *el);            ///< Creates engine list
 void EngList_Destroy(EngineList *el);           ///< Deallocate and destroy engine list
--- a/src/engine_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/engine_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -8,6 +8,7 @@
 #include "window_gui.h"
 #include "gfx_func.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "command_func.h"
 #include "economy_func.h"
 #include "news_func.h"
--- a/src/engine_type.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/engine_type.h	Tue Apr 29 21:31:29 2008 +0000
@@ -18,6 +18,8 @@
 typedef uint16 EngineRenewID;
 typedef EngineID *EngineList; ///< engine list type placeholder acceptable for C code (see helpers.cpp)
 
+struct Engine;
+
 enum RailVehicleTypes {
 	RAILVEH_SINGLEHEAD,  ///< indicates a "standalone" locomotive
 	RAILVEH_MULTIHEAD,   ///< indicates a combination of two locomotives
@@ -119,22 +121,6 @@
 	StringID string_id; ///< Default name of engine
 };
 
-struct Engine {
-	char *name;         ///< Custom name of engine
-	Date intro_date;
-	Date age;
-	uint16 reliability;
-	uint16 reliability_spd_dec;
-	uint16 reliability_start, reliability_max, reliability_final;
-	uint16 duration_phase_1, duration_phase_2, duration_phase_3;
-	byte lifelength;
-	byte flags;
-	uint8 preview_player_rank;
-	byte preview_wait;
-	byte player_avail;
-	VehicleType type; ///< type, ie VEH_ROAD, VEH_TRAIN, etc.
-};
-
 /**
  * EngineInfo.misc_flags is a bitmask, with the following values
  */
@@ -160,18 +146,4 @@
 
 static const EngineID INVALID_ENGINE = 0xFFFF;
 
-enum {
-	NUM_NORMAL_RAIL_ENGINES = 54,
-	NUM_MONORAIL_ENGINES    = 30,
-	NUM_MAGLEV_ENGINES      = 32,
-	NUM_TRAIN_ENGINES       = NUM_NORMAL_RAIL_ENGINES + NUM_MONORAIL_ENGINES + NUM_MAGLEV_ENGINES,
-	NUM_ROAD_ENGINES        = 88,
-	NUM_SHIP_ENGINES        = 11,
-	NUM_AIRCRAFT_ENGINES    = 41,
-	TOTAL_NUM_ENGINES       = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES + NUM_AIRCRAFT_ENGINES,
-	AIRCRAFT_ENGINES_INDEX  = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES + NUM_SHIP_ENGINES,
-	SHIP_ENGINES_INDEX      = NUM_TRAIN_ENGINES + NUM_ROAD_ENGINES,
-	ROAD_ENGINES_INDEX      = NUM_TRAIN_ENGINES,
-};
-
 #endif /* ENGINE_TYPE_H */
--- a/src/group.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/group.h	Tue Apr 29 21:31:29 2008 +0000
@@ -21,7 +21,7 @@
 	VehicleTypeByte vehicle_type;           ///< Vehicle type of the group
 
 	bool replace_protection;                ///< If set to true, the global autoreplace have no effect on the group
-	uint16 num_engines[TOTAL_NUM_ENGINES];  ///< Caches the number of engines of each type the player owns (no need to save this)
+	uint16 *num_engines;                    ///< Caches the number of engines of each type the player owns (no need to save this)
 
 	Group(PlayerID owner = INVALID_PLAYER);
 	virtual ~Group();
--- a/src/group_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/group_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -22,6 +22,7 @@
 #include "player_func.h"
 #include "order_func.h"
 #include "oldpool_func.h"
+#include "core/alloc_func.hpp"
 
 #include "table/strings.h"
 
@@ -50,12 +51,14 @@
 Group::Group(PlayerID owner)
 {
 	this->owner = owner;
+	this->num_engines = CallocT<uint16>(GetEnginePoolSize());
 }
 
 Group::~Group()
 {
 	free(this->name);
 	this->owner = INVALID_PLAYER;
+	free(this->num_engines);
 }
 
 bool Group::IsValid() const
--- a/src/lang/english.txt	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/lang/english.txt	Tue Apr 29 21:31:29 2008 +0000
@@ -1054,6 +1054,7 @@
 STR_CONFIG_PATCHES_PLANE_SPEED                                  :{LTBLUE}Plane speed factor: {ORANGE}1 / {STRING1}
 STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD                            :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING}
 STR_CONFIG_PATCHES_ADJACENT_STATIONS                            :{LTBLUE}Allow building adjacent stations: {ORANGE}{STRING}
+STR_CONFIG_PATCHES_DYNAMIC_ENGINES                              :{LTBLUE}Enable multiple NewGRF engine sets: {ORANGE}{STRING}
 
 STR_CONFIG_PATCHES_SMALL_AIRPORTS                               :{LTBLUE}Always allow small airports: {ORANGE}{STRING1}
 
--- a/src/newgrf.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/newgrf.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -10,6 +10,7 @@
 #include "debug.h"
 #include "fileio.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "spritecache.h"
 #include "sprite.h"
 #include "newgrf.h"
@@ -45,6 +46,7 @@
 #include "player_base.h"
 #include "settings_type.h"
 #include "map_func.h"
+#include <map>
 
 #include <map>
 
@@ -97,20 +99,6 @@
 
 typedef void (*SpecialSpriteHandler)(byte *buf, int len);
 
-static const uint _vehcounts[4] = {
-	/* GSF_TRAIN */    NUM_TRAIN_ENGINES,
-	/* GSF_ROAD */     NUM_ROAD_ENGINES,
-	/* GSF_SHIP */     NUM_SHIP_ENGINES,
-	/* GSF_AIRCRAFT */ NUM_AIRCRAFT_ENGINES
-};
-
-static const uint _vehshifts[4] = {
-	/* GSF_TRAIN */    0,
-	/* GSF_ROAD */     ROAD_ENGINES_INDEX,
-	/* GSF_SHIP */     SHIP_ENGINES_INDEX,
-	/* GSF_AIRCRAFT */ AIRCRAFT_ENGINES_INDEX,
-};
-
 enum {
 	MAX_STATIONS = 256,
 };
@@ -123,8 +111,10 @@
 
 static GRFTempEngineData *_gted;
 
-/* Contains the GRF ID of the owner of a vehicle if it has been reserved */
-static uint32 _grm_engines[TOTAL_NUM_ENGINES];
+/* Contains the GRF ID of the owner of a vehicle if it has been reserved.
+ * GRM for vehicles is only used if dynamic engine allocation is disabled,
+ * so 256 is the number of original engines. */
+static uint32 _grm_engines[256];
 
 /* Contains the GRF ID of the owner of a cargo if it has been reserved */
 static uint32 _grm_cargos[NUM_CARGO * 2];
@@ -310,6 +300,65 @@
 	return colour;
 }
 
+static std::map<uint32, uint32> _grf_id_overrides;
+
+static void SetNewGRFOverride(uint32 source_grfid, uint32 target_grfid)
+{
+	_grf_id_overrides[source_grfid] = target_grfid;
+	grfmsg(5, "SetNewGRFOverride: Added override of 0x%X to 0x%X", BSWAP32(source_grfid), BSWAP32(target_grfid));
+}
+
+static Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16 internal_id)
+{
+	/* Hack for add-on GRFs that need to modify another GRF's engines. This lets
+	 * them use the same engine slots. */
+	const GRFFile *grf_match = NULL;
+	if (_patches.dynamic_engines) {
+		uint32 override = _grf_id_overrides[file->grfid];
+		if (override != 0) {
+			grf_match = GetFileByGRFID(override);
+			if (grf_match == NULL) {
+				grfmsg(5, "Tried mapping from GRFID %x to %x but target is not loaded", BSWAP32(file->grfid), BSWAP32(override));
+			} else {
+				grfmsg(5, "Mapping from GRFID %x to %x", BSWAP32(file->grfid), BSWAP32(override));
+			}
+		}
+	}
+
+	/* Check if this vehicle is already defined... */
+	Engine *e = NULL;
+	FOR_ALL_ENGINES(e) {
+		if (_patches.dynamic_engines && e->grffile != NULL && e->grffile != file && e->grffile != grf_match) continue;
+		if (e->type != type) continue;
+		if (e->internal_id != internal_id) continue;
+
+		if (e->grffile == NULL) {
+			e->grffile = file;
+			grfmsg(5, "Replaced engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id);
+		}
+		return e;
+	}
+
+	uint engine_pool_size = GetEnginePoolSize();
+
+	/* ... it's not, so create a new one based off an existing engine */
+	e = new Engine(type, internal_id);
+	e->grffile = file;
+
+	if (engine_pool_size != GetEnginePoolSize()) {
+		/* Resize temporary engine data ... */
+		_gted = ReallocT(_gted, GetEnginePoolSize());
+
+		/* and blank the new block. */
+		size_t len = (GetEnginePoolSize() - engine_pool_size) * sizeof(*_gted);
+		memset(_gted + engine_pool_size, 0, len);
+	}
+
+	grfmsg(5, "Created new engine at index %d for GRFID %x, type %d, index %d", e->index, BSWAP32(file->grfid), type, internal_id);
+
+	return e;
+}
+
 /** Map the colour modifiers of TTDPatch to those that Open is using.
  * @param grf_sprite pointer to the structure been modified
  */
@@ -333,18 +382,15 @@
 
 typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
 
-static void dewagonize(int condition, int engine)
+static void dewagonize(int condition, Engine *e)
 {
-	EngineInfo *ei = &_engine_info[engine];
-	RailVehicleInfo *rvi = &_rail_vehicle_info[engine];
-
 	if (condition != 0) {
-		ei->unk2 &= ~0x80;
-		if (rvi->railveh_type == RAILVEH_WAGON)
-			rvi->railveh_type = RAILVEH_SINGLEHEAD;
+		e->info.unk2 &= ~0x80;
+		if (e->u.rail.railveh_type == RAILVEH_WAGON)
+			e->u.rail.railveh_type = RAILVEH_SINGLEHEAD;
 	} else {
-		ei->unk2 |= 0x80;
-		rvi->railveh_type = RAILVEH_WAGON;
+		e->info.unk2 |= 0x80;
+		e->u.rail.railveh_type = RAILVEH_WAGON;
 	}
 }
 
@@ -354,8 +400,9 @@
 	bool ret = false;
 
 	for (int i = 0; i < numinfo; i++) {
-		EngineInfo *ei       = &_engine_info[engine + i];
-		RailVehicleInfo *rvi = &_rail_vehicle_info[engine + i];
+		Engine *e = GetNewEngine(_cur_grffile, VEH_TRAIN, engine + i);
+		EngineInfo *ei = &e->info;
+		RailVehicleInfo *rvi = &e->u.rail;
 
 		switch (prop) {
 			case 0x05: { // Track type
@@ -390,7 +437,7 @@
 				if (rvi->railveh_type == RAILVEH_MULTIHEAD) power /= 2;
 
 				rvi->power = power;
-				dewagonize(power, engine + i);
+				dewagonize(power, e);
 			} break;
 
 			case 0x0D: { // Running cost factor
@@ -505,15 +552,9 @@
 				rvi->engclass = engclass;
 			} break;
 
-			case 0x1A: { // Alter purchase list sort order
-				EngineID pos = grf_load_byte(&buf);
-
-				if (pos < NUM_TRAIN_ENGINES) {
-					AlterRailVehListOrder(engine + i, pos);
-				} else {
-					grfmsg(2, "RailVehicleChangeInfo: Invalid train engine ID %d, ignoring", pos);
-				}
-			} break;
+			case 0x1A: // Alter purchase list sort order
+				AlterRailVehListOrder(e->index, grf_load_byte(&buf));
+				break;
 
 			case 0x1B: // Powered wagons power bonus
 				rvi->pow_wag_power = grf_load_word(&buf);
@@ -578,11 +619,11 @@
 				break;
 
 			case 0x28: // Cargo classes allowed
-				_gted[engine + i].cargo_allowed = grf_load_word(&buf);
+				_gted[e->index].cargo_allowed = grf_load_word(&buf);
 				break;
 
 			case 0x29: // Cargo classes disallowed
-				_gted[engine + i].cargo_disallowed = grf_load_word(&buf);
+				_gted[e->index].cargo_disallowed = grf_load_word(&buf);
 				break;
 
 			case 0x2A: // Long format introduction date (days since year 0)
@@ -605,8 +646,9 @@
 	bool ret = false;
 
 	for (int i = 0; i < numinfo; i++) {
-		EngineInfo *ei       = &_engine_info[ROAD_ENGINES_INDEX + engine + i];
-		RoadVehicleInfo *rvi = &_road_vehicle_info[engine + i];
+		Engine *e = GetNewEngine(_cur_grffile, VEH_ROAD, engine + i);
+		EngineInfo *ei = &e->info;
+		RoadVehicleInfo *rvi = &e->u.road;
 
 		switch (prop) {
 			case 0x08: // Speed (1 unit is 0.5 kmh)
@@ -708,11 +750,11 @@
 				break;
 
 			case 0x1D: // Cargo classes allowed
-				_gted[ROAD_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf);
+				_gted[e->index].cargo_allowed = grf_load_word(&buf);
 				break;
 
 			case 0x1E: // Cargo classes disallowed
-				_gted[ROAD_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf);
+				_gted[e->index].cargo_disallowed = grf_load_word(&buf);
 				break;
 
 			case 0x1F: // Long format introduction date (days since year 0)
@@ -735,8 +777,9 @@
 	bool ret = false;
 
 	for (int i = 0; i < numinfo; i++) {
-		EngineInfo *ei       = &_engine_info[SHIP_ENGINES_INDEX + engine + i];
-		ShipVehicleInfo *svi = &_ship_vehicle_info[engine + i];
+		Engine *e = GetNewEngine(_cur_grffile, VEH_SHIP, engine + i);
+		EngineInfo *ei = &e->info;
+		ShipVehicleInfo *svi = &e->u.ship;
 
 		switch (prop) {
 			case 0x08: { // Sprite ID
@@ -814,11 +857,11 @@
 				break;
 
 			case 0x18: // Cargo classes allowed
-				_gted[SHIP_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf);
+				_gted[e->index].cargo_allowed = grf_load_word(&buf);
 				break;
 
 			case 0x19: // Cargo classes disallowed
-				_gted[SHIP_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf);
+				_gted[e->index].cargo_disallowed = grf_load_word(&buf);
 				break;
 
 			case 0x1A: // Long format introduction date (days since year 0)
@@ -841,8 +884,9 @@
 	bool ret = false;
 
 	for (int i = 0; i < numinfo; i++) {
-		EngineInfo *ei           = &_engine_info[AIRCRAFT_ENGINES_INDEX + engine + i];
-		AircraftVehicleInfo *avi = &_aircraft_vehicle_info[engine + i];
+		Engine *e = GetNewEngine(_cur_grffile, VEH_AIRCRAFT, engine + i);
+		EngineInfo *ei = &e->info;
+		AircraftVehicleInfo *avi = &e->u.air;
 
 		switch (prop) {
 			case 0x08: { // Sprite ID
@@ -918,11 +962,11 @@
 				break;
 
 			case 0x18: // Cargo classes allowed
-				_gted[AIRCRAFT_ENGINES_INDEX + engine + i].cargo_allowed = grf_load_word(&buf);
+				_gted[e->index].cargo_allowed = grf_load_word(&buf);
 				break;
 
 			case 0x19: // Cargo classes disallowed
-				_gted[AIRCRAFT_ENGINES_INDEX + engine + i].cargo_disallowed = grf_load_word(&buf);
+				_gted[e->index].cargo_disallowed = grf_load_word(&buf);
 				break;
 
 			case 0x1A: // Long format introduction date (days since year 0)
@@ -1604,6 +1648,12 @@
 				}
 				break;
 
+			case 0x11: // GRF match for engine allocation
+				/* This is loaded during the reservation stage, so just skip it here. */
+				/* Each entry is 8 bytes. */
+				buf += 8;
+				break;
+
 			default:
 				ret = true;
 				break;
@@ -2211,13 +2261,6 @@
 		return;
 	}
 
-	if (feature <= GSF_AIRCRAFT) {
-		if (engine + numinfo > _vehcounts[feature]) {
-			grfmsg(0, "FeatureChangeInfo: Last engine ID %d out of bounds (max %d), skipping", engine + numinfo, _vehcounts[feature]);
-			return;
-		}
-	}
-
 	while (numprops-- && buf < bufend) {
 		uint8 prop = grf_load_byte(&buf);
 		bool ignoring = false;
@@ -2230,7 +2273,8 @@
 				bool handled = true;
 
 				for (uint i = 0; i < numinfo; i++) {
-					EngineInfo *ei = &_engine_info[engine + _vehshifts[feature] + i];
+					Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, engine + i);
+					EngineInfo *ei = &e->info;
 
 					/* Common properties for vehicles */
 					switch (prop) {
@@ -2252,6 +2296,8 @@
 
 						case 0x06: // Climates available
 							ei->climates = grf_load_byte(&buf);
+							// XXX sometimes a grf wants hidden vehicles :o
+							if (ei->climates == 0) ei->climates = 0x80;
 							break;
 
 						case 0x07: // Loading speed
@@ -2345,6 +2391,14 @@
 							_cur_grffile->cargo_list[i] = BSWAP32(cl);
 						}
 						break;
+
+					case 0x11: // GRF match for engine allocation
+						for (uint i = 0; i < numinfo; i++) {
+							uint32 s = grf_load_dword(&buf);
+							uint32 t = grf_load_dword(&buf);
+							SetNewGRFOverride(s, t);
+						}
+						break;
 				}
 				break;
 		}
@@ -2857,14 +2911,9 @@
 
 	for (uint i = 0; i < idcount; i++) {
 		uint8 engine_id = buf[3 + i];
-		uint8 engine = engine_id + _vehshifts[feature];
+		EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, engine_id)->index;
 		byte *bp = &buf[4 + idcount];
 
-		if (engine_id > _vehcounts[feature]) {
-			grfmsg(0, "Id %u for feature 0x%02X is out of bounds", engine_id, feature);
-			return;
-		}
-
 		grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
 
 		for (uint c = 0; c < cidcount; c++) {
@@ -2897,7 +2946,7 @@
 		grfmsg(8, "-- Default group id 0x%04X", groupid);
 
 		for (uint i = 0; i < idcount; i++) {
-			uint8 engine = buf[3 + i] + _vehshifts[feature];
+			EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, buf[3 + i])->index;
 
 			/* Don't tell me you don't love duplicated code! */
 			if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
@@ -3213,9 +3262,6 @@
 
 	ClrBit(lang, 7);
 
-	if (feature <= GSF_AIRCRAFT && id < _vehcounts[feature]) {
-		id += _vehshifts[feature];
-	}
 	uint16 endid = id + num;
 
 	grfmsg(6, "FeatureNewName: About to rename engines %d..%d (feature %d) in language 0x%02X",
@@ -3236,10 +3282,10 @@
 			case GSF_ROAD:
 			case GSF_SHIP:
 			case GSF_AIRCRAFT:
-				if (id < TOTAL_NUM_ENGINES) {
-					StringID string = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_8000_KIRBY_PAUL_TANK_STEAM + id);
-					EngineInfo *ei = &_engine_info[id];
-					ei->string_id = string;
+				if (id < GetEnginePoolSize()) {
+					Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, id);
+					StringID string = AddGRFString(_cur_grffile->grfid, e->index, lang, new_scheme, name, e->info.string_id);
+					e->info.string_id = string;
 				} else {
 					AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id);
 				}
@@ -4303,8 +4349,22 @@
 						case 0x01: // Road Vehicles
 						case 0x02: // Ships
 						case 0x03: // Aircraft
-							src1 = PerformGRM(&_grm_engines[_vehshifts[feature]], _vehcounts[feature], count, op, target, "vehicles");
-							if (_skip_sprites == -1) return;
+							if (!_patches.dynamic_engines) {
+								src1 = PerformGRM(&_grm_engines[_engine_offsets[feature]], _engine_counts[feature], count, op, target, "vehicles");
+								if (_skip_sprites == -1) return;
+							} else {
+								// GRM does not apply for dynamic engine allocation.
+								switch (op) {
+									case 2:
+									case 3:
+										src1 = _cur_grffile->param[target];
+										break;
+
+									default:
+										src1 = 0;
+										break;
+								}
+							}
 							break;
 
 						case 0x08: // General sprites
@@ -5068,6 +5128,7 @@
 	                   |                                        (0 << 0x15)  // enhancetunnels
 	                   |                                        (1 << 0x16)  // shortrvs
 	                   |                                        (1 << 0x17)  // articulatedrvs
+	                   |       ((_patches.dynamic_engines ? 1 : 0) << 0x18)  // dynamic engines
 	                   |                                        (1 << 0x1E); // variablerunningcosts
 }
 
@@ -5224,17 +5285,12 @@
 	ResetBridges();
 
 	/* Allocate temporary refit/cargo class data */
-	_gted = CallocT<GRFTempEngineData>(TOTAL_NUM_ENGINES);
+	_gted = CallocT<GRFTempEngineData>(GetEnginePoolSize());
 
 	/* Reset GRM reservations */
 	memset(&_grm_engines, 0, sizeof(_grm_engines));
 	memset(&_grm_cargos, 0, sizeof(_grm_cargos));
 
-	/* Unload sprite group data */
-	UnloadWagonOverrides();
-	UnloadCustomEngineSprites();
-	ResetEngineListOrder();
-
 	/* Reset generic feature callback lists */
 	ResetGenericCallbacks();
 
@@ -5284,6 +5340,9 @@
 	_loaded_newgrf_features.has_newindustries = false;
 	_loaded_newgrf_features.shore             = SHORE_REPLACE_NONE;
 
+	/* Clear all GRF overrides */
+	_grf_id_overrides.clear();
+
 	InitializeSoundPool();
 	InitializeSpriteGroupPool();
 }
@@ -5397,14 +5456,17 @@
  */
 static void CalculateRefitMasks()
 {
-	for (EngineID engine = 0; engine < TOTAL_NUM_ENGINES; engine++) {
-		EngineInfo *ei = &_engine_info[engine];
+	Engine *e;
+
+	FOR_ALL_ENGINES(e) {
+		EngineID engine = e->index;
+		EngineInfo *ei = &e->info;
 		uint32 mask = 0;
 		uint32 not_mask = 0;
 		uint32 xor_mask = 0;
 
 		if (ei->refit_mask != 0) {
-			const GRFFile *file = GetEngineGRF(engine);
+			const GRFFile *file = e->grffile;
 			if (file != NULL && file->cargo_max != 0) {
 				/* Apply cargo translation table to the refit mask */
 				uint num_cargo = min(32, file->cargo_max);
@@ -5434,15 +5496,10 @@
 				if (_gted[engine].cargo_allowed    & cs->classes) SetBit(mask,     i);
 				if (_gted[engine].cargo_disallowed & cs->classes) SetBit(not_mask, i);
 			}
-		} else {
+		} else if (xor_mask == 0) {
 			/* Don't apply default refit mask to wagons or engines with no capacity */
-			if (xor_mask == 0 && (
-						GetEngine(engine)->type != VEH_TRAIN || (
-							RailVehInfo(engine)->capacity != 0 &&
-							RailVehInfo(engine)->railveh_type != RAILVEH_WAGON
-						)
-					)) {
-				const CargoLabel *cl = _default_refitmasks[GetEngine(engine)->type];
+			if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) {
+				const CargoLabel *cl = _default_refitmasks[e->type];
 				for (uint i = 0;; i++) {
 					if (cl[i] == 0) break;
 
@@ -5458,25 +5515,25 @@
 
 		/* Check if this engine's cargo type is valid. If not, set to the first refittable
 		 * cargo type. Apparently cargo_type isn't a common property... */
-		switch (GetEngine(engine)->type) {
+		switch (e->type) {
 			default: NOT_REACHED();
 			case VEH_AIRCRAFT: break;
 			case VEH_TRAIN: {
-				RailVehicleInfo *rvi = &_rail_vehicle_info[engine];
+				RailVehicleInfo *rvi = &e->u.rail;
 				if (rvi->cargo_type == CT_INVALID) rvi->cargo_type = FindFirstRefittableCargo(engine);
-				if (rvi->cargo_type == CT_INVALID) ei->climates = 0;
+				if (rvi->cargo_type == CT_INVALID) ei->climates = 0x80;
 				break;
 			}
 			case VEH_ROAD: {
-				RoadVehicleInfo *rvi = &_road_vehicle_info[engine - ROAD_ENGINES_INDEX];
+				RoadVehicleInfo *rvi = &e->u.road;
 				if (rvi->cargo_type == CT_INVALID) rvi->cargo_type = FindFirstRefittableCargo(engine);
-				if (rvi->cargo_type == CT_INVALID) ei->climates = 0;
+				if (rvi->cargo_type == CT_INVALID) ei->climates = 0x80;
 				break;
 			}
 			case VEH_SHIP: {
-				ShipVehicleInfo *svi = &_ship_vehicle_info[engine - SHIP_ENGINES_INDEX];
+				ShipVehicleInfo *svi = &e->u.ship;
 				if (svi->cargo_type == CT_INVALID) svi->cargo_type = FindFirstRefittableCargo(engine);
-				if (svi->cargo_type == CT_INVALID) ei->climates = 0;
+				if (svi->cargo_type == CT_INVALID) ei->climates = 0x80;
 				break;
 			}
 		}
@@ -5851,6 +5908,9 @@
 	/* Update the townname generators list */
 	InitGRFTownGeneratorNames();
 
+	/* Run all queued vehicle list order changes */
+	CommitRailVehListOrderChanges();
+
 	/* Load old shore sprites in new position, if they were replaced by ActionA */
 	ActivateOldShore();
 
--- a/src/newgrf_engine.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/newgrf_engine.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -7,6 +7,7 @@
 #include "variables.h"
 #include "debug.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "train.h"
 #include "player_func.h"
 #include "player_base.h"
@@ -25,6 +26,8 @@
 #include "direction_func.h"
 #include "rail_map.h"
 #include "rail.h"
+#include "settings_type.h"
+#include <map>
 
 
 int _traininfo_vehicle_pitch = 0;
@@ -37,29 +40,17 @@
 	const SpriteGroup *group;
 };
 
-struct WagonOverrides {
-	uint overrides_count;
-	WagonOverride *overrides;
-};
-
-static WagonOverrides _engine_wagon_overrides[TOTAL_NUM_ENGINES];
-
 void SetWagonOverrideSprites(EngineID engine, CargoID cargo, const SpriteGroup *group, EngineID *train_id, uint trains)
 {
-	WagonOverrides *wos;
+	Engine *e = GetEngine(engine);
 	WagonOverride *wo;
 
-	assert(engine < TOTAL_NUM_ENGINES);
 	assert(cargo < NUM_CARGO + 2); // Include CT_DEFAULT and CT_PURCHASE pseudo cargos.
 
-	wos = &_engine_wagon_overrides[engine];
-	wos->overrides_count++;
-	wos->overrides = ReallocT(wos->overrides, wos->overrides_count);
+	e->overrides_count++;
+	e->overrides = ReallocT(e->overrides, e->overrides_count);
 
-	wo = &wos->overrides[wos->overrides_count - 1];
-	/* FIXME: If we are replacing an override, release original SpriteGroup
-	 * to prevent leaks. But first we need to refcount the SpriteGroup.
-	 * --pasky */
+	wo = &e->overrides[e->overrides_count - 1];
 	wo->group = group;
 	wo->cargo = cargo;
 	wo->trains = trains;
@@ -69,15 +60,15 @@
 
 const SpriteGroup *GetWagonOverrideSpriteSet(EngineID engine, CargoID cargo, EngineID overriding_engine)
 {
-	const WagonOverrides *wos = &_engine_wagon_overrides[engine];
+	const Engine *e = GetEngine(engine);
 
 	/* XXX: This could turn out to be a timesink on profiles. We could
 	 * always just dedicate 65535 bytes for an [engine][train] trampoline
 	 * for O(1). Or O(logMlogN) and searching binary tree or smt. like
 	 * that. --pasky */
 
-	for (uint i = 0; i < wos->overrides_count; i++) {
-		const WagonOverride *wo = &wos->overrides[i];
+	for (uint i = 0; i < e->overrides_count; i++) {
+		const WagonOverride *wo = &e->overrides[i];
 
 		if (wo->cargo != cargo && wo->cargo != CT_DEFAULT) continue;
 
@@ -91,43 +82,29 @@
 /**
  * Unload all wagon override sprite groups.
  */
-void UnloadWagonOverrides()
+void UnloadWagonOverrides(Engine *e)
 {
-	for (EngineID engine = 0; engine < TOTAL_NUM_ENGINES; engine++) {
-		WagonOverrides *wos = &_engine_wagon_overrides[engine];
-		for (uint i = 0; i < wos->overrides_count; i++) {
-			WagonOverride *wo = &wos->overrides[i];
-			free(wo->train_id);
-		}
-		free(wos->overrides);
-		wos->overrides_count = 0;
-		wos->overrides = NULL;
+	for (uint i = 0; i < e->overrides_count; i++) {
+		WagonOverride *wo = &e->overrides[i];
+		free(wo->train_id);
 	}
+	free(e->overrides);
+	e->overrides_count = 0;
+	e->overrides = NULL;
 }
 
-/* Space for NUM_CARGO real cargos and 2 pseudo cargos, CT_DEFAULT and CT_PURCHASE */
-static const SpriteGroup *_engine_custom_sprites[TOTAL_NUM_ENGINES][NUM_CARGO + 2];
-static const GRFFile *_engine_grf[TOTAL_NUM_ENGINES];
 
 void SetCustomEngineSprites(EngineID engine, byte cargo, const SpriteGroup *group)
 {
-	assert(engine < lengthof(_engine_custom_sprites));
-	assert(cargo < lengthof(*_engine_custom_sprites));
+	Engine *e = GetEngine(engine);
+	assert(cargo < lengthof(e->group));
 
-	if (_engine_custom_sprites[engine][cargo] != NULL) {
+	if (e->group[cargo] != NULL) {
 		grfmsg(6, "SetCustomEngineSprites: engine %d cargo %d already has group -- replacing", engine, cargo);
 	}
-	_engine_custom_sprites[engine][cargo] = group;
+	e->group[cargo] = group;
 }
 
-/**
- * Unload all engine sprite groups.
- */
-void UnloadCustomEngineSprites()
-{
-	memset(_engine_custom_sprites, 0, sizeof(_engine_custom_sprites));
-	memset(_engine_grf, 0, sizeof(_engine_grf));
-}
 
 /**
  * Tie a GRFFile entry to an engine, to allow us to retrieve GRF parameters
@@ -137,8 +114,8 @@
  */
 void SetEngineGRF(EngineID engine, const GRFFile *file)
 {
-	assert(engine < TOTAL_NUM_ENGINES);
-	_engine_grf[engine] = file;
+	Engine *e = GetEngine(engine);
+	e->grffile = file;
 }
 
 
@@ -149,8 +126,7 @@
  */
 const GRFFile *GetEngineGRF(EngineID engine)
 {
-	assert(engine < TOTAL_NUM_ENGINES);
-	return _engine_grf[engine];
+	return GetEngine(engine)->grffile;
 }
 
 
@@ -161,8 +137,7 @@
  */
 uint32 GetEngineGRFID(EngineID engine)
 {
-	assert(engine < TOTAL_NUM_ENGINES);
-	return _engine_grf[engine]->grfid;
+	return GetEngineGRF(engine)->grfid;
 }
 
 
@@ -468,6 +443,7 @@
 {
 	const GRFFile *file = GetEngineGRF(engine_type);
 
+	if (file == NULL) return 0;
 	if (parameter >= file->param_end) return 0;
 	return file->param[parameter];
 }
@@ -643,12 +619,13 @@
 
 		/* Variables which use the parameter */
 		case 0x60: // Count consist's engine ID occurance
-			if (v->type != VEH_TRAIN) return v->engine_type == parameter;
+			//EngineID engine = GetNewEngineID(GetEngineGRF(v->engine_type), v->type, parameter);
+			if (v->type != VEH_TRAIN) return GetEngine(v->engine_type)->internal_id == parameter;
 
 			{
 				uint count = 0;
 				for (; v != NULL; v = v->Next()) {
-					if (v->engine_type == parameter) count++;
+					if (GetEngine(v->engine_type)->internal_id == parameter) count++;
 				}
 				return count;
 			}
@@ -723,8 +700,8 @@
 		case 0x43: return GB(v->max_age, 8, 8);
 		case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 		case 0x45: return v->unitnumber;
-		case 0x46: return v->engine_type;
-		case 0x47: return GB(v->engine_type, 8, 8);
+		case 0x46: return GetEngine(v->engine_type)->internal_id;
+		case 0x47: return GB(GetEngine(v->engine_type)->internal_id, 8, 8);
 		case 0x48:
 			if (v->type != VEH_TRAIN || v->spritenum != 0xFD) return v->spritenum;
 			return HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD;
@@ -883,11 +860,13 @@
 		}
 	}
 
-	group = _engine_custom_sprites[engine][cargo];
+	const Engine *e = GetEngine(engine);
+
+	group = e->group[cargo];
 	if (group != NULL) return group;
 
 	/* Fall back to the default set if the selected cargo type is not defined */
-	return _engine_custom_sprites[engine][CT_DEFAULT];
+	return e->group[CT_DEFAULT];
 }
 
 
@@ -907,14 +886,14 @@
 
 SpriteID GetRotorOverrideSprite(EngineID engine, const Vehicle *v, bool info_view)
 {
+	const Engine *e = GetEngine(engine);
 	const SpriteGroup *group;
 	ResolverObject object;
 
-	assert(engine >= AIRCRAFT_ENGINES_INDEX);
-	assert(engine < AIRCRAFT_ENGINES_INDEX + NUM_AIRCRAFT_ENGINES);
+	assert(e->type == VEH_AIRCRAFT);
 
 	/* Only valid for helicopters */
-	assert(!(AircraftVehInfo(engine)->subtype & AIR_CTOL));
+	assert(!(e->u.air.subtype & AIR_CTOL));
 
 	NewVehicleResolver(&object, engine, v);
 
@@ -1090,18 +1069,6 @@
 
 /* Functions for changing the order of vehicle purchase lists
  * This is currently only implemented for rail vehicles. */
-static EngineID _engine_list_order[NUM_TRAIN_ENGINES];
-static byte _engine_list_position[NUM_TRAIN_ENGINES];
-
-void ResetEngineListOrder()
-{
-	EngineID i;
-
-	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
-		_engine_list_order[i] = i;
-		_engine_list_position[i] = i;
-	}
-}
 
 /**
  * Get the list position of an engine.
@@ -1109,36 +1076,72 @@
  * @param engine ID of the engine.
  * @return The list position of the engine.
  */
-uint16 ListPositionOfEngine(EngineID engine)
+uint ListPositionOfEngine(EngineID engine)
 {
-	if (engine < NUM_TRAIN_ENGINES) return _engine_list_position[engine];
-	return engine;
+	const Engine *e = GetEngine(engine);
+	if (e->grffile == NULL) return e->list_position;
+
+	/* Crude sorting to group by GRF ID */
+	return (e->grffile->grfid * 256) + e->list_position;
 }
 
+struct ListOrderChange {
+	EngineID engine;
+	EngineID target;
+};
+
+static std::list<ListOrderChange> _list_order_changes;
+
 void AlterRailVehListOrder(EngineID engine, EngineID target)
 {
-	EngineID i;
-	bool moving = false;
+	/* Add the list order change to a queue */
+	ListOrderChange loc;
+	loc.engine = engine;
+	loc.target = target;
+	_list_order_changes.push_back(loc);
+}
 
-	if (engine == target) return;
+void CommitRailVehListOrderChanges()
+{
+	/* List position to Engine map */
+	typedef std::map<uint16, Engine*> ListPositionMap;
+	ListPositionMap lptr_map;
 
-	/* First, remove our ID from the list. */
-	for (i = 0; i < NUM_TRAIN_ENGINES - 1; i++) {
-		if (_engine_list_order[i] == engine) moving = true;
-		if (moving) _engine_list_order[i] = _engine_list_order[i + 1];
+	std::list<ListOrderChange>::iterator it;
+	for (it = _list_order_changes.begin(); it != _list_order_changes.end(); ++it) {
+		EngineID engine = it->engine;
+		EngineID target = it->target;
+
+		if (engine == target) continue;
+
+		Engine *source_e = GetEngine(engine);
+		Engine *target_e = NULL;
+
+		/* Populate map with current list positions */
+		Engine *e;
+		FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+			if (!_patches.dynamic_engines || e->grffile == source_e->grffile) {
+				if (e->internal_id == target) target_e = e;
+				lptr_map[e->list_position] = e;
+			}
+		}
+
+		/* Get the target position, if it exists */
+		if (target_e != NULL) {
+			uint16 target_position = target_e->list_position;
+
+			bool moving = false;
+			for (ListPositionMap::iterator it = lptr_map.begin(); it != lptr_map.end(); ++it) {
+				if (it->first == target_position) moving = true;
+				if (moving) it->second->list_position++;
+			}
+
+			source_e->list_position = target_position;
+		}
+
+		lptr_map.clear();
 	}
 
-	/* Now, insert it again, before the target engine. */
-	for (i = NUM_TRAIN_ENGINES - 1; i > 0; i--) {
-		_engine_list_order[i] = _engine_list_order[i - 1];
-		if (_engine_list_order[i] == target) {
-			_engine_list_order[i - 1] = engine;
-			break;
-		}
-	}
-
-	/* Update the engine list position (a reverse of engine list order) */
-	for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
-		_engine_list_position[_engine_list_order[i]] = i;
-	}
+	/* Clear out the queue */
+	_list_order_changes.clear();
 }
--- a/src/newgrf_engine.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/newgrf_engine.h	Tue Apr 29 21:31:29 2008 +0000
@@ -53,11 +53,10 @@
 };
 void TriggerVehicle(Vehicle *veh, VehicleTrigger trigger);
 
-void UnloadWagonOverrides();
-void UnloadCustomEngineSprites();
+void UnloadWagonOverrides(Engine *e);
 
-void ResetEngineListOrder();
-uint16 ListPositionOfEngine(EngineID engine);
+uint ListPositionOfEngine(EngineID engine);
 void AlterRailVehListOrder(EngineID engine, EngineID target);
+void CommitRailVehListOrderChanges();
 
 #endif /* NEWGRF_ENGINE_H */
--- a/src/newgrf_sound.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/newgrf_sound.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -6,6 +6,7 @@
 #include "openttd.h"
 #include "oldpool.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_engine.h"
 #include "newgrf_sound.h"
--- a/src/oldloader.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/oldloader.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -1330,18 +1330,19 @@
 
 static bool LoadOldEngine(LoadgameState *ls, int num)
 {
-	if (!LoadChunk(ls, GetEngine(num), engine_chunk)) return false;
+	Engine *e = GetTempDataEngine(num);
+	if (!LoadChunk(ls, e, engine_chunk)) return false;
 
 	/* Make sure wagons are marked as do-not-age */
 	if ((num >= 27 && num < 54) || (num >= 57 && num < 84) || (num >= 89 && num < 116))
-		GetEngine(num)->age = 0xFFFF;
+		e->age = 0xFFFF;
 
 	return true;
 }
 
 static bool LoadOldEngineName(LoadgameState *ls, int num)
 {
-	Engine *e = GetEngine(num);
+	Engine *e = GetTempDataEngine(num);
 	e->name = CopyFromOldName(RemapOldStringID(ReadUint16(ls)));
 	return true;
 }
--- a/src/openttd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/openttd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -305,6 +305,7 @@
 	_Order_pool.CleanPool();
 	_Group_pool.CleanPool();
 	_CargoPacket_pool.CleanPool();
+	_Engine_pool.CleanPool();
 
 	free((void*)_town_sort);
 	free((void*)_industry_sort);
@@ -1332,6 +1333,8 @@
 	/* Recalculate */
 	Group *g;
 	FOR_ALL_GROUPS(g) {
+		g->num_engines = CallocT<uint16>(GetEnginePoolSize());
+
 		const Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
 			if (!IsEngineCountable(v)) continue;
@@ -1354,6 +1357,9 @@
 		 * thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */
 		if (_file_to_saveload.filetype == FT_SCENARIO && players[i]->inaugurated_year != MIN_YEAR)
 			players[i]->inaugurated_year = _cur_year;
+
+		free(players[i]->num_engines);
+		players[i]->num_engines = CallocT<uint16>(GetEnginePoolSize());
 	}
 
 	FOR_ALL_VEHICLES(v) {
@@ -1444,10 +1450,16 @@
 	 * must be done before loading sprites as some newgrfs check it */
 	SetDate(_date);
 
+	/* Force dynamic engines off when loading older savegames */
+	if (CheckSavegameVersion(95)) _patches.dynamic_engines = 0;
+
 	/* Load the sprites */
 	GfxLoadSprites();
 	LoadStringWidthTable();
 
+	/* Copy temporary data to Engine pool */
+	CopyTempEngineData();
+
 	/* Connect front and rear engines of multiheaded trains and converts
 	 * subtype to the new format */
 	if (CheckSavegameVersionOldStyle(17, 1)) ConvertOldMultiheadToNew();
--- a/src/player_base.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/player_base.h	Tue Apr 29 21:31:29 2008 +0000
@@ -70,7 +70,7 @@
 	bool renew_keep_length;
 	int16 engine_renew_months;
 	uint32 engine_renew_money;
-	uint16 num_engines[TOTAL_NUM_ENGINES]; ///< caches the number of engines of each type the player owns (no need to save this)
+	uint16 *num_engines; ///< caches the number of engines of each type the player owns (no need to save this)
 };
 
 struct PlayerMoneyBackup {
--- a/src/players.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/players.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -5,6 +5,7 @@
 #include "stdafx.h"
 #include "openttd.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "player_func.h"
 #include "player_gui.h"
 #include "town.h"
@@ -26,6 +27,7 @@
 #include "date_func.h"
 #include "vehicle_func.h"
 #include "sound_func.h"
+#include "core/alloc_func.hpp"
 #include "autoreplace_func.h"
 #include "autoreplace_gui.h"
 #include "string_func.h"
@@ -548,7 +550,8 @@
 	if (is_ai && (!_networking || _network_server) && _ai.enabled)
 		AI_StartNewAI(p->index);
 
-	memset(p->num_engines, 0, sizeof(p->num_engines));
+	free(p->num_engines);
+	p->num_engines = CallocT<uint16>(GetEnginePoolSize());
 
 	return p;
 }
--- a/src/rail.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/rail.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -14,6 +14,7 @@
 #include "player_func.h"
 #include "player_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 
 
 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
@@ -202,14 +203,13 @@
 {
 	RailTypes rt = RAILTYPES_NONE;
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_TRAIN) {
-		const Engine* e = GetEngine(eid);
-		const EngineInfo *ei = EngInfo(eid);
+	Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
+		const EngineInfo *ei = &e->info;
 
 		if (HasBit(ei->climates, _opt.landscape) &&
 				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
-			const RailVehicleInfo *rvi = RailVehInfo(eid);
+			const RailVehicleInfo *rvi = &e->u.rail;
 
 			if (rvi->railveh_type != RAILVEH_WAGON) {
 				assert(rvi->railtype < RAILTYPE_END);
--- a/src/rail_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/rail_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -18,6 +18,7 @@
 #include "command_func.h"
 #include "pathfind.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "town.h"
 #include "sprite.h"
 #include "depot_base.h"
--- a/src/road.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/road.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -10,6 +10,7 @@
 #include "player_func.h"
 #include "player_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "settings_type.h"
 #include "date_func.h"
 
@@ -96,10 +97,9 @@
 {
 	RoadTypes rt = ROADTYPES_NONE;
 
-	EngineID eid;
-	FOR_ALL_ENGINEIDS_OF_TYPE(eid, VEH_ROAD) {
-		const Engine* e = GetEngine(eid);
-		const EngineInfo *ei = EngInfo(eid);
+	Engine *e;
+	FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+		const EngineInfo *ei = &e->info;
 
 		if (HasBit(ei->climates, _opt.landscape) &&
 				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
--- a/src/roadveh.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/roadveh.h	Tue Apr 29 21:31:29 2008 +0000
@@ -7,6 +7,7 @@
 
 #include "vehicle_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "economy_func.h"
 
 enum RoadVehicleSubType {
--- a/src/roadveh_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/roadveh_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -102,7 +102,7 @@
 		SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W);
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_road_vehicle_info[engine - ROAD_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(engine)->image_index;
 	}
 
 	return 6 + _roadveh_images[spritenum];
@@ -117,7 +117,7 @@
 		sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_road_vehicle_info[this->engine_type - ROAD_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(this->engine_type)->image_index;
 	}
 
 	sprite = direction + _roadveh_images[spritenum];
--- a/src/saveload.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/saveload.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -34,7 +34,7 @@
 
 #include "table/strings.h"
 
-extern const uint16 SAVEGAME_VERSION = 94;
+extern const uint16 SAVEGAME_VERSION = 95;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
--- a/src/settings.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/settings.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -1459,6 +1459,7 @@
 	SDT_CONDVAR(Patches, freight_trains, SLE_UINT8, 39, SL_MAX_VERSION, 0,NN, 1, 1, 255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS, NULL),
 	SDT_CONDBOOL(Patches, timetabling,              67, SL_MAX_VERSION, 0, 0, true,  STR_CONFIG_PATCHES_TIMETABLE_ALLOW,      NULL),
 	SDT_CONDVAR(Patches, plane_speed,    SLE_UINT8, 90, SL_MAX_VERSION, 0, 0, 4, 1,   4, 0, STR_CONFIG_PATCHES_PLANE_SPEED,   NULL),
+	SDT_CONDBOOL(Patches, dynamic_engines,          95, SL_MAX_VERSION, 0,NN, false, STR_CONFIG_PATCHES_DYNAMIC_ENGINES,      NULL),
 
 	/***************************************************************************/
 	/* Station section of the GUI-configure patches window */
--- a/src/settings_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/settings_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -819,6 +819,7 @@
 	"freight_trains",
 	"plane_speed",
 	"timetabling",
+	"dynamic_engines",
 };
 
 struct PatchEntry {
--- a/src/settings_type.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/settings_type.h	Tue Apr 29 21:31:29 2008 +0000
@@ -232,6 +232,8 @@
 	bool give_money;             ///< allow giving other players money
 
 	bool enable_signal_gui;      ///< Show the signal GUI when the signal button is pressed
+
+	bool dynamic_engines;    ///< Enable dynamic allocation of engine data
 };
 
 extern Patches _patches;
--- a/src/ship.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/ship.h	Tue Apr 29 21:31:29 2008 +0000
@@ -7,6 +7,7 @@
 
 #include "vehicle_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "economy_func.h"
 
 void CcBuildShip(bool success, TileIndex tile, uint32 p1, uint32 p2);
--- a/src/ship_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/ship_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -14,6 +14,7 @@
 #include "station_base.h"
 #include "news_func.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "player_func.h"
 #include "player_base.h"
 #include "npf.h"
@@ -65,7 +66,7 @@
 		SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W);
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_ship_vehicle_info[engine - SHIP_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(engine)->image_index;
 	}
 
 	return 6 + _ship_sprites[spritenum];
@@ -97,7 +98,7 @@
 		SpriteID sprite = GetCustomVehicleSprite(this, direction);
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_ship_vehicle_info[this->engine_type - SHIP_ENGINES_INDEX].image_index;
+		spritenum = GetEngine(this->engine_type)->image_index;
 	}
 
 	return _ship_sprites[spritenum] + direction;
--- a/src/strings.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/strings.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -37,6 +37,7 @@
 #include "settings_type.h"
 #include "video/video_driver.hpp"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "saveload.h"
 
 #include "table/strings.h"
@@ -934,7 +935,7 @@
 				if (e->name != NULL) {
 					buff = strecpy(buff, e->name, last);
 				} else {
-					buff = GetStringWithArgs(buff, EngInfo(engine)->string_id, NULL, last);
+					buff = GetStringWithArgs(buff, e->info.string_id, NULL, last);
 				}
 				break;
 			}
--- a/src/table/engines.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/table/engines.h	Tue Apr 29 21:31:29 2008 +0000
@@ -69,7 +69,7 @@
 #define A 2
 #define S 4
 #define Y 8
-const EngineInfo _orig_engine_info[] = {
+static const EngineInfo _orig_engine_info[] = {
 	MK(  1827,  20,  15,  30, T      ), /*   0 Kirby Paul Tank (Steam) */
 	MK( 12784,  20,  22,  30,   A|S  ), /*   1 MJS 250 (Diesel) */
 	MK(  9497,  20,  20,  50,       Y), /*   2 Ploddyphut Choo-Choo */
@@ -370,7 +370,7 @@
 #define O RAILTYPE_MONO
 #define L RAILTYPE_MAGLEV
 
-const RailVehicleInfo _orig_rail_vehicle_info[NUM_TRAIN_ENGINES] = {
+static const RailVehicleInfo _orig_rail_vehicle_info[] = {
 	//   image_index  max_speed (kph)      running_cost                   ai_rank
 	//   |  flags     |        power (hp)  |  running_cost_class          |  railtype
 	//   |  |    base_cost     |    weight |  |      capacity             |  |
@@ -519,7 +519,7 @@
  * @param h refittable
  */
 #define SVI(a, b, c, d, e, f, g, h) { a, b, c, d, e, f, {g}, h }
-const ShipVehicleInfo _orig_ship_vehicle_info[NUM_SHIP_ENGINES] = {
+static const ShipVehicleInfo _orig_ship_vehicle_info[] = {
 	//   image_index  cargo_type     cargo_amount                 refittable
 	//   |    base_cost |              |    running_cost          |
 	//   |    |    max_speed           |    |  sfx                |
@@ -554,7 +554,7 @@
 #define H AIR_HELI
 #define P AIR_CTOL
 #define J AIR_CTOL | AIR_FAST
-const AircraftVehicleInfo _orig_aircraft_vehicle_info[NUM_AIRCRAFT_ENGINES] = {
+static const AircraftVehicleInfo _orig_aircraft_vehicle_info[] = {
 	//    image_index         sfx                         acceleration
 	//    |   base_cost       |                           |   max_speed
 	//    |   |    running_cost                           |   |    mail_capacity
@@ -618,7 +618,7 @@
  * @param g cargo_type
  */
 #define ROV(a, b, c, d, e, f, g) { a, b, c, RC_R, {d}, e, f, g }
-const RoadVehicleInfo _orig_road_vehicle_info[NUM_ROAD_ENGINES] = {
+static const RoadVehicleInfo _orig_road_vehicle_info[] = {
 	//    image_index       sfx                                 max_speed
 	//    |    base_cost    |                                   |   capacity
 	//    |    |    running_cost                                |   |  cargo_type
--- a/src/table/files.h	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/table/files.h	Tue Apr 29 21:31:29 2008 +0000
@@ -33,7 +33,7 @@
 		{ "TRGT.GRF",      {0xfc, 0xde, 0x1d, 0x7e, 0x8a, 0x74, 0x19, 0x7d, 0x72, 0xa6, 0x26, 0x95, 0x88, 0x4b, 0x90, 0x9e} }
 	},
 	{ "SAMPLE.CAT",    {0x42, 0x2e, 0xa3, 0xdd, 0x07, 0x4d, 0x28, 0x59, 0xbb, 0x51, 0x63, 0x9a, 0x6e, 0x0e, 0x85, 0xda} },
-	{ "OPENTTDD.GRF",  {0x32, 0xb4, 0xec, 0x0c, 0xc9, 0x5d, 0xa0, 0x14, 0x3a, 0x2f, 0xe1, 0xd4, 0x20, 0x63, 0x49, 0x74} }
+	{ "OPENTTDD.GRF",  {0xb2, 0xbd, 0xd2, 0xa4, 0x1b, 0xfa, 0x2c, 0x60, 0x4f, 0xd5, 0x5e, 0x4c, 0xb5, 0xba, 0x37, 0x73} }
 };
 
 
@@ -47,5 +47,5 @@
 		{ "TRGTR.GRF",     {0xde, 0x53, 0x65, 0x05, 0x17, 0xfe, 0x66, 0x1c, 0xea, 0xa3, 0x13, 0x8c, 0x6e, 0xdb, 0x0e, 0xb8} }
 	},
 	{ "SAMPLE.CAT",    {0x92, 0x12, 0xe8, 0x1e, 0x72, 0xba, 0xdd, 0x4b, 0xbe, 0x1e, 0xae, 0xae, 0x66, 0x45, 0x8e, 0x10} },
-	{ "OPENTTDW.GRF",  {0xc6, 0x1f, 0xcc, 0x4e, 0x83, 0x98, 0x5b, 0x67, 0xb7, 0x03, 0xa0, 0x31, 0x39, 0x2e, 0x75, 0xfc} }
+	{ "OPENTTDW.GRF",  {0x3b, 0x1a, 0x0d, 0x8c, 0x2d, 0x01, 0x0e, 0xee, 0x47, 0x7f, 0x5d, 0x70, 0x8f, 0xb2, 0xe4, 0xfb} }
 };
--- a/src/train_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/train_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -18,6 +18,7 @@
 #include "station_base.h"
 #include "news_func.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "player_func.h"
 #include "player_base.h"
 #include "depot_base.h"
@@ -487,7 +488,7 @@
 		sprite = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(spritenum)));
 		if (sprite != 0) return sprite;
 
-		spritenum = _orig_rail_vehicle_info[this->engine_type].image_index;
+		spritenum = GetEngine(this->engine_type)->image_index;
 	}
 
 	sprite = _engine_sprite_base[spritenum] + ((direction + _engine_sprite_add[spritenum]) & _engine_sprite_and[spritenum]);
@@ -509,7 +510,7 @@
 			return sprite;
 		}
 
-		spritenum = _orig_rail_vehicle_info[engine].image_index;
+		spritenum = GetEngine(engine)->image_index;
 	}
 
 	if (rear_head) spritenum++;
--- a/src/train_gui.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/train_gui.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -17,6 +17,7 @@
 #include "settings_type.h"
 #include "order_func.h"
 #include "engine_func.h"
+#include "engine_base.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
--- a/src/tunnelbridge_cmd.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/tunnelbridge_cmd.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -35,6 +35,7 @@
 #include "tunnelbridge.h"
 #include "player_base.h"
 #include "engine_func.h"
+#include "engine_base.h"
 #include "economy_func.h"
 #include "rail.h"
 #include "cheat_func.h"
--- a/src/vehicle.cpp	Tue Apr 29 18:19:29 2008 +0000
+++ b/src/vehicle.cpp	Tue Apr 29 21:31:29 2008 +0000
@@ -1985,9 +1985,9 @@
 	/* We can build vehicle infrastructure when we may build the vehicle type */
 	if (max > 0) {
 		/* Can we actually build the vehicle type? */
-		EngineID eid;
-		FOR_ALL_ENGINEIDS_OF_TYPE(eid, type) {
-			if (HasBit(GetEngine(eid)->player_avail, _local_player)) return true;
+		const Engine *e;
+		FOR_ALL_ENGINES_OF_TYPE(e, type) {
+			if (HasBit(e->player_avail, _local_player)) return true;
 		}
 		return false;
 	}