changeset 6143:bccc948d9804 draft

(svn r8886) -Codechange: (NewGRF) Add (partial) cargo translation table support, applied to action 3s only.
author peter1138 <peter1138@openttd.org>
date Sat, 24 Feb 2007 19:36:47 +0000
parents 586baa62c8d6
children 1a17a9fc035f
files src/cargotype.cpp src/cargotype.h src/newgrf.cpp src/newgrf.h
diffstat 4 files changed, 120 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/cargotype.cpp
+++ b/src/cargotype.cpp
@@ -75,3 +75,14 @@
 {
 	return bitnum != INVALID_CARGO;
 }
+
+
+CargoID GetCargoIDByLabel(CargoLabel cl)
+{
+	for (CargoID c = 0; c < lengthof(_cargo); c++) {
+		if (_cargo[c].label == cl) return c;
+	}
+
+	/* No matching label was found, so it is invalid */
+	return CT_INVALID;
+}
--- a/src/cargotype.h
+++ b/src/cargotype.h
@@ -47,6 +47,8 @@
 const CargoSpec *GetCargo(CargoID c);
 /* Get the cargo ID of a cargo bitnum */
 CargoID GetCargoIDByBitnum(byte bitnum);
+/* Get the cargo ID with the cargo label */
+CargoID GetCargoIDByLabel(CargoLabel cl);
 
 
 #endif /* CARGOTYPE_H */
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -68,6 +68,10 @@
 /* Set if any vehicle is loaded which uses 2cc (two company colours) */
 bool _have_2cc = false;
 
+/* Default cargo translation table. By default there are 27 possible cargo types */
+static const uint _default_cargo_max = 27;
+static CargoLabel _default_cargo_list[_default_cargo_max];
+
 
 typedef enum GrfDataType {
 	GDT_SOUND,
@@ -1189,6 +1193,12 @@
 			}
 			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 {
 				uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
@@ -1273,7 +1283,6 @@
 			}
 			break;
 
-		case 0x09: // Cargo translation table
 		case 0x10: // 12 * 32 * B Snow line height table
 		default:
 			ret = true;
@@ -1501,6 +1510,55 @@
 	_skip_sprites = -1;
 }
 
+/* Action 0x00 (GLS_INIT) */
+static void InitChangeInfo(byte *buf, int len)
+{
+	byte *bufend = buf + len;
+	uint8 feature;
+	uint8 numprops;
+	uint8 numinfo;
+	uint8 index;
+
+	if (len == 1) {
+		grfmsg(8, "Silently ignoring one-byte special sprite 0x00");
+		return;
+	}
+
+	if (!check_length(len, 6, "InitChangeInfo")) return;
+	buf++;
+	feature  = grf_load_byte(&buf);
+	numprops = grf_load_byte(&buf);
+	numinfo  = grf_load_byte(&buf);
+	index    = grf_load_byte(&buf);
+
+	while (numprops-- && buf < bufend) {
+		uint8 prop = grf_load_byte(&buf);
+
+		switch (feature) {
+			case GSF_GLOBALVAR:
+				switch (prop) {
+					case 0x09: /* Cargo Translation Table */
+						if (index != 0) {
+							grfmsg(1, "InitChangeInfo: Cargo translation table must start at zero");
+							return;
+						}
+
+						free(_cur_grffile->cargo_list);
+						_cur_grffile->cargo_max = numinfo;
+						_cur_grffile->cargo_list = MallocT<CargoLabel>(numinfo);
+
+						int i;
+						FOR_EACH_OBJECT {
+							CargoLabel cl = grf_load_dword(&buf);
+							_cur_grffile->cargo_list[i] = BSWAP32(cl);
+						}
+						break;
+				}
+				break;
+		}
+	}
+}
+
 #undef FOR_EACH_OBJECT
 
 /**
@@ -1834,6 +1892,38 @@
 	_cur_grffile->spritegroups[setid] = group;
 }
 
+static CargoID TranslateCargo(uint8 feature, uint8 ctype)
+{
+	/* Special cargo types for purchase list and stations */
+	if (feature == GSF_STATION && ctype == 0xFE) return GC_DEFAULT_NA;
+	if (ctype == 0xFF) return GC_PURCHASE;
+
+	/* Check if the cargo type is out of bounds of the cargo translation table */
+	if (ctype >= (_cur_grffile->cargo_max == 0 ? _default_cargo_max : _cur_grffile->cargo_max)) {
+		grfmsg(1, "FeatureMapSpriteGroup: Cargo type %d out of range (max %d), skipping.", ctype, (_cur_grffile->cargo_max == 0 ? _default_cargo_max : _cur_grffile->cargo_max) - 1);
+		return CT_INVALID;
+	}
+
+	/* Look up the cargo label from the translation table */
+	CargoLabel cl = _cur_grffile->cargo_max == 0 ? _default_cargo_list[ctype] : _cur_grffile->cargo_list[ctype];
+	if (cl == 0) {
+		grfmsg(5, "FeatureMapSpriteGroup: Cargo type %d not available in this climate, skipping.", ctype);
+		return CT_INVALID;
+	}
+
+	ctype = GetCargoIDByLabel(cl);
+	if (ctype == CT_INVALID) {
+		grfmsg(5, "FeatureMapSpriteGroup: Cargo '%c%c%c%c' unsupported, skipping.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8));
+		return CT_INVALID;
+	}
+
+	/* Remap back to global cargo */
+	ctype = GetCargo(ctype)->bitnum;
+
+	grfmsg(6, "FeatureMapSpriteGroup: Cargo '%c%c%c%c' mapped to cargo type %d.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8), ctype);
+	return ctype;
+}
+
 /* Action 0x03 */
 static void FeatureMapSpriteGroup(byte *buf, int len)
 {
@@ -1905,13 +1995,8 @@
 					return;
 				}
 
-				if (ctype == 0xFE) ctype = GC_DEFAULT_NA;
-				if (ctype == 0xFF) ctype = GC_PURCHASE;
-
-				if (ctype >= NUM_GLOBAL_CID) {
-					grfmsg(1, "FeatureMapSpriteGroup: Cargo type %d out of range, skipping.", ctype);
-					continue;
-				}
+				ctype = TranslateCargo(feature, ctype);
+				if (ctype == CT_INVALID) continue;
 
 				statspec->spritegroup[ctype] = _cur_grffile->spritegroups[groupid];
 			}
