Fix serialization of Tilemap::Autotiles and TilemapVX::BitmapArray in libretro builds, for real this time

This commit is contained in:
刘皓 2025-05-27 19:11:58 -04:00
parent 002b66d167
commit ede42dbb1b
No known key found for this signature in database
GPG key ID: 7901753DB465B711
10 changed files with 70 additions and 54 deletions

View file

@ -25,12 +25,10 @@
using namespace mkxp_sandbox;
template <typename T> static typename std::enable_if<std::is_constructible<T>::value, void *>::type constructor() {
static_assert(!(std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value), "this type should not have a public constructor");
return new T;
}
template <typename T> static typename std::enable_if<!std::is_constructible<T>::value && std::is_constructible<T, Exception &>::value, void *>::type constructor() {
static_assert(!(std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::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 <typename T> static typename std::enable_if<!std::is_constructible<T>::
}
}
template <typename T> static typename std::enable_if<!std::is_constructible<T>::value && !std::is_constructible<T, Exception &>::value, void *>::type constructor() {
static_assert((std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value), "this type should have a public constructor");
return nullptr;
}
template <typename T> static typename std::enable_if<std::is_destructible<T>::value>::type destructor(void *self) {
static_assert(!(std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value), "this type should not have a public destructor");
template <typename T> static void destructor(void *self) {
if (self != nullptr) {
delete (T *)self;
}
}
template <typename T> static typename std::enable_if<!std::is_destructible<T>::value>::type destructor(void *self) {
static_assert(std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value, "this type should have a public destructor");
}
template <typename T> static bool serialize(const void *self, void *&data, wasm_size_t &max_size) {
return ((const T *)self)->sandbox_serialize(data, max_size);
}

View file

@ -60,10 +60,6 @@ struct tilemap_autotiles_binding_init : boost::asio::coroutine {
BOOST_ASIO_CORO_REENTER (this) {
GFX_LOCK;
if (get_private_data<Tilemap::Autotiles>(self) == nullptr) {
return self;
}
SANDBOX_AWAIT_S(0, rb_num2ulong, i);
get_private_data<Tilemap::Autotiles>(self)->set(SANDBOX_SLOT(0), get_private_data<Bitmap>(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<Tilemap>(self)->getAutotiles(sb().e), "autotiles", tilemap_autotiles_class));
SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, get_private_data<Tilemap>(self)->getAutotiles(sb().e), "autotiles", tilemap_autotiles_class));
SANDBOX_GUARD(SANDBOX_AWAIT(wrap_property, self, &get_private_data<Tilemap>(self)->getColor(sb().e), "color", color_class));
SANDBOX_GUARD(SANDBOX_AWAIT(wrap_property, self, &get_private_data<Tilemap>(self)->getTone(sb().e), "tone", tone_class));

View file

@ -59,10 +59,6 @@ struct bitmap_array_binding_init : boost::asio::coroutine {
BOOST_ASIO_CORO_REENTER (this) {
GFX_LOCK;
if (get_private_data<TilemapVX::BitmapArray>(self) == nullptr) {
return self;
}
SANDBOX_AWAIT_S(0, rb_num2ulong, i);
get_private_data<TilemapVX::BitmapArray>(self)->set(SANDBOX_SLOT(0), get_private_data<Bitmap>(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<TilemapVX>(self)->getBitmapArray(sb().e), "bitmap_array", bitmap_array_class));
SANDBOX_GUARD(SANDBOX_AWAIT_S(1, wrap_property, self, get_private_data<TilemapVX>(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)) {

View file

@ -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<Tilemap::Autotiles>);
#else
#define TilemapAutotilesType "TilemapAutotiles"
DEF_ALLOCFUNC_CUSTOMFREE(TilemapAutotiles, freeInstance<Tilemap::Autotiles>);
#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);

View file

@ -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<TilemapVX::BitmapArray>);
#else
DEF_ALLOCFUNC(TilemapVX);
#define BitmapArrayType "BitmapArray"
DEF_ALLOCFUNC_CUSTOMFREE(BitmapArray, freeInstance<TilemapVX::BitmapArray>);
#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);

View file

@ -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<Tilemap::Autotiles>::value && typenum != get_typenum<TilemapVX::BitmapArray>::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<Color>::value && typenum != get_typenum<Tone>::value && typenum != get_typenum<Rect>::value) DESER_OBJECTS_END_FAIL;
void *ptr = typenum_table[typenum - 1].constructor();
if (ptr == nullptr && typenum != get_typenum<Tilemap::Autotiles>::value && typenum != get_typenum<TilemapVX::BitmapArray>::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;

View file

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

View file

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

View file

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

View file

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