(svn r556) -newgrf: Some seemingly proper support for loading stages of grf files (octo & pasky).
authordarkvater
Fri, 12 Nov 2004 23:26:02 +0000
changeset 368 32aad6ad36e1
parent 367 d0d895bd4972
child 369 ab2266938fa8
(svn r556) -newgrf: Some seemingly proper support for loading stages of grf files (octo & pasky).
grfspecial.c
spritecache.c
--- a/grfspecial.c	Fri Nov 12 22:39:00 2004 +0000
+++ b/grfspecial.c	Fri Nov 12 23:26:02 2004 +0000
@@ -30,6 +30,7 @@
 
 static struct GRFFile *_cur_grffile, *_first_grffile;
 static int _cur_spriteid;
+static int _cur_stage;
 
 static int32 _paramlist[0x7f];
 static int _param_max;
@@ -77,7 +78,8 @@
 } while (0)
 
 
-static byte INLINE grf_load_byte(byte **buf) {
+static byte INLINE grf_load_byte(byte **buf)
+{
 	return *(*buf)++;
 }
 
@@ -115,19 +117,16 @@
 	return file;
 }
 
-#if 0
-/* Will be used very soon. */
-static struct GRFFile *GetFileByFilename(char *filename)
+static struct GRFFile *GetFileByFilename(const char *filename)
 {
 	struct GRFFile *file;
 
 	file = _first_grffile;
 	while ((file != NULL) && strcmp(file->filename, filename))
-		file = retval->next;
+		file = file->next;
 
 	return file;
 }
-#endif
 
 
 typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
@@ -900,7 +899,6 @@
 	 * B condition-type
 	 * V value
 	 * B num-sprites */
-	/* TODO: We only support few tests. */
 	/* TODO: More params. More condition types. */
 	uint8 param;
 	uint8 paramsize;
@@ -933,8 +931,7 @@
 			param_val = _opt.landscape;
 			break;
 		case 0x84:
-			/* XXX: This should be always true (at least until we get multiple loading stages?). */
-			param_val = 1;
+			param_val = _cur_stage;
 			break;
 		case 0x85:
 			param_val = _ttdpatch_flags[cond_val / 0x20];
@@ -1231,7 +1228,6 @@
 	 * B num           Number of GRFIDs that follow
 	 * D grfids        GRFIDs of the files to deactivate */
 	/* XXX: Should we handle forward deactivations? */
-	/* XXX: Even so will fully work only with stages support. */
 
 	byte num;
 	int i;
@@ -1271,7 +1267,8 @@
 		| (1 << 0x17);		/* newstartyear */
 }
 
-void InitNewGRFFile(const char *filename, int sprite_offset) {
+void InitNewGRFFile(const char *filename, int sprite_offset)
+{
 	struct GRFFile *newfile;
 
 	newfile = malloc(sizeof(struct GRFFile));
@@ -1297,12 +1294,12 @@
 
 /* Here we perform initial decoding of some special sprites (as are they
  * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
- * partial implementation yet; also, we ignore the stages stuff). */
+ * partial implementation yet). */
 /* XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
  * a crafted invalid GRF file. We should tell that to the user somehow, or
  * better make this more robust in the future. */
 
-void DecodeSpecialSprite(int num, int spriteid)
+void DecodeSpecialSprite(const char *filename, int num, int spriteid, int stage)
 {
 #define NUM_ACTIONS 0xF
 	static const SpecialSpriteHandler handlers[NUM_ACTIONS] = {
@@ -1334,17 +1331,70 @@
 		initialized = 1;
 	}
 
+	_cur_stage = stage;
 	_cur_spriteid = spriteid;
 
 	for (i = 0; i != num; i++)
 		buf[i] = FioReadByte();
 
 	action = buf[0];
-	if (action < NUM_ACTIONS) {
-		if (_cur_grffile->flags & 0x0001)
+
+	/* XXX: Action 0x03 is temporarily processed together with actions 0x01
+	 * and 0x02 before it is fixed to be reentrant (probably storing the
+	 * superset information in {struct GRFFile}). --pasky */
+
+	if (stage == 0) {
+		/* During initialization, actions 0, 3, 4, 5 and 7 are ignored. */
+
+		if ((action == 0x00) /*|| (action == 0x03)*/ || (action == 0x04)
+		    || (action == 0x05) || (action == 0x07)) {
+			DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 0, Skipped", action);
+			/* Do nothing. */
+
+		} else if (action < NUM_ACTIONS) {
+			DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 0", action);
+ 			handlers[action](buf, num);
+
+		} else {
+			grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
+		}
+
+	} else if (stage == 1) {
+		/* A .grf file is activated only if it was active when the game was
+		 * started.  If a game is loaded, only its active .grfs will be
+		 * reactivated, unless "loadallgraphics on" is used.  A .grf file is
+		 * considered active if its action 8 has been processed, i.e. its
+		 * action 8 hasn't been skipped using an action 7.
+		 *
+		 * During activation, only actions 0, 3, 4, 5, 7, 8, 9 and 0A are
+		 * carried out.  All others are ignored, because they only need to be
+		 * processed once at initialization.  */
+
+		if ((_cur_grffile == NULL) || strcmp(_cur_grffile->filename, filename))
+			_cur_grffile = GetFileByFilename(filename);
+
+		if (_cur_grffile == NULL)
+			error("File ``%s'' lost in cache.\n", filename);
+
+		if (!(_cur_grffile->flags & 0x0001)) {
+			DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1, Not activated", action);
+			/* Do nothing. */
+
+		} else if ((action == 0x00) /*|| (action == 0x03)*/ || (action == 0x04) || (action == 0x05)
+		           || (action == 0x07) || (action == 0x08) || (action == 0x09) || (action == 0x0A)) {
+			DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1", action);
 			handlers[action](buf, num);
+
+		} else if (action < NUM_ACTIONS) {
+			DEBUG (grf, 5) ("DecodeSpecialSprite: Action: %x, Stage 1, Skipped", action);
+			/* Do nothing. */
+
+		} else {
+			grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
+		}
+
 	} else {
-		grfmsg(GMS_WARN, "Unknown special sprite action %x, skipping.", action);
+		error("Invalid stage %d", stage);
 	}
 
 	free(buf);
--- a/spritecache.c	Fri Nov 12 22:39:00 2004 +0000
+++ b/spritecache.c	Fri Nov 12 23:26:02 2004 +0000
@@ -19,6 +19,8 @@
 int _replace_sprites_count[16];
 int _replace_sprites_offset[16];
 
+static const char *_cur_grffile;
+static int _loading_stage;
 static int _skip_specials;
 static SpriteHdr _cur_sprite;
 
@@ -85,7 +87,7 @@
 static void CompactSpriteCache();
 
 void InitNewGRFFile(const char *filename, int sprite_offset);
-void DecodeSpecialSprite(int num, int load_index);
+void DecodeSpecialSprite(const char *filename, int num, int load_index, int stage);
 
 static void ReadSpriteHeaderSkipData(int num, int load_index)
 {
@@ -110,7 +112,7 @@
 		if (_skip_specials || deaf) {
 			FioSkipBytes(num);
 		} else {
-			DecodeSpecialSprite(num, load_index);
+			DecodeSpecialSprite(_cur_grffile, num, load_index, _loading_stage);
 		}
 		return;
 	}
@@ -311,6 +313,7 @@
 	int i;
 	
 	FioOpenFile(file_index, filename);
+	_cur_grffile = filename;
 	_skip_specials = 0;
 	_skip_sprites = 0;
 
@@ -772,6 +775,8 @@
 {
 	int i,j;
 
+	_loading_stage = 1;
+
 	/*
 	 * Note for developers:
 	 *   Keep in mind that when you add a LoadGrfIndexed in the 'if'-section below
@@ -789,6 +794,8 @@
 		// So just load all files from disk..
 
 		int load_index = 0;
+		int old_load_index = 0;
+
 		for(i=0; _filename_list[i] != NULL; i++) {
 			load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i);
 		}
@@ -805,11 +812,23 @@
 
 		load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1;
 
-		for(j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++) {
+
+		/* Load newgrf sprites */
+
+		_loading_stage = 0;
+		old_load_index = load_index;
+
+		for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++) {
 			InitNewGRFFile(_newgrf_files[j], load_index);
 			load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
 		}
 
+		_loading_stage = 1;
+		load_index = old_load_index;
+		for (j = 0; j != lengthof(_newgrf_files) && _newgrf_files[j]; j++)
+			load_index += LoadNewGrfFile(_newgrf_files[j], load_index, i++);
+
+
 		// If needed, save the cache to file
 		HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false);
 	} else {