src/spritecache.cpp
changeset 10056 48659f7d4fa5
parent 10052 f946c7632df2
child 10062 8ec5e3f048b7
equal deleted inserted replaced
10055:b3bf982d7879 10056:48659f7d4fa5
    26 	void *ptr;
    26 	void *ptr;
    27 	size_t file_pos;
    27 	size_t file_pos;
    28 	uint32 id;
    28 	uint32 id;
    29 	uint16 file_slot;
    29 	uint16 file_slot;
    30 	int16 lru;
    30 	int16 lru;
    31 	bool real_sprite; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as non-real sprite. If the non-real sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
    31 	SpriteType type; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
    32 };
    32 };
    33 
    33 
    34 
    34 
    35 static uint _spritecache_items = 0;
    35 static uint _spritecache_items = 0;
    36 static SpriteCache *_spritecache = NULL;
    36 static SpriteCache *_spritecache = NULL;
   131 	return !(GetSpriteCache(id)->file_pos == 0 && GetSpriteCache(id)->file_slot == 0);
   131 	return !(GetSpriteCache(id)->file_pos == 0 && GetSpriteCache(id)->file_slot == 0);
   132 }
   132 }
   133 
   133 
   134 void* AllocSprite(size_t);
   134 void* AllocSprite(size_t);
   135 
   135 
   136 static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
   136 static void* ReadSprite(SpriteCache *sc, SpriteID id, SpriteType sprite_type)
   137 {
   137 {
   138 	uint8 file_slot = sc->file_slot;
   138 	uint8 file_slot = sc->file_slot;
   139 	size_t file_pos = sc->file_pos;
   139 	size_t file_pos = sc->file_pos;
   140 
   140 
   141 	DEBUG(sprite, 9, "Load sprite %d", id);
   141 	DEBUG(sprite, 9, "Load sprite %d", id);
   147 		id = SPR_IMG_QUERY;
   147 		id = SPR_IMG_QUERY;
   148 		file_slot = GetSpriteCache(SPR_IMG_QUERY)->file_slot;
   148 		file_slot = GetSpriteCache(SPR_IMG_QUERY)->file_slot;
   149 		file_pos  = GetSpriteCache(SPR_IMG_QUERY)->file_pos;
   149 		file_pos  = GetSpriteCache(SPR_IMG_QUERY)->file_pos;
   150 	}
   150 	}
   151 
   151 
   152 	if (real_sprite && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) {
   152 	if (sprite_type == ST_NORMAL && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 32) {
   153 #ifdef WITH_PNG
   153 #ifdef WITH_PNG
   154 		/* Try loading 32bpp graphics in case we are 32bpp output */
   154 		/* Try loading 32bpp graphics in case we are 32bpp output */
   155 		SpriteLoaderPNG sprite_loader;
   155 		SpriteLoaderPNG sprite_loader;
   156 		SpriteLoader::Sprite sprite;
   156 		SpriteLoader::Sprite sprite;
   157 
   157 
   158 		if (sprite_loader.LoadSprite(&sprite, file_slot, sc->id)) {
   158 		if (sprite_loader.LoadSprite(&sprite, file_slot, sc->id, sprite_type)) {
   159 			sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   159 			sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   160 			free(sprite.data);
   160 			free(sprite.data);
   161 
   161 
   162 			sc->real_sprite = real_sprite;
   162 			sc->type = sprite_type;
   163 
   163 
   164 			return sc->ptr;
   164 			return sc->ptr;
   165 		}
   165 		}
   166 		/* If the PNG couldn't be loaded, fall back to 8bpp grfs */
   166 		/* If the PNG couldn't be loaded, fall back to 8bpp grfs */
   167 #else
   167 #else
   178 	/* Read the size and type */
   178 	/* Read the size and type */
   179 	int num  = FioReadWord();
   179 	int num  = FioReadWord();
   180 	byte type = FioReadByte();
   180 	byte type = FioReadByte();
   181 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
   181 	/* Type 0xFF indicates either a colormap or some other non-sprite info */
   182 	if (type == 0xFF) {
   182 	if (type == 0xFF) {
   183 		if (real_sprite) {
   183 		if (sprite_type != ST_RECOLOUR) {
   184 			static byte warning_level = 0;
   184 			static byte warning_level = 0;
   185 			DEBUG(sprite, warning_level, "Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id);
   185 			DEBUG(sprite, warning_level, "Tried to load recolour sprite #%d as a real sprite. Probable cause: NewGRF interference", id);
   186 			warning_level = 6;
   186 			warning_level = 6;
   187 			if (id == SPR_IMG_QUERY) usererror("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?");
   187 			if (id == SPR_IMG_QUERY) usererror("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a recolour-sprite?");
   188 			return (void*)GetRawSprite(SPR_IMG_QUERY, true);
   188 			return (void*)GetRawSprite(SPR_IMG_QUERY, ST_NORMAL);
   189 		}
   189 		}
   190 
   190 
   191 		byte *dest = (byte *)AllocSprite(num);
   191 		byte *dest = (byte *)AllocSprite(num);
   192 
   192 
   193 		sc->ptr = dest;
   193 		sc->ptr = dest;
   194 		sc->real_sprite = real_sprite;
   194 		sc->type = sprite_type;
   195 		FioReadBlock(dest, num);
   195 		FioReadBlock(dest, num);
   196 
   196 
   197 		return sc->ptr;
   197 		return sc->ptr;
   198 	}
   198 	}
   199 	/* Ugly hack to work around the problem that the old landscape
   199 	/* Ugly hack to work around the problem that the old landscape
   203 	 *  result in a data array in the format the blitter likes most), but
   203 	 *  result in a data array in the format the blitter likes most), but
   204 	 *  read the data directly from disk and store that as sprite.
   204 	 *  read the data directly from disk and store that as sprite.
   205 	 * Ugly: yes. Other solution: no. Blame the original author or
   205 	 * Ugly: yes. Other solution: no. Blame the original author or
   206 	 *  something ;) The image should really have been a data-stream
   206 	 *  something ;) The image should really have been a data-stream
   207 	 *  (so type = 0xFF basicly). */
   207 	 *  (so type = 0xFF basicly). */
   208 	if (id >= 4845 && id <= 4881) {
   208 	assert((id >= 4845 && id <= 4881) == (sprite_type == ST_MAPGEN));
   209 		assert(real_sprite);
   209 	if (sprite_type == ST_MAPGEN) {
   210 		uint height = FioReadByte();
   210 		uint height = FioReadByte();
   211 		uint width  = FioReadWord();
   211 		uint width  = FioReadWord();
   212 		Sprite *sprite;
   212 		Sprite *sprite;
   213 		byte *dest;
   213 		byte *dest;
   214 
   214 
   232 				num -= i;
   232 				num -= i;
   233 				for (; i > 0; --i) *dest++ = *rel++;
   233 				for (; i > 0; --i) *dest++ = *rel++;
   234 			}
   234 			}
   235 		}
   235 		}
   236 
   236 
   237 		sc->real_sprite = real_sprite;
   237 		sc->type = sprite_type;
   238 
   238 
   239 		return sc->ptr;
   239 		return sc->ptr;
   240 	}
   240 	}
   241 
   241 
   242 	if (!real_sprite) {
   242 	if (sprite_type == ST_RECOLOUR) {
   243 		static byte warning_level = 0;
   243 		static byte warning_level = 0;
   244 		DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
   244 		DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a recolour sprite. Probable cause: NewGRF interference", id);
   245 		warning_level = 6;
   245 		warning_level = 6;
   246 		return (void*)GetRawSprite(id, true);
   246 		return (void*)GetRawSprite(id, ST_NORMAL);
   247 	}
   247 	}
   248 
   248 
   249 	SpriteLoaderGrf sprite_loader;
   249 	SpriteLoaderGrf sprite_loader;
   250 	SpriteLoader::Sprite sprite;
   250 	SpriteLoader::Sprite sprite;
   251 
   251 
   252 	sc->real_sprite = real_sprite;
   252 	sc->type = sprite_type;
   253 
   253 
   254 	if (!sprite_loader.LoadSprite(&sprite, file_slot, file_pos)) return NULL;
   254 	if (!sprite_loader.LoadSprite(&sprite, file_slot, file_pos, sprite_type)) return NULL;
   255 	sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   255 	sc->ptr = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, &AllocSprite);
   256 	free(sprite.data);
   256 	free(sprite.data);
   257 
   257 
   258 	return sc->ptr;
   258 	return sc->ptr;
   259 }
   259 }
   274 	sc->file_slot = file_slot;
   274 	sc->file_slot = file_slot;
   275 	sc->file_pos = file_pos;
   275 	sc->file_pos = file_pos;
   276 	sc->ptr = NULL;
   276 	sc->ptr = NULL;
   277 	sc->lru = 0;
   277 	sc->lru = 0;
   278 	sc->id = file_sprite_id;
   278 	sc->id = file_sprite_id;
   279 	sc->real_sprite = false;
   279 	sc->type = ST_NORMAL;
   280 
   280 
   281 	return true;
   281 	return true;
   282 }
   282 }
   283 
   283 
   284 
   284 
   289 
   289 
   290 	scnew->file_slot = scold->file_slot;
   290 	scnew->file_slot = scold->file_slot;
   291 	scnew->file_pos = scold->file_pos;
   291 	scnew->file_pos = scold->file_pos;
   292 	scnew->ptr = NULL;
   292 	scnew->ptr = NULL;
   293 	scnew->id = scold->id;
   293 	scnew->id = scold->id;
   294 	scnew->real_sprite = scold->real_sprite;
   294 	scnew->type = scold->type;
   295 }
   295 }
   296 
   296 
   297 
   297 
   298 #define S_FREE_MASK 1
   298 #define S_FREE_MASK 1
   299 
   299 
   459 		DeleteEntryFromSpriteCache();
   459 		DeleteEntryFromSpriteCache();
   460 	}
   460 	}
   461 }
   461 }
   462 
   462 
   463 
   463 
   464 const void *GetRawSprite(SpriteID sprite, bool real_sprite)
   464 const void *GetRawSprite(SpriteID sprite, SpriteType type)
   465 {
   465 {
   466 	SpriteCache *sc;
   466 	SpriteCache *sc;
   467 	void* p;
   467 	void* p;
   468 
   468 
   469 	assert(sprite < _spritecache_items);
   469 	assert(sprite < _spritecache_items);
   474 	sc->lru = ++_sprite_lru_counter;
   474 	sc->lru = ++_sprite_lru_counter;
   475 
   475 
   476 	p = sc->ptr;
   476 	p = sc->ptr;
   477 
   477 
   478 	/* Load the sprite, if it is not loaded, yet */
   478 	/* Load the sprite, if it is not loaded, yet */
   479 	if (p == NULL || sc->real_sprite != real_sprite) p = ReadSprite(sc, sprite, real_sprite);
   479 	if (p == NULL || sc->type != type) p = ReadSprite(sc, sprite, type);
   480 
   480 
   481 	return p;
   481 	return p;
   482 }
   482 }
   483 
   483 
   484 
   484