mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-08-23 23:33:45 +02:00
Continue implementing save state deserialization in libretro builds
This commit is contained in:
parent
290ce15875
commit
8ca753d85d
36 changed files with 758 additions and 148 deletions
|
@ -220,6 +220,8 @@ void binding_base::strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t
|
||||||
sandbox_strncpy(instance(), dst_address, src, max_size);
|
sandbox_strncpy(instance(), dst_address, src, max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding_base::object::object() : inner {.next = 0}, typenum(0) {}
|
||||||
|
|
||||||
binding_base::object::object(wasm_size_t typenum, void *ptr) : inner {.ptr = ptr}, typenum(typenum) {}
|
binding_base::object::object(wasm_size_t typenum, void *ptr) : inner {.ptr = ptr}, typenum(typenum) {}
|
||||||
|
|
||||||
binding_base::object::object(struct object &&object) noexcept : inner(std::exchange(object.inner, (union binding_base::object::inner){.next = 0})), typenum(std::exchange(object.typenum, 0)) {}
|
binding_base::object::object(struct object &&object) noexcept : inner(std::exchange(object.inner, (union binding_base::object::inner){.next = 0})), typenum(std::exchange(object.typenum, 0)) {}
|
||||||
|
@ -239,10 +241,6 @@ binding_base::object::~object() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<struct binding_base::object> &binding_base::get_objects() const noexcept {
|
|
||||||
return objects;
|
|
||||||
}
|
|
||||||
|
|
||||||
wasm_objkey_t binding_base::create_object(wasm_size_t typenum, void *ptr) {
|
wasm_objkey_t binding_base::create_object(wasm_size_t typenum, void *ptr) {
|
||||||
if (ptr == nullptr || typenum == 0 || typenum > typenum_table_size) {
|
if (ptr == nullptr || typenum == 0 || typenum > typenum_table_size) {
|
||||||
std::abort();
|
std::abort();
|
||||||
|
|
|
@ -199,8 +199,10 @@ namespace mkxp_sandbox {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct typenum_table_entry {
|
struct typenum_table_entry {
|
||||||
|
void *(*constructor)();
|
||||||
void (*destructor)(void *self);
|
void (*destructor)(void *self);
|
||||||
bool (*serialize)(const void *self, void *&data, wasm_size_t &max_size);
|
bool (*serialize)(const void *self, void *&data, wasm_size_t &max_size);
|
||||||
|
bool (*deserialize)(void *self, const void *&data, wasm_size_t &max_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct typenum_table_entry typenum_table[];
|
extern const struct typenum_table_entry typenum_table[];
|
||||||
|
@ -270,6 +272,7 @@ namespace mkxp_sandbox {
|
||||||
// Otherwise, this is a number corresponding to the type of the object.
|
// Otherwise, this is a number corresponding to the type of the object.
|
||||||
wasm_size_t typenum;
|
wasm_size_t typenum;
|
||||||
|
|
||||||
|
object();
|
||||||
object(wasm_size_t typenum, void *ptr);
|
object(wasm_size_t typenum, void *ptr);
|
||||||
object(const struct object &object) = delete;
|
object(const struct object &object) = delete;
|
||||||
object(struct object &&object) noexcept;
|
object(struct object &&object) noexcept;
|
||||||
|
@ -278,12 +281,14 @@ namespace mkxp_sandbox {
|
||||||
~object();
|
~object();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<struct w2c_ruby> _instance;
|
public:
|
||||||
std::vector<struct object> objects;
|
std::vector<struct object> objects;
|
||||||
wasm_objkey_t next_free_objkey;
|
private:
|
||||||
|
std::shared_ptr<struct w2c_ruby> _instance;
|
||||||
wasm_ptr_t stack_ptr;
|
wasm_ptr_t stack_ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
wasm_objkey_t next_free_objkey;
|
||||||
std::unordered_map<key_t, struct fiber, boost::hash<key_t>> fibers;
|
std::unordered_map<key_t, struct fiber, boost::hash<key_t>> fibers;
|
||||||
|
|
||||||
binding_base(std::shared_ptr<struct w2c_ruby> m);
|
binding_base(std::shared_ptr<struct w2c_ruby> m);
|
||||||
|
@ -335,9 +340,6 @@ namespace mkxp_sandbox {
|
||||||
return sandbox_arycpy(instance(), dst_address, src, num_elements);
|
return sandbox_arycpy(instance(), dst_address, src, num_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a reference to all currently existing objects.
|
|
||||||
const std::vector<struct object> &get_objects() const noexcept;
|
|
||||||
|
|
||||||
// Creates a new object and returns its key.
|
// Creates a new object and returns its key.
|
||||||
wasm_objkey_t create_object(wasm_size_t typenum, void *ptr);
|
wasm_objkey_t create_object(wasm_size_t typenum, void *ptr);
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,33 @@
|
||||||
|
|
||||||
using namespace mkxp_sandbox;
|
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()) {
|
||||||
|
return obj;
|
||||||
|
} else {
|
||||||
|
delete obj;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
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");
|
static_assert(!(std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value), "this type should not have a public destructor");
|
||||||
delete (T *)self;
|
if (self != nullptr) {
|
||||||
|
delete (T *)self;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> static typename std::enable_if<!std::is_destructible<T>::value>::type destructor(void *self) {
|
template <typename T> static typename std::enable_if<!std::is_destructible<T>::value>::type destructor(void *self) {
|
||||||
|
@ -37,7 +61,11 @@ template <typename T> static bool serialize(const void *self, void *&data, wasm_
|
||||||
return ((const T *)self)->sandbox_serialize(data, max_size);
|
return ((const T *)self)->sandbox_serialize(data, max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) {.destructor = destructor<T>, .serialize = serialize<T>},
|
template <typename T> static bool deserialize(void *self, const void *&data, wasm_size_t &max_size) {
|
||||||
|
return ((T *)self)->sandbox_deserialize(data, max_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) {.constructor = constructor<T>, .destructor = destructor<T>, .serialize = serialize<T>, .deserialize = deserialize<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 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;
|
extern const wasm_size_t mkxp_sandbox::typenum_table_size = SANDBOX_NUM_TYPENUMS;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ std::vector<std::tuple<const void *, wasm_size_t>> mkxp_sandbox::extra_objects;
|
||||||
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::objects_deser;
|
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::objects_deser;
|
||||||
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::extra_objects_deser;
|
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::extra_objects_deser;
|
||||||
|
|
||||||
sandbox_object_deser_info::sandbox_object_deser_info() : ptr(new std::vector<void **>), typenum(0), ref_count(0), exists(false) {}
|
sandbox_object_deser_info::sandbox_object_deser_info(void *ptr, wasm_size_t typenum) : ptr(ptr), typenum(typenum), ref_count(0), exists(true) {}
|
||||||
|
|
||||||
sandbox_object_deser_info::sandbox_object_deser_info(struct sandbox_object_deser_info &&info) noexcept : ptr(std::exchange(info.ptr, nullptr)), typenum(info.typenum), ref_count(std::exchange(info.ref_count, 1)), exists(std::exchange(info.exists, true)) {}
|
sandbox_object_deser_info::sandbox_object_deser_info(struct sandbox_object_deser_info &&info) noexcept : ptr(std::exchange(info.ptr, nullptr)), typenum(info.typenum), ref_count(std::exchange(info.ref_count, 1)), exists(std::exchange(info.exists, true)) {}
|
||||||
|
|
||||||
|
@ -66,6 +66,32 @@ wasm_size_t sandbox_object_deser_info::get_ref_count() const noexcept {
|
||||||
return ref_count;
|
return ref_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sandbox_object_deser_info::set_ptr(void *ptr, wasm_size_t typenum) {
|
||||||
|
if (this->typenum != typenum) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (exists && ptr != this->ptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!exists) {
|
||||||
|
for (void **ref : *(std::vector<void **> *)this->ptr) {
|
||||||
|
*ref = ptr;
|
||||||
|
}
|
||||||
|
delete (std::vector<void **> *)this->ptr;
|
||||||
|
exists = true;
|
||||||
|
this->ptr = ptr;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *sandbox_object_deser_info::get_ptr() {
|
||||||
|
return exists ? ptr : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wasm_size_t sandbox_object_deser_info::get_typenum() {
|
||||||
|
return typenum;
|
||||||
|
}
|
||||||
|
|
||||||
template <> bool mkxp_sandbox::sandbox_serialize(bool value, void *&data, wasm_size_t &max_size) {
|
template <> bool mkxp_sandbox::sandbox_serialize(bool value, void *&data, wasm_size_t &max_size) {
|
||||||
RESERVE(sizeof(uint8_t));
|
RESERVE(sizeof(uint8_t));
|
||||||
*(uint8_t *)data = value;
|
*(uint8_t *)data = value;
|
||||||
|
@ -221,7 +247,8 @@ template <> bool mkxp_sandbox::sandbox_deserialize(double &value, const void *&d
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> bool mkxp_sandbox::sandbox_serialize(const char *value, void *&data, wasm_size_t &max_size) {
|
template <> bool mkxp_sandbox::sandbox_serialize(const char *value, void *&data, wasm_size_t &max_size) {
|
||||||
wasm_size_t size = std::strlen(value) + 1;
|
wasm_size_t size = std::strlen(value);
|
||||||
|
if (!sandbox_serialize(size, data, max_size)) return false;
|
||||||
RESERVE(size);
|
RESERVE(size);
|
||||||
std::memcpy(data, value, size);
|
std::memcpy(data, value, size);
|
||||||
ADVANCE(size);
|
ADVANCE(size);
|
||||||
|
@ -229,7 +256,8 @@ template <> bool mkxp_sandbox::sandbox_serialize(const char *value, void *&data,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> bool mkxp_sandbox::sandbox_serialize(const std::string &value, void *&data, wasm_size_t &max_size) {
|
template <> bool mkxp_sandbox::sandbox_serialize(const std::string &value, void *&data, wasm_size_t &max_size) {
|
||||||
wasm_size_t size = value.length() + 1;
|
wasm_size_t size = value.length();
|
||||||
|
if (!sandbox_serialize(size, data, max_size)) return false;
|
||||||
RESERVE(size);
|
RESERVE(size);
|
||||||
std::memcpy(data, value.c_str(), size);
|
std::memcpy(data, value.c_str(), size);
|
||||||
ADVANCE(size);
|
ADVANCE(size);
|
||||||
|
@ -239,12 +267,12 @@ template <> bool mkxp_sandbox::sandbox_serialize(const std::string &value, void
|
||||||
template <> bool mkxp_sandbox::sandbox_deserialize(std::string &value, const void *&data, wasm_size_t &max_size) {
|
template <> bool mkxp_sandbox::sandbox_deserialize(std::string &value, const void *&data, wasm_size_t &max_size) {
|
||||||
wasm_size_t size;
|
wasm_size_t size;
|
||||||
if (!sandbox_deserialize(size, data, max_size)) return false;
|
if (!sandbox_deserialize(size, data, max_size)) return false;
|
||||||
if (size == 0 || ((const char *)data)[size - 1] != 0) return false;
|
|
||||||
RESERVE(size);
|
RESERVE(size);
|
||||||
value.resize(size - 1);
|
value.clear();
|
||||||
|
value.resize(size);
|
||||||
char *str = &value[0];
|
char *str = &value[0];
|
||||||
std::memcpy(str, data, size - 1);
|
std::memcpy(str, data, size);
|
||||||
if (std::strlen(str) != size - 1) {
|
if (std::strlen(str) != size) {
|
||||||
value.clear();
|
value.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
|
|
||||||
namespace mkxp_sandbox {
|
namespace mkxp_sandbox {
|
||||||
struct sandbox_object_deser_info {
|
struct sandbox_object_deser_info {
|
||||||
sandbox_object_deser_info();
|
template <typename T> sandbox_object_deser_info(T *&ref) : ptr(new std::vector<void **>({(void **)&ref})), typenum(mkxp_sandbox::get_typenum<T>::value), ref_count(1), exists(false) {}
|
||||||
template <typename T> sandbox_object_deser_info(T *ptr) : ptr(ptr), typenum(get_typenum<T>::value), ref_count(0), exists(true) {}
|
sandbox_object_deser_info(void *ptr, wasm_size_t typenum);
|
||||||
sandbox_object_deser_info(const struct sandbox_object_deser_info &) = delete;
|
sandbox_object_deser_info(const struct sandbox_object_deser_info &) = delete;
|
||||||
sandbox_object_deser_info(struct sandbox_object_deser_info &&) noexcept;
|
sandbox_object_deser_info(struct sandbox_object_deser_info &&) noexcept;
|
||||||
struct sandbox_object_deser_info &operator=(const struct sandbox_object_deser_info &) = delete;
|
struct sandbox_object_deser_info &operator=(const struct sandbox_object_deser_info &) = delete;
|
||||||
|
@ -41,37 +41,25 @@ namespace mkxp_sandbox {
|
||||||
~sandbox_object_deser_info();
|
~sandbox_object_deser_info();
|
||||||
wasm_size_t get_ref_count() const noexcept;
|
wasm_size_t get_ref_count() const noexcept;
|
||||||
template <typename T> bool add_ref(T *&ref) {
|
template <typename T> bool add_ref(T *&ref) {
|
||||||
if (typenum == 0) {
|
if (typenum != mkxp_sandbox::get_typenum<T>::value) {
|
||||||
typenum = get_typenum<T>::value;
|
return false;
|
||||||
} else if (typenum != get_typenum<T>::value) {
|
}
|
||||||
|
if (ref_count > 0 && (std::is_same<T, Color>::value || std::is_same<T, Tone>::value || std::is_same<T, Rect>::value || std::is_same<T, Tilemap::Autotiles>::value || std::is_same<T, TilemapVX::BitmapArray>::value)) {
|
||||||
|
// Don't allow types that are copied by value (Color, Tone and Rect) or autotiles/bitmap arrays to be referenced more than once
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (exists) {
|
if (exists) {
|
||||||
ref = (T *)ptr;
|
ref = (T *)ptr;
|
||||||
} else {
|
} else {
|
||||||
|
ref = nullptr;
|
||||||
((std::vector<void **> *)ptr)->push_back((void **)&ref);
|
((std::vector<void **> *)ptr)->push_back((void **)&ref);
|
||||||
}
|
}
|
||||||
++ref_count;
|
++ref_count;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
template <typename T> bool set_ptr(T *ptr) {
|
bool set_ptr(void *ptr, wasm_size_t typenum);
|
||||||
if (typenum == 0) {
|
void *get_ptr();
|
||||||
typenum = get_typenum<T>::value;
|
wasm_size_t get_typenum();
|
||||||
} else if (typenum != get_typenum<T>::value) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (exists && ptr != this->ptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!exists) {
|
|
||||||
for (void **ref : *(std::vector<void **> *)this->ptr) {
|
|
||||||
*(T **)ref = ptr;
|
|
||||||
}
|
|
||||||
delete (std::vector<void **> *)this->ptr;
|
|
||||||
exists = true;
|
|
||||||
this->ptr = ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// If `exists` is true, this is a pointer to the object. Otherwise, this is a `std::vector<void **>` of pointers that are waiting to point to the object.
|
// If `exists` is true, this is a pointer to the object. Otherwise, this is a `std::vector<void **>` of pointers that are waiting to point to the object.
|
||||||
|
@ -138,7 +126,7 @@ namespace mkxp_sandbox {
|
||||||
extra_objects.clear();
|
extra_objects.clear();
|
||||||
|
|
||||||
wasm_objkey_t key = 0;
|
wasm_objkey_t key = 0;
|
||||||
for (const auto &object : sb()->get_objects()) {
|
for (const auto &object : sb()->objects) {
|
||||||
++key;
|
++key;
|
||||||
if (object.typenum == get_typenum<T>::value) {
|
if (object.typenum == get_typenum<T>::value) {
|
||||||
map.emplace((T *)object.inner.ptr, (struct info){.key = key, .is_extra = false});
|
map.emplace((T *)object.inner.ptr, (struct info){.key = key, .is_extra = false});
|
||||||
|
@ -221,7 +209,8 @@ namespace mkxp_sandbox {
|
||||||
auto &deser_map = type != 0 ? extra_objects_deser : objects_deser;
|
auto &deser_map = type != 0 ? extra_objects_deser : objects_deser;
|
||||||
const auto it = deser_map.find(key);
|
const auto it = deser_map.find(key);
|
||||||
if (it == deser_map.end()) {
|
if (it == deser_map.end()) {
|
||||||
return deser_map.emplace(key, sandbox_object_deser_info()).first->second.add_ref(ref);
|
deser_map.emplace(key, sandbox_object_deser_info(ref));
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return it->second.add_ref(ref);
|
return it->second.add_ref(ref);
|
||||||
}
|
}
|
||||||
|
@ -234,6 +223,15 @@ namespace mkxp_sandbox {
|
||||||
|
|
||||||
is_deserializing = false;
|
is_deserializing = false;
|
||||||
objects_deser.clear();
|
objects_deser.clear();
|
||||||
|
|
||||||
|
// Delete extra objects with no references so we don't leak them
|
||||||
|
for (auto &pair : extra_objects_deser) {
|
||||||
|
struct sandbox_object_deser_info &info = pair.second;
|
||||||
|
if (info.get_ref_count() == 0 && info.get_ptr() != nullptr) {
|
||||||
|
typenum_table[info.get_typenum() - 1].destructor(info.get_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extra_objects_deser.clear();
|
extra_objects_deser.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -268,9 +266,6 @@ namespace mkxp_sandbox {
|
||||||
if (!sandbox_deserialize(value.back(), data, max_size)) return false;
|
if (!sandbox_deserialize(value.back(), data, max_size)) return false;
|
||||||
--size;
|
--size;
|
||||||
}
|
}
|
||||||
for (T &item : value) {
|
|
||||||
if (!sandbox_deserialize(item, data, max_size)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,10 @@ bool sandbox::sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) cons
|
||||||
return wasi->sandbox_serialize(data, max_size);
|
return wasi->sandbox_serialize(data, max_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sandbox::sandbox_deserialize_fdtable(const void *&data, wasm_size_t &max_size) {
|
||||||
|
return wasi->sandbox_deserialize(data, max_size);
|
||||||
|
}
|
||||||
|
|
||||||
Movie *sandbox::get_movie_from_main_thread() {
|
Movie *sandbox::get_movie_from_main_thread() {
|
||||||
return movie.load(std::memory_order_relaxed); // No need for synchronization because we always set the movie from the main thread
|
return movie.load(std::memory_order_relaxed); // No need for synchronization because we always set the movie from the main thread
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace mkxp_sandbox {
|
||||||
sandbox();
|
sandbox();
|
||||||
~sandbox();
|
~sandbox();
|
||||||
bool sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const;
|
bool sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const;
|
||||||
|
bool sandbox_deserialize_fdtable(const void *&data, wasm_size_t &max_size);
|
||||||
Movie *get_movie_from_main_thread();
|
Movie *get_movie_from_main_thread();
|
||||||
Movie *get_movie_from_audio_thread();
|
Movie *get_movie_from_audio_thread();
|
||||||
void set_movie(Movie *new_movie);
|
void set_movie(Movie *new_movie);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -41,8 +42,8 @@ struct fs_dir *wasi_file_entry::dir_handle() const noexcept {
|
||||||
return (struct fs_dir *)handle;
|
return (struct fs_dir *)handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileSystem::File *wasi_file_entry::file_handle() const noexcept {
|
struct fs_file *wasi_file_entry::file_handle() const noexcept {
|
||||||
return (struct FileSystem::File *)handle;
|
return (struct fs_file *)handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ruby(ruby) {
|
wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ruby(ruby) {
|
||||||
|
@ -50,15 +51,15 @@ wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ru
|
||||||
fdtable.push_back({.type = wasi_fd_type::STDIN});
|
fdtable.push_back({.type = wasi_fd_type::STDIN});
|
||||||
fdtable.push_back({.type = wasi_fd_type::STDOUT});
|
fdtable.push_back({.type = wasi_fd_type::STDOUT});
|
||||||
fdtable.push_back({.type = wasi_fd_type::STDERR});
|
fdtable.push_back({.type = wasi_fd_type::STDERR});
|
||||||
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Game"), .writable = true}});
|
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.path = std::string("/Game"), .writable = true}});
|
||||||
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Save"), .writable = true}});
|
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.path = std::string("/Save"), .writable = true}});
|
||||||
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/System"), .writable = false}});
|
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.path = std::string("/System"), .writable = false}});
|
||||||
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Dist"), .writable = false}});
|
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.path = std::string("/Dist"), .writable = false}});
|
||||||
}
|
}
|
||||||
|
|
||||||
wasi_t::~w2c_wasi__snapshot__preview1() {
|
wasi_t::~w2c_wasi__snapshot__preview1() {
|
||||||
// Close all of the open WASI file descriptors
|
// Close all of the open WASI file descriptors
|
||||||
for (size_t i = fdtable.size(); i > 0;) {
|
for (uint32_t i = fdtable.size(); i > 0;) {
|
||||||
deallocate_file_descriptor(--i);
|
deallocate_file_descriptor(--i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,12 +77,17 @@ struct fs_enumerate_data {
|
||||||
|
|
||||||
uint32_t wasi_t::allocate_file_descriptor(enum wasi_fd_type type, void *handle) {
|
uint32_t wasi_t::allocate_file_descriptor(enum wasi_fd_type type, void *handle) {
|
||||||
if (vacant_fds.empty()) {
|
if (vacant_fds.empty()) {
|
||||||
|
if (fdtable.size() >= UINT32_MAX) {
|
||||||
|
MKXPZ_THROW(std::bad_alloc());
|
||||||
|
}
|
||||||
uint32_t fd = fdtable.size();
|
uint32_t fd = fdtable.size();
|
||||||
fdtable.push_back({.type = type, .handle = handle});
|
fdtable.push_back({.type = type, .handle = handle});
|
||||||
return fd;
|
return fd;
|
||||||
} else {
|
} else {
|
||||||
uint32_t fd = vacant_fds.back();
|
uint32_t fd = vacant_fds.back();
|
||||||
vacant_fds.pop_back();
|
vacant_fds.pop_back();
|
||||||
|
fdtable[fd].type = type;
|
||||||
|
fdtable[fd].handle = handle;
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,16 +103,12 @@ void wasi_t::deallocate_file_descriptor(uint32_t fd) {
|
||||||
delete fdtable[fd].file_handle();
|
delete fdtable[fd].file_handle();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fdtable.empty() && fd == fdtable.size() - 1) {
|
fdtable[fd] = {.type = wasi_fd_type::VACANT, .handle = nullptr};
|
||||||
fdtable.pop_back();
|
vacant_fds.push_back(fd);
|
||||||
} else {
|
|
||||||
fdtable[fd] = {.type = wasi_fd_type::VACANT, .handle = nullptr};
|
|
||||||
vacant_fds.push_back(fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wasi_t::ptr(wasm_ptr_t address) const noexcept {
|
void *wasi_t::ptr(wasm_ptr_t address) const noexcept {
|
||||||
|
@ -130,9 +132,9 @@ const char *wasi_t::str(wasm_ptr_t address) const noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const {
|
bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const {
|
||||||
if (!::sandbox_serialize((wasm_size_t)fdtable.size(), data, max_size)) return false;
|
if (!::sandbox_serialize((uint32_t)fdtable.size(), data, max_size)) return false;
|
||||||
|
|
||||||
wasm_size_t num_free_handles = 0;
|
uint32_t num_free_handles = 0;
|
||||||
|
|
||||||
for (const struct wasi_file_entry &entry : fdtable) {
|
for (const struct wasi_file_entry &entry : fdtable) {
|
||||||
if (entry.type == wasi_fd_type::FSDIR) {
|
if (entry.type == wasi_fd_type::FSDIR) {
|
||||||
|
@ -142,8 +144,8 @@ bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
num_free_handles = 0;
|
num_free_handles = 0;
|
||||||
}
|
}
|
||||||
if (!::sandbox_serialize((uint8_t)1, data, max_size)) return false;
|
if (!::sandbox_serialize((uint8_t)1, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(entry.dir_handle()->root, data, max_size)) return false;
|
||||||
if (!::sandbox_serialize(entry.dir_handle()->path, data, max_size)) return false;
|
if (!::sandbox_serialize(entry.dir_handle()->path, data, max_size)) return false;
|
||||||
if (!::sandbox_serialize(entry.dir_handle()->root->path, data, max_size)) return false;
|
|
||||||
} else if (entry.type == wasi_fd_type::FSFILE) {
|
} else if (entry.type == wasi_fd_type::FSFILE) {
|
||||||
if (num_free_handles > 0) {
|
if (num_free_handles > 0) {
|
||||||
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||||
|
@ -151,7 +153,8 @@ bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
num_free_handles = 0;
|
num_free_handles = 0;
|
||||||
}
|
}
|
||||||
if (!::sandbox_serialize((uint8_t)2, data, max_size)) return false;
|
if (!::sandbox_serialize((uint8_t)2, data, max_size)) return false;
|
||||||
if (!::sandbox_serialize(entry.file_handle()->path(), data, max_size)) return false;
|
if (!::sandbox_serialize(entry.file_handle()->root, data, max_size)) return false;
|
||||||
|
if (!::sandbox_serialize(entry.file_handle()->file.path(), data, max_size)) return false;
|
||||||
} else {
|
} else {
|
||||||
++num_free_handles;
|
++num_free_handles;
|
||||||
}
|
}
|
||||||
|
@ -165,6 +168,79 @@ bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wasi_t::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) {
|
||||||
|
uint32_t size;
|
||||||
|
if (!::sandbox_deserialize(size, data, max_size)) return false;
|
||||||
|
|
||||||
|
for (uint32_t i = fdtable.size(); i > size;) {
|
||||||
|
deallocate_file_descriptor(--i);
|
||||||
|
}
|
||||||
|
vacant_fds.clear();
|
||||||
|
fdtable.resize(size, {.type = wasi_fd_type::VACANT});
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
while (i < size) {
|
||||||
|
uint8_t type;
|
||||||
|
if (!::sandbox_deserialize(type, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
|
uint32_t num_free_handles;
|
||||||
|
if (!::sandbox_deserialize(num_free_handles, data, max_size)) return false;
|
||||||
|
if (i + num_free_handles > size || i + num_free_handles < i) return false;
|
||||||
|
for (uint32_t j = i; j < i + num_free_handles; ++j) {
|
||||||
|
deallocate_file_descriptor(j);
|
||||||
|
vacant_fds.clear();
|
||||||
|
}
|
||||||
|
i += num_free_handles;
|
||||||
|
} else {
|
||||||
|
if (fdtable[i].type != wasi_fd_type::VACANT && fdtable[i].type != wasi_fd_type::FSDIR && fdtable[i].type != wasi_fd_type::FSFILE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type == 1) {
|
||||||
|
if (fdtable[i].type != wasi_fd_type::VACANT && fdtable[i].type != wasi_fd_type::FSDIR) {
|
||||||
|
deallocate_file_descriptor(i);
|
||||||
|
vacant_fds.clear();
|
||||||
|
}
|
||||||
|
uint32_t root;
|
||||||
|
if (!::sandbox_deserialize(root, data, max_size)) return false;
|
||||||
|
if (root >= fdtable.size() || fdtable[root].type != wasi_fd_type::FS) return false;
|
||||||
|
std::string path;
|
||||||
|
if (!::sandbox_deserialize(path, data, max_size)) return false;
|
||||||
|
path = mkxp_retro::fs->normalize(path.c_str(), false, true);
|
||||||
|
fdtable[i] = {.type = wasi_fd_type::FSDIR, .handle = new fs_dir {.path = path, .root = root, .writable = fdtable[root].dir_handle()->writable}};
|
||||||
|
} else if (type == 2) {
|
||||||
|
if (fdtable[i].type != wasi_fd_type::VACANT && fdtable[i].type != wasi_fd_type::FSFILE) {
|
||||||
|
deallocate_file_descriptor(i);
|
||||||
|
vacant_fds.clear();
|
||||||
|
}
|
||||||
|
uint32_t root;
|
||||||
|
if (!::sandbox_deserialize(root, data, max_size)) return false;
|
||||||
|
if (root >= fdtable.size() || fdtable[root].type != wasi_fd_type::FS) return false;
|
||||||
|
std::string path;
|
||||||
|
if (!::sandbox_deserialize(path, data, max_size)) return false;
|
||||||
|
path = mkxp_retro::fs->normalize(path.c_str(), false, true);
|
||||||
|
struct fs_file *handle = new fs_file {.file {*mkxp_retro::fs, path.c_str(), fdtable[root].dir_handle()->writable ? fdtable[root].dir_handle()->path.c_str() : nullptr, false}, .root = root};
|
||||||
|
if (!handle->file.is_open() || (fdtable[root].dir_handle()->writable && !handle->file.is_write_open())) {
|
||||||
|
delete handle;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fdtable[i] = {.type = wasi_fd_type::FSFILE, .handle = handle};
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t j = 0; i < fdtable.size(); ++j) {
|
||||||
|
if (fdtable[j].type == wasi_fd_type::VACANT) {
|
||||||
|
vacant_fds.push_back(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" uint32_t w2c_wasi__snapshot__preview1_args_get(wasi_t *wasi, wasm_ptr_t argv, wasm_ptr_t argv_buf) {
|
extern "C" uint32_t w2c_wasi__snapshot__preview1_args_get(wasi_t *wasi, wasm_ptr_t argv, wasm_ptr_t argv_buf) {
|
||||||
return WASI_ESUCCESS;
|
return WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -212,6 +288,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_close(wasi_t *wasi, uint32_t
|
||||||
case wasi_fd_type::STDOUT:
|
case wasi_fd_type::STDOUT:
|
||||||
case wasi_fd_type::STDERR:
|
case wasi_fd_type::STDERR:
|
||||||
case wasi_fd_type::FS:
|
case wasi_fd_type::FS:
|
||||||
|
return WASI_EINVAL;
|
||||||
|
|
||||||
case wasi_fd_type::FSDIR:
|
case wasi_fd_type::FSDIR:
|
||||||
case wasi_fd_type::FSFILE:
|
case wasi_fd_type::FSFILE:
|
||||||
|
@ -324,7 +401,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_filestat_get(wasi_t *wasi, u
|
||||||
case wasi_fd_type::FSFILE:
|
case wasi_fd_type::FSFILE:
|
||||||
{
|
{
|
||||||
PHYSFS_Stat stat;
|
PHYSFS_Stat stat;
|
||||||
if (!PHYSFS_stat(wasi->fdtable[fd].file_handle()->path(), &stat)) {
|
if (!PHYSFS_stat(wasi->fdtable[fd].file_handle()->file.path(), &stat)) {
|
||||||
return WASI_ENOENT;
|
return WASI_ENOENT;
|
||||||
}
|
}
|
||||||
if (stat.filetype != PHYSFS_FILETYPE_REGULAR) {
|
if (stat.filetype != PHYSFS_FILETYPE_REGULAR) {
|
||||||
|
@ -448,7 +525,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_read(wasi_t *wasi, uint32_t
|
||||||
#ifdef MKXPZ_BIG_ENDIAN
|
#ifdef MKXPZ_BIG_ENDIAN
|
||||||
ptr -= length;
|
ptr -= length;
|
||||||
#endif // MKXPZ_BIG_ENDIAN
|
#endif // MKXPZ_BIG_ENDIAN
|
||||||
PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->get(), ptr, length);
|
PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->file.get(), ptr, length);
|
||||||
#ifdef MKXPZ_BIG_ENDIAN
|
#ifdef MKXPZ_BIG_ENDIAN
|
||||||
std::reverse(ptr, ptr + length);
|
std::reverse(ptr, ptr + length);
|
||||||
#endif // MKXPZ_BIG_ENDIAN
|
#endif // MKXPZ_BIG_ENDIAN
|
||||||
|
@ -597,12 +674,8 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_renumber(wasi_t *wasi, uint3
|
||||||
} else {
|
} else {
|
||||||
wasi->fdtable[to] = wasi->fdtable[fd];
|
wasi->fdtable[to] = wasi->fdtable[fd];
|
||||||
}
|
}
|
||||||
if (!wasi->fdtable.empty() && fd == wasi->fdtable.size() - 1) {
|
wasi->fdtable[fd] = {.type = wasi_fd_type::VACANT, .handle = nullptr};
|
||||||
wasi->fdtable.pop_back();
|
wasi->vacant_fds.push_back(fd);
|
||||||
} else {
|
|
||||||
wasi->fdtable[fd] = {.type = wasi_fd_type::VACANT, .handle = nullptr};
|
|
||||||
wasi->vacant_fds.push_back(fd);
|
|
||||||
}
|
|
||||||
return WASI_ESUCCESS;
|
return WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +707,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_tell(wasi_t *wasi, uint32_t
|
||||||
return WASI_EINVAL;
|
return WASI_EINVAL;
|
||||||
|
|
||||||
case wasi_fd_type::FSFILE:
|
case wasi_fd_type::FSFILE:
|
||||||
wasi->ref<uint64_t>(result) = PHYSFS_tell(wasi->fdtable[fd].file_handle()->get());
|
wasi->ref<uint64_t>(result) = PHYSFS_tell(wasi->fdtable[fd].file_handle()->file.get());
|
||||||
return WASI_ESUCCESS;
|
return WASI_ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +754,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_write(wasi_t *wasi, uint32_t
|
||||||
|
|
||||||
case wasi_fd_type::FSFILE:
|
case wasi_fd_type::FSFILE:
|
||||||
{
|
{
|
||||||
if (!wasi->fdtable[fd].file_handle()->is_write_open()) {
|
if (!wasi->fdtable[fd].file_handle()->file.is_write_open()) {
|
||||||
return WASI_EROFS;
|
return WASI_EROFS;
|
||||||
}
|
}
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
|
@ -692,7 +765,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_write(wasi_t *wasi, uint32_t
|
||||||
ptr -= length;
|
ptr -= length;
|
||||||
std::reverse(ptr, ptr + length);
|
std::reverse(ptr, ptr + length);
|
||||||
#endif // MKXPZ_BIG_ENDIAN
|
#endif // MKXPZ_BIG_ENDIAN
|
||||||
PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->get_write(), ptr, length);
|
PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->file.get_write(), ptr, length);
|
||||||
#ifdef MKXPZ_BIG_ENDIAN
|
#ifdef MKXPZ_BIG_ENDIAN
|
||||||
std::reverse(ptr, ptr + length);
|
std::reverse(ptr, ptr + length);
|
||||||
#endif // MKXPZ_BIG_ENDIAN
|
#endif // MKXPZ_BIG_ENDIAN
|
||||||
|
@ -777,6 +850,10 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_path_open(wasi_t *wasi, uint32_
|
||||||
return WASI_EBADF;
|
return WASI_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wasi->fdtable.size() >= UINT32_MAX && wasi->vacant_fds.empty()) {
|
||||||
|
return WASI_EMFILE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (wasi->fdtable[fd].type) {
|
switch (wasi->fdtable[fd].type) {
|
||||||
case wasi_fd_type::VACANT:
|
case wasi_fd_type::VACANT:
|
||||||
return WASI_EBADF;
|
return WASI_EBADF;
|
||||||
|
@ -833,26 +910,27 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_path_open(wasi_t *wasi, uint32_
|
||||||
return WASI_EROFS;
|
return WASI_EROFS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t root = wasi->fdtable[fd].type == wasi_fd_type::FS ? fd : wasi->fdtable[fd].dir_handle()->root;
|
||||||
|
|
||||||
if (exists && stat.filetype == PHYSFS_FILETYPE_DIRECTORY) {
|
if (exists && stat.filetype == PHYSFS_FILETYPE_DIRECTORY) {
|
||||||
struct fs_dir *root = wasi->fdtable[fd].dir_handle()->root != nullptr ? wasi->fdtable[fd].dir_handle()->root : wasi->fdtable[fd].dir_handle();
|
struct fs_dir *handle = new fs_dir {.path = new_path, .root = root, .writable = writable};
|
||||||
struct fs_dir *handle = new fs_dir {.root = root, .path = new_path, .writable = writable};
|
|
||||||
wasi->ref<uint32_t>(result) = wasi->allocate_file_descriptor(wasi_fd_type::FSDIR, handle);
|
wasi->ref<uint32_t>(result) = wasi->allocate_file_descriptor(wasi_fd_type::FSDIR, handle);
|
||||||
} else {
|
} else {
|
||||||
const char *write_path_prefix;
|
const char *write_path_prefix;
|
||||||
if (writable) {
|
if (writable) {
|
||||||
struct fs_dir *root = wasi->fdtable[fd].dir_handle()->root != nullptr ? wasi->fdtable[fd].dir_handle()->root : wasi->fdtable[fd].dir_handle();
|
uint32_t root = wasi->fdtable[fd].type == wasi_fd_type::FS ? fd : wasi->fdtable[fd].dir_handle()->root;
|
||||||
write_path_prefix = root->path.c_str();
|
write_path_prefix = wasi->fdtable[root].dir_handle()->path.c_str();
|
||||||
} else {
|
} else {
|
||||||
write_path_prefix = nullptr;
|
write_path_prefix = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileSystem::File *handle = new FileSystem::File(*mkxp_retro::fs, new_path.c_str(), write_path_prefix, truncate, exists);
|
struct fs_file *handle = new fs_file {.file {*mkxp_retro::fs, new_path.c_str(), write_path_prefix, truncate, exists}, .root = root};
|
||||||
|
|
||||||
// Check for errors opening the read handle and/or write handle
|
// Check for errors opening the read handle and/or write handle
|
||||||
if (!handle->is_open() || (needs_write && writable && !handle->is_write_open())) {
|
if (!handle->file.is_open() || (needs_write && writable && !handle->file.is_write_open())) {
|
||||||
PHYSFS_ErrorCode error = handle->get_read_error();
|
PHYSFS_ErrorCode error = handle->file.get_read_error();
|
||||||
if (error == handle->get_read_error()) {
|
if (error == handle->file.get_read_error()) {
|
||||||
error = handle->get_write_error();
|
error = handle->file.get_write_error();
|
||||||
}
|
}
|
||||||
delete handle;
|
delete handle;
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
@ -922,8 +1000,8 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_path_remove_directory(wasi_t *w
|
||||||
return WASI_ENOTDIR;
|
return WASI_ENOTDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dir *root = wasi->fdtable[fd].dir_handle()->root != nullptr ? wasi->fdtable[fd].dir_handle()->root : wasi->fdtable[fd].dir_handle();
|
uint32_t root = wasi->fdtable[fd].type == wasi_fd_type::FS ? fd : wasi->fdtable[fd].dir_handle()->root;
|
||||||
if (!PHYSFS_delete(new_path.c_str() + root->path.length())) {
|
if (!PHYSFS_delete(new_path.c_str() + wasi->fdtable[root].dir_handle()->path.length())) {
|
||||||
switch (PHYSFS_getLastErrorCode()) {
|
switch (PHYSFS_getLastErrorCode()) {
|
||||||
case PHYSFS_ERR_DIR_NOT_EMPTY:
|
case PHYSFS_ERR_DIR_NOT_EMPTY:
|
||||||
return WASI_ENOTEMPTY;
|
return WASI_ENOTEMPTY;
|
||||||
|
@ -996,8 +1074,8 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_path_unlink_file(wasi_t *wasi,
|
||||||
return WASI_EIO;
|
return WASI_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fs_dir *root = wasi->fdtable[fd].dir_handle()->root != nullptr ? wasi->fdtable[fd].dir_handle()->root : wasi->fdtable[fd].dir_handle();
|
uint32_t root = wasi->fdtable[fd].type == wasi_fd_type::FS ? fd : wasi->fdtable[fd].dir_handle()->root;
|
||||||
if (!PHYSFS_delete(new_path.c_str() + root->path.length())) {
|
if (!PHYSFS_delete(new_path.c_str() + wasi->fdtable[root].dir_handle()->path.length())) {
|
||||||
switch (PHYSFS_getLastErrorCode()) {
|
switch (PHYSFS_getLastErrorCode()) {
|
||||||
case PHYSFS_ERR_READ_ONLY:
|
case PHYSFS_ERR_READ_ONLY:
|
||||||
case PHYSFS_ERR_NO_WRITE_DIR:
|
case PHYSFS_ERR_NO_WRITE_DIR:
|
||||||
|
|
|
@ -160,18 +160,23 @@
|
||||||
typedef std::pair<u32, std::string> path_cache_entry_t;
|
typedef std::pair<u32, std::string> path_cache_entry_t;
|
||||||
|
|
||||||
struct fs_dir {
|
struct fs_dir {
|
||||||
struct fs_dir *root; // Null if this is a preopened directory handle, otherwise a pointer to the handle of the preopened directory that contains this directory.
|
|
||||||
std::string path; // Path of the directory.
|
std::string path; // Path of the directory.
|
||||||
|
uint32_t root; // Undefined if this is a preopened directory, otherwise the file descriptor of the preopened directory that contains this directory.
|
||||||
bool writable; // If true, writes made to this directory handle will be routed into the save directory. Otherwise, writes are disallowed.
|
bool writable; // If true, writes made to this directory handle will be routed into the save directory. Otherwise, writes are disallowed.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fs_file {
|
||||||
|
struct FileSystem::File file;
|
||||||
|
uint32_t root; // The file descriptor of the preopened directory that contains this file.
|
||||||
|
};
|
||||||
|
|
||||||
enum wasi_fd_type {
|
enum wasi_fd_type {
|
||||||
STDIN, // This file descriptor is standard input. The `handle` field is null.
|
STDIN, // This file descriptor is standard input. The `handle` field is null.
|
||||||
STDOUT, // This file descriptor is standard output. The `handle` field is null.
|
STDOUT, // This file descriptor is standard output. The `handle` field is null.
|
||||||
STDERR, // This file descriptor is standard error. The `handle` field is null.
|
STDERR, // This file descriptor is standard error. The `handle` field is null.
|
||||||
FS, // This file descriptor is a preopened directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
FS, // This file descriptor is a preopened directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
||||||
FSDIR, // This file descriptor is a directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
FSDIR, // This file descriptor is a directory handled by PhysFS. The `handle` field is a `struct fs_dir *`.
|
||||||
FSFILE, // This file descriptor is a file handled by PhysFS. The `handle` field is a `struct FileSystem::File *`.
|
FSFILE, // This file descriptor is a file handled by PhysFS. The `handle` field is a `struct fs_file *`.
|
||||||
VACANT, // Indicates this is a vacant file descriptor that doesn't correspond to a file. The `handle` field is null.
|
VACANT, // Indicates this is a vacant file descriptor that doesn't correspond to a file. The `handle` field is null.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,7 +187,7 @@ struct wasi_file_entry {
|
||||||
void *handle;
|
void *handle;
|
||||||
|
|
||||||
struct fs_dir *dir_handle() const noexcept;
|
struct fs_dir *dir_handle() const noexcept;
|
||||||
struct FileSystem::File *file_handle() const noexcept;
|
struct fs_file *file_handle() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct w2c_wasi__snapshot__preview1 {
|
typedef struct w2c_wasi__snapshot__preview1 {
|
||||||
|
@ -232,6 +237,8 @@ typedef struct w2c_wasi__snapshot__preview1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
} wasi_t;
|
} wasi_t;
|
||||||
|
|
||||||
#endif /* MKXPZ_SANDBOX_WASI_H */
|
#endif /* MKXPZ_SANDBOX_WASI_H */
|
||||||
|
|
170
src/core.cpp
170
src/core.cpp
|
@ -32,6 +32,7 @@
|
||||||
#include <alext.h>
|
#include <alext.h>
|
||||||
#include <fluidsynth.h>
|
#include <fluidsynth.h>
|
||||||
|
|
||||||
|
#include "binding-util.h"
|
||||||
#include "mkxp-polyfill.h" // std::mutex, std::strtoul
|
#include "mkxp-polyfill.h" // std::mutex, std::strtoul
|
||||||
#include "git-hash.h"
|
#include "git-hash.h"
|
||||||
|
|
||||||
|
@ -1567,11 +1568,18 @@ extern "C" RETRO_API size_t retro_serialize_size() {
|
||||||
max_size -= (bytes); \
|
max_size -= (bytes); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define OBJECTS_BEGIN_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_serialize_begin();
|
#define SER_OBJECTS_BEGIN_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_serialize_begin();
|
||||||
#define OBJECTS_BEGIN do { BOOST_PP_SEQ_FOR_EACH(OBJECTS_BEGIN_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
#define SER_OBJECTS_BEGIN do { BOOST_PP_SEQ_FOR_EACH(SER_OBJECTS_BEGIN_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
||||||
#define OBJECTS_END_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_serialize_end();
|
#define SER_OBJECTS_END_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_serialize_end();
|
||||||
#define OBJECTS_END do { BOOST_PP_SEQ_FOR_EACH(OBJECTS_END_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
#define SER_OBJECTS_END do { BOOST_PP_SEQ_FOR_EACH(SER_OBJECTS_END_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
||||||
#define OBJECTS_END_FAIL do { OBJECTS_END; return false; } while (0)
|
#define SER_OBJECTS_END_FAIL do { SER_OBJECTS_END; return false; } while (0)
|
||||||
|
|
||||||
|
#define DESER_FAIL do { deinit_sandbox(); return false; } while (0)
|
||||||
|
#define DESER_OBJECTS_BEGIN_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_deserialize_begin();
|
||||||
|
#define DESER_OBJECTS_BEGIN do { BOOST_PP_SEQ_FOR_EACH(DESER_OBJECTS_BEGIN_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
||||||
|
#define DESER_OBJECTS_END_DETAIL(_r, _data, T) sandbox_ptr_map<T>::sandbox_deserialize_end();
|
||||||
|
#define DESER_OBJECTS_END do { BOOST_PP_SEQ_FOR_EACH(DESER_OBJECTS_END_DETAIL, _, SANDBOX_TYPENUM_TYPES) } while (0)
|
||||||
|
#define DESER_OBJECTS_END_FAIL do { DESER_OBJECTS_END; sb()->objects.clear(); sb()->next_free_objkey = 0; DESER_FAIL; } while (0)
|
||||||
|
|
||||||
extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
||||||
wasm_size_t max_size = len;
|
wasm_size_t max_size = len;
|
||||||
|
@ -1646,49 +1654,48 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
||||||
if (!sb().sandbox_serialize_fdtable(data, max_size)) return false;
|
if (!sb().sandbox_serialize_fdtable(data, max_size)) return false;
|
||||||
|
|
||||||
// Write the number of objects, then each object
|
// Write the number of objects, then each object
|
||||||
OBJECTS_BEGIN;
|
SER_OBJECTS_BEGIN;
|
||||||
if (!sandbox_serialize((wasm_size_t)sb()->get_objects().size(), data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize((wasm_size_t)sb()->objects.size(), data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
wasm_size_t num_free_objects = 0;
|
wasm_size_t num_free_objects = 0;
|
||||||
for (const auto &object : sb()->get_objects()) {
|
for (const auto &object : sb()->objects) {
|
||||||
if (object.typenum == 0) {
|
if (object.typenum == 0) {
|
||||||
++num_free_objects;
|
++num_free_objects;
|
||||||
} else if (object.typenum > SANDBOX_NUM_TYPENUMS) {
|
} else if (object.typenum > SANDBOX_NUM_TYPENUMS) {
|
||||||
std::abort();
|
std::abort();
|
||||||
} else {
|
} else {
|
||||||
if (num_free_objects > 0) {
|
if (num_free_objects > 0) {
|
||||||
if (!sandbox_serialize((wasm_size_t)0, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize((wasm_size_t)0, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
if (!sandbox_serialize(num_free_objects, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize(num_free_objects, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
num_free_objects = 0;
|
num_free_objects = 0;
|
||||||
}
|
}
|
||||||
if (!sandbox_serialize(object.typenum, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize(object.typenum, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
if (!typenum_table[object.typenum - 1].serialize(object.inner.ptr, data, max_size)) OBJECTS_END_FAIL;
|
if (!typenum_table[object.typenum - 1].serialize(object.inner.ptr, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (num_free_objects > 0) {
|
if (num_free_objects > 0) {
|
||||||
if (!sandbox_serialize((wasm_size_t)0, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize((wasm_size_t)0, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
if (!sandbox_serialize(num_free_objects, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize(num_free_objects, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
num_free_objects = 0;
|
num_free_objects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the number of extra objects that were found during serialization of the normal objects, then each such object
|
// Write the number of extra objects that were found during serialization of the normal objects, then each such object
|
||||||
if (max_size < sizeof(wasm_size_t)) OBJECTS_END_FAIL;
|
if (max_size < sizeof(wasm_size_t)) SER_OBJECTS_END_FAIL;
|
||||||
wasm_size_t *num_extra_objects_ptr = (wasm_size_t *)data;
|
wasm_size_t *num_extra_objects_ptr = (wasm_size_t *)data;
|
||||||
ADVANCE(sizeof(wasm_size_t));
|
ADVANCE(sizeof(wasm_size_t));
|
||||||
for (size_t i = 0; i < extra_objects.size(); ++i) { // More items can be added to this vector during iteration
|
for (size_t i = 0; i < extra_objects.size(); ++i) { // More items can be added to this vector during iteration
|
||||||
const void *ptr = std::get<0>(extra_objects[i]);
|
const void *ptr = std::get<0>(extra_objects[i]);
|
||||||
wasm_size_t typenum = std::get<1>(extra_objects[i]);
|
wasm_size_t typenum = std::get<1>(extra_objects[i]);
|
||||||
if (typenum == 0) {
|
if (typenum != get_typenum<Color>::value && typenum != get_typenum<Tone>::value && typenum != get_typenum<Rect>::value) {
|
||||||
std::abort();
|
std::fprintf(stderr, "extra object other than Color, Tone or Rect found during save state serialization with typenum %llu (there's probably a bug in the sandbox bindings)\n", (unsigned long long)typenum);
|
||||||
} else if (typenum > SANDBOX_NUM_TYPENUMS) {
|
|
||||||
std::abort();
|
std::abort();
|
||||||
} else {
|
} else {
|
||||||
if (!sandbox_serialize(typenum, data, max_size)) OBJECTS_END_FAIL;
|
if (!sandbox_serialize(typenum, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
if (!typenum_table[typenum - 1].serialize(ptr, data, max_size)) OBJECTS_END_FAIL;
|
if (!typenum_table[typenum - 1].serialize(ptr, data, max_size)) SER_OBJECTS_END_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*num_extra_objects_ptr = (wasm_size_t)extra_objects.size();
|
*num_extra_objects_ptr = (wasm_size_t)extra_objects.size();
|
||||||
|
|
||||||
OBJECTS_END;
|
SER_OBJECTS_END;
|
||||||
std::memset(data, 0, max_size);
|
std::memset(data, 0, max_size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1727,37 +1734,37 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
||||||
// Read the sandbox state
|
// Read the sandbox state
|
||||||
{
|
{
|
||||||
wasm_ptr_t value;
|
wasm_ptr_t value;
|
||||||
if (!sandbox_deserialize(value, data, max_size)) return false;
|
if (!sandbox_deserialize(value, data, max_size)) DESER_FAIL;
|
||||||
sb()->set_machine_stack_pointer(value);
|
sb()->set_machine_stack_pointer(value);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
if (!sandbox_deserialize(value, data, max_size)) return false;
|
if (!sandbox_deserialize(value, data, max_size)) DESER_FAIL;
|
||||||
sb()->set_asyncify_state(value);
|
sb()->set_asyncify_state(value);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
wasm_ptr_t value;
|
wasm_ptr_t value;
|
||||||
if (!sandbox_deserialize(value, data, max_size)) return false;
|
if (!sandbox_deserialize(value, data, max_size)) DESER_FAIL;
|
||||||
sb()->set_asyncify_data(value);
|
sb()->set_asyncify_data(value);
|
||||||
}
|
}
|
||||||
if (!sandbox_deserialize(frame_count, data, max_size)) return false;
|
if (!sandbox_deserialize(frame_count, data, max_size)) DESER_FAIL;
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!sandbox_deserialize(value, data, max_size)) return false;
|
if (!sandbox_deserialize(value, data, max_size)) DESER_FAIL;
|
||||||
frame_time = value;
|
frame_time = value;
|
||||||
}
|
}
|
||||||
if (!sandbox_deserialize(frame_time_remainder, data, max_size)) return false;
|
if (!sandbox_deserialize(frame_time_remainder, data, max_size)) DESER_FAIL;
|
||||||
if (!sandbox_deserialize(retro_run_count, data, max_size)) return false;
|
if (!sandbox_deserialize(retro_run_count, data, max_size)) DESER_FAIL;
|
||||||
if (!sandbox_deserialize(sb().transitioning, data, max_size)) return false;
|
if (!sandbox_deserialize(sb().transitioning, data, max_size)) DESER_FAIL;
|
||||||
{
|
{
|
||||||
bool have_trans_map;
|
bool have_trans_map;
|
||||||
if (!sandbox_deserialize(have_trans_map, data, max_size)) return false;
|
if (!sandbox_deserialize(have_trans_map, data, max_size)) DESER_FAIL;
|
||||||
if (have_trans_map) {
|
if (have_trans_map) {
|
||||||
if (sb().trans_map == nullptr) {
|
if (sb().trans_map == nullptr) {
|
||||||
// TODO
|
// TODO
|
||||||
return false;
|
DESER_FAIL;
|
||||||
}
|
}
|
||||||
if (!sandbox_deserialize(*sb().trans_map, data, max_size)) return false;
|
if (!sandbox_deserialize(*sb().trans_map, data, max_size)) DESER_FAIL;
|
||||||
} else {
|
} else {
|
||||||
if (sb().trans_map != nullptr) {
|
if (sb().trans_map != nullptr) {
|
||||||
delete sb().trans_map;
|
delete sb().trans_map;
|
||||||
|
@ -1768,14 +1775,14 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
||||||
{
|
{
|
||||||
// TODO: movie
|
// TODO: movie
|
||||||
bool have_movie;
|
bool have_movie;
|
||||||
if (!sandbox_deserialize(have_movie, data, max_size)) return false;
|
if (!sandbox_deserialize(have_movie, data, max_size)) DESER_FAIL;
|
||||||
if (have_movie) return false;
|
if (have_movie) DESER_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Read sandbox fibers
|
// Read sandbox fibers
|
||||||
wasm_size_t num_fibers;
|
wasm_size_t num_fibers;
|
||||||
if (!sandbox_deserialize(num_fibers, data, max_size)) return false;
|
if (!sandbox_deserialize(num_fibers, data, max_size)) DESER_FAIL;
|
||||||
|
|
||||||
sb()->fibers.clear();
|
sb()->fibers.clear();
|
||||||
sb()->fibers.reserve(num_fibers);
|
sb()->fibers.reserve(num_fibers);
|
||||||
|
@ -1783,25 +1790,25 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
||||||
while (num_fibers > 0) {
|
while (num_fibers > 0) {
|
||||||
// Read the key of the fiber
|
// Read the key of the fiber
|
||||||
std::tuple<wasm_size_t, wasm_size_t, wasm_size_t> key;
|
std::tuple<wasm_size_t, wasm_size_t, wasm_size_t> key;
|
||||||
if (!sandbox_deserialize(std::get<0>(key), data, max_size)) return false;
|
if (!sandbox_deserialize(std::get<0>(key), data, max_size)) DESER_FAIL;
|
||||||
if (!sandbox_deserialize(std::get<1>(key), data, max_size)) return false;
|
if (!sandbox_deserialize(std::get<1>(key), data, max_size)) DESER_FAIL;
|
||||||
if (!sandbox_deserialize(std::get<2>(key), data, max_size)) return false;
|
if (!sandbox_deserialize(std::get<2>(key), data, max_size)) DESER_FAIL;
|
||||||
|
|
||||||
// Construct the fiber
|
// Construct the fiber
|
||||||
auto &fiber = sb()->fibers.emplace(key, key).first->second;
|
auto &fiber = sb()->fibers.emplace(key, key).first->second;
|
||||||
|
|
||||||
// Read the stack index of the fiber
|
// Read the stack index of the fiber
|
||||||
if (!sandbox_deserialize(fiber.stack_index, data, max_size)) return false;
|
if (!sandbox_deserialize(fiber.stack_index, data, max_size)) DESER_FAIL;
|
||||||
|
|
||||||
// Read sandbox frames
|
// Read sandbox frames
|
||||||
wasm_size_t num_frames;
|
wasm_size_t num_frames;
|
||||||
if (!sandbox_deserialize(num_frames, data, max_size)) return false;
|
if (!sandbox_deserialize(num_frames, data, max_size)) DESER_FAIL;
|
||||||
fiber.deser_stack.reserve(num_frames);
|
fiber.deser_stack.reserve(num_frames);
|
||||||
while (num_frames > 0) {
|
while (num_frames > 0) {
|
||||||
wasm_ptr_t stack_pointer;
|
wasm_ptr_t stack_pointer;
|
||||||
if (!sandbox_deserialize(stack_pointer, data, max_size)) return false;
|
if (!sandbox_deserialize(stack_pointer, data, max_size)) DESER_FAIL;
|
||||||
int32_t state;
|
int32_t state;
|
||||||
if (!sandbox_deserialize(state, data, max_size)) return false;
|
if (!sandbox_deserialize(state, data, max_size)) DESER_FAIL;
|
||||||
fiber.deser_stack.emplace_back(stack_pointer, state);
|
fiber.deser_stack.emplace_back(stack_pointer, state);
|
||||||
--num_frames;
|
--num_frames;
|
||||||
}
|
}
|
||||||
|
@ -1810,6 +1817,85 @@ extern "C" RETRO_API bool retro_unserialize(const void *data, size_t len) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the open WASI file descriptors
|
||||||
|
if (!sb().sandbox_deserialize_fdtable(data, max_size)) DESER_FAIL;
|
||||||
|
|
||||||
|
// Read objects
|
||||||
|
DESER_OBJECTS_BEGIN;
|
||||||
|
sb()->next_free_objkey = 0;
|
||||||
|
wasm_objkey_t object_key = 1;
|
||||||
|
wasm_size_t num_objects;
|
||||||
|
if (!sandbox_deserialize(num_objects, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||||
|
sb()->objects.resize(num_objects);
|
||||||
|
while (object_key <= num_objects) {
|
||||||
|
wasm_size_t typenum;
|
||||||
|
if (!sandbox_deserialize(typenum, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||||
|
if (typenum == 0) {
|
||||||
|
wasm_size_t num_free_objects;
|
||||||
|
if (!::sandbox_deserialize(num_free_objects, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||||
|
if (object_key - 1 + num_free_objects > num_objects || object_key + num_free_objects < object_key) DESER_OBJECTS_END_FAIL;
|
||||||
|
for (wasm_size_t i = object_key; i < object_key + num_free_objects; ++i) {
|
||||||
|
auto &object = sb()->objects[i - 1];
|
||||||
|
if (object.typenum > 0) {
|
||||||
|
if (object.typenum > SANDBOX_NUM_TYPENUMS) {
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
typenum_table[object.typenum - 1].destructor(object.inner.ptr);
|
||||||
|
object.typenum = 0;
|
||||||
|
}
|
||||||
|
object.inner.next = sb()->next_free_objkey;
|
||||||
|
sb()->next_free_objkey = i;
|
||||||
|
}
|
||||||
|
object_key += num_free_objects;
|
||||||
|
} else {
|
||||||
|
if (typenum > SANDBOX_NUM_TYPENUMS) DESER_OBJECTS_END_FAIL;
|
||||||
|
auto &object = sb()->objects[object_key - 1];
|
||||||
|
if (object.typenum > 0 && object.typenum != typenum) {
|
||||||
|
typenum_table[object.typenum - 1].destructor(object.inner.ptr);
|
||||||
|
}
|
||||||
|
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 (!typenum_table[typenum - 1].deserialize(object.inner.ptr, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||||
|
auto it = objects_deser.find(object_key);
|
||||||
|
if (it == objects_deser.end()) {
|
||||||
|
objects_deser.emplace(object_key, sandbox_object_deser_info(object.inner.ptr, typenum));
|
||||||
|
} else {
|
||||||
|
it->second.set_ptr(object.inner.ptr, typenum);
|
||||||
|
}
|
||||||
|
++object_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read extra objects
|
||||||
|
wasm_objkey_t extra_object_key = 1;
|
||||||
|
wasm_size_t num_extra_objects;
|
||||||
|
if (!sandbox_deserialize(num_extra_objects, data, max_size)) DESER_OBJECTS_END_FAIL;
|
||||||
|
while (extra_object_key <= num_extra_objects) {
|
||||||
|
wasm_size_t typenum;
|
||||||
|
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 (!typenum_table[typenum - 1].deserialize(ptr, data, max_size)) {
|
||||||
|
typenum_table[typenum - 1].destructor(ptr);
|
||||||
|
DESER_OBJECTS_END_FAIL;
|
||||||
|
}
|
||||||
|
auto it = extra_objects_deser.find(extra_object_key);
|
||||||
|
if (it == extra_objects_deser.end()) {
|
||||||
|
extra_objects_deser.emplace(extra_object_key, sandbox_object_deser_info(ptr, typenum));
|
||||||
|
} else {
|
||||||
|
if (!it->second.set_ptr(ptr, typenum)) {
|
||||||
|
typenum_table[typenum - 1].destructor(ptr);
|
||||||
|
DESER_OBJECTS_END_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++extra_object_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
DESER_OBJECTS_END;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class Bitmap : public Disposable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Bitmap(Exception &exception, const char *filename);
|
Bitmap(Exception &exception, const char *filename);
|
||||||
Bitmap(Exception &exception, int width, int height, bool isHires = false);
|
Bitmap(Exception &exception, int width = 1, int height = 1, bool isHires = false);
|
||||||
Bitmap(Exception &exception, void *pixeldata, int width, int height);
|
Bitmap(Exception &exception, void *pixeldata, int width, int height);
|
||||||
Bitmap(Exception &exception, TEXFBO &other);
|
Bitmap(Exception &exception, TEXFBO &other);
|
||||||
Bitmap(Exception &exception, SDL_Surface *imgSurf, SDL_Surface *imgSurfHires, bool forceMega = false);
|
Bitmap(Exception &exception, SDL_Surface *imgSurf, SDL_Surface *imgSurfHires, bool forceMega = false);
|
||||||
|
|
|
@ -693,15 +693,42 @@ Font::getSdlFont(Exception &exception)
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool Font::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
bool Font::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
||||||
{
|
{
|
||||||
if (!mkxp_sandbox::sandbox_serialize((int32_t)p->size, data, max_size)) return false;
|
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->bold, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->bold, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->italic, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->italic, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->outline, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->outline, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->shadow, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->shadow, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->name, data, max_size)) return false;
|
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->color, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->color, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->outColor, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->outColor, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_serialize((int32_t)p->size, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_serialize(p->name, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Font::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bold, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->italic, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->outline, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->shadow, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->outColor, data, max_size)) return false;
|
||||||
|
|
||||||
|
// Invalidate the inner font object if either the name or size of this font is different from before
|
||||||
|
if (p->sdlFont != nullptr) {
|
||||||
|
int32_t size = p->size;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->size, data, max_size)) return false;
|
||||||
|
std::string name(p->name);
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->name, data, max_size)) return false;
|
||||||
|
if (p->size != size || p->name != name) {
|
||||||
|
p->sdlFont = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->size, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->name, data, max_size)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -151,6 +151,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -211,10 +211,19 @@ void SceneElement::unlink()
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool SceneElement::sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
bool SceneElement::sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
||||||
{
|
{
|
||||||
if (!mkxp_sandbox::sandbox_serialize((uint64_t)creationStamp, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(creationStamp, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize((int32_t)z, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize((int32_t)z, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(visible, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(visible, data, max_size)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SceneElement::sandbox_deserialize_scene_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(creationStamp, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)z, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(visible, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_REROO
|
#endif // MKXPZ_REROO
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
bool sandbox_serialize_scene_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
||||||
|
bool sandbox_deserialize_scene_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_REROO
|
#endif // MKXPZ_REROO
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -131,7 +132,7 @@ protected:
|
||||||
void unlink();
|
void unlink();
|
||||||
|
|
||||||
IntruListLink<SceneElement> link;
|
IntruListLink<SceneElement> link;
|
||||||
const unsigned int creationStamp;
|
uint64_t creationStamp;
|
||||||
int z;
|
int z;
|
||||||
bool visible;
|
bool visible;
|
||||||
Scene *scene;
|
Scene *scene;
|
||||||
|
|
|
@ -372,4 +372,33 @@ bool Plane::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Plane::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->blendType, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->ox, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->oy, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->zoomX, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->zoomY, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->sceneGeo, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->quadSourceDirty, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->qArray, data, max_size)) return false;
|
||||||
|
if (!sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bitmap, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -896,4 +896,51 @@ bool Sprite::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sprite::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->quad, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->trans, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->mirrored, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->bushDepth, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->efBushDepth, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bushOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->blendType, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->patternBlendType, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->patternTile, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->patternOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->patternScroll, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->patternZoom, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->invert, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->sceneRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->sceneOrig, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->isVisible, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.amp, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.length, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->wave.speed, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->wave.phase, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->wave.qArray, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bitmap, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pattern, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->srcRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -84,6 +84,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -136,6 +136,11 @@ struct FlashMap
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Table *&getData()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void setData(Table *value)
|
void setData(Table *value)
|
||||||
{
|
{
|
||||||
if (data == value)
|
if (data == value)
|
||||||
|
|
|
@ -1463,6 +1463,11 @@ bool Tilemap::Autotiles::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tilemap::Autotiles::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Tilemap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
bool Tilemap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
||||||
{
|
{
|
||||||
if (isDisposed()) return mkxp_sandbox::sandbox_serialize(false, data, max_size);
|
if (isDisposed()) return mkxp_sandbox::sandbox_serialize(false, data, max_size);
|
||||||
|
@ -1515,4 +1520,64 @@ bool Tilemap::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tilemap::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->visible, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->origin, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->dispPos, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->atlas.size, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->atlas.efTilesetH, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->atlas.usableATs, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->atlas.animatedATs, data, max_size)) return false;
|
||||||
|
for (size_t i = 0; i < autotileCount; ++i)
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->atlas.smallATs[i], data, max_size)) return false;
|
||||||
|
for (size_t i = 0; i < autotileCount; ++i)
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->atlas.nATFrames[i], data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->viewpPos, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->groundVert, data, max_size)) return false;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->flashAlphaIdx, data, max_size)) return false;
|
||||||
|
|
||||||
|
if (!p->elem.ground->sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->blendType, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->viewport, data, max_size)) return false;
|
||||||
|
for (size_t i = 0; i < autotileCount; ++i)
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->autotiles[i], data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tileset, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->mapData, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->priorities, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->flashMap.getData(), data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -86,6 +87,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -621,6 +621,11 @@ bool TilemapVX::BitmapArray::sandbox_serialize(void *&data, mkxp_sandbox::wasm_s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TilemapVX::BitmapArray::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool TilemapVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
bool TilemapVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const
|
||||||
{
|
{
|
||||||
if (isDisposed()) return mkxp_sandbox::sandbox_serialize(false, data, max_size);
|
if (isDisposed()) return mkxp_sandbox::sandbox_serialize(false, data, max_size);
|
||||||
|
@ -645,4 +650,36 @@ bool TilemapVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_si
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TilemapVX::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->origin, data, max_size)) return false;
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
if (!p->above.sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
if (!p->sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
for (size_t i = 0; i < BM_COUNT; ++i)
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bitmaps[i], data, max_size)) return false;
|
||||||
|
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;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -74,6 +75,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -244,6 +244,28 @@ bool Viewport::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_siz
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Viewport::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->screenRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->isOnScreen, data, max_size)) return false;
|
||||||
|
if (!sandbox_deserialize_scene_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->rect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->color, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MXKPZ_RETRO
|
#endif // MXKPZ_RETRO
|
||||||
|
|
||||||
|
|
||||||
|
@ -293,4 +315,12 @@ bool ViewportElement::sandbox_serialize_viewport_element(void *&data, mkxp_sandb
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ViewportElement::sandbox_deserialize_viewport_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
if (!sandbox_deserialize_scene_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(m_viewport, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MXKPZ_RETRO
|
#endif // MXKPZ_RETRO
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MXKPZ_RETRO
|
#endif // MXKPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -85,6 +86,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize_viewport_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
bool sandbox_serialize_viewport_element(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
||||||
|
bool sandbox_deserialize_viewport_element(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MXKPZ_RETRO
|
#endif // MXKPZ_RETRO
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -982,4 +982,43 @@ bool Window::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->bgStretch, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->active, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pause, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->sceneOffset, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->position, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->size, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsOffset, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->backOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->baseQuadArray, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->useBaseTex, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->baseTexQuad, data, max_size)) return false;
|
||||||
|
if (!p->controlsElement.sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->controlsQuadArray, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsQuad, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->cursorAniAlphaIdx, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pauseAniAlphaIdx, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pauseAniQuadIdx, data, max_size)) return false;
|
||||||
|
if (!sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->windowskin, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contents, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->cursorRect, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1183,11 +1183,6 @@ bool WindowVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_siz
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->contentsOpacity, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->contentsOpacity, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->openness, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->openness, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->ctrlVert, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->ctrlVert, data, max_size)) return false;
|
||||||
|
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->pauseVert != nullptr, data, max_size)) return false;
|
|
||||||
if (p->pauseVert != nullptr)
|
|
||||||
if (!mkxp_sandbox::sandbox_serialize(*p->pauseVert, data, max_size)) return false;
|
|
||||||
|
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->contentsQuad, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->contentsQuad, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->padRect, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->padRect, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize(p->clipRect, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize(p->clipRect, data, max_size)) return false;
|
||||||
|
@ -1204,4 +1199,47 @@ bool WindowVX::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_siz
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowVX::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool active;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(active, data, max_size)) return false;
|
||||||
|
if (!active) {
|
||||||
|
dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// TODO: undispose
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->active, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->arrowsVisible, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pause, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->width, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->height, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->geo, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsOff, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->padding, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)p->paddingBottom, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->opacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->backOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsOpacity, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->openness, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->ctrlVert, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contentsQuad, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->padRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->clipRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->cursorVert, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pauseAlphaIdx, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->pauseQuadIdx, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->cursorAlphaIdx, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->sceneOffset, data, max_size)) return false;
|
||||||
|
if (!sandbox_deserialize_viewport_element(data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->windowskin, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->contents, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->cursorRect, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(p->tone, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -191,6 +191,15 @@ bool Color::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Color::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) {
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(red, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(green, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(blue, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(alpha, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
|
|
||||||
|
@ -320,6 +329,15 @@ bool Tone::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) c
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Tone::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) {
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(red, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(green, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(blue, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize(gray, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
|
|
||||||
|
@ -472,4 +490,13 @@ bool Rect::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) c
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Rect::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size) {
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)x, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)y, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)width, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)height, data, max_size)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -94,6 +94,7 @@ struct Color : public Serializable
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
/* Range (0.0 ~ 255.0) */
|
/* Range (0.0 ~ 255.0) */
|
||||||
|
@ -150,6 +151,7 @@ struct Tone : public Serializable
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
/* Range (-255.0 ~ 255.0) */
|
/* Range (-255.0 ~ 255.0) */
|
||||||
|
@ -213,6 +215,7 @@ struct Rect : public Serializable
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
|
|
|
@ -172,11 +172,25 @@ bool Table::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
if (!mkxp_sandbox::sandbox_serialize((int32_t)xs, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize((int32_t)xs, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize((int32_t)ys, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize((int32_t)ys, data, max_size)) return false;
|
||||||
if (!mkxp_sandbox::sandbox_serialize((int32_t)zs, data, max_size)) return false;
|
if (!mkxp_sandbox::sandbox_serialize((int32_t)zs, data, max_size)) return false;
|
||||||
if (xs * ys * zs != this->data.size()) std::abort();
|
if ((uint32_t)xs * (uint32_t)ys * (uint32_t)zs != this->data.size()) std::abort();
|
||||||
if (max_size < this->data.size() * sizeof(int16_t)) return false;
|
if (max_size < this->data.size() * sizeof(int16_t)) return false;
|
||||||
memcpy(data, this->data.data(), this->data.size() * sizeof(int16_t));
|
memcpy(data, this->data.data(), this->data.size() * sizeof(int16_t));
|
||||||
data = (uint8_t *)data + this->data.size() * sizeof(int16_t);
|
data = (uint8_t *)data + this->data.size() * sizeof(int16_t);
|
||||||
max_size -= this->data.size() * sizeof(int16_t);
|
max_size -= this->data.size() * sizeof(int16_t);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Table::sandbox_deserialize(const void *&data, mkxp_sandbox::wasm_size_t &max_size)
|
||||||
|
{
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)xs, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)ys, data, max_size)) return false;
|
||||||
|
if (!mkxp_sandbox::sandbox_deserialize((int32_t &)zs, data, max_size)) return false;
|
||||||
|
this->data.clear();
|
||||||
|
this->data.resize((uint32_t)xs * (uint32_t)ys * (uint32_t)zs);
|
||||||
|
if (max_size < this->data.size() * sizeof(int16_t)) return false;
|
||||||
|
memcpy(this->data.data(), data, this->data.size() * sizeof(int16_t));
|
||||||
|
data = (uint8_t *)data + this->data.size() * sizeof(int16_t);
|
||||||
|
max_size -= this->data.size() * sizeof(int16_t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
class Table : public Serializable
|
class Table : public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Table(int x, int y = 1, int z = 1);
|
Table(int x = 1, int y = 1, int z = 1);
|
||||||
/* Clone constructor */
|
/* Clone constructor */
|
||||||
Table(const Table &other);
|
Table(const Table &other);
|
||||||
virtual ~Table() {}
|
virtual ~Table() {}
|
||||||
|
@ -70,6 +70,7 @@ public:
|
||||||
|
|
||||||
#ifdef MKXPZ_RETRO
|
#ifdef MKXPZ_RETRO
|
||||||
bool sandbox_serialize(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(const void *&data, mkxp_sandbox::wasm_size_t &max_size);
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -107,7 +107,7 @@ struct SharedStatePrivate
|
||||||
|
|
||||||
Quad gpQuad;
|
Quad gpQuad;
|
||||||
|
|
||||||
unsigned int stampCounter;
|
uint64_t stampCounter;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> startupTime;
|
std::chrono::time_point<std::chrono::steady_clock> startupTime;
|
||||||
|
|
||||||
|
@ -435,7 +435,7 @@ double SharedState::runTime() {
|
||||||
#endif // MKXPZ_RETRO
|
#endif // MKXPZ_RETRO
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int SharedState::genTimeStamp()
|
uint64_t SharedState::genTimeStamp()
|
||||||
{
|
{
|
||||||
return p->stampCounter++;
|
return p->stampCounter++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ struct SharedState
|
||||||
|
|
||||||
sigslot::signal<> prepareDraw;
|
sigslot::signal<> prepareDraw;
|
||||||
|
|
||||||
unsigned int genTimeStamp();
|
uint64_t genTimeStamp();
|
||||||
|
|
||||||
// Returns time since SharedState was constructed in microseconds
|
// Returns time since SharedState was constructed in microseconds
|
||||||
double runTime();
|
double runTime();
|
||||||
|
|
Loading…
Add table
Reference in a new issue