@@ -1987,12 +2072,8 @@
 				return;
 			}
 
-			if (ctype == GC_INVALID) ctype = GC_PURCHASE;
-
-			if (ctype >= NUM_GLOBAL_CID) {
-				grfmsg(1, "FeatureMapSpriteGroup: Cargo type %d out of range, skipping.", ctype);
-				continue;
-			}
+			ctype = TranslateCargo(feature, ctype);
+			if (ctype == CT_INVALID) continue;
 
 			if (wagover) {
 				SetWagonOverrideSprites(engine, ctype, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
@@ -3589,6 +3670,13 @@
 	/* Set up the default cargo types */
 	SetupCargoForClimate(_opt.landscape);
 
+	/* Generate default cargo translation table */
+	memset(_default_cargo_list, 0, sizeof(_default_cargo_list));
+	for (CargoID c = 0; c != NUM_CARGO; c++) {
+		const CargoSpec *cs = GetCargo(c);
+		if (cs->IsValid()) _default_cargo_list[cs->bitnum] = cs->label;
+	}
+
 	/* Reset misc GRF features and train list display variables */
 	_misc_grf_features = 0;
 	_traininfo_vehicle_pitch = 0;
@@ -3755,7 +3843,7 @@
 	 * is not in memory and scanning the file every time would be too expensive.
 	 * In other stages we skip action 0x10 since it's already dealt with. */
 	static const SpecialSpriteHandler handlers[][GLS_END] = {
-		/* 0x00 */ { NULL,     SafeChangeInfo, NULL,       NULL,       FeatureChangeInfo, },
+		/* 0x00 */ { NULL,     SafeChangeInfo, NULL,       InitChangeInfo, FeatureChangeInfo, },
 		/* 0x01 */ { NULL,     GRFUnsafe, NULL,            NULL,       NewSpriteSet, },
 		/* 0x02 */ { NULL,     GRFUnsafe, NULL,            NULL,       NewSpriteGroup, },
 		/* 0x03 */ { NULL,     GRFUnsafe, NULL,            NULL,       FeatureMapSpriteGroup, },
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -6,6 +6,7 @@
 #include "station.h"
 #include "newgrf_config.h"
 #include "helpers.hpp"
+#include "cargotype.h"
 
 typedef enum GrfLoadingStage {
 	GLS_FILESCAN,
@@ -60,6 +61,9 @@
 	uint param_end; /// one more than the highest set parameter
 
 	GRFLabel *label; ///< Pointer to the first label. This is a linked list, not an array.
+
+	uint8 cargo_max;
+	CargoLabel *cargo_list;
 } GRFFile;
 
 extern GRFFile *_first_grffile;