--- 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;
}