diff --git a/spritecache.c b/spritecache.c index 681af180e1..a85f38b56f 100644 --- a/spritecache.c +++ b/spritecache.c @@ -52,7 +52,7 @@ static const char * const _filename_list[] = { "TRG1R.GRF", "TRGIR.GRF", "signalsw.grf", //0x1320 - 0x1405 inclusive -// "openttd.grf", //0x1406 - +// "openttd.grf", //0x1406 - NULL }; @@ -93,7 +93,7 @@ static void ReadSpriteHeaderSkipData(int num, int load_index) _skip_sprites--; deaf = 1; } - + type = FioReadByte(); if (type == 0xFF) { /* We need to really skip only special sprites in the deaf @@ -108,7 +108,7 @@ static void ReadSpriteHeaderSkipData(int num, int load_index) } return; } - + _cur_sprite.info = type; #ifdef WANT_SPRITESIZES _cur_sprite.height = FioReadByte(); @@ -146,7 +146,7 @@ static void ReadSprite(int num, byte *dest) byte *rel; int8 i; int j, dist; - + type = FioReadByte(); /* We've decoded special sprites when reading headers. */ if (type != 0xFF) { @@ -173,7 +173,7 @@ static void ReadSprite(int num, byte *dest) dist = -(((i&7)<<8)|FioReadByte()); i = -(i >> 3); num -= i; - + rel = &dest[dist]; while (i--) *dest++ = *rel++; @@ -209,7 +209,7 @@ static bool LoadNextSprite(int load_index, byte file_index) #if defined(WANT_NEW_LRU) _sprite_lru_new[load_index] = 0; -#else +#else _sprite_lru[load_index] = 0xFFFF; _sprite_lru_cur[load_index] = 0; #endif @@ -282,7 +282,7 @@ static void LoadGrfIndexed(const char *filename, const uint16 *index_tbl, int fi } while (++start <= end); } } -} +} typedef size_t CDECL fread_t(void*,size_t,size_t,FILE*); @@ -398,20 +398,20 @@ static void CompactSpriteCache() byte *s, *t; size_t size, sizeb, cur_size; int i; - + DEBUG(spritecache, 2) ("compacting sprite cache, inuse=%d", GetSpriteCacheUsage()); s = _spritecache_ptr; - + while (true) { size = S_DATA(s); - + // Only look for free blocks. if (size & S_FREE_MASK) { size -= S_FREE_MASK; // Since free blocks are automatically coalesced, this should hold true. assert(!(S_DATA(s+size) & S_FREE_MASK)); - + // If the next block is the sentinel block, we can safely return if ( (sizeb=S_DATA(s + size)) == 0) break; @@ -427,13 +427,13 @@ static void CompactSpriteCache() // Offset the sprite pointer by the size of the free block _sprite_ptr[i] -= size; - // Move the memory + // Move the memory memcpy_overlapping(s+S_HDRSIZE, s+S_HDRSIZE+size, sizeb - S_HDRSIZE ); // What we just did had the effect of swapping the allocated block with the free block, so we need to update // the block pointers. First update the allocated one. It is in use. S_DATA(s) = sizeb; - + // Then coalesce the free ones that follow. s += sizeb; while ((cur_size = S_DATA(s+size)) & S_FREE_MASK) @@ -485,7 +485,7 @@ static void DeleteEntryFromSpriteCache() #endif _sprite_lru[i] < cur_lru) continue; - + // Found a sprite with a higher LRU value, then remember it. if (_sprite_lru[i] != cur_lru) { cur_lru = _sprite_lru[i]; @@ -551,7 +551,7 @@ restart: // Now s points at a free block. // The block is exactly the size we need? if (cur_size != mem_req) { - + // No.. is it too small? if (cur_size < mem_req + S_HDRSIZE) break; @@ -567,7 +567,7 @@ restart: FioSeekToFile(_sprite_file_pos[sprite]); ReadSprite(_sprite_size[sprite], s); - + // Patch the height to compensate for a TTD bug? if (sprite == 142) { s[1] = 10; } @@ -580,7 +580,7 @@ restart: DeleteEntryFromSpriteCache(); goto restart; } - + s += cur_size; } } @@ -628,7 +628,7 @@ uint RotateSprite(uint s) } #endif -byte *GetSpritePtr(uint sprite) +byte *GetSpritePtr(uint sprite) { byte *p; @@ -650,7 +650,7 @@ byte *GetSpritePtr(uint sprite) p = _sprite_ptr[sprite]; if (p == NULL) p = LoadSpriteToMem(sprite); // No, need to load it. - return p; + return p; } byte _sprite_page_to_load = 0xFF; @@ -680,9 +680,18 @@ static void LoadSpriteTables() { int i,j; - /* load initial sprites */ + /* + * Note for developers: + * Keep in mind that when you add a LoadGrfIndexed in the 'if'-section below + * that you should also add the corresponding FioOpenFile to the 'else'-section + * below. + */ + + // Try to load the sprites from cache if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) { - + // We do not have the sprites in cache yet, or cache is disabled + // So just load all files from disk.. + int load_index = 0; for(i=0; _filename_list[i] != NULL; i++) { load_index += LoadGrfFile(_filename_list[i], load_index, (byte)i); @@ -690,38 +699,48 @@ static void LoadSpriteTables() LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++); - { - int l; - if ((l=_sprite_page_to_load) != 0) - LoadGrfIndexed(_landscape_filenames[l-1], _landscape_spriteindexes[l-1], i++); - } - + if (_sprite_page_to_load != 0) + LoadGrfIndexed(_landscape_filenames[_sprite_page_to_load-1], _landscape_spriteindexes[_sprite_page_to_load-1], i++); + LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++); load_index = SPR_CANALS_BASE; load_index += LoadGrfFile("canalsw.grf", load_index, i++); - /* XXX: Only for debugging. Will be more generic. */ - load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT+1; + load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT + 1; for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) load_index += LoadGrfFile(_newgrf_files[j], load_index, i++); -// load_index += LoadGrfFile("arcticseto.grf", load_index, i++); -// load_index += LoadGrfFile("tempsetpo.grf", load_index, i++); -// load_index += LoadGrfFile("newshipso.grf", load_index, i++); - //load_index += LoadGrfFile("brseto.grf", load_index, i++); - + // If needed, save the cache to file HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], false); } else { + // We have sprites cached. We just loaded the cached files + // now we only have to open a file-pointer to all the original grf-files + // This is very important. Not all sprites are in the cache. So sometimes + // the game needs to load the sprite from disk. When the file is not + // open it can not read. So all files that are in the 'if'-section + // above should also be in this 'else'-section. + // + // NOTE: the order of the files must be identical as in the section above!! + for(i=0; _filename_list[i] != NULL; i++) - FioOpenFile(i,_filename_list[i]); - - FioOpenFile(i, "openttd.grf"); - FioOpenFile(i+1, "canalsw.grf"); - + FioOpenFile(i,_filename_list[i]); + + FioOpenFile(i++, "openttd.grf"); + if (_sprite_page_to_load != 0) - FioOpenFile(i+2, _landscape_filenames[_sprite_page_to_load-1]); + FioOpenFile(i++, _landscape_filenames[_sprite_page_to_load-1]); + + FioOpenFile(i++, "trkfoundw.grf"); + FioOpenFile(i++, "canalsw.grf"); + + // FIXME: if a user changes his newgrf's, the cached-sprites gets + // invalid. We should have some kind of check for this. + // The best solution for this is to delete the cached-sprites.. but how + // do we detect it? + for(j=0; j!=lengthof(_newgrf_files) && _newgrf_files[j]; j++) + FioOpenFile(i++, _newgrf_files[j]); } _compact_cache_counter = 0; @@ -744,7 +763,7 @@ void GfxInitSpriteMem(byte *ptr, uint32 size) void GfxLoadSprites() { static byte *_sprite_mem; - + // Need to reload the sprites only if the landscape changed if (_sprite_page_to_load != _opt.landscape) { _sprite_page_to_load = _opt.landscape; @@ -793,4 +812,4 @@ const SpriteDimension *GetSpriteDimension(uint sprite) */ return sd; } - +