src/spritecache.cpp
branchgamebalance
changeset 9913 e79cd19772dd
parent 9912 1ac8aac92385
--- a/src/spritecache.cpp	Wed Jun 13 12:05:56 2007 +0000
+++ b/src/spritecache.cpp	Tue Jun 19 07:21:01 2007 +0000
@@ -4,6 +4,8 @@
 
 #include "stdafx.h"
 #include "openttd.h"
+#include "variables.h"
+#include "string.h"
 #include "debug.h"
 #include "functions.h"
 #include "macros.h"
@@ -12,7 +14,10 @@
 #include "fileio.h"
 #include "helpers.hpp"
 #include "spriteloader/grf.hpp"
-#include "blitter/blitter.hpp"
+#ifdef WITH_PNG
+#include "spriteloader/png.hpp"
+#endif /* WITH_PNG */
+#include "blitter/factory.hpp"
 
 /* Default of 4MB spritecache */
 uint _sprite_cache_size = 4;
@@ -22,6 +27,8 @@
 	void *ptr;
 	uint32 file_pos;
 	int16 lru;
+	uint32 id;
+	const char *grf_name;
 };
 
 
@@ -118,7 +125,7 @@
 
 void* AllocSprite(size_t);
 
-static void* ReadSprite(SpriteCache *sc, SpriteID id)
+static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
 {
 	uint32 file_pos = sc->file_pos;
 
@@ -132,6 +139,28 @@
 		file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos;
 	}
 
+	if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) {
+#ifdef WITH_PNG
+		/* Try loading 32bpp graphics in case we are 32bpp output */
+		SpriteLoaderPNG sprite_loader;
+		SpriteLoader::Sprite sprite;
+
+		if (sprite_loader.LoadSprite(&sprite, sc->grf_name, sc->id)) {
+			sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
+			free(sprite.data);
+
+			return sc->ptr;
+		}
+		/* If the PNG couldn't be loaded, fall back to 8bpp grfs */
+#else
+		static bool show_once = true;
+		if (show_once) {
+			DEBUG(misc, 0, "You are running a 32bpp blitter, but this build is without libpng support; falling back to 8bpp graphics");
+			show_once = false;
+		}
+#endif /* WITH_PNG */
+	}
+
 	FioSeekToFile(file_pos);
 
 	/* Read the size and type */
@@ -139,18 +168,71 @@
 	byte type = FioReadByte();
 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
 	if (type == 0xFF) {
+		if (real_sprite) {
+			static byte warning_level = 0;
+			DEBUG(sprite, warning_level, "Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id);
+			warning_level = 6;
+			if (id == SPR_IMG_QUERY) error("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?");
+			return (void*)GetSprite(SPR_IMG_QUERY);
+		}
+
 		byte *dest = (byte *)AllocSprite(num);
 
 		sc->ptr = dest;
 		FioReadBlock(dest, num);
 
-		return dest;
+		return sc->ptr;
+	}
+	/* Ugly hack to work around the problem that the old landscape
+	 *  generator assumes that those sprites are stored uncompressed in
+	 *  the memory, and they are only read directly by the code, never
+	 *  send to the blitter. So do not send it to the blitter (which will
+	 *  result in a data array in the format the blitter likes most), but
+	 *  read the data directly from disk and store that as sprite.
+	 * Ugly: yes. Other solution: no. Blame the original author or
+	 *  something ;) The image should really have been a data-stream
+	 *  (so type = 0xFF basicly). */
+	if (id >= 4845 && id <= 4881) {
+		uint height = FioReadByte();
+		uint width  = FioReadWord();
+		Sprite *sprite;
+		byte *dest;
+
+		num = width * height;
+		sprite = (Sprite *)AllocSprite(sizeof(*sprite) + num);
+		sc->ptr = sprite;
+		sprite->height = height;
+		sprite->width  = width;
+		sprite->x_offs = FioReadWord();
+		sprite->y_offs = FioReadWord();
+
+		dest = sprite->data;
+		while (num > 0) {
+			int8 i = FioReadByte();
+			if (i >= 0) {
+				num -= i;
+				for (; i > 0; --i) *dest++ = FioReadByte();
+			} else {
+				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
+				i = -(i >> 3);
+				num -= i;
+				for (; i > 0; --i) *dest++ = *rel++;
+			}
+		}
+
+		return sc->ptr;
+	}
+
+	if (!real_sprite) {
+		static byte warning_level = 0;
+		DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
+		warning_level = 6;
 	}
 
 	SpriteLoaderGrf sprite_loader;
 	SpriteLoader::Sprite sprite;
 
-	if (!sprite_loader.LoadSprite(&sprite, file_pos)) return NULL;
+	if (!sprite_loader.LoadSprite(&sprite, sc->grf_name, file_pos)) return NULL;
 	if (id == 142) sprite.height = 10; // Compensate for a TTD bug
 	sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
 	free(sprite.data);
@@ -159,7 +241,7 @@
 }
 
 
-bool LoadNextSprite(int load_index, byte file_index)
+bool LoadNextSprite(int load_index, byte file_index, uint file_sprite_id)
 {
 	SpriteCache *sc;
 	uint32 file_pos = FioGetPos() | (file_index << 24);
@@ -174,6 +256,20 @@
 	sc->file_pos = file_pos;
 	sc->ptr = NULL;
 	sc->lru = 0;
+	sc->id = file_sprite_id;
+
+	const char *fio_grf_name = FioGetFilename();
+	const char *t = strrchr(fio_grf_name, PATHSEPCHAR);
+	char *grf_name;
+	if (t == NULL) grf_name = strdup(fio_grf_name);
+	else           grf_name = strdup(t);
+	/* Make the string lowercase and strip extension */
+	char *t2 = strrchr(grf_name, '.');
+	if (t2 != NULL) *t2 = '\0';
+	strtolower(grf_name);
+
+	free((char *)sc->grf_name);
+	sc->grf_name = grf_name;
 
 	return true;
 }
@@ -186,6 +282,8 @@
 
 	scnew->file_pos = scold->file_pos;
 	scnew->ptr = NULL;
+	scnew->id = scold->id;
+	scnew->grf_name = strdup(scold->grf_name);
 }
 
 
@@ -364,7 +462,7 @@
 }
 
 
-const void *GetRawSprite(SpriteID sprite)
+const void *GetRawSprite(SpriteID sprite, bool real_sprite)
 {
 	SpriteCache *sc;
 	void* p;
@@ -379,7 +477,7 @@
 	p = sc->ptr;
 
 	/* Load the sprite, if it is not loaded, yet */
-	if (p == NULL) p = ReadSprite(sc, sprite);
+	if (p == NULL) p = ReadSprite(sc, sprite, real_sprite);
 	return p;
 }