src/newgrf.cpp
branchgamebalance
changeset 9912 1ac8aac92385
parent 9911 0b8b245a2391
child 9913 e79cd19772dd
--- a/src/newgrf.cpp	Wed Jun 13 11:45:14 2007 +0000
+++ b/src/newgrf.cpp	Wed Jun 13 12:05:56 2007 +0000
@@ -74,12 +74,8 @@
 /* Used by Action 0x06 to preload a pseudo sprite and modify its content */
 static byte *_preload_sprite = NULL;
 
-/* Set if any vehicle is loaded which uses 2cc (two company colours) */
-bool _have_2cc = false;
-
-/* Set if there are any newhouses loaded. */
-bool _have_newhouses = false;
-
+/* Indicates which are the newgrf features currently loaded ingame */
+uint8 _loaded_newgrf_features;
 
 enum GrfDataType {
 	GDT_SOUND,
@@ -132,6 +128,9 @@
 /* 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 cargo if it has been reserved */
+static uint32 _grm_cargos[NUM_CARGO];
+
 /** DEBUG() function dedicated to newGRF debugging messages
  * Function is essentialy the same as DEBUG(grf, severity, ...) with the
  * addition of file:line information when parsing grf files.
@@ -539,7 +538,7 @@
 		case 0x27: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) _have_2cc = true;
+				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
 			}
 			break;
 
@@ -661,7 +660,7 @@
 		case 0x1C: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) _have_2cc = true;
+				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
 			}
 			break;
 
@@ -772,7 +771,7 @@
 		case 0x17: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) _have_2cc = true;
+				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
 			}
 			break;
 
@@ -888,7 +887,7 @@
 		case 0x17: // Miscellaneous flags
 			FOR_EACH_OBJECT {
 				ei[i].misc_flags = grf_load_byte(&buf);
-				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) _have_2cc = true;
+				if (HASBIT(ei[i].misc_flags, EF_USES_2CC)) SETBIT(_loaded_newgrf_features, GRFLOADED_2CC);
 			}
 			break;
 
@@ -1297,7 +1296,7 @@
 				 * FinaliseHouseArray() for more details. */
 				if (housespec[i]->min_date < 1930) housespec[i]->min_date = 1930;
 			}
-			_have_newhouses = true;
+			SETBIT(_loaded_newgrf_features, GRFLOADED_NEWHOUSES);
 			break;
 
 		case 0x09: // Building flags
@@ -2505,7 +2504,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;
 			}
@@ -2897,6 +2896,14 @@
 			replace = SPR_CANALS_BASE + 5;
 			break;
 
+		case 0x09: // One way graphics
+			if (num != 6) {
+				grfmsg(1, "GraphicsNew: One way road graphics sprite count must be 6, skipping");
+				return;
+			}
+			replace = SPR_ONEWAY_BASE;
+			break;
+
 		case 0x0A: // 2CC colour maps
 			if (num != 256) {
 				grfmsg(1, "GraphicsNew: 2CC colour maps sprite count must be 256, skipping");
@@ -2905,6 +2912,14 @@
 			replace = SPR_2CCMAP_BASE;
 			break;
 
+		case 0x0B: // tramways
+			if (num != 113) {
+				grfmsg(1, "GraphicsNew: Tramway graphics sprite count must be 113, skipping");
+				return;
+			}
+			replace = SPR_TRAMWAY_BASE;
+			break;
+
 		case 0x0D: // Coast graphics
 			if (num != 16) {
 				grfmsg(1, "GraphicsNew: Coast graphics sprite count must be 16, skipping");
@@ -2932,6 +2947,7 @@
 		default:
 			grfmsg(2, "GraphicsNew: Custom graphics (type 0x%02X) sprite block of length %u (unimplemented, ignoring)",
 					type, num);
+			_skip_sprites = num;
 			return;
 	}
 
@@ -2971,8 +2987,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) {
@@ -3255,7 +3277,7 @@
 		_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_DISABLED;
 	}
 }
 
