diff --git a/Common/ac/spritecache.cpp b/Common/ac/spritecache.cpp index 552258ce5e..ace652fcfe 100644 --- a/Common/ac/spritecache.cpp +++ b/Common/ac/spritecache.cpp @@ -78,6 +78,13 @@ bool SpriteCache::IsSpriteLoaded(sprkey_t index) const return ResourceCache::Exists(index); } +bool SpriteCache::IsAssetUnloaded(sprkey_t index) const +{ + return index >= 0 && (size_t)index < _spriteData.size() && // in the valid range + _spriteData[index].IsAssetSprite() && // found in the game resources + !ResourceCache::Exists(index); +} + void SpriteCache::Reset() { _file.Close(); diff --git a/Common/ac/spritecache.h b/Common/ac/spritecache.h index 14bbd127c7..ce91c201de 100644 --- a/Common/ac/spritecache.h +++ b/Common/ac/spritecache.h @@ -123,6 +123,11 @@ class SpriteCache : bool IsAssetSprite(sprkey_t index) const; // Tells if the sprite is loaded into the memory (either from asset file, or assigned directly) bool IsSpriteLoaded(sprkey_t index) const; + // Tells if the given slot represents an "asset sprite", which is currently unloaded. + // This is a helper method that lets distinguish an asset missing from memory, + // because IsSpriteLoaded() also reports true for external sprites, and false for + // any non-occupied sprite slots. + bool IsAssetUnloaded(sprkey_t index) const; // Loads sprite using SpriteFile if such index is known, // frees the space if cache size reaches the limit void PrecacheSprite(sprkey_t index); diff --git a/Engine/ac/draw.cpp b/Engine/ac/draw.cpp index a80476e17d..bd076ed33e 100644 --- a/Engine/ac/draw.cpp +++ b/Engine/ac/draw.cpp @@ -2681,6 +2681,9 @@ static void construct_overlays() overcache[i].X = pos.X; overcache[i].Y = pos.Y; } + // Test if must recache the unloaded sprite in software mode + has_changed |= (is_software_mode && spriteset.IsAssetUnloaded(over.GetSpriteNum())); + if (has_changed || overtx.IsChangeNotified()) { overtx.SpriteID = over.GetSpriteNum(); @@ -2783,10 +2786,11 @@ void construct_game_screen_overlay(bool draw_mouse) } // Mouse cursor - if ((play.screen_is_faded_out == 0) && - draw_mouse && !play.mouse_cursor_hidden) + if ((play.screen_is_faded_out == 0) && draw_mouse && !play.mouse_cursor_hidden) { - if (cursor_gstate.HasChanged() || cursor_tx.IsChangeNotified()) + if (cursor_gstate.HasChanged() || cursor_tx.IsChangeNotified() || + // Test if must recache the unloaded sprite in software mode + (drawstate.SoftwareRender && (cursor_gstate.GetSpriteNum() >= 0) && spriteset.IsAssetUnloaded(cursor_gstate.GetSpriteNum()))) { cursor_tx.SpriteID = cursor_gstate.GetSpriteNum(); if (cursor_tx.SpriteID != UINT32_MAX) diff --git a/Engine/ac/screenoverlay.h b/Engine/ac/screenoverlay.h index 26332bc498..d7988d2ad3 100644 --- a/Engine/ac/screenoverlay.h +++ b/Engine/ac/screenoverlay.h @@ -93,8 +93,8 @@ struct ScreenOverlay } // Gets actual overlay's image, whether owned by overlay or by a sprite reference Common::Bitmap *GetImage() const; - // Get sprite id, or 0 if none set - int GetSpriteNum() const { return _sprnum; } + // Get this overlay's sprite id + int GetSpriteNum() const { return _sprnum; } Size GetGraphicSize() const; // Assigns an exclusive image to this overlay; the image will be stored as a dynamic sprite // in a sprite cache, but owned by this overlay and therefore disposed at its disposal