Fix libretro save state serialization of hires transition map

This commit is contained in:
刘皓 2025-07-28 23:11:29 -04:00
parent c6e33a9ff1
commit e2be5b5d50
No known key found for this signature in database
GPG key ID: 7901753DB465B711
3 changed files with 85 additions and 9 deletions

View file

@ -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) {

View file

@ -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;
}

View file

@ -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);