Fix some bugs in bitmap deserialization for libretro save states

This commit is contained in:
刘皓 2025-06-24 18:14:08 -04:00
parent c96c571241
commit 2f5850bfc1
No known key found for this signature in database
GPG key ID: 7901753DB465B711
2 changed files with 19 additions and 8 deletions

View file

@ -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); typenum_table[object.typenum - 1].destroy(object.ptr);
object.typenum = 0; object.typenum = 0;
vacant_object_keys.push_back(i);
} }
vacant_object_keys.push_back(i);
} }
object_key += num_free_objects; object_key += num_free_objects;

View file

@ -4083,18 +4083,23 @@ bool Bitmap::sandbox_deserialize_pixels(const void *&data, mkxp_sandbox::wasm_si
bool is_not_empty; bool is_not_empty;
if (!mkxp_sandbox::sandbox_deserialize(is_not_empty, data, max_size)) return false; 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) { if (!is_not_empty) {
mkxp_sandbox::wasm_size_t num_empty_tiles; mkxp_sandbox::wasm_size_t num_empty_tiles;
if (!mkxp_sandbox::sandbox_deserialize(num_empty_tiles, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(num_empty_tiles, data, max_size)) return false;
while (num_empty_tiles > 0) { while (num_empty_tiles > 0) {
if (!diff[tile_number].empty()) { std::vector<uint32_t> &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); FBO::bind(p->animation.enabled ? p->animation.frames[frame_number].gl.fbo : p->gl.fbo);
glState.scissorTest.pushSet(true); glState.scissorTest.pushSet(true);
@ -4116,6 +4121,12 @@ bool Bitmap::sandbox_deserialize_pixels(const void *&data, mkxp_sandbox::wasm_si
--num_empty_tiles; --num_empty_tiles;
} }
} else { } 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; if (max_size < 4 * tile_width * tile_height) return false;
bool tile_modified = false; bool tile_modified = false;