From e5968ecab74a9eff4f7cfc9445ab1ce967a1e8a5 Mon Sep 17 00:00:00 2001 From: Viet Dinh <36768030+Desdaemon@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:23:11 -0400 Subject: [PATCH] Cherry-pick Yume 2kki patches (#40) * Effects: Use the filename for the cache, not the bitmap pointer The pointer can be reused by a new bitmap and cause wrong animations. For individual tiles the filename is lost. "filename" in bitmap was renamed to "id" and gets now filename+tileid in that case. Fix #3256 Co-Authored-By: Viet Dinh <54ckb0y789@gmail.com> * Fix flickering in Yume2kki on map 3D Underworld (ID 1884). The map uses a MoveRoute with a jump and SetVehicleLocation for party movement in a tight loop which causes heavy flickering in our Player. This fix does not appear to be completely correct as RPG_RT does not reset the jump flag here but the "damage" is reduced because SetVehicleLocation -1 cannot happen without patching the game. Fix #3254 Co-Authored-By: Viet Dinh <54ckb0y789@gmail.com> --------- Co-authored-by: Ghabry --- src/bitmap.cpp | 2 +- src/bitmap.h | 28 +++++++++++++++++++++------- src/cache.cpp | 10 +++++++--- src/game_interpreter.cpp | 8 ++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 25992d636..2278dd7f3 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -130,7 +130,7 @@ Bitmap::Bitmap(Filesystem_Stream::InputStream stream, bool transparent, uint32_t CheckPixels(flags); - filename = ToString(stream.GetName()); + id = ToString(stream.GetName()); } Bitmap::Bitmap(const uint8_t* data, unsigned bytes, bool transparent, uint32_t flags) { diff --git a/src/bitmap.h b/src/bitmap.h index 3fbfc699d..a8979f63d 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -217,12 +217,21 @@ class Bitmap { Color GetShadowColor() const; /** - * Gets the filename this bitmap was loaded from. - * This will be empty when the origin was not a file. + * Returns an identifier for the bitmap. + * When the bitmap was loaded from a file this contains the filename. + * In all other cases this is implementation defined (and can be empty). * - * @return filename + * @return Bitmap identifier */ - StringView GetFilename() const; + StringView GetId() const; + + /** + * Sets the identifier of the bitmap. + * To avoid bugs the function will reject changing non-empty IDs. + * + * @param id new identifier + */ + void SetId(std::string id); void CheckPixels(uint32_t flags); @@ -597,7 +606,7 @@ class Bitmap { TileOpacity tile_opacity; Color bg_color, sh_color; - std::string filename; + std::string id; /** Bitmap data. */ PixmanImagePtr bitmap; @@ -668,8 +677,13 @@ inline bool Bitmap::GetTransparent() const { return format.alpha_type != PF::NoAlpha; } -inline StringView Bitmap::GetFilename() const { - return filename; +inline StringView Bitmap::GetId() const { + return id; +} + +inline void Bitmap::SetId(std::string id) { + assert(this->id.empty()); + this->id = id; } #endif diff --git a/src/cache.cpp b/src/cache.cpp index bfa3dfbb2..b1c8e27c0 100644 --- a/src/cache.cpp +++ b/src/cache.cpp @@ -81,7 +81,7 @@ namespace { std::unordered_map> cache_tiles; // rect, flip_x, flip_y, tone, blend - using effect_key_type = std::tuple; + using effect_key_type = std::tuple; std::map> cache_effects; std::string system_name; @@ -438,13 +438,17 @@ BitmapRef Cache::Tile(StringView filename, int tile_id) { rect.x += sub_tile_id % 6 * 16; rect.y += sub_tile_id / 6 * 16; - return(cache_tiles[key] = Bitmap::Create(*chipset, rect)).lock(); + auto bmp = Bitmap::Create(*chipset, rect); + bmp->SetId(fmt::format("{}/{}", chipset->GetId(), tile_id)); + cache_tiles[key] = bmp; + + return bmp; } else { return it->second.lock(); } } BitmapRef Cache::SpriteEffect(const BitmapRef& src_bitmap, const Rect& rect, bool flip_x, bool flip_y, const Tone& tone, const Color& blend) { const effect_key_type key { - src_bitmap.get(), + src_bitmap->GetId(), rect, flip_x, flip_y, diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index d694dae1b..90ae59d00 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -2331,6 +2331,14 @@ bool Game_Interpreter::CommandSetVehicleLocation(lcf::rpg::EventCommand const& c vehicle->MoveTo(map_id, x, y); } Main_Data::game_player->MoveTo(map_id, x, y); + if (vehicle_id == 0) { + // This fixes a bug in Yume2kki on map 3D Underworld (ID 1884) + // The map uses a MoveRoute with a jump and SetVehicleLocation for party movement in a tight loop which + // causes heavy flickering in our Player. + // TODO: This fix does not appear to be completely correct as RPG_RT does not reset the jump flag here + // but the "damage" is reduced because SetVehicleLocation -1 cannot happen without patching the game. + Main_Data::game_player->SetJumping(false); + } return true; };