Properly set assumingRubyGC when deserializing bitmaps from libretro save states

This commit is contained in:
刘皓 2025-07-06 11:08:44 -04:00
parent e587768f9c
commit 1a275a1866
No known key found for this signature in database
GPG key ID: 7901753DB465B711
5 changed files with 32 additions and 12 deletions

View file

@ -262,7 +262,7 @@ namespace mkxp_sandbox {
bool (*serialize)(const void *self, void *&data, wasm_size_t &max_size);
bool (*deserialize)(void *self, const void *&data, wasm_size_t &max_size);
void (*deserialize_begin)(void *self, bool is_new);
void (*deserialize_end)(void *self);
void (*deserialize_end)(void *self, bool is_sandbox_object);
void (*reinit)(void *self);
};

View file

@ -99,13 +99,18 @@ template <typename T> static typename std::enable_if<!boost::is_detected<deseria
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value && !boost::is_detected<deserialize_begin_declaration_without_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {}
template <typename T> using deserialize_end_declaration = decltype(std::declval<T *>()->sandbox_deserialize_end());
template <typename T> using deserialize_end_declaration_with_is_sandbox_object = decltype(std::declval<T *>()->sandbox_deserialize_end(std::declval<bool>()));
template <typename T> using deserialize_end_declaration_without_is_sandbox_object = decltype(std::declval<T *>()->sandbox_deserialize_end());
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_end_declaration_with_is_sandbox_object, T>::value>::type deserialize_end(void *self, bool is_sandbox_object) {
((T *)self)->sandbox_deserialize_end(is_sandbox_object);
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_end_declaration_with_is_sandbox_object, T>::value && boost::is_detected<deserialize_end_declaration_without_is_sandbox_object, T>::value>::type deserialize_end(void *self, bool is_sandbox_object) {
((T *)self)->sandbox_deserialize_end();
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_end_declaration_with_is_sandbox_object, T>::value && !boost::is_detected<deserialize_end_declaration_without_is_sandbox_object, T>::value>::type deserialize_end(void *self, bool is_sandbox_object) {}
template <typename T> using reinit_declaration = decltype(std::declval<T *>()->sandbox_reinit());
@ -115,7 +120,17 @@ template <typename T> static typename std::enable_if<boost::is_detected<reinit_d
template <typename T> static typename std::enable_if<!boost::is_detected<reinit_declaration, T>::value>::type reinit(void *self) {}
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) {construct<T>, destroy<T>, dispose<T>, disposed<T>, serialize<T>, deserialize<T>, deserialize_begin<T>, deserialize_end<T>, reinit<T>},
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) { \
construct<T>, \
destroy<T>, \
dispose<T>, \
disposed<T>, \
serialize<T>, \
deserialize<T>, \
deserialize_begin<T>, \
deserialize_end<T>, \
reinit<T>, \
},
extern const struct typenum_table_entry mkxp_sandbox::typenum_table[SANDBOX_NUM_TYPENUMS] = {BOOST_PP_SEQ_FOR_EACH(_SANDBOX_DEF_TYPENUM_TABLE_ENTRY, _, SANDBOX_TYPENUM_TYPES)};
extern const wasm_size_t mkxp_sandbox::typenum_table_size = SANDBOX_NUM_TYPENUMS;

View file

@ -2062,11 +2062,11 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
}
if (sb().trans_map != nullptr) {
sb().trans_map->sandbox_deserialize_end();
sb().trans_map->sandbox_deserialize_end(false);
}
for (const auto &object : sb()->objects) {
if (object.typenum > 0) {
typenum_table[object.typenum - 1].deserialize_end(object.ptr);
typenum_table[object.typenum - 1].deserialize_end(object.ptr, true);
}
}
sb()->vacant_object_keys = boost::container::priority_deque<wasm_objkey_t>(std::less<wasm_objkey_t>(), std::move(vacant_object_keys));

View file

@ -3634,9 +3634,9 @@ int Bitmap::maxSize(){
return glState.caps.maxTexSize;
}
void Bitmap::assumeRubyGC()
void Bitmap::assumeRubyGC(bool value)
{
p->assumingRubyGC = true;
p->assumingRubyGC = value;
}
void Bitmap::releaseResources()
@ -4158,9 +4158,11 @@ void Bitmap::sandbox_deserialize_begin(bool is_new)
deserModified = is_new;
deserSizeChanged = is_new;
assumeRubyGC(false);
}
void Bitmap::sandbox_deserialize_end()
void Bitmap::sandbox_deserialize_end(bool is_sandbox_object)
{
if (isDisposed()) return;
if (p->selfLores != nullptr) {
@ -4174,6 +4176,9 @@ void Bitmap::sandbox_deserialize_end()
if ((p->selfHires != nullptr && p->selfHires->deserModified) || (p->selfLores != nullptr && p->selfLores->deserModified)) {
deserModified = true;
}
if (isDisposed()) return;
assumeRubyGC(is_sandbox_object && p->selfHires != nullptr);
}
void Bitmap::sandbox_reinit()

View file

@ -215,13 +215,13 @@ public:
static int maxSize();
void assumeRubyGC();
void assumeRubyGC(bool value = true);
#ifdef MKXPZ_RETRO
bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
bool sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
void sandbox_deserialize_begin(bool is_new);
void sandbox_deserialize_end();
void sandbox_deserialize_end(bool is_sandbox_object);
void sandbox_reinit();
#endif // MKXPZ_RETRO