changeset 4961:b6a4791bc3c1 draft

(svn r6960) - Feature: NewGRF: Implement some support for GRF Resource Management (GRM)
author peter1138 <peter1138@openttd.org>
date Fri, 27 Oct 2006 13:15:21 +0000
parents 332b6729aa40
children 10d41b6df880
files newgrf.c
diffstat 1 files changed, 98 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/newgrf.c
+++ b/newgrf.c
@@ -90,14 +90,14 @@
 
 typedef void (*SpecialSpriteHandler)(byte *buf, int len);
 
-static const int _vehcounts[4] = {
+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 int _vehshifts[4] = {
+static const uint _vehshifts[4] = {
 	/* GSF_TRAIN */    0,
 	/* GSF_ROAD */     ROAD_ENGINES_INDEX,
 	/* GSF_SHIP */     SHIP_ENGINES_INDEX,
@@ -111,6 +111,9 @@
 static uint16 cargo_allowed[TOTAL_NUM_ENGINES];
 static uint16 cargo_disallowed[TOTAL_NUM_ENGINES];
 
+/* Contains the GRF ID of the owner of a vehicle if it has been reserved */
+static uint32 _grm_engines[TOTAL_NUM_ENGINES];
+
 /* Debugging messages policy:
  *
  * These should be the severities used for direct DEBUG() calls
@@ -2595,8 +2598,91 @@
 				return;
 			} else {
 				/* GRF Resource Management */
-				grfmsg(GMS_NOTICE, "ParamSet: GRF Resource Management unsupported.");
-				return;
+				if (_cur_stage != 2) {
+					/* Ignore GRM during initialization */
+					src1 = 0;
+				} else {
+					uint8  op      = src1;
+					uint8  feature = GB(data, 8, 8);
+					uint16 count   = GB(data, 16, 16);
+
+					switch (feature) {
+						case 0x00: /* Trains */
+						case 0x01: /* Road Vehicles */
+						case 0x02: /* Ships */
+						case 0x03: /* Aircraft */
+						{
+							uint start = 0;
+							uint size  = 0;
+							uint shift = _vehshifts[feature];
+							uint i;
+
+							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 (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(GMS_NOTICE, "GRM: Reserving %d vehicles at %d", count, start);
+									for (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(GMS_FATAL, "GRM: Unable to allocate %d vehicles, deactivating", count);
+									SETBIT(_cur_grffile->flags, 2);
+									return;
+								}
+
+								grfmsg(GMS_WARN, "GRM: Unable to allocate %d vehicles", count);
+								src1 = -1;
+							}
+							break;
+						}
+
+						case 0x08: /* General sprites */
+							switch (op) {
+								case 0:
+									/* 'Reserve' space at the current sprite ID */
+									src1 = _cur_spriteid;
+									_cur_spriteid += count;
+									break;
+
+								case 1:
+									src1 = _cur_spriteid;
+									break;
+
+								default:
+									grfmsg(GMS_WARN, "GRM: Unsupported operation %d for general sprites", op);
+									return;
+							}
+							break;
+
+						default:
+							grfmsg(GMS_WARN, "GRM: Unsupported feature 0x%X", feature);
+							return;
+					}
+				}
 			}
 		} else {
 			/* Read another GRF File's parameter */
@@ -3116,6 +3202,9 @@
 	memset(&cargo_allowed, 0, sizeof(cargo_allowed));
 	memset(&cargo_disallowed, 0, sizeof(cargo_disallowed));
 
+	// Reset GRM reservations
+	memset(&_grm_engines, 0, sizeof(_grm_engines));
+
 	// Unload sprite group data
 	UnloadWagonOverrides();
 	UnloadRotorOverrideSprites();
@@ -3361,6 +3450,11 @@
 		if (type == 0xFF) {
 			if (_skip_sprites == 0) {
 				DecodeSpecialSprite(num, stage);
+				if (HASBIT(_cur_grffile->flags, 2)) {
+					/* GRF has been deactivated... */
+					CLRBIT(_cur_grffile->flags, 1);
+					return;
+				}
 				continue;
 			} else {
 				FioSkipBytes(num);