From 2f5850bfc1e83200d5fee45d06747b593c85f2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Tue, 24 Jun 2025 18:14:08 -0400 Subject: [PATCH] Fix some bugs in bitmap deserialization for libretro save states --- src/core.cpp | 2 +- src/display/bitmap.cpp | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index 08eb67ef..5dc280e4 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -1951,8 +1951,8 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) { } typenum_table[object.typenum - 1].destroy(object.ptr); object.typenum = 0; - vacant_object_keys.push_back(i); } + vacant_object_keys.push_back(i); } object_key += num_free_objects; diff --git a/src/display/bitmap.cpp b/src/display/bitmap.cpp index 080ada69..bd03cee6 100644 --- a/src/display/bitmap.cpp +++ b/src/display/bitmap.cpp @@ -4083,18 +4083,23 @@ bool Bitmap::sandbox_deserialize_pixels(const void *&data, mkxp_sandbox::wasm_si bool is_not_empty; if (!mkxp_sandbox::sandbox_deserialize(is_not_empty, data, max_size)) return false; - size_t tile_col = tile_number % CEIL_DIV_DIFF_TILE_SIZE(width()); - size_t tile_row = tile_number / CEIL_DIV_DIFF_TILE_SIZE(width()); - size_t tile_width = std::min(DIFF_TILE_SIZE, width() - DIFF_TILE_SIZE * tile_col); - size_t tile_height = std::min(DIFF_TILE_SIZE, height() - DIFF_TILE_SIZE * tile_row); - IntRect rect = IntRect(DIFF_TILE_SIZE * tile_col, DIFF_TILE_SIZE * tile_row, tile_width, tile_height); - if (!is_not_empty) { mkxp_sandbox::wasm_size_t num_empty_tiles; if (!mkxp_sandbox::sandbox_deserialize(num_empty_tiles, data, max_size)) return false; while (num_empty_tiles > 0) { - if (!diff[tile_number].empty()) { + std::vector &tile = diff[tile_number]; + + // Clear tiles that are empty in the save state but not currently empty + if (!tile.empty()) { + tile.clear(); + + size_t tile_col = tile_number % CEIL_DIV_DIFF_TILE_SIZE(width()); + size_t tile_row = tile_number / CEIL_DIV_DIFF_TILE_SIZE(width()); + size_t tile_width = std::min(DIFF_TILE_SIZE, width() - DIFF_TILE_SIZE * tile_col); + size_t tile_height = std::min(DIFF_TILE_SIZE, height() - DIFF_TILE_SIZE * tile_row); + IntRect rect = IntRect(DIFF_TILE_SIZE * tile_col, DIFF_TILE_SIZE * tile_row, tile_width, tile_height); + FBO::bind(p->animation.enabled ? p->animation.frames[frame_number].gl.fbo : p->gl.fbo); glState.scissorTest.pushSet(true); @@ -4116,6 +4121,12 @@ bool Bitmap::sandbox_deserialize_pixels(const void *&data, mkxp_sandbox::wasm_si --num_empty_tiles; } } else { + size_t tile_col = tile_number % CEIL_DIV_DIFF_TILE_SIZE(width()); + size_t tile_row = tile_number / CEIL_DIV_DIFF_TILE_SIZE(width()); + size_t tile_width = std::min(DIFF_TILE_SIZE, width() - DIFF_TILE_SIZE * tile_col); + size_t tile_height = std::min(DIFF_TILE_SIZE, height() - DIFF_TILE_SIZE * tile_row); + IntRect rect = IntRect(DIFF_TILE_SIZE * tile_col, DIFF_TILE_SIZE * tile_row, tile_width, tile_height); + if (max_size < 4 * tile_width * tile_height) return false; bool tile_modified = false;