mirror of https://github.com/OpenTTD/OpenTTD
(svn r13674) -Fix [FS#2127]: crash when drawing a non-real sprite. The drawing of the non-real sprite is caused when two NewGRFs replace the same sprite and the first replaces it with a real sprite (and thus assumes it remains a real sprite) and the second replaces it with a non-real sprite. OpenTTD already looked at whether the sprite to load should be seen as a real or non-real sprite, but it failed to replace non-real sprites with a substitute real sprite when getting the sprite from the cache.
parent
f37a47c0cb
commit
173f0f4cd5
|
@ -24,10 +24,11 @@ uint _sprite_cache_size = 4;
|
||||||
|
|
||||||
struct SpriteCache {
|
struct SpriteCache {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
uint32 id;
|
|
||||||
size_t file_pos;
|
size_t file_pos;
|
||||||
|
uint32 id;
|
||||||
uint16 file_slot;
|
uint16 file_slot;
|
||||||
int16 lru;
|
int16 lru;
|
||||||
|
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.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,6 +177,7 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
|
||||||
byte *dest = (byte *)AllocSprite(num);
|
byte *dest = (byte *)AllocSprite(num);
|
||||||
|
|
||||||
sc->ptr = dest;
|
sc->ptr = dest;
|
||||||
|
sc->real_sprite = false;
|
||||||
FioReadBlock(dest, num);
|
FioReadBlock(dest, num);
|
||||||
|
|
||||||
return sc->ptr;
|
return sc->ptr;
|
||||||
|
@ -217,9 +219,13 @@ static void* ReadSprite(SpriteCache *sc, SpriteID id, bool real_sprite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc->real_sprite = false;
|
||||||
|
|
||||||
return sc->ptr;
|
return sc->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc->real_sprite = true;
|
||||||
|
|
||||||
if (!real_sprite) {
|
if (!real_sprite) {
|
||||||
static byte warning_level = 0;
|
static byte warning_level = 0;
|
||||||
DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
|
DEBUG(sprite, warning_level, "Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id);
|
||||||
|
@ -255,6 +261,7 @@ bool LoadNextSprite(int load_index, byte file_slot, uint file_sprite_id)
|
||||||
sc->ptr = NULL;
|
sc->ptr = NULL;
|
||||||
sc->lru = 0;
|
sc->lru = 0;
|
||||||
sc->id = file_sprite_id;
|
sc->id = file_sprite_id;
|
||||||
|
sc->real_sprite = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +276,7 @@ void DupSprite(SpriteID old_spr, SpriteID new_spr)
|
||||||
scnew->file_pos = scold->file_pos;
|
scnew->file_pos = scold->file_pos;
|
||||||
scnew->ptr = NULL;
|
scnew->ptr = NULL;
|
||||||
scnew->id = scold->id;
|
scnew->id = scold->id;
|
||||||
|
scnew->real_sprite = scold->real_sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -453,7 +461,7 @@ const void *GetRawSprite(SpriteID sprite, bool real_sprite)
|
||||||
p = sc->ptr;
|
p = sc->ptr;
|
||||||
|
|
||||||
/* Load the sprite, if it is not loaded, yet */
|
/* Load the sprite, if it is not loaded, yet */
|
||||||
if (p == NULL) p = ReadSprite(sc, sprite, real_sprite);
|
if (p == NULL || sc->real_sprite != real_sprite) p = ReadSprite(sc, sprite, real_sprite);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue