src/spritecache.cpp
branchgamebalance
changeset 9913 e79cd19772dd
parent 9912 1ac8aac92385
equal deleted inserted replaced
9912:1ac8aac92385 9913:e79cd19772dd
     2 
     2 
     3 /** @file spritecache.cpp */
     3 /** @file spritecache.cpp */
     4 
     4 
     5 #include "stdafx.h"
     5 #include "stdafx.h"
     6 #include "openttd.h"
     6 #include "openttd.h"
       
     7 #include "variables.h"
       
     8 #include "string.h"
     7 #include "debug.h"
     9 #include "debug.h"
     8 #include "functions.h"
    10 #include "functions.h"
     9 #include "macros.h"
    11 #include "macros.h"
    10 #include "spritecache.h"
    12 #include "spritecache.h"
    11 #include "table/sprites.h"
    13 #include "table/sprites.h"
    12 #include "fileio.h"
    14 #include "fileio.h"
    13 #include "helpers.hpp"
    15 #include "helpers.hpp"
    14 #include "spriteloader/grf.hpp"
    16 #include "spriteloader/grf.hpp"
    15 #include "blitter/blitter.hpp"
    17 #ifdef WITH_PNG
       
    18 #include "spriteloader/png.hpp"
       
    19 #endif /* WITH_PNG */
       
    20 #include "blitter/factory.hpp"
    16 
    21 
    17 /* Default of 4MB spritecache */
    22 /* Default of 4MB spritecache */
    18 uint _sprite_cache_size = 4;
    23 uint _sprite_cache_size = 4;
    19 
    24 
    20 
    25 
    21 struct SpriteCache {
    26 struct SpriteCache {
    22 	void *ptr;
    27 	void *ptr;
    23 	uint32 file_pos;
    28 	uint32 file_pos;
    24 	int16 lru;
    29 	int16 lru;
       
    30 	uint32 id;
       
    31 	const char *grf_name;
    25 };
    32 };
    26 
    33 
    27 
    34 
    28 static uint _spritecache_items = 0;
    35 static uint _spritecache_items = 0;
    29 static SpriteCache *_spritecache = NULL;
    36 static SpriteCache *_spritecache = NULL;
   116 	return GetSpriteCache(id)->file_pos != 0;
   123 	return GetSpriteCache(id)->file_pos != 0;
   117 }
   124 }
   118 
   125 
   119 void* AllocSprite(size_t);
   126 void* AllocSprite(size_t);
   120 
   127 
   121 static void* ReadSprite(SpriteCache *sc, SpriteID id)
   128 static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
   122 {
   129 {
   123 	uint32 file_pos = sc->file_pos;
   130 	uint32 file_pos = sc->file_pos;
   124 
   131 
   125 	DEBUG(sprite, 9, "Load sprite %d", id);
   132 	DEBUG(sprite, 9, "Load sprite %d", id);
   126 
   133 
   128 		DEBUG(sprite, 1, "Tried to load non-existing sprite #%d. Probable cause: Wrong/missing NewGRFs", id);
   135 		DEBUG(sprite, 1, "Tried to load non-existing sprite #%d. Probable cause: Wrong/missing NewGRFs", id);
   129 
   136 
   130 		/* SPR_IMG_QUERY is a BIG FAT RED ? */
   137 		/* SPR_IMG_QUERY is a BIG FAT RED ? */
   131 		id = SPR_IMG_QUERY;
   138 		id = SPR_IMG_QUERY;
   132 		file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos;
   139 		file_pos = GetSpriteCache(SPR_IMG_QUERY)->file_pos;
       
   140 	}
       
   141 
       
   142 	if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) {
       
   143 #ifdef WITH_PNG
       
   144 		/* Try loading 32bpp graphics in case we are 32bpp output */
       
   145 		SpriteLoaderPNG sprite_loader;
       
   146 		SpriteLoader::Sprite sprite;
       
   147 
       
   148 		if (sprite_loader.LoadSprite(&sprite, sc->grf_name, sc->id)) {
       
   149 			sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
       
   150 			free(sprite.data);
       
   151 
       
   152 			return sc->ptr;
       
   153 		}
       
   154 		/* If the PNG couldn't be loaded, fall back to 8bpp grfs */
       
   155 #else
       
   156 		static bool show_once = true;
       
   157 		if (show_once) {
       
   158 			DEBUG(misc, 0, "You are running a 32bpp blitter, but this build is without libpng support; falling back to 8bpp graphics");
       
   159 			show_once = false;
       
   160 		}
       
   161 #endif /* WITH_PNG */
   133 	}
   162 	}
   134 
   163 
   135 	FioSeekToFile(file_pos);
   164 	FioSeekToFile(file_pos);
   136 
   165 
   137 	/* Read the size and type */
   166 	/* Read the size and type */
   138 	int num  = FioReadWord();
   167 	int num  = FioReadWord();
   139 	byte type = FioReadByte();
   168 	byte type = FioReadByte();
   140 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
   169 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
   141 	if (type == 0xFF) {
   170 	if (type == 0xFF) {
       
   171 		if (real_sprite) {
       
   172 			static byte warning_level = 0;
       
   173 			DEBUG(sprite, warning_level, "Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id);
       
   174 			warning_level = 6;
       
   175 			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?");
       
   176 			return (void*)GetSprite(SPR_IMG_QUERY);
       
   177 		}
       
   178 
   142 		byte *dest = (byte *)AllocSprite(num);
   179 		byte *dest = (byte *)AllocSprite(num);
   143 
   180 
   144 		sc->ptr = dest;
   181 		sc->ptr = dest;
   145 		FioReadBlock(dest, num);
   182 		FioReadBlock(dest, num);
   146 
   183 
   147 		return dest;
   184 		return sc->ptr;
       
   185 	}
       
   186 	/* Ugly hack to work around the problem that the old landscape
       
   187 	 *  generator assumes that those sprites are stored uncompressed in
       
   188 	 *  the memory, and they are only read directly by the code, never
       
   189 	 *  send to the blitter. So do not send it to the blitter (which will
       
   190 	 *  result in a data array in the format the blitter likes most), but
       
   191 	 *  read the data directly from disk and store that as sprite.
       
   192 	 * Ugly: yes. Other solution: no. Blame the original author or
       
   193 	 *  something ;) The image should really have been a data-stream
       
   194 	 *  (so type = 0xFF basicly). */
       
   195 	if (id >= 4845 && id <= 4881) {
       
   196 		uint height = FioReadByte();
       
   197 		uint width  = FioReadWord();
       
   198 		Sprite *sprite;
       
   199 		byte *dest;
       
   200 
       
   201 		num = width * height;
       
   202 		sprite = (Sprite *)AllocSprite(sizeof(*sprite) + num);
       
   203 		sc->ptr = sprite;
       
   204 		sprite->height = height;
       
   205 		sprite->width  = width;
       
   206 		sprite->x_offs = FioReadWord();
       
   207 		sprite->y_offs = FioReadWord();
       
   208 
       
   209 		dest = sprite->data;
       
   210 		while (num > 0) {
       
   211 			int8 i = FioReadByte();
       
   212 			if (i >= 0) {
       
   213 				num -= i;
       
   214 				for (; i > 0; --i) *dest++ = FioReadByte();
       
   215 			} else {
       
   216 				const byte* rel = dest - (((i & 7) << 8) | FioReadByte());
       
   217 				i = -(i >> 3);
       
   218 				num -= i;
       
   219 				for (; i > 0; --i) *dest++ = *rel++;
       
   220 			}
       
   221 		}
       
   222 
       
   223 		return sc->ptr;
       
   224 	}
       
   225 
       
   226 	if (!real_sprite) {
       
   227 		static byte warning_level = 0;
       
   228 		DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
       
   229 		warning_level = 6;
   148 	}
   230 	}
   149 
   231 
   150 	SpriteLoaderGrf sprite_loader;
   232 	SpriteLoaderGrf sprite_loader;
   151 	SpriteLoader::Sprite sprite;
   233 	SpriteLoader::Sprite sprite;
   152 
   234 
   153 	if (!sprite_loader.LoadSprite(&sprite, file_pos)) return NULL;
   235 	if (!sprite_loader.LoadSprite(&sprite, sc->grf_name, file_pos)) return NULL;
   154 	if (id == 142) sprite.height = 10; // Compensate for a TTD bug
   236 	if (id == 142) sprite.height = 10; // Compensate for a TTD bug
   155 	sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   237 	sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   156 	free(sprite.data);
   238 	free(sprite.data);
   157 
   239 
   158 	return sc->ptr;
   240 	return sc->ptr;
   159 }
   241 }
   160 
   242 
   161 
   243 
   162 bool LoadNextSprite(int load_index, byte file_index)
   244 bool LoadNextSprite(int load_index, byte file_index, uint file_sprite_id)
   163 {
   245 {
   164 	SpriteCache *sc;
   246 	SpriteCache *sc;
   165 	uint32 file_pos = FioGetPos() | (file_index << 24);
   247 	uint32 file_pos = FioGetPos() | (file_index << 24);
   166 
   248 
   167 	if (!ReadSpriteHeaderSkipData()) return false;
   249 	if (!ReadSpriteHeaderSkipData()) return false;
   172 
   254 
   173 	sc = AllocateSpriteCache(load_index);
   255 	sc = AllocateSpriteCache(load_index);
   174 	sc->file_pos = file_pos;
   256 	sc->file_pos = file_pos;
   175 	sc->ptr = NULL;
   257 	sc->ptr = NULL;
   176 	sc->lru = 0;
   258 	sc->lru = 0;
       
   259 	sc->id = file_sprite_id;
       
   260 
       
   261 	const char *fio_grf_name = FioGetFilename();
       
   262 	const char *t = strrchr(fio_grf_name, PATHSEPCHAR);
       
   263 	char *grf_name;
       
   264 	if (t == NULL) grf_name = strdup(fio_grf_name);
       
   265 	else           grf_name = strdup(t);
       
   266 	/* Make the string lowercase and strip extension */
       
   267 	char *t2 = strrchr(grf_name, '.');
       
   268 	if (t2 != NULL) *t2 = '\0';
       
   269 	strtolower(grf_name);
       
   270 
       
   271 	free((char *)sc->grf_name);
       
   272 	sc->grf_name = grf_name;
   177 
   273 
   178 	return true;
   274 	return true;
   179 }
   275 }
   180 
   276 
   181 
   277 
   184 	SpriteCache *scold = GetSpriteCache(old_spr);
   280 	SpriteCache *scold = GetSpriteCache(old_spr);
   185 	SpriteCache *scnew = AllocateSpriteCache(new_spr);
   281 	SpriteCache *scnew = AllocateSpriteCache(new_spr);
   186 
   282 
   187 	scnew->file_pos = scold->file_pos;
   283 	scnew->file_pos = scold->file_pos;
   188 	scnew->ptr = NULL;
   284 	scnew->ptr = NULL;
       
   285 	scnew->id = scold->id;
       
   286 	scnew->grf_name = strdup(scold->grf_name);
   189 }
   287 }
   190 
   288 
   191 
   289 
   192 void SkipSprites(uint count)
   290 void SkipSprites(uint count)
   193 {
   291 {
   362 		DeleteEntryFromSpriteCache();
   460 		DeleteEntryFromSpriteCache();
   363 	}
   461 	}
   364 }
   462 }
   365 
   463 
   366 
   464 
   367 const void *GetRawSprite(SpriteID sprite)
   465 const void *GetRawSprite(SpriteID sprite, bool real_sprite)
   368 {
   466 {
   369 	SpriteCache *sc;
   467 	SpriteCache *sc;
   370 	void* p;
   468 	void* p;
   371 
   469 
   372 	assert(sprite < _spritecache_items);
   470 	assert(sprite < _spritecache_items);
   377 	sc->lru = ++_sprite_lru_counter;
   475 	sc->lru = ++_sprite_lru_counter;
   378 
   476 
   379 	p = sc->ptr;
   477 	p = sc->ptr;
   380 
   478 
   381 	/* Load the sprite, if it is not loaded, yet */
   479 	/* Load the sprite, if it is not loaded, yet */
   382 	if (p == NULL) p = ReadSprite(sc, sprite);
   480 	if (p == NULL) p = ReadSprite(sc, sprite, real_sprite);
   383 	return p;
   481 	return p;
   384 }
   482 }
   385 
   483 
   386 
   484 
   387 void GfxInitSpriteMem()
   485 void GfxInitSpriteMem()