@ -8,7 +8,7 @@
/** @file spritecache.cpp Caching of sprites. */
/** @file spritecache.cpp Caching of sprites. */
# include "stdafx.h"
# include "stdafx.h"
# include " fileio_func .h"
# include " random_access_file_type .h"
# include "spriteloader/grf.hpp"
# include "spriteloader/grf.hpp"
# include "gfx_func.h"
# include "gfx_func.h"
# include "error.h"
# include "error.h"
@ -36,6 +36,7 @@
uint _sprite_cache_size = 4 ;
uint _sprite_cache_size = 4 ;
static size_t _spritecache_bytes_used = 0 ;
static size_t _spritecache_bytes_used = 0 ;
static uint32 _sprite_lru_counter ;
PACK_N ( class SpriteDataBuffer {
PACK_N ( class SpriteDataBuffer {
void * ptr = nullptr ;
void * ptr = nullptr ;
@ -88,11 +89,14 @@ public:
} , 4 ) ;
} , 4 ) ;
PACK_N ( struct SpriteCache {
PACK_N ( struct SpriteCache {
SpriteFile * file ; ///< The file the sprite in this entry can be found in.
size_t file_pos ;
size_t file_pos ;
SpriteDataBuffer buffer ;
SpriteDataBuffer buffer ;
uint32 id ;
uint32 id ;
uint32 lru ;
uint32 lru ;
uint16 file_slot ;
uint count ;
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.
/**
/**
* Bits 6 - 0 : 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 .
* Bits 6 - 0 : 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 .
@ -100,8 +104,6 @@ PACK_N(struct SpriteCache {
*/
*/
byte type_field ;
byte type_field ;
byte container_ver ; ///< Container version of the GRF the sprite is from.
void * GetPtr ( ) { return this - > buffer . GetPtr ( ) ; }
void * GetPtr ( ) { return this - > buffer . GetPtr ( ) ; }
SpriteType GetType ( ) const { return ( SpriteType ) GB ( this - > type_field , 0 , 7 ) ; }
SpriteType GetType ( ) const { return ( SpriteType ) GB ( this - > type_field , 0 , 7 ) ; }
@ -109,10 +111,10 @@ PACK_N(struct SpriteCache {
bool GetWarned ( ) const { return GB ( this - > type_field , 7 , 1 ) ; }
bool GetWarned ( ) const { return GB ( this - > type_field , 7 , 1 ) ; }
void SetWarned ( bool warned ) { SB ( this - > type_field , 7 , 1 , warned ? 1 : 0 ) ; }
void SetWarned ( bool warned ) { SB ( this - > type_field , 7 , 1 , warned ? 1 : 0 ) ; }
} , 4 ) ;
} , 4 ) ;
static_assert ( sizeof ( SpriteCache ) < = 32 ) ;
static std : : vector < SpriteCache > _spritecache ;
static std : : vector < SpriteCache > _spritecache ;
static SpriteDataBuffer _last_sprite_allocation ;
static SpriteDataBuffer _last_sprite_allocation ;
static std : : vector < std : : unique_ptr < SpriteFile > > _sprite_files ;
static inline SpriteCache * GetSpriteCache ( uint index )
static inline SpriteCache * GetSpriteCache ( uint index )
{
{
@ -133,7 +135,37 @@ static SpriteCache *AllocateSpriteCache(uint index)
return GetSpriteCache ( index ) ;
return GetSpriteCache ( index ) ;
}
}
static uint32 _sprite_lru_counter ;
/**
* Get the cached SpriteFile given the name of the file .
* @ param filename The name of the file at the disk .
* @ return The SpriteFile or \ c null .
*/
static SpriteFile * GetCachedSpriteFileByName ( const std : : string & filename ) {
for ( auto & f : _sprite_files ) {
if ( f - > GetFilename ( ) = = filename ) {
return f . get ( ) ;
}
}
return nullptr ;
}
/**
* Open / get the SpriteFile that is cached for use in the sprite cache .
* @ param filename Name of the file at the disk .
* @ param subdir The sub directory to search this file in .
* @ param palette_remap Whether a palette remap needs to be performed for this file .
* @ return The reference to the SpriteCache .
*/
SpriteFile & OpenCachedSpriteFile ( const std : : string & filename , Subdirectory subdir , bool palette_remap )
{
SpriteFile * file = GetCachedSpriteFileByName ( filename ) ;
if ( file = = nullptr ) {
file = _sprite_files . emplace_back ( new SpriteFile ( filename , subdir , palette_remap ) ) . get ( ) ;
} else {
file - > SeekToBegin ( ) ;
}
return * file ;
}
static void * AllocSprite ( size_t mem_req ) ;
static void * AllocSprite ( size_t mem_req ) ;
@ -143,22 +175,22 @@ static void *AllocSprite(size_t mem_req);
* @ param num the amount of sprites to skip
* @ param num the amount of sprites to skip
* @ return true if the data could be correctly skipped .
* @ return true if the data could be correctly skipped .
*/
*/
bool SkipSpriteData ( byte type , uint16 num )
bool SkipSpriteData ( SpriteFile & file , byte type , uint16 num )
{
{
if ( type & 2 ) {
if ( type & 2 ) {
Fio SkipBytes( num ) ;
file. SkipBytes( num ) ;
} else {
} else {
while ( num > 0 ) {
while ( num > 0 ) {
int8 i = Fio ReadByte( ) ;
int8 i = file. ReadByte( ) ;
if ( i > = 0 ) {
if ( i > = 0 ) {
int size = ( i = = 0 ) ? 0x80 : i ;
int size = ( i = = 0 ) ? 0x80 : i ;
if ( size > num ) return false ;
if ( size > num ) return false ;
num - = size ;
num - = size ;
Fio SkipBytes( size ) ;
file. SkipBytes( size ) ;
} else {
} else {
i = - ( i > > 3 ) ;
i = - ( i > > 3 ) ;
num - = i ;
num - = i ;
Fio ReadByte( ) ;
file. ReadByte( ) ;
}
}
}
}
}
}
@ -172,7 +204,7 @@ bool SpriteExists(SpriteID id)
/* Special case for Sprite ID zero -- its position is also 0... */
/* Special case for Sprite ID zero -- its position is also 0... */
if ( id = = 0 ) return true ;
if ( id = = 0 ) return true ;
return ! ( GetSpriteCache ( id ) - > file_pos = = 0 & & GetSpriteCache ( id ) - > file _slot = = 0 ) ;
return ! ( GetSpriteCache ( id ) - > file_pos = = 0 & & GetSpriteCache ( id ) - > file = = nullptr ) ;
}
}
/**
/**
@ -187,14 +219,14 @@ SpriteType GetSpriteType(SpriteID sprite)
}
}
/**
/**
* Get the ( FIOS ) file slot of a given sprite .
* Get the SpriteFile of a given sprite .
* @ param sprite The sprite to look at .
* @ param sprite The sprite to look at .
* @ return the FIOS file slot
* @ return The SpriteFile .
*/
*/
uint GetOriginFileSlot ( SpriteID sprite )
SpriteFile * GetOriginFile ( SpriteID sprite )
{
{
if ( ! SpriteExists ( sprite ) ) return 0 ;
if ( ! SpriteExists ( sprite ) ) return nullptr ;
return GetSpriteCache ( sprite ) - > file _slot ;
return GetSpriteCache ( sprite ) - > file ;
}
}
/**
/**
@ -209,19 +241,22 @@ uint32 GetSpriteLocalID(SpriteID sprite)
}
}
/**
/**
* Count the sprites which originate from a specific file slot in a range of SpriteIDs .
* Count the sprites which originate from a specific file in a range of SpriteIDs .
* @ param file _slot FIOS file slot .
* @ param file The loaded SpriteFile .
* @ param begin First sprite in range .
* @ param begin First sprite in range .
* @ param end First sprite not in range .
* @ param end First sprite not in range .
* @ return Number of sprites .
* @ return Number of sprites .
*/
*/
uint GetSpriteCountFor Slot( uint file_slot , SpriteID begin , SpriteID end )
uint GetSpriteCountFor File( const std : : string & filename , SpriteID begin , SpriteID end )
{
{
SpriteFile * file = GetCachedSpriteFileByName ( filename ) ;
if ( file = = nullptr ) return 0 ;
uint count = 0 ;
uint count = 0 ;
for ( SpriteID i = begin ; i ! = end ; i + + ) {
for ( SpriteID i = begin ; i ! = end ; i + + ) {
if ( SpriteExists ( i ) ) {
if ( SpriteExists ( i ) ) {
SpriteCache * sc = GetSpriteCache ( i ) ;
SpriteCache * sc = GetSpriteCache ( i ) ;
if ( sc - > file _slot = = file _slot ) count + + ;
if ( sc - > file = = file ) count + + ;
}
}
}
}
return count ;
return count ;
@ -398,7 +433,7 @@ static bool PadSprites(SpriteLoader::Sprite *sprite, unsigned int sprite_avail,
return true ;
return true ;
}
}
static bool ResizeSprites ( SpriteLoader : : Sprite * sprite , unsigned int sprite_avail , uint32 file_slot , uint32 file_pos , SpriteEncoder * encoder )
static bool ResizeSprites ( SpriteLoader : : Sprite * sprite , unsigned int sprite_avail , SpriteEncoder * encoder )
{
{
/* Create a fully zoomed image if it does not exist */
/* Create a fully zoomed image if it does not exist */
ZoomLevel first_avail = static_cast < ZoomLevel > ( FIND_FIRST_BIT ( sprite_avail ) ) ;
ZoomLevel first_avail = static_cast < ZoomLevel > ( FIND_FIRST_BIT ( sprite_avail ) ) ;
@ -429,11 +464,11 @@ static bool ResizeSprites(SpriteLoader::Sprite *sprite, unsigned int sprite_avai
/**
/**
* Load a recolour sprite into memory .
* Load a recolour sprite into memory .
* @ param file _slot GRF we ' re reading from .
* @ param file GRF we ' re reading from .
* @ param num Size of the sprite in the GRF .
* @ param num Size of the sprite in the GRF .
* @ return Sprite data .
* @ return Sprite data .
*/
*/
static void * ReadRecolourSprite ( uint16 file_slot , uint num )
static void * ReadRecolourSprite ( SpriteFile & file , uint num )
{
{
/* "Normal" recolour sprites are ALWAYS 257 bytes. Then there is a small
/* "Normal" recolour sprites are ALWAYS 257 bytes. Then there is a small
* number of recolour sprites that are 17 bytes that only exist in DOS
* number of recolour sprites that are 17 bytes that only exist in DOS
@ -442,19 +477,19 @@ static void *ReadRecolourSprite(uint16 file_slot, uint num)
static const uint RECOLOUR_SPRITE_SIZE = 257 ;
static const uint RECOLOUR_SPRITE_SIZE = 257 ;
byte * dest = ( byte * ) AllocSprite ( std : : max ( RECOLOUR_SPRITE_SIZE , num ) ) ;
byte * dest = ( byte * ) AllocSprite ( std : : max ( RECOLOUR_SPRITE_SIZE , num ) ) ;
if ( _palette_remap_grf[ file_slot ] ) {
if ( file. NeedsPaletteRemap ( ) ) {
byte * dest_tmp = AllocaM ( byte , std : : max ( RECOLOUR_SPRITE_SIZE , num ) ) ;
byte * dest_tmp = AllocaM ( byte , std : : max ( RECOLOUR_SPRITE_SIZE , num ) ) ;
/* Only a few recolour sprites are less than 257 bytes */
/* Only a few recolour sprites are less than 257 bytes */
if ( num < RECOLOUR_SPRITE_SIZE ) memset ( dest_tmp , 0 , RECOLOUR_SPRITE_SIZE ) ;
if ( num < RECOLOUR_SPRITE_SIZE ) memset ( dest_tmp , 0 , RECOLOUR_SPRITE_SIZE ) ;
Fio ReadBlock( dest_tmp , num ) ;
file. ReadBlock( dest_tmp , num ) ;
/* The data of index 0 is never used; "literal 00" according to the (New)GRF specs. */
/* The data of index 0 is never used; "literal 00" according to the (New)GRF specs. */
for ( uint i = 1 ; i < RECOLOUR_SPRITE_SIZE ; i + + ) {
for ( uint i = 1 ; i < RECOLOUR_SPRITE_SIZE ; i + + ) {
dest [ i ] = _palmap_w2d [ dest_tmp [ _palmap_d2w [ i - 1 ] + 1 ] ] ;
dest [ i ] = _palmap_w2d [ dest_tmp [ _palmap_d2w [ i - 1 ] + 1 ] ] ;
}
}
} else {
} else {
Fio ReadBlock( dest , num ) ;
file. ReadBlock( dest , num ) ;
}
}
return dest ;
return dest ;
@ -474,10 +509,10 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
/* Use current blitter if no other sprite encoder is given. */
/* Use current blitter if no other sprite encoder is given. */
if ( encoder = = nullptr ) encoder = BlitterFactory : : GetCurrentBlitter ( ) ;
if ( encoder = = nullptr ) encoder = BlitterFactory : : GetCurrentBlitter ( ) ;
uint file_slot = sc - > file_slot ;
SpriteFile & file = * sc - > file ;
size_t file_pos = sc - > file_pos ;
size_t file_pos = sc - > file_pos ;
SCOPE_INFO_FMT ( [ & ] , " ReadSprite: pos: " PRINTF_SIZE " , id: %u, slot: %u (%s), type: %u" , file_pos , id , file_slot , FioGetFilename ( file_slot ) , sprite_type ) ;
SCOPE_INFO_FMT ( [ & ] , " ReadSprite: pos: " PRINTF_SIZE " , id: %u, file: (%s), type: %u" , file_pos , id , file . GetSimplifiedFilename ( ) . c_str ( ) , sprite_type ) ;
assert ( sprite_type ! = ST_RECOLOUR ) ;
assert ( sprite_type ! = ST_RECOLOUR ) ;
assert ( IsMapgenSpriteID ( id ) = = ( sprite_type = = ST_MAPGEN ) ) ;
assert ( IsMapgenSpriteID ( id ) = = ( sprite_type = = ST_MAPGEN ) ) ;
@ -489,13 +524,13 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
uint8 sprite_avail = 0 ;
uint8 sprite_avail = 0 ;
sprite [ ZOOM_LVL_NORMAL ] . type = sprite_type ;
sprite [ ZOOM_LVL_NORMAL ] . type = sprite_type ;
SpriteLoaderGrf sprite_loader ( sc- > container_ver ) ;
SpriteLoaderGrf sprite_loader ( file. GetContainerVersion ( ) ) ;
if ( sprite_type ! = ST_MAPGEN & & encoder - > Is32BppSupported ( ) ) {
if ( sprite_type ! = ST_MAPGEN & & encoder - > Is32BppSupported ( ) ) {
/* Try for 32bpp sprites first. */
/* Try for 32bpp sprites first. */
sprite_avail = sprite_loader . LoadSprite ( sprite , file _slot , file_pos , sprite_type , true ) ;
sprite_avail = sprite_loader . LoadSprite ( sprite , file , file_pos , sprite_type , true ) ;
}
}
if ( sprite_avail = = 0 ) {
if ( sprite_avail = = 0 ) {
sprite_avail = sprite_loader . LoadSprite ( sprite , file _slot , file_pos , sprite_type , false ) ;
sprite_avail = sprite_loader . LoadSprite ( sprite , file , file_pos , sprite_type , false ) ;
}
}
if ( sprite_avail = = 0 ) {
if ( sprite_avail = = 0 ) {
@ -532,7 +567,7 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
return s ;
return s ;
}
}
if ( ! ResizeSprites ( sprite , sprite_avail , file_slot, sc - > id , encoder) ) {
if ( ! ResizeSprites ( sprite , sprite_avail , encoder) ) {
if ( id = = SPR_IMG_QUERY ) usererror ( " Okay... something went horribly wrong. I couldn't resize the fallback sprite. What should I do? " ) ;
if ( id = = SPR_IMG_QUERY ) usererror ( " Okay... something went horribly wrong. I couldn't resize the fallback sprite. What should I do? " ) ;
return ( void * ) GetRawSprite ( SPR_IMG_QUERY , ST_NORMAL , allocator , encoder ) ;
return ( void * ) GetRawSprite ( SPR_IMG_QUERY , ST_NORMAL , allocator , encoder ) ;
}
}
@ -569,27 +604,27 @@ size_t GetGRFSpriteOffset(uint32 id)
* Parse the sprite section of GRFs .
* Parse the sprite section of GRFs .
* @ param container_version Container version of the GRF we ' re currently processing .
* @ param container_version Container version of the GRF we ' re currently processing .
*/
*/
void ReadGRFSpriteOffsets ( byte container_version )
void ReadGRFSpriteOffsets ( SpriteFile & file )
{
{
_grf_sprite_offsets . clear ( ) ;
_grf_sprite_offsets . clear ( ) ;
if ( container_version > = 2 ) {
if ( file. GetContainerVersion ( ) > = 2 ) {
/* Seek to sprite section of the GRF. */
/* Seek to sprite section of the GRF. */
size_t data_offset = Fio ReadDword( ) ;
size_t data_offset = file. ReadDword( ) ;
size_t old_pos = Fio GetPos( ) ;
size_t old_pos = file. GetPos( ) ;
Fio SeekTo( data_offset , SEEK_CUR ) ;
file. SeekTo( data_offset , SEEK_CUR ) ;
/* Loop over all sprite section entries and store the file
/* Loop over all sprite section entries and store the file
* offset for each newly encountered ID . */
* offset for each newly encountered ID . */
uint32 id , prev_id = 0 ;
uint32 id , prev_id = 0 ;
while ( ( id = Fio ReadDword( ) ) ! = 0 ) {
while ( ( id = file. ReadDword( ) ) ! = 0 ) {
if ( id ! = prev_id ) _grf_sprite_offsets [ id ] = Fio GetPos( ) - 4 ;
if ( id ! = prev_id ) _grf_sprite_offsets [ id ] = file. GetPos( ) - 4 ;
prev_id = id ;
prev_id = id ;
FioSkipBytes( Fio ReadDword( ) ) ;
file. SkipBytes ( file . ReadDword( ) ) ;
}
}
/* Continue processing the data section. */
/* Continue processing the data section. */
Fio SeekTo( old_pos , SEEK_SET ) ;
file. SeekTo( old_pos , SEEK_SET ) ;
}
}
}
}
@ -597,21 +632,21 @@ void ReadGRFSpriteOffsets(byte container_version)
/**
/**
* Load a real or recolour sprite .
* Load a real or recolour sprite .
* @ param load_index Global sprite index .
* @ param load_index Global sprite index .
* @ param file _slot GRF to load from .
* @ param file GRF to load from .
* @ param file_sprite_id Sprite number in the GRF .
* @ param file_sprite_id Sprite number in the GRF .
* @ param container_version Container version of the GRF .
* @ param container_version Container version of the GRF .
* @ return True if a valid sprite was loaded , false on any error .
* @ return True if a valid sprite was loaded , false on any error .
*/
*/
bool LoadNextSprite ( int load_index , uint file_slot , uint file_sprite_id , byte container_version )
bool LoadNextSprite ( int load_index , SpriteFile & file , uint file_sprite_id )
{
{
size_t file_pos = Fio GetPos( ) ;
size_t file_pos = file. GetPos( ) ;
SCOPE_INFO_FMT ( [ & ] , " LoadNextSprite: pos: " PRINTF_SIZE " , slot: %u (%s) , load_index: %d, file_sprite_id: %u, container_ver: %u" , file_pos , file _slot, FioGetFilename ( file_slot ) , load_index , file_sprite_id , container_version ) ;
SCOPE_INFO_FMT ( [ & ] , " LoadNextSprite: pos: " PRINTF_SIZE " , file: %s , load_index: %d, file_sprite_id: %u, container_ver: %u" , file_pos , file . GetSimplifiedFilename ( ) . c_str ( ) , load_index , file_sprite_id , file . GetContainerVersion ( ) ) ;
/* Read sprite header. */
/* Read sprite header. */
uint32 num = container_version > = 2 ? FioReadDword ( ) : Fio ReadWord( ) ;
uint32 num = file. GetContainerVersion ( ) > = 2 ? file . ReadDword ( ) : file . ReadWord( ) ;
if ( num = = 0 ) return false ;
if ( num = = 0 ) return false ;
byte grf_type = Fio ReadByte( ) ;
byte grf_type = file. ReadByte( ) ;
SpriteType type ;
SpriteType type ;
void * data = nullptr ;
void * data = nullptr ;
@ -619,25 +654,25 @@ bool LoadNextSprite(int load_index, uint file_slot, uint file_sprite_id, byte co
/* Some NewGRF files have "empty" pseudo-sprites which are 1
/* Some NewGRF files have "empty" pseudo-sprites which are 1
* byte long . Catch these so the sprites won ' t be displayed . */
* byte long . Catch these so the sprites won ' t be displayed . */
if ( num = = 1 ) {
if ( num = = 1 ) {
Fio ReadByte( ) ;
file. ReadByte( ) ;
return false ;
return false ;
}
}
type = ST_RECOLOUR ;
type = ST_RECOLOUR ;
data = ReadRecolourSprite ( file _slot , num ) ;
data = ReadRecolourSprite ( file , num ) ;
} else if ( container_version > = 2 & & grf_type = = 0xFD ) {
} else if ( file. GetContainerVersion ( ) > = 2 & & grf_type = = 0xFD ) {
if ( num ! = 4 ) {
if ( num ! = 4 ) {
/* Invalid sprite section include, ignore. */
/* Invalid sprite section include, ignore. */
Fio SkipBytes( num ) ;
file. SkipBytes( num ) ;
return false ;
return false ;
}
}
/* It is not an error if no sprite with the provided ID is found in the sprite section. */
/* It is not an error if no sprite with the provided ID is found in the sprite section. */
file_pos = GetGRFSpriteOffset ( Fio ReadDword( ) ) ;
file_pos = GetGRFSpriteOffset ( file. ReadDword( ) ) ;
type = ST_NORMAL ;
type = ST_NORMAL ;
} else {
} else {
Fio SkipBytes( 7 ) ;
file. SkipBytes( 7 ) ;
type = SkipSpriteData ( grf_type, num - 8 ) ? ST_NORMAL : ST_INVALID ;
type = SkipSpriteData ( file, grf_type, num - 8 ) ? ST_NORMAL : ST_INVALID ;
/* Inline sprites are not supported for container version >= 2. */
/* Inline sprites are not supported for container version >= 2. */
if ( container_version > = 2 ) return false ;
if ( file. GetContainerVersion ( ) > = 2 ) return false ;
}
}
if ( type = = ST_INVALID ) return false ;
if ( type = = ST_INVALID ) return false ;
@ -654,7 +689,7 @@ bool LoadNextSprite(int load_index, uint file_slot, uint file_sprite_id, byte co
}
}
SpriteCache * sc = AllocateSpriteCache ( load_index ) ;
SpriteCache * sc = AllocateSpriteCache ( load_index ) ;
sc - > file _slot = file _slot ;
sc - > file = & file ;
sc - > file_pos = file_pos ;
sc - > file_pos = file_pos ;
if ( data ! = nullptr ) {
if ( data ! = nullptr ) {
assert ( data = = _last_sprite_allocation . GetPtr ( ) ) ;
assert ( data = = _last_sprite_allocation . GetPtr ( ) ) ;
@ -664,7 +699,6 @@ bool LoadNextSprite(int load_index, uint file_slot, uint file_sprite_id, byte co
sc - > id = file_sprite_id ;
sc - > id = file_sprite_id ;
sc - > SetType ( type ) ;
sc - > SetType ( type ) ;
sc - > SetWarned ( false ) ;
sc - > SetWarned ( false ) ;
sc - > container_ver = container_version ;
return true ;
return true ;
}
}
@ -675,12 +709,11 @@ void DupSprite(SpriteID old_spr, SpriteID new_spr)
SpriteCache * scnew = AllocateSpriteCache ( new_spr ) ; // may reallocate: so put it first
SpriteCache * scnew = AllocateSpriteCache ( new_spr ) ; // may reallocate: so put it first
SpriteCache * scold = GetSpriteCache ( old_spr ) ;
SpriteCache * scold = GetSpriteCache ( old_spr ) ;
scnew - > file _slot = scold - > file _slot ;
scnew - > file = scold - > file ;
scnew - > file_pos = scold - > file_pos ;
scnew - > file_pos = scold - > file_pos ;
scnew - > id = scold - > id ;
scnew - > id = scold - > id ;
scnew - > SetType ( scold - > GetType ( ) ) ;
scnew - > SetType ( scold - > GetType ( ) ) ;
scnew - > SetWarned ( false ) ;
scnew - > SetWarned ( false ) ;
scnew - > container_ver = scold - > container_ver ;
}
}
static size_t GetSpriteCacheUsage ( )
static size_t GetSpriteCacheUsage ( )
@ -900,18 +933,18 @@ uint32 GetSpriteMainColour(SpriteID sprite_id, PaletteID palette_id)
const byte * const remap = ( palette_id = = PAL_NONE ? nullptr : GetNonSprite ( GB ( palette_id , 0 , PALETTE_WIDTH ) , ST_RECOLOUR ) + 1 ) ;
const byte * const remap = ( palette_id = = PAL_NONE ? nullptr : GetNonSprite ( GB ( palette_id , 0 , PALETTE_WIDTH ) , ST_RECOLOUR ) + 1 ) ;
uint file_slot = sc - > file_slot ;
SpriteFile & file = * sc - > file ;
size_t file_pos = sc - > file_pos ;
size_t file_pos = sc - > file_pos ;
SpriteLoader : : Sprite sprites [ ZOOM_LVL_COUNT ] ;
SpriteLoader : : Sprite sprites [ ZOOM_LVL_COUNT ] ;
sprites [ ZOOM_LVL_NORMAL ] . type = ST_NORMAL ;
sprites [ ZOOM_LVL_NORMAL ] . type = ST_NORMAL ;
SpriteLoaderGrf sprite_loader ( sc- > container_ver ) ;
SpriteLoaderGrf sprite_loader ( file. GetContainerVersion ( ) ) ;
uint8 sprite_avail ;
uint8 sprite_avail ;
const uint8 screen_depth = BlitterFactory : : GetCurrentBlitter ( ) - > GetScreenDepth ( ) ;
const uint8 screen_depth = BlitterFactory : : GetCurrentBlitter ( ) - > GetScreenDepth ( ) ;
/* Try to read the 32bpp sprite first. */
/* Try to read the 32bpp sprite first. */
if ( screen_depth = = 32 ) {
if ( screen_depth = = 32 ) {
sprite_avail = sprite_loader . LoadSprite ( sprites , file _slot , file_pos , ST_NORMAL , true ) ;
sprite_avail = sprite_loader . LoadSprite ( sprites , file , file_pos , ST_NORMAL , true ) ;
if ( sprite_avail ! = 0 ) {
if ( sprite_avail ! = 0 ) {
SpriteLoader : : Sprite * sprite = & sprites [ FindFirstBit ( sprite_avail ) ] ;
SpriteLoader : : Sprite * sprite = & sprites [ FindFirstBit ( sprite_avail ) ] ;
/* Return the average colour. */
/* Return the average colour. */
@ -941,7 +974,7 @@ uint32 GetSpriteMainColour(SpriteID sprite_id, PaletteID palette_id)
}
}
/* No 32bpp, try 8bpp. */
/* No 32bpp, try 8bpp. */
sprite_avail = sprite_loader . LoadSprite ( sprites , file _slot , file_pos , ST_NORMAL , false ) ;
sprite_avail = sprite_loader . LoadSprite ( sprites , file , file_pos , ST_NORMAL , false ) ;
if ( sprite_avail ! = 0 ) {
if ( sprite_avail ! = 0 ) {
SpriteLoader : : Sprite * sprite = & sprites [ FindFirstBit ( sprite_avail ) ] ;
SpriteLoader : : Sprite * sprite = & sprites [ FindFirstBit ( sprite_avail ) ] ;
SpriteLoader : : CommonPixel * pixel = sprite - > data ;
SpriteLoader : : CommonPixel * pixel = sprite - > data ;
@ -987,6 +1020,7 @@ void GfxInitSpriteMem()
{
{
/* Reset the spritecache 'pool' */
/* Reset the spritecache 'pool' */
_spritecache . clear ( ) ;
_spritecache . clear ( ) ;
_sprite_files . clear ( ) ;
assert ( _spritecache_bytes_used = = 0 ) ;
assert ( _spritecache_bytes_used = = 0 ) ;
}
}