diff --git a/src/core.cpp b/src/core.cpp index 16e7b27f..f22ca604 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -1806,7 +1806,19 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) { if (!sandbox_serialize(sb().transitioning, data, max_size)) return false; if (!sandbox_serialize(sb().trans_map != nullptr, data, max_size)) return false; if (sb().trans_map != nullptr) { - if (!sandbox_serialize(*sb().trans_map, data, max_size)) return false; + if (sb().trans_map->isDisposed()) { + std::abort(); + } + if (!sb().trans_map->sandbox_serialize_without_hires(data, max_size)) return false; + Exception e; + Bitmap *hires = sb().trans_map->getHires(e); + if (!e.is_ok()) { + std::abort(); + } + if (!sandbox_serialize(hires != nullptr, data, max_size)) return false; + if (hires != nullptr) { + if (!hires->sandbox_serialize_without_hires(data, max_size)) return false; + } } if (!sandbox_serialize(sb().get_movie_from_main_thread() != nullptr, data, max_size)) return false; if (sb().get_movie_from_main_thread() != nullptr) { @@ -2078,15 +2090,41 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) { if (!sb().transitioning) { DESER_OBJECTS_END_FAIL; } - if (sb().trans_map == nullptr) { - Exception e; - sb().trans_map = new Bitmap(e); + Exception e; + bool is_new = sb().trans_map == nullptr; + if (is_new) { + sb().trans_map = new Bitmap(e, 1, 1, true); if (e.is_error()) { DESER_OBJECTS_END_FAIL; } sb().trans_map->sandbox_deserialize_begin(true); } - if (!sandbox_deserialize(*sb().trans_map, data, max_size)) DESER_OBJECTS_END_FAIL; + Bitmap *hires = sb().trans_map->getHires(e); + if (e.is_error()) { + DESER_OBJECTS_END_FAIL; + } + if (hires != nullptr) { + hires->sandbox_deserialize_begin(is_new); + } + if (!sb().trans_map->sandbox_deserialize_without_hires(data, max_size)) DESER_OBJECTS_END_FAIL; + bool have_trans_map_hires; + if (!sandbox_deserialize(have_trans_map_hires, data, max_size)) DESER_OBJECTS_END_FAIL; + if (e.is_error()) { + DESER_OBJECTS_END_FAIL; + } + if (have_trans_map_hires && hires == nullptr) { + hires = new Bitmap(e, 1, 1, true); + if (e.is_error()) { + DESER_OBJECTS_END_FAIL; + } + hires->sandbox_deserialize_begin(true); + } else if (!have_trans_map_hires && hires != nullptr) { + delete hires; + hires = nullptr; + } + if (hires != nullptr) { + if (!hires->sandbox_deserialize_without_hires(data, max_size)) DESER_OBJECTS_END_FAIL; + } } else { if (sb().trans_map != nullptr) { delete sb().trans_map; @@ -2110,6 +2148,15 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) { if (sb().trans_map != nullptr) { sb().trans_map->sandbox_deserialize_end(false); + Exception e; + Bitmap *hires = sb().trans_map->getHires(e); + if (e.is_error()) { + DESER_OBJECTS_END_FAIL; + } + if (hires != nullptr) { + sb().trans_map->setHiresRaw(e, hires); + hires->sandbox_deserialize_end(false); + } } for (const auto &object : sb()->objects) { if (object.typenum > 0) { diff --git a/src/display/bitmap.cpp b/src/display/bitmap.cpp index 35d9cbb1..4991ccd8 100644 --- a/src/display/bitmap.cpp +++ b/src/display/bitmap.cpp @@ -1335,6 +1335,13 @@ Bitmap *Bitmap::getHires(Exception &exception) const { return p->selfHires; } +void Bitmap::setHiresRaw(Exception &exception, Bitmap *hires) { + GUARD(guardDisposed(exception)); + + GUARD(hires->setLoresRaw(exception, this)); + p->selfHires = hires; +} + void Bitmap::setHires(Exception &exception, Bitmap *hires) { GUARD(guardDisposed(exception)); @@ -1343,6 +1350,12 @@ void Bitmap::setHires(Exception &exception, Bitmap *hires) { p->selfHires = hires; } +void Bitmap::setLoresRaw(Exception &exception, Bitmap *lores) { + GUARD(guardDisposed(exception)); + + p->selfLores = lores; +} + void Bitmap::setLores(Exception &exception, Bitmap *lores) { GUARD(guardDisposed(exception)); @@ -3683,7 +3696,7 @@ void Bitmap::loresDisposal() } #ifdef MKXPZ_RETRO -bool Bitmap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const +bool Bitmap::sandbox_serialize_without_hires(void *&data, mkxp_sandbox::wasm_size_t &max_size) const { if (!mkxp_sandbox::sandbox_serialize((int32_t)width(), data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize((int32_t)height(), data, max_size)) return false; @@ -3712,9 +3725,15 @@ bool Bitmap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) } if (!mkxp_sandbox::sandbox_serialize(p->font == &shState->defaultFont() ? nullptr : p->font, data, max_size)) return false; + + return true; +} + +bool Bitmap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const +{ + if (!sandbox_serialize_without_hires(data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->selfHires, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->selfLores, data, max_size)) return false; - return true; } @@ -3756,7 +3775,7 @@ bool Bitmap::sandbox_serialize_pixels(void *&data, mkxp_sandbox::wasm_size_t &ma return true; } -bool Bitmap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) +bool Bitmap::sandbox_deserialize_without_hires(const void *&data, mkxp_sandbox::wasm_size_t &max_size) { int32_t old_width = width(); int32_t old_height = height(); @@ -3994,9 +4013,15 @@ bool Bitmap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &m if (p->font == nullptr) { p->font = &shState->defaultFont(); } + + return true; +} + +bool Bitmap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) +{ + if (!sandbox_deserialize_without_hires(data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->selfHires, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->selfLores, data, max_size)) return false; - return true; } diff --git a/src/display/bitmap.h b/src/display/bitmap.h index e7b64fd8..50f76d3f 100644 --- a/src/display/bitmap.h +++ b/src/display/bitmap.h @@ -88,7 +88,9 @@ public: int getWidth(Exception &exception) const; int getHeight(Exception &exception) const; bool getHasHires(Exception &exception) const; + void setHiresRaw(Exception &exception, Bitmap *hires); DECL_ATTR(Hires, Bitmap*) + void setLoresRaw(Exception &exception, Bitmap *lores); void setLores(Exception &exception, Bitmap *lores); bool getIsMega(Exception &exception) const; bool getIsAnimated(Exception &exception) const; @@ -218,7 +220,9 @@ public: void assumeRubyGC(bool value = true); #ifdef MKXPZ_RETRO + bool sandbox_serialize_without_hires(void *&data, mkxp_sandbox::wasm_size_t &max_size) const; bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const; + bool sandbox_deserialize_without_hires(const void *&data, mkxp_sandbox::wasm_size_t &max_size); bool sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size); void sandbox_deserialize_begin(bool is_new); void sandbox_deserialize_end(bool is_sandbox_object);