@@ -3305,7 +3327,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);
@@ -3412,8 +3434,8 @@
 
 	/* 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);
@@ -3529,6 +3551,54 @@
 }
 
 
+static uint32 PerformGRM(uint32 *grm, uint16 num_ids, uint16 count, uint8 op, uint8 target, const char *type)
+{
+	uint start = 0;
+	uint size  = 0;
+
+	if (op == 6) {
+		/* Return GRFID of set that reserved ID */
+		return grm[_cur_grffile->param[target]];
+	}
+
+	/* With an operation of 2 or 3, we want to reserve a specific block of IDs */
+	if (op == 2 || op == 3) start = _cur_grffile->param[target];
+
+	for (uint i = start; i < num_ids; i++) {
+		if (grm[i] == 0) {
+			size++;
+		} else {
+			if (op == 2 || op == 3) break;
+			start = i + 1;
+			size = 0;
+		}
+
+		if (size == count) break;
+	}
+
+	if (size == count) {
+		/* Got the slot... */
+		if (op == 0 || op == 3) {
+			grfmsg(2, "ParamSet: GRM: Reserving %d %s at %d", count, type, start);
+			for (uint i = 0; i < count; i++) grm[start + i] = _cur_grffile->grfid;
+		}
+		return start;
+	}
+
+	/* Unable to allocate */
+	if (op != 4 && op != 5) {
+		/* Deactivate GRF */
+		grfmsg(0, "ParamSet: GRM: Unable to allocate %d %s, deactivating", count, type);
+		_cur_grfconfig->status = GCS_DISABLED;
+		_skip_sprites = -1;
+		return UINT_MAX;
+	}
+
+	grfmsg(1, "ParamSet: GRM: Unable to allocate %d %s", count, type);
+	return UINT_MAX;
+}
+
+
 /* Action 0x0D */
 static void ParamSet(byte *buf, int len)
 {
@@ -3599,55 +3669,9 @@
 						case 0x01: // Road Vehicles
 						case 0x02: // Ships
 						case 0x03: // Aircraft
-						{
-							uint start = 0;
-							uint size  = 0;
-							uint shift = _vehshifts[feature];
-
-							if (op == 6) {
-								/* Return GRFID of set that reserved ID */
-								src1 = _grm_engines[shift + _cur_grffile->param[target]];
-								break;
-							}
-
-							/* With an operation of 2 or 3, we want to reserve a specific block of IDs */
-							if (op == 2 || op == 3) start = _cur_grffile->param[target];
-
-							for (uint i = start; i < _vehcounts[feature]; i++) {
-								if (_grm_engines[shift + i] == 0) {
-									size++;
-								} else {
-									if (op == 2 || op == 3) break;
-									start = i + 1;
-									size = 0;
-								}
-
-								if (size == count) break;
-							}
-
-							if (size == count) {
-								/* Got the slot... */
-								if (op == 0 || op == 3) {
-									grfmsg(2, "ParamSet: GRM: Reserving %d vehicles at %d", count, start);
-									for (uint i = 0; i < count; i++) _grm_engines[shift + start + i] = _cur_grffile->grfid;
-								}
-								src1 = start;
-							} else {
-								/* Unable to allocate */
-								if (op != 4 && op != 5) {
-									/* Deactivate GRF */
-									grfmsg(0, "ParamSet: GRM: Unable to allocate %d vehicles, deactivating", count);
-									_cur_grfconfig->status = GCS_DISABLED;
-
-									_skip_sprites = -1;
-									return;
-								}
-
-								grfmsg(1, "ParamSet: GRM: Unable to allocate %d vehicles", count);
-								src1 = UINT_MAX;
-							}
+							src1 = PerformGRM(&_grm_engines[_vehshifts[feature]], _vehcounts[feature], count, op, target, "vehicles");
+							if (_skip_sprites == -1) return;
 							break;
-						}
 
 						case 0x08: // General sprites
 							switch (op) {
@@ -3676,6 +3700,11 @@
 							}
 							break;
 
+						case 0x0B: // Cargo
+							src1 = PerformGRM(_grm_cargos, NUM_CARGO, count, op, target, "cargos");
+							if (_skip_sprites == -1) return;
+							break;
+
 						default: grfmsg(1, "ParamSet: GRM: Unsupported feature 0x%X", feature); return;
 					}
 				}
@@ -4237,10 +4266,10 @@
 	                   |                                        (1 << 0x11)  // autoreplace
 	                   |                                        (1 << 0x12)  // autoslope
 	                   |                                        (0 << 0x13)  // followvehicle
-	                   |                                        (0 << 0x14)  // trams
+	                   |                                        (1 << 0x14)  // trams
 	                   |                                        (0 << 0x15)  // enhancetunnels
-	                   |                                        (0 << 0x16)  // shortrvs
-	                   |                                        (0 << 0x17)  // articulatedrvs
+	                   |                                        (1 << 0x16)  // shortrvs
+	                   |                                        (1 << 0x17)  // articulatedrvs
 	                   |                                        (1 << 0x1E); // variablerunningcosts
 }
 
@@ -4289,13 +4318,70 @@
 
 	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;
 	}
 }
 
+static void ResetCustomIndustries()
+{
+	GRFFile *file;
+
+	for (file = _first_grffile; file != NULL; file = file->next) {
+		uint i;
+		/* We are verifiying both tiles and industries specs loaded from the grf file
+		 * First, let's deal with industryspec */
+		if (file->industryspec != NULL) {
+
+			for (i = 0; i < NUM_INDUSTRYTYPES; i++) {
+				IndustrySpec *ind = file->industryspec[i];
+
+				if (ind != NULL) {
+					/* We need to remove the sounds array */
+					if (HASBIT(ind->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
+						free((void*)ind->random_sounds);
+					}
+
+					/* We need to remove the tiles layouts */
+					if (HASBIT(ind->cleanup_flag, CLEAN_TILELSAYOUT) && ind->table != NULL) {
+						for (int j = 0; j < ind->num_table; j++) {
+							/* remove the individual layouts */
+							if (ind->table[j] != NULL) {
+								free((IndustryTileTable*)ind->table[j]);
+							}
+						}
+						/* remove the layouts pointers */
+						free((IndustryTileTable**)ind->table);
+						ind->table = NULL;
+					}
+
+					free(ind);
+					ind = NULL;
+				}
+			}
+
+			free(file->industryspec);
+			file->industryspec = NULL;
+		}
+
+		if (file->indtspec != NULL) {
+			for (i = 0; i < NUM_INDUSTRYTILES; i++) {
+				if (file->indtspec[i] != NULL) {
+					free(file->indtspec[i]);
+					file->indtspec[i] = NULL;
+				}
+			}
+
+			free(file->indtspec);
+			file->indtspec = NULL;
+		}
+	}
+}
+
 static void ResetNewGRF()
 {
 	GRFFile *next;
@@ -4304,6 +4390,7 @@
 		next = f->next;
 
 		free(f->filename);
+		free(f->cargo_list);
 		free(f);
 	}
 
@@ -4342,6 +4429,7 @@
 
 	/* Reset GRM reservations */
 	memset(&_grm_engines, 0, sizeof(_grm_engines));
+	memset(&_grm_cargos, 0, sizeof(_grm_cargos));
 
 	/* Unload sprite group data */
 	UnloadWagonOverrides();
@@ -4360,6 +4448,10 @@
 	ResetCustomHouses();
 	ResetHouses();
 
+	/* Reset the industries structures*/
+	ResetCustomIndustries();
+	ResetIndustries();
+
 	/* Reset station classes */
 	ResetStationClasses();
 	ResetCustomStations();
@@ -4383,8 +4475,9 @@
 	_misc_grf_features = 0;
 	_traininfo_vehicle_pitch = 0;
 	_traininfo_vehicle_width = 29;
-	_have_2cc = false;
-	_have_newhouses = false;
+
+	_loaded_newgrf_features = 0;
+
 	_signal_base = 0;
 	_coast_base = 0;
 
@@ -4669,7 +4762,7 @@
 		/* 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, },
@@ -4738,6 +4831,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;
 	}
 
@@ -4807,6 +4901,13 @@
 
 static void AfterLoadGRFs()
 {
+	/* Update the bitmasks for the vehicle lists */
+	Player *p;
+	FOR_ALL_PLAYERS(p) {
+		p->avail_railtypes = GetPlayerRailtypes(p->index);
+		p->avail_roadtypes = GetPlayerRoadtypes(p->index);
+	}
+
 	/* Pre-calculate all refit masks after loading GRF files. */
 	CalculateRefitMasks();
 
@@ -4842,11 +4943,13 @@
 			if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
 
 			/* @todo usererror() */
-			if (!FileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename);
+			if (!FioCheckFileExists(c->full_path)) 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);