From ede42dbb1bd19270f44463d22200584a9f8c17c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Tue, 27 May 2025 19:11:58 -0400 Subject: [PATCH] Fix serialization of `Tilemap::Autotiles` and `TilemapVX::BitmapArray` in libretro builds, for real this time --- binding-sandbox/binding-util.cpp | 14 +----------- binding-sandbox/tilemap-binding.cpp | 6 +----- binding-sandbox/tilemapvx-binding.cpp | 6 +----- binding/tilemap-binding.cpp | 8 ++++--- binding/tilemapvx-binding.cpp | 8 ++++--- src/core.cpp | 4 ++-- src/display/tilemap.cpp | 25 +++++++++++++++------ src/display/tilemap.h | 11 +++++----- src/display/tilemapvx.cpp | 31 +++++++++++++++++++++------ src/display/tilemapvx.h | 11 +++++----- 10 files changed, 70 insertions(+), 54 deletions(-) diff --git a/binding-sandbox/binding-util.cpp b/binding-sandbox/binding-util.cpp index a8806c15..5ac4cf5b 100644 --- a/binding-sandbox/binding-util.cpp +++ b/binding-sandbox/binding-util.cpp @@ -25,12 +25,10 @@ using namespace mkxp_sandbox; template static typename std::enable_if::value, void *>::type constructor() { - static_assert(!(std::is_same::value || std::is_same::value), "this type should not have a public constructor"); return new T; } template static typename std::enable_if::value && std::is_constructible::value, void *>::type constructor() { - static_assert(!(std::is_same::value || std::is_same::value), "this type should not have a public constructor"); Exception e; T *obj = new T(e); if (e.is_ok()) { @@ -41,22 +39,12 @@ template static typename std::enable_if:: } } -template static typename std::enable_if::value && !std::is_constructible::value, void *>::type constructor() { - static_assert((std::is_same::value || std::is_same::value), "this type should have a public constructor"); - return nullptr; -} - -template static typename std::enable_if::value>::type destructor(void *self) { - static_assert(!(std::is_same::value || std::is_same::value), "this type should not have a public destructor"); +template static void destructor(void *self) { if (self != nullptr) { delete (T *)self; } } -template static typename std::enable_if::value>::type destructor(void *self) { - static_assert(std::is_same::value || std::is_same::value, "this type should have a public destructor"); -} - template static bool serialize(const void *self, void *&data, wasm_size_t &max_size) { return ((const T *)self)->sandbox_serialize(data, max_size); } diff --git a/binding-sandbox/tilemap-binding.cpp b/binding-sandbox/tilemap-binding.cpp index 557a855a..608fc069 100644 --- a/binding-sandbox/tilemap-binding.cpp +++ b/binding-sandbox/tilemap-binding.cpp @@ -60,10 +60,6 @@ struct tilemap_autotiles_binding_init : boost::asio::coroutine { BOOST_ASIO_CORO_REENTER (this) { GFX_LOCK; - if (get_private_data(self) == nullptr) { - return self; - } - SANDBOX_AWAIT_S(0, rb_num2ulong, i); get_private_data(self)->set(SANDBOX_SLOT(0), get_private_data(obj)); @@ -128,7 +124,7 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) { set_private_data(SANDBOX_SLOT(1), (Tilemap::Autotiles *)nullptr); } - SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, &get_private_data(self)->getAutotiles(sb().e), "autotiles", tilemap_autotiles_class)); + SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, get_private_data(self)->getAutotiles(sb().e), "autotiles", tilemap_autotiles_class)); SANDBOX_GUARD(SANDBOX_AWAIT(wrap_property, self, &get_private_data(self)->getColor(sb().e), "color", color_class)); SANDBOX_GUARD(SANDBOX_AWAIT(wrap_property, self, &get_private_data(self)->getTone(sb().e), "tone", tone_class)); diff --git a/binding-sandbox/tilemapvx-binding.cpp b/binding-sandbox/tilemapvx-binding.cpp index 79b0630f..51d71c2d 100644 --- a/binding-sandbox/tilemapvx-binding.cpp +++ b/binding-sandbox/tilemapvx-binding.cpp @@ -59,10 +59,6 @@ struct bitmap_array_binding_init : boost::asio::coroutine { BOOST_ASIO_CORO_REENTER (this) { GFX_LOCK; - if (get_private_data(self) == nullptr) { - return self; - } - SANDBOX_AWAIT_S(0, rb_num2ulong, i); get_private_data(self)->set(SANDBOX_SLOT(0), get_private_data(obj)); @@ -122,7 +118,7 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) { set_private_data(SANDBOX_SLOT(1), (TilemapVX::BitmapArray *)nullptr); } - SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, &get_private_data(self)->getBitmapArray(sb().e), "bitmap_array", bitmap_array_class)); + SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, get_private_data(self)->getBitmapArray(sb().e), "bitmap_array", bitmap_array_class)); SANDBOX_AWAIT_S(2, rb_class_new_instance, 0, nullptr, sb()->rb_cArray()); for (SANDBOX_SLOT(3) = 0; SANDBOX_SLOT(3) < 9; ++SANDBOX_SLOT(3)) { diff --git a/binding/tilemap-binding.cpp b/binding/tilemap-binding.cpp index d2ce0374..7004b78c 100644 --- a/binding/tilemap-binding.cpp +++ b/binding/tilemap-binding.cpp @@ -29,9 +29,9 @@ #include "disposable-binding.h" #if RAPI_FULL > 187 -DEF_TYPE_CUSTOMFREE(TilemapAutotiles, RUBY_TYPED_NEVER_FREE); +DEF_TYPE_CUSTOMFREE(TilemapAutotiles, freeInstance); #else -#define TilemapAutotilesType "TilemapAutotiles" +DEF_ALLOCFUNC_CUSTOMFREE(TilemapAutotiles, freeInstance); #endif RB_METHOD(tilemapAutotilesSet) { @@ -102,7 +102,7 @@ RB_METHOD(tilemapInitialize) { if (autotilesObj != Qnil) setPrivateData(autotilesObj, 0); - BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, &t->getAutotiles(e), "autotiles", TilemapAutotilesType)); + BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, t->getAutotiles(e), "autotiles", TilemapAutotilesType)); BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, &t->getColor(e), "color", ColorType)); BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, &t->getTone(e), "tone", ToneType)); @@ -167,6 +167,8 @@ void tilemapBindingInit() { VALUE klass = rb_define_class("TilemapAutotiles", rb_cObject); #if RAPI_FULL > 187 rb_define_alloc_func(klass, classAllocate<&TilemapAutotilesType>); +#else + rb_define_alloc_func(klass, TilemapAutotilesAllocate); #endif _rb_define_method(klass, "[]=", tilemapAutotilesSet); diff --git a/binding/tilemapvx-binding.cpp b/binding/tilemapvx-binding.cpp index 638b9dce..25dc0eea 100644 --- a/binding/tilemapvx-binding.cpp +++ b/binding/tilemapvx-binding.cpp @@ -32,10 +32,10 @@ #if RAPI_FULL > 187 DEF_TYPE_CUSTOMNAME(TilemapVX, "Tilemap"); -DEF_TYPE_CUSTOMFREE(BitmapArray, RUBY_TYPED_NEVER_FREE); +DEF_TYPE_CUSTOMFREE(BitmapArray, freeInstance); #else DEF_ALLOCFUNC(TilemapVX); -#define BitmapArrayType "BitmapArray" +DEF_ALLOCFUNC_CUSTOMFREE(BitmapArray, freeInstance); #endif RB_METHOD(tilemapVXInitialize) { @@ -64,7 +64,7 @@ RB_METHOD(tilemapVXInitialize) { if (autotilesObj != Qnil) setPrivateData(autotilesObj, 0); - BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, &t->getBitmapArray(e), "bitmap_array", BitmapArrayType, + BINDING_GUARD_F(GFX_UNLOCK, wrapProperty(self, t->getBitmapArray(e), "bitmap_array", BitmapArrayType, rb_const_get(rb_cObject, rb_intern("Tilemap")))); autotilesObj = rb_iv_get(self, "bitmap_array"); @@ -173,6 +173,8 @@ void tilemapVXBindingInit() { klass = rb_define_class_under(klass, "BitmapArray", rb_cObject); #if RAPI_FULL > 187 rb_define_alloc_func(klass, classAllocate<&BitmapArrayType>); +#else + rb_define_alloc_func(klass, BitmapArrayAllocate); #endif _rb_define_method(klass, "[]=", tilemapVXBitmapsSet); diff --git a/src/core.cpp b/src/core.cpp index bf559268..28a02bdf 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -1857,7 +1857,7 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) { if (object.typenum != typenum) { object.typenum = typenum; object.inner.ptr = typenum_table[typenum - 1].constructor(); - if (object.inner.ptr == nullptr && typenum != get_typenum::value && typenum != get_typenum::value) DESER_OBJECTS_END_FAIL; + if (object.inner.ptr == nullptr) DESER_OBJECTS_END_FAIL; } if (!typenum_table[typenum - 1].deserialize(object.inner.ptr, data, max_size)) DESER_OBJECTS_END_FAIL; auto it = objects_deser.find(object_key); @@ -1879,7 +1879,7 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) { if (!sandbox_deserialize(typenum, data, max_size)) DESER_OBJECTS_END_FAIL; if (typenum != get_typenum::value && typenum != get_typenum::value && typenum != get_typenum::value) DESER_OBJECTS_END_FAIL; void *ptr = typenum_table[typenum - 1].constructor(); - if (ptr == nullptr && typenum != get_typenum::value && typenum != get_typenum::value) DESER_OBJECTS_END_FAIL; + if (ptr == nullptr) DESER_OBJECTS_END_FAIL; if (!typenum_table[typenum - 1].deserialize(ptr, data, max_size)) { typenum_table[typenum - 1].destructor(ptr); DESER_OBJECTS_END_FAIL; diff --git a/src/display/tilemap.cpp b/src/display/tilemap.cpp index fde98461..8e0fa149 100644 --- a/src/display/tilemap.cpp +++ b/src/display/tilemap.cpp @@ -1267,7 +1267,7 @@ Bitmap *Tilemap::Autotiles::get(int i) const Tilemap::Tilemap(Viewport *viewport) { p = new TilemapPrivate(viewport); - atProxy.tilemap = this; + atProxy = new Autotiles(this); } Tilemap::~Tilemap() @@ -1293,9 +1293,9 @@ void Tilemap::update(Exception &exception) ++p->tiles.aniIdx; } -Tilemap::Autotiles &Tilemap::getAutotiles(Exception &exception) +Tilemap::Autotiles *Tilemap::getAutotiles(Exception &exception) { - GUARD_V(atProxy, guardDisposed(exception)); + GUARD_V(nullptr, guardDisposed(exception)); return atProxy; } @@ -1454,7 +1454,8 @@ void Tilemap::initDynAttribs() void Tilemap::releaseResources() { delete p; - atProxy.tilemap = 0; + if (atProxy) + atProxy->tilemap = 0; } #ifdef MKXPZ_RETRO @@ -1522,6 +1523,8 @@ bool Tilemap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size if (!mkxp_sandbox::sandbox_serialize(p->color, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->tone, data, max_size)) return false; + if (!mkxp_sandbox::sandbox_serialize(atProxy, data, max_size)) return false; + return true; } @@ -1555,7 +1558,11 @@ bool Tilemap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t & for (size_t i = 0; i < zlayersMax; ++i) if (!mkxp_sandbox::sandbox_deserialize(p->zlayerVert[i], data, max_size)) return false; for (size_t i = 0; i < zlayersMax + 1; ++i) - if (!mkxp_sandbox::sandbox_deserialize((mkxp_sandbox::wasm_size_t &)p->zlayerBases[i], data, max_size)) return false; + { + mkxp_sandbox::wasm_size_t value; + if (!mkxp_sandbox::sandbox_deserialize(value, data, max_size)) return false; + p->zlayerBases[i] = value; + } if (!mkxp_sandbox::sandbox_deserialize(p->tiles.animated, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->tiles.aniIdx, data, max_size)) return false; @@ -1567,7 +1574,11 @@ bool Tilemap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t & for (size_t i = 0; i < zlayersMax; ++i) if (!p->elem.zlayers[i]->sandbox_deserialize_viewport_element(data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((mkxp_sandbox::wasm_size_t &)p->elem.activeLayers, data, max_size)) return false; + { + mkxp_sandbox::wasm_size_t value; + if (!mkxp_sandbox::sandbox_deserialize(value, data, max_size)) return false; + p->elem.activeLayers = value; + } if (!mkxp_sandbox::sandbox_deserialize(p->elem.sceneGeo, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false; @@ -1582,6 +1593,8 @@ bool Tilemap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t & if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false; + if (!mkxp_sandbox::sandbox_deserialize(atProxy, data, max_size)) return false; + return true; } #endif // MKXPZ_RETRO diff --git a/src/display/tilemap.h b/src/display/tilemap.h index 486ef16c..a5d0f112 100644 --- a/src/display/tilemap.h +++ b/src/display/tilemap.h @@ -45,6 +45,10 @@ public: class Autotiles { public: + Autotiles() : tilemap(nullptr) {} + Autotiles(Tilemap *tilemap) : tilemap(tilemap) {} + ~Autotiles() { if (tilemap) tilemap->atProxy = nullptr; } + void set(int i, Bitmap *bitmap); Bitmap *get(int i) const; @@ -54,9 +58,6 @@ public: #endif // MKXPZ_RETRO private: - Autotiles() {} - ~Autotiles() {} - Tilemap *tilemap; friend class Tilemap; friend struct TilemapPrivate; @@ -67,7 +68,7 @@ public: void update(Exception &exception); - Autotiles &getAutotiles(Exception &exception); + Autotiles *getAutotiles(Exception &exception); Viewport *getViewport(Exception &exception) const; DECL_ATTR( Tileset, Bitmap* ) @@ -92,7 +93,7 @@ public: private: TilemapPrivate *p; - Autotiles atProxy; + Autotiles *atProxy; void releaseResources(); const char *klassName() const { return "tilemap"; } diff --git a/src/display/tilemapvx.cpp b/src/display/tilemapvx.cpp index 6ab261b9..469f40d8 100644 --- a/src/display/tilemapvx.cpp +++ b/src/display/tilemapvx.cpp @@ -474,7 +474,7 @@ Bitmap *TilemapVX::BitmapArray::get(int i) const TilemapVX::TilemapVX(Viewport *viewport) { p = new TilemapVXPrivate(viewport); - bmProxy.tilemap = this; + bmProxy = new BitmapArray(this); } TilemapVX::~TilemapVX() @@ -505,9 +505,9 @@ void TilemapVX::update(Exception &exception) p->flashAlphaIdx = 0; } -TilemapVX::BitmapArray &TilemapVX::getBitmapArray(Exception &exception) +TilemapVX::BitmapArray *TilemapVX::getBitmapArray(Exception &exception) { - GUARD_V(bmProxy, guardDisposed(exception)); + GUARD_V(nullptr, guardDisposed(exception)); return bmProxy; } @@ -612,7 +612,8 @@ void TilemapVX::setOY(Exception &exception, int value) void TilemapVX::releaseResources() { delete p; - bmProxy.tilemap = 0; + if (bmProxy) + bmProxy->tilemap = 0; } #ifdef MKXPZ_RETRO @@ -652,6 +653,8 @@ bool TilemapVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_si if (!mkxp_sandbox::sandbox_serialize(p->mapData, data, max_size)) return false; if (!mkxp_sandbox::sandbox_serialize(p->flashMap.getData(), data, max_size)) return false; + if (!mkxp_sandbox::sandbox_serialize(bmProxy, data, max_size)) return false; + return true; } @@ -671,9 +674,21 @@ bool TilemapVX::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t if (!mkxp_sandbox::sandbox_deserialize(p->dispPos, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->groundVert, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->aboveVert, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((mkxp_sandbox::wasm_size_t &)p->allocQuads, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((mkxp_sandbox::wasm_size_t &)p->groundQuads, data, max_size)) return false; - if (!mkxp_sandbox::sandbox_deserialize((mkxp_sandbox::wasm_size_t &)p->aboveQuads, data, max_size)) return false; + { + mkxp_sandbox::wasm_size_t value; + if (!mkxp_sandbox::sandbox_deserialize(value, data, max_size)) return false; + p->allocQuads = value; + } + { + mkxp_sandbox::wasm_size_t value; + if (!mkxp_sandbox::sandbox_deserialize(value, data, max_size)) return false; + p->groundQuads = value; + } + { + mkxp_sandbox::wasm_size_t value; + if (!mkxp_sandbox::sandbox_deserialize(value, data, max_size)) return false; + p->aboveQuads = value; + } if (!mkxp_sandbox::sandbox_deserialize(p->frameIdx, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->aniOffset, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->flashAlphaIdx, data, max_size)) return false; @@ -684,6 +699,8 @@ bool TilemapVX::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t if (!mkxp_sandbox::sandbox_deserialize(p->mapData, data, max_size)) return false; if (!mkxp_sandbox::sandbox_deserialize(p->flashMap.getData(), data, max_size)) return false; + if (!mkxp_sandbox::sandbox_deserialize(bmProxy, data, max_size)) return false; + return true; } #endif // MKXPZ_RETRO diff --git a/src/display/tilemapvx.h b/src/display/tilemapvx.h index a339f530..1069577b 100644 --- a/src/display/tilemapvx.h +++ b/src/display/tilemapvx.h @@ -41,6 +41,10 @@ public: class BitmapArray { public: + BitmapArray() : tilemap(nullptr) {} + BitmapArray(TilemapVX *tilemap) : tilemap(tilemap) {} + ~BitmapArray() { if (tilemap) tilemap->bmProxy = nullptr; } + void set(int i, Bitmap *bitmap); Bitmap *get(int i) const; @@ -50,9 +54,6 @@ public: #endif // MKXPZ_RETRO private: - BitmapArray() {} - ~BitmapArray() {} - TilemapVX *tilemap; friend class TilemapVX; friend struct TilemapVXPrivate; @@ -63,7 +64,7 @@ public: void update(Exception &exception); - BitmapArray &getBitmapArray(Exception &exception); + BitmapArray *getBitmapArray(Exception &exception); DECL_ATTR( Viewport, Viewport* ) DECL_ATTR( MapData, Table* ) @@ -80,7 +81,7 @@ public: private: TilemapVXPrivate *p; - BitmapArray bmProxy; + BitmapArray *bmProxy; void releaseResources(); const char *klassName() const { return "tilemap"; }