(svn r12958) -Codechange: Allocate sprites reserved by GRM in advance of 'Action 1' sprites, giving much less chance of GRM reservation failure if lots of NewGRF sets are loaded.
authorpeter1138
Mon, 05 May 2008 19:02:10 +0000
changeset 10416 96e869d65b9c
parent 10415 53ed7c3b441c
child 10417 6956db57fb1e
(svn r12958) -Codechange: Allocate sprites reserved by GRM in advance of 'Action 1' sprites, giving much less chance of GRM reservation failure if lots of NewGRF sets are loaded.
src/newgrf.cpp
--- a/src/newgrf.cpp	Mon May 05 18:27:57 2008 +0000
+++ b/src/newgrf.cpp	Mon May 05 19:02:10 2008 +0000
@@ -118,6 +118,20 @@
 /* Contains the GRF ID of the owner of a cargo if it has been reserved */
 static uint32 _grm_cargos[NUM_CARGO * 2];
 
+struct GRMSpriteEntry {
+	uint32 grfid;
+	uint32 nfoline;
+
+	GRMSpriteEntry(uint32 grfid, uint32 nfoline) : grfid(grfid), nfoline(nfoline) { }
+
+	bool operator<(const GRMSpriteEntry &other) const
+	{
+		return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline);
+	}
+};
+
+static std::map<GRMSpriteEntry, SpriteID> _grm_sprites;
+
 /** 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.
@@ -4355,14 +4369,32 @@
 				src1 = GetPatchVariable(src1);
 			} else {
 				/* GRF Resource Management */
-				if (_cur_stage != GLS_ACTIVATION) {
-					/* Ignore GRM during initialization */
+				uint8  op      = src1;
+				uint8  feature = GB(data, 8, 8);
+				uint16 count   = GB(data, 16, 16);
+
+				if (_cur_stage == GLS_RESERVE) {
+					if (feature == 0x08) {
+						/* General sprites */
+						if (op == 0) {
+							/* Check if the allocated sprites will fit below the original sprite limit */
+							if (_cur_spriteid + count >= 16384) {
+								grfmsg(0, "ParamSet: GRM: Unable to allocate %d sprites; try changing NewGRF order", count);
+								_cur_grfconfig->status = GCS_DISABLED;
+
+								_skip_sprites = -1;
+								return;
+							}
+
+							/* Reserve space at the current sprite ID */
+							grfmsg(4, "ParamSet: GRM: Allocated %d sprites at %d", count, _cur_spriteid);
+							_grm_sprites[GRMSpriteEntry(_cur_grffile->grfid, _nfo_line)] = _cur_spriteid;
+							_cur_spriteid += count;
+						}
+					}
+					/* Ignore GRM result during reservation */
 					src1 = 0;
-				} else {
-					uint8  op      = src1;
-					uint8  feature = GB(data, 8, 8);
-					uint16 count   = GB(data, 16, 16);
-
+				} else if (_cur_stage == GLS_ACTIVATION) {
 					switch (feature) {
 						case 0x00: // Trains
 						case 0x01: // Road Vehicles
@@ -4389,18 +4421,9 @@
 						case 0x08: // General sprites
 							switch (op) {
 								case 0:
-									/* Check if the allocated sprites will fit below the original sprite limit */
-									if (_cur_spriteid + count >= 16384) {
-										grfmsg(0, "ParamSet: GRM: Unable to allocate %d sprites; try changing NewGRF order", count);
-										_cur_grfconfig->status = GCS_DISABLED;
-
-										_skip_sprites = -1;
-										return;
-									}
-
-									/* 'Reserve' space at the current sprite ID */
-									src1 = _cur_spriteid;
-									_cur_spriteid += count;
+									/* Return space reserved during reservation stage */
+									src1 = _grm_sprites[GRMSpriteEntry(_cur_grffile->grfid, _nfo_line)];
+									grfmsg(4, "ParamSet: GRM: Using pre-allocated sprites at %d", src1);
 									break;
 
 								case 1:
@@ -4421,6 +4444,9 @@
 
 						default: grfmsg(1, "ParamSet: GRM: Unsupported feature 0x%X", feature); return;
 					}
+				} else {
+					/* Ignore GRM during initialization */
+					src1 = 0;
 				}
 			}
 		} else {
@@ -5935,6 +5961,7 @@
 
 	/* Deallocate temporary loading data */
 	free(_gted);
+	_grm_sprites.clear();
 }
 
 void LoadNewGRF(uint load_index, uint file_index)
@@ -5954,6 +5981,8 @@
 		if (c->status != GCS_NOT_FOUND) c->status = GCS_UNKNOWN;
 	}
 
+	_cur_spriteid = load_index;
+
 	/* Load newgrf sprites
 	 * in each loading stage, (try to) open each file specified in the config
 	 * and load information from it. */
@@ -5967,7 +5996,6 @@
 		uint slot = file_index;
 
 		_cur_stage = stage;
-		_cur_spriteid = load_index;
 		for (GRFConfig *c = _grfconfig; c != NULL; c = c->next) {
 			if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue;
 			if (stage > GLS_INIT && HasBit(c->flags, GCF_INIT_ONLY)) continue;