Fix handling of big-endian platforms in libretro builds

In big-endian libretro builds, the WebAssembly memory is reversed, so no
byte-swapping is required to read from/write to WebAssembly memory
(which is little-endian).

However, that means the ways to get and set values in WebAssembly memory
are endianness-dependent, so I've added the correct such ways for
big-endian platforms.
This commit is contained in:
刘皓 2025-05-10 18:55:14 -04:00
parent 09ed08c087
commit 3ba12e5672
No known key found for this signature in database
GPG key ID: 7901753DB465B711
24 changed files with 337 additions and 291 deletions

View file

@ -37,15 +37,15 @@ static VALUE bgm_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(3) = 100; SANDBOX_SLOT(3) = 100;
SANDBOX_SLOT(5) = false; SANDBOX_SLOT(5) = false;
SANDBOX_AWAIT_S(1, rb_string_value_cstr, (VALUE *)(**sb() + argv)); SANDBOX_AWAIT_S(1, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 2));
if (argc >= 4) { if (argc >= 4) {
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
if (argc >= 5) { if (argc >= 5) {
SANDBOX_AWAIT_S(4, rb_num2int, ((VALUE *)(**sb() + argv))[4]); SANDBOX_AWAIT_S(4, rb_num2int, sb()->ref<VALUE>(argv, 4));
SANDBOX_SLOT(5) = true; SANDBOX_SLOT(5) = true;
} }
} }
@ -53,9 +53,9 @@ static VALUE bgm_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
} }
if (SANDBOX_SLOT(5)) { if (SANDBOX_SLOT(5)) {
mkxp_retro::audio->bgmPlay((const char *)(**sb() + SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0), SANDBOX_SLOT(4)); mkxp_retro::audio->bgmPlay(sb()->str(SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0), SANDBOX_SLOT(4));
} else { } else {
mkxp_retro::audio->bgmPlay((const char *)(**sb() + SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0)); mkxp_retro::audio->bgmPlay(sb()->str(SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0));
} }
} }
@ -78,9 +78,9 @@ static VALUE bgm_fade(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(1) = -127; SANDBOX_SLOT(1) = -127;
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
} }
mkxp_retro::audio->bgmFade(SANDBOX_SLOT(0), SANDBOX_SLOT(1)); mkxp_retro::audio->bgmFade(SANDBOX_SLOT(0), SANDBOX_SLOT(1));
} }
@ -100,7 +100,7 @@ static VALUE bgm_pos(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(2) = -127; SANDBOX_SLOT(2) = -127;
if (argc >= 1) { if (argc >= 1) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 0));
} }
SANDBOX_SLOT(0) = mkxp_retro::audio->bgmPos(SANDBOX_SLOT(2)); SANDBOX_SLOT(0) = mkxp_retro::audio->bgmPos(SANDBOX_SLOT(2));
SANDBOX_AWAIT_S(1, rb_float_new, SANDBOX_SLOT(0)); SANDBOX_AWAIT_S(1, rb_float_new, SANDBOX_SLOT(0));
@ -121,7 +121,7 @@ static VALUE bgm_volume(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(1) = -127; SANDBOX_SLOT(1) = -127;
if (argc >= 1) { if (argc >= 1) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 0));
} }
SANDBOX_SLOT(2) = mkxp_retro::audio->bgmGetVolume(SANDBOX_SLOT(1)); SANDBOX_SLOT(2) = mkxp_retro::audio->bgmGetVolume(SANDBOX_SLOT(1));
SANDBOX_AWAIT_S(0, rb_ll2inum, SANDBOX_SLOT(2)); SANDBOX_AWAIT_S(0, rb_ll2inum, SANDBOX_SLOT(2));
@ -141,9 +141,9 @@ static VALUE bgm_set_volume(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(1) = -127; SANDBOX_SLOT(1) = -127;
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
} }
mkxp_retro::audio->bgmSetVolume(SANDBOX_SLOT(0), SANDBOX_SLOT(1)); mkxp_retro::audio->bgmSetVolume(SANDBOX_SLOT(0), SANDBOX_SLOT(1));
} }
@ -165,18 +165,18 @@ static VALUE bgs_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(2) = 100; SANDBOX_SLOT(2) = 100;
SANDBOX_SLOT(3) = 100; SANDBOX_SLOT(3) = 100;
SANDBOX_AWAIT_S(1, rb_string_value_cstr, (VALUE *)(**sb() + argv)); SANDBOX_AWAIT_S(1, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 2));
if (argc >= 4) { if (argc >= 4) {
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
} }
} }
} }
mkxp_retro::audio->bgsPlay((const char *)(**sb() + SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0)); mkxp_retro::audio->bgsPlay(sb()->str(SANDBOX_SLOT(1)), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(0));
} }
return SANDBOX_NIL; return SANDBOX_NIL;
@ -234,15 +234,15 @@ static VALUE me_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(1) = 100; SANDBOX_SLOT(1) = 100;
SANDBOX_SLOT(2) = 100; SANDBOX_SLOT(2) = 100;
SANDBOX_AWAIT_S(0, rb_string_value_cstr, (VALUE *)(**sb() + argv)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
} }
} }
mkxp_retro::audio->mePlay((const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2)); mkxp_retro::audio->mePlay(sb()->str(SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2));
} }
return SANDBOX_NIL; return SANDBOX_NIL;
@ -283,15 +283,15 @@ static VALUE se_play(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(1) = 100; SANDBOX_SLOT(1) = 100;
SANDBOX_SLOT(2) = 100; SANDBOX_SLOT(2) = 100;
SANDBOX_AWAIT_S(0, rb_string_value_cstr, (VALUE *)(**sb() + argv)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
} }
} }
mkxp_retro::audio->sePlay((const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2)); mkxp_retro::audio->sePlay(sb()->str(SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2));
} }
return SANDBOX_NIL; return SANDBOX_NIL;

View file

@ -71,14 +71,6 @@ struct w2c_ruby &binding_base::instance() const noexcept {
return *_instance; return *_instance;
} }
uint8_t *binding_base::get() const noexcept {
return instance().w2c_memory.data;
}
uint8_t *binding_base::operator*() const noexcept {
return get();
}
wasm_ptr_t binding_base::sandbox_malloc(wasm_size_t size) { wasm_ptr_t binding_base::sandbox_malloc(wasm_size_t size) {
wasm_ptr_t buf = w2c_ruby_mkxp_sandbox_malloc(&instance(), size); wasm_ptr_t buf = w2c_ruby_mkxp_sandbox_malloc(&instance(), size);

View file

@ -37,20 +37,6 @@
#include <mkxp-sandbox-ruby.h> #include <mkxp-sandbox-ruby.h>
#include "types.h" #include "types.h"
#ifdef MKXPZ_BIG_ENDIAN
# define SERIALIZE_32(value) __builtin_bswap32(value)
# define SERIALIZE_64(value) __builtin_bswap64(value)
#else
# define SERIALIZE_32(value) (value)
# define SERIALIZE_64(value) (value)
#endif
#ifdef MKXPZ_RETRO_MEMORY64
# define SERIALIZE_VALUE(value) SERIALIZE_64(value)
#else
# define SERIALIZE_VALUE(value) SERIALIZE_32(value)
#endif
// LLVM uses a stack alignment of 16 on WebAssembly targets // LLVM uses a stack alignment of 16 on WebAssembly targets
#define WASMSTACKALIGN 16 #define WASMSTACKALIGN 16
@ -190,8 +176,6 @@ namespace mkxp_sandbox {
binding_base(std::shared_ptr<struct w2c_ruby> m); binding_base(std::shared_ptr<struct w2c_ruby> m);
~binding_base(); ~binding_base();
struct w2c_ruby &instance() const noexcept; struct w2c_ruby &instance() const noexcept;
uint8_t *get() const noexcept;
uint8_t *operator*() const noexcept;
wasm_ptr_t sandbox_malloc(wasm_size_t); wasm_ptr_t sandbox_malloc(wasm_size_t);
void sandbox_free(wasm_ptr_t ptr); void sandbox_free(wasm_ptr_t ptr);
wasm_ptr_t rtypeddata_data(VALUE obj) const noexcept; wasm_ptr_t rtypeddata_data(VALUE obj) const noexcept;
@ -200,6 +184,53 @@ namespace mkxp_sandbox {
wasm_size_t rtypeddata_dsize(wasm_ptr_t data, wasm_ptr_t ptr); wasm_size_t rtypeddata_dsize(wasm_ptr_t data, wasm_ptr_t ptr);
void rtypeddata_dcompact(wasm_ptr_t data, wasm_ptr_t ptr); void rtypeddata_dcompact(wasm_ptr_t data, wasm_ptr_t ptr);
// Gets a pointer to the given address in sandbox memory.
void *ptr(wasm_ptr_t address) const noexcept {
#ifdef MKXPZ_BIG_ENDIAN
return instance().w2c_memory.data + instance().w2c_memory.size - address;
#else
return instance().w2c_memory.data + address;
#endif // MKXPZ_BIG_ENDIAN
}
// Gets a reference to the value stored at a given address in sandbox memory.
template <typename T> T &ref(wasm_ptr_t address) const noexcept {
// TODO: require T to be numeric
#ifdef MKXPZ_BIG_ENDIAN
return *(T *)(ptr(address) - sizeof(T));
#else
return *(T *)ptr(address);
#endif // MKXPZ_BIG_ENDIAN
}
// Gets a reference to the value stored at the given index in the array at a given address in sandbox memory.
template <typename T> T &ref(wasm_ptr_t array_address, wasm_size_t array_index) const noexcept {
return ref<T>(array_address + array_index * sizeof(T));
}
// Gets a string stored at a given address in sandbox memory.
// The returned string doesn't need to be freed but only lives until the next call to this function,
// so you need to store the returned string in a buffer somewhere if you need to get more than one.
const char *str(wasm_ptr_t address) {
#ifdef MKXPZ_BIG_ENDIAN
static std::string buf;
buf.clear();
const char *s = (const char *)ptr(address);
const char *t = s;
wasm_size_t n = -1;
while (*--s) {
++n;
}
buf.reserve(n);
while (*--t) {
buf.push_back(*t);
}
return buf.c_str();
#else
return (const char *)ptr(address);
#endif // MKXPZ_BIG_ENDIAN
}
template <typename T> struct stack_frame_guard { template <typename T> struct stack_frame_guard {
static_assert(std::is_base_of<boost::asio::coroutine, T>::value, "`T` must be a subclass of `boost::asio::coroutine`"); static_assert(std::is_base_of<boost::asio::coroutine, T>::value, "`T` must be a subclass of `boost::asio::coroutine`");
friend struct binding_base; friend struct binding_base;
@ -215,9 +246,9 @@ namespace mkxp_sandbox {
static struct fiber &init_fiber(struct binding_base &bind) { static struct fiber &init_fiber(struct binding_base &bind) {
key_t key = { key_t key = {
*(wasm_ptr_t *)(*bind + bind.instance().w2c_mkxp_sandbox_fiber_entry_point), bind.ref<wasm_ptr_t>(bind.instance().w2c_mkxp_sandbox_fiber_entry_point),
*(wasm_ptr_t *)(*bind + bind.instance().w2c_mkxp_sandbox_fiber_arg0), bind.ref<wasm_ptr_t>(bind.instance().w2c_mkxp_sandbox_fiber_arg0),
*(wasm_ptr_t *)(*bind + bind.instance().w2c_mkxp_sandbox_fiber_arg1), bind.ref<wasm_ptr_t>(bind.instance().w2c_mkxp_sandbox_fiber_arg1),
}; };
if (bind.fibers.count(key) == 0) { if (bind.fibers.count(key) == 0) {
bind.fibers[key] = (struct fiber){.key = key}; bind.fibers[key] = (struct fiber){.key = key};
@ -335,8 +366,4 @@ namespace mkxp_sandbox {
}; };
} }
#undef SERIALIZE_32
#undef SERIALIZE_64
#undef SERIALIZE_VALUE
#endif // MKXPZ_SANDBOX_BINDING_BASE #endif // MKXPZ_SANDBOX_BINDING_BASE

View file

@ -104,7 +104,7 @@ struct run_rmxp_scripts : boost::asio::coroutine {
zlib_result = uncompress( zlib_result = uncompress(
sb().script_decode_buffer.data(), sb().script_decode_buffer.data(),
&buffer_len, &buffer_len,
(unsigned char *)(**sb() + SANDBOX_SLOT(6)), (const unsigned char *)sb()->str(SANDBOX_SLOT(6)),
SANDBOX_SLOT(7) SANDBOX_SLOT(7)
); );
sb().script_decode_buffer[buffer_len] = 0; sb().script_decode_buffer[buffer_len] = 0;
@ -121,7 +121,7 @@ struct run_rmxp_scripts : boost::asio::coroutine {
} }
if (zlib_result != Z_OK) { if (zlib_result != Z_OK) {
mkxp_retro::log_printf(RETRO_LOG_ERROR, "Error decoding script %zu: '%s'\n", SANDBOX_SLOT(3), **sb() + SANDBOX_SLOT(5)); mkxp_retro::log_printf(RETRO_LOG_ERROR, "Error decoding script %zu: '%s'\n", SANDBOX_SLOT(3), sb()->str(SANDBOX_SLOT(5)));
break; break;
} }
} }
@ -164,7 +164,7 @@ static VALUE load_data(VALUE self, VALUE path) {
VALUE operator()(VALUE path) { VALUE operator()(VALUE path) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &path); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &path);
SANDBOX_AWAIT_S(1, rb_file_open, (const char *)(**sb() + SANDBOX_SLOT(0)), "rb"); SANDBOX_AWAIT_S(1, rb_file_open, sb()->str(SANDBOX_SLOT(0)), "rb");
SANDBOX_AWAIT_S(2, rb_marshal_load, SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(2, rb_marshal_load, SANDBOX_SLOT(1));
SANDBOX_AWAIT(rb_io_close, SANDBOX_SLOT(1)); SANDBOX_AWAIT(rb_io_close, SANDBOX_SLOT(1));
} }

View file

@ -34,15 +34,15 @@ void mkxp_sandbox::set_private_data(VALUE obj, void *ptr) {
wasm_ptr_t data = sb()->rtypeddata_data(obj); wasm_ptr_t data = sb()->rtypeddata_data(obj);
// Free the old value if it already exists (initialize called twice?) // Free the old value if it already exists (initialize called twice?)
if (*(wasm_ptr_t *)(**sb() + data) != 0 && *(void **)(**sb() + *(wasm_ptr_t *)(**sb() + data)) != ptr) { if (sb()->ref<wasm_ptr_t>(data) != 0 && sb()->ref<void *>(sb()->ref<wasm_ptr_t>(data)) != ptr) {
sb()->rtypeddata_dfree(obj, *(wasm_ptr_t *)(**sb() + data)); sb()->rtypeddata_dfree(obj, sb()->ref<wasm_ptr_t>(data));
*(wasm_ptr_t *)(**sb() + data) = 0; sb()->ref<wasm_ptr_t>(data) = 0;
} }
if (*(wasm_ptr_t *)(**sb() + data) == 0) { if (sb()->ref<wasm_ptr_t>(data) == 0) {
wasm_ptr_t buf = sb()->sandbox_malloc(sizeof(void *)); wasm_ptr_t buf = sb()->sandbox_malloc(sizeof(void *));
*(void **)(**sb() + buf) = ptr; sb()->ref<void *>(buf) = ptr;
*(wasm_ptr_t *)(**sb() + data) = buf; sb()->ref<wasm_ptr_t>(data) = buf;
} }
} }
@ -85,6 +85,6 @@ void log_backtrace::operator()(VALUE exception) {
SANDBOX_AWAIT_S(2, rb_str_new_cstr, "\n\t"); SANDBOX_AWAIT_S(2, rb_str_new_cstr, "\n\t");
SANDBOX_AWAIT_S(1, rb_funcall, SANDBOX_SLOT(1), SANDBOX_SLOT(0), 1, SANDBOX_SLOT(2)); SANDBOX_AWAIT_S(1, rb_funcall, SANDBOX_SLOT(1), SANDBOX_SLOT(0), 1, SANDBOX_SLOT(2));
SANDBOX_AWAIT_S(3, rb_string_value_cstr, &SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(3, rb_string_value_cstr, &SANDBOX_SLOT(1));
mkxp_retro::log_printf(RETRO_LOG_ERROR, "%s\n", **sb() + SANDBOX_SLOT(3)); mkxp_retro::log_printf(RETRO_LOG_ERROR, "%s\n", sb()->str(SANDBOX_SLOT(3)));
} }
} }

View file

@ -29,7 +29,7 @@
#define GFX_GUARD_EXC(exp) exp #define GFX_GUARD_EXC(exp) exp
#define SANDBOX_SLOT(slot_index) (*(typename ::mkxp_sandbox::slot_type<(slot_index), slots>::type *)(**::mkxp_sandbox::sb() + ::mkxp_sandbox::sb()->stack_pointer() + ::mkxp_sandbox::slot_offset<(slot_index), slots>::value)) #define SANDBOX_SLOT(slot_index) (::mkxp_sandbox::sb()->ref<typename ::mkxp_sandbox::slot_type<(slot_index), slots>::type>(::mkxp_sandbox::sb()->stack_pointer() + ::mkxp_sandbox::slot_offset<(slot_index), slots>::value))
#define SANDBOX_AWAIT(coroutine, ...) \ #define SANDBOX_AWAIT(coroutine, ...) \
do { \ do { \
@ -103,7 +103,7 @@
namespace mkxp_sandbox { namespace mkxp_sandbox {
template <class T> void dfree(wasm_ptr_t buf) { template <class T> void dfree(wasm_ptr_t buf) {
delete *(T **)(**sb() + buf); delete sb()->ref<T *>(buf);
sb()->sandbox_free(buf); sb()->sandbox_free(buf);
} }
} }
@ -439,7 +439,7 @@ namespace mkxp_sandbox {
// Given Ruby typed data `obj`, retrieves the private data field of `obj`. // Given Ruby typed data `obj`, retrieves the private data field of `obj`.
template <typename T> inline T *get_private_data(VALUE obj) { template <typename T> inline T *get_private_data(VALUE obj) {
return *(T **)(**sb() + *(wasm_ptr_t *)(**sb() + sb()->rtypeddata_data(obj))); return sb()->ref<T *>(sb()->ref<wasm_ptr_t>(sb()->rtypeddata_data(obj)));
} }
// Gets the length of a Ruby object. // Gets the length of a Ruby object.

View file

@ -58,16 +58,16 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) { if (argc == 1) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, (VALUE *)(**sb() + argv)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
} else { } else {
SANDBOX_AWAIT_S(1, rb_num2ulong, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2ulong, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(2, rb_num2ulong, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(2, rb_num2ulong, sb()->ref<VALUE>(argv, 1));
} }
{ {
Bitmap *bitmap; Bitmap *bitmap;
if (argc == 1) { if (argc == 1) {
GFX_GUARD_EXC(bitmap = new Bitmap((const char *)(**sb() + SANDBOX_SLOT(0)));) GFX_GUARD_EXC(bitmap = new Bitmap(sb()->str(SANDBOX_SLOT(0)));)
} else { } else {
GFX_GUARD_EXC(bitmap = new Bitmap(SANDBOX_SLOT(1), SANDBOX_SLOT(2));) GFX_GUARD_EXC(bitmap = new Bitmap(SANDBOX_SLOT(1), SANDBOX_SLOT(2));)
} }
@ -145,12 +145,12 @@ static VALUE blt(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
// TODO: require at least 4 arguments // TODO: require at least 4 arguments
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_SLOT(0) = ((VALUE *)(**sb() + argv))[2]; SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 2);
SANDBOX_SLOT(1) = ((VALUE *)(**sb() + argv))[3]; SANDBOX_SLOT(1) = sb()->ref<VALUE>(argv, 3);
if (argc > 4) { if (argc > 4) {
SANDBOX_AWAIT_S(4, rb_num2int, ((VALUE *)(**sb() + argv))[4]); SANDBOX_AWAIT_S(4, rb_num2int, sb()->ref<VALUE>(argv, 4));
} }
Bitmap *src = get_private_data<Bitmap>(SANDBOX_SLOT(0)); Bitmap *src = get_private_data<Bitmap>(SANDBOX_SLOT(0));
@ -177,11 +177,11 @@ static VALUE stretch_blt(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(0) = ((VALUE *)(**sb() + argv))[0]; SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
SANDBOX_SLOT(1) = ((VALUE *)(**sb() + argv))[1]; SANDBOX_SLOT(1) = sb()->ref<VALUE>(argv, 1);
SANDBOX_SLOT(2) = ((VALUE *)(**sb() + argv))[2]; SANDBOX_SLOT(2) = sb()->ref<VALUE>(argv, 2);
if (argc > 3) { if (argc > 3) {
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
} }
Bitmap *src = get_private_data<Bitmap>(SANDBOX_SLOT(1)); Bitmap *src = get_private_data<Bitmap>(SANDBOX_SLOT(1));
@ -211,14 +211,14 @@ static VALUE fill_rect(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 2) { if (argc == 2) {
Bitmap *bitmap = get_private_data<Bitmap>(self); Bitmap *bitmap = get_private_data<Bitmap>(self);
GFX_GUARD_EXC(bitmap->fillRect(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])->toIntRect(), get_private_data<Color>(((VALUE *)(**sb() + argv))[1])->norm);) GFX_GUARD_EXC(bitmap->fillRect(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0))->toIntRect(), get_private_data<Color>(sb()->ref<VALUE>(argv, 1))->norm);)
} else { } else {
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
Bitmap *bitmap = get_private_data<Bitmap>(self); Bitmap *bitmap = get_private_data<Bitmap>(self);
GFX_GUARD_EXC(bitmap->fillRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), get_private_data<Color>(((VALUE *)(**sb() + argv))[4])->norm);) GFX_GUARD_EXC(bitmap->fillRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), get_private_data<Color>(sb()->ref<VALUE>(argv, 4))->norm);)
} }
} }
@ -319,33 +319,33 @@ static VALUE draw_text(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 2 || argc == 3) { if (argc == 2 || argc == 3) {
if (rgssVer >= 2) { if (rgssVer >= 2) {
SANDBOX_AWAIT_S(1, rb_obj_as_string, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_obj_as_string, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(1));
} else { } else {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, (VALUE *)(**sb() + argv) + 1); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 1));
} }
if (argc == 2) { if (argc == 2) {
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])->toIntRect(), (const char *)(**sb() + SANDBOX_SLOT(0)));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0))->toIntRect(), sb()->str(SANDBOX_SLOT(0))););
} else { } else {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])->toIntRect(), (const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(2));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0))->toIntRect(), sb()->str(SANDBOX_SLOT(0)), SANDBOX_SLOT(2)););
} }
} else { } else {
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(4, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(4, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(5, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(5, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(6, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(6, rb_num2int, sb()->ref<VALUE>(argv, 3));
if (rgssVer >= 2) { if (rgssVer >= 2) {
SANDBOX_AWAIT_S(1, rb_obj_as_string, ((VALUE *)(**sb() + argv))[4]); SANDBOX_AWAIT_S(1, rb_obj_as_string, sb()->ref<VALUE>(argv, 4));
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(1));
} else { } else {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, (VALUE *)(**sb() + argv) + 4); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 4));
} }
if (argc < 6) { if (argc < 6) {
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(SANDBOX_SLOT(3), SANDBOX_SLOT(4), SANDBOX_SLOT(5), SANDBOX_SLOT(6), (const char *)(**sb() + SANDBOX_SLOT(0)));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(SANDBOX_SLOT(3), SANDBOX_SLOT(4), SANDBOX_SLOT(5), SANDBOX_SLOT(6), sb()->str(SANDBOX_SLOT(0))););
} else { } else {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[5]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 5));
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(SANDBOX_SLOT(3), SANDBOX_SLOT(4), SANDBOX_SLOT(5), SANDBOX_SLOT(6), (const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(2));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->drawText(SANDBOX_SLOT(3), SANDBOX_SLOT(4), SANDBOX_SLOT(5), SANDBOX_SLOT(6), sb()->str(SANDBOX_SLOT(0)), SANDBOX_SLOT(2)););
} }
} }
} }
@ -370,7 +370,7 @@ static VALUE text_size(VALUE self, VALUE text) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &text); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &text);
} }
SANDBOX_AWAIT_S(1, rb_obj_alloc, rect_class); SANDBOX_AWAIT_S(1, rb_obj_alloc, rect_class);
set_private_data(SANDBOX_SLOT(1), new Rect(get_private_data<Bitmap>(self)->textSize((const char *)(**sb() + SANDBOX_SLOT(0))))); set_private_data(SANDBOX_SLOT(1), new Rect(get_private_data<Bitmap>(self)->textSize(sb()->str(SANDBOX_SLOT(0)))));
} }
return SANDBOX_SLOT(1); return SANDBOX_SLOT(1);
@ -392,7 +392,7 @@ static VALUE get_raw_data(VALUE self) {
SANDBOX_AWAIT_S(1, rb_str_new_cstr, ""); SANDBOX_AWAIT_S(1, rb_str_new_cstr, "");
SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(1), size); SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(1), size);
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(1));
GFX_GUARD_EXC(bitmap->getRaw(**sb() + SANDBOX_SLOT(0), size);); GFX_GUARD_EXC(bitmap->getRaw(sb()->ptr(SANDBOX_SLOT(0)), size););
} }
return SANDBOX_SLOT(1); return SANDBOX_SLOT(1);
@ -411,7 +411,7 @@ static VALUE set_raw_data(VALUE self, VALUE value) {
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &value); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &value);
SANDBOX_AWAIT_S(1, get_bytesize, value); SANDBOX_AWAIT_S(1, get_bytesize, value);
Bitmap *bitmap = get_private_data<Bitmap>(self); Bitmap *bitmap = get_private_data<Bitmap>(self);
GFX_GUARD_EXC(bitmap->replaceRaw(**sb() + SANDBOX_SLOT(0), SANDBOX_SLOT(1));); GFX_GUARD_EXC(bitmap->replaceRaw(sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1)););
} }
return self; return self;
@ -429,7 +429,7 @@ static VALUE to_file(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value);
Bitmap *bitmap = get_private_data<Bitmap>(self); Bitmap *bitmap = get_private_data<Bitmap>(self);
GFX_GUARD_EXC(bitmap->saveToFile((const char *)(**sb() + SANDBOX_SLOT(0)));); GFX_GUARD_EXC(bitmap->saveToFile(sb()->str(SANDBOX_SLOT(0))););
} }
return SANDBOX_NIL; return SANDBOX_NIL;
@ -449,7 +449,7 @@ static VALUE snap_to_bitmap(int32_t argc, wasm_ptr_t argv, VALUE self) {
if (argc < 1) { if (argc < 1) {
SANDBOX_SLOT(1) = -1; SANDBOX_SLOT(1) = -1;
} else { } else {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 0));
} }
SANDBOX_AWAIT_S(0, rb_obj_alloc, bitmap_class); SANDBOX_AWAIT_S(0, rb_obj_alloc, bitmap_class);
@ -478,22 +478,22 @@ static VALUE gradient_fill_rect(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 3 || argc == 4) { if (argc == 3 || argc == 4) {
if (argc == 4) { if (argc == 4) {
SANDBOX_SLOT(4) = SANDBOX_VALUE_TO_BOOL(((VALUE *)(**sb() + argv))[3]); SANDBOX_SLOT(4) = SANDBOX_VALUE_TO_BOOL(sb()->ref<VALUE>(argv, 3));
} else { } else {
SANDBOX_SLOT(4) = false; SANDBOX_SLOT(4) = false;
} }
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->gradientFillRect(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])->toIntRect(), get_private_data<Color>(((VALUE *)(**sb() + argv))[1])->norm, get_private_data<Color>(((VALUE *)(**sb() + argv))[2])->norm, SANDBOX_SLOT(4));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->gradientFillRect(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0))->toIntRect(), get_private_data<Color>(sb()->ref<VALUE>(argv, 1))->norm, get_private_data<Color>(sb()->ref<VALUE>(argv, 2))->norm, SANDBOX_SLOT(4)););
} else { } else {
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
if (argc >= 7) { if (argc >= 7) {
SANDBOX_SLOT(4) = SANDBOX_VALUE_TO_BOOL(((VALUE *)(**sb() + argv))[6]); SANDBOX_SLOT(4) = SANDBOX_VALUE_TO_BOOL(sb()->ref<VALUE>(argv, 6));
} else { } else {
SANDBOX_SLOT(4) = false; SANDBOX_SLOT(4) = false;
} }
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->gradientFillRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), get_private_data<Color>(((VALUE *)(**sb() + argv))[4])->norm, get_private_data<Color>(((VALUE *)(**sb() + argv))[5])->norm, SANDBOX_SLOT(4));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->gradientFillRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), get_private_data<Color>(sb()->ref<VALUE>(argv, 4))->norm, get_private_data<Color>(sb()->ref<VALUE>(argv, 5))->norm, SANDBOX_SLOT(4)););
} }
} }
@ -511,12 +511,12 @@ static VALUE clear_rect(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) { if (argc == 1) {
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->clearRect(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])->toIntRect());); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->clearRect(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0))->toIntRect()););
} else { } else {
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
GFX_GUARD_EXC(get_private_data<Bitmap>(self)->clearRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3));); GFX_GUARD_EXC(get_private_data<Bitmap>(self)->clearRect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)););
} }
} }
@ -637,13 +637,13 @@ static VALUE add_frame(int32_t argc, wasm_ptr_t argv, VALUE self) {
if (argc < 2) { if (argc < 2) {
SANDBOX_SLOT(1) = -1; SANDBOX_SLOT(1) = -1;
} else { } else {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (SANDBOX_SLOT(1) < 0) { if (SANDBOX_SLOT(1) < 0) {
SANDBOX_SLOT(1) = 0; SANDBOX_SLOT(1) = 0;
} }
} }
if (argc >= 1) { if (argc >= 1) {
Bitmap *src = get_private_data<Bitmap>(((VALUE *)(**sb() + argv))[0]); Bitmap *src = get_private_data<Bitmap>(sb()->ref<VALUE>(argv, 0));
Bitmap *b = get_private_data<Bitmap>(self); Bitmap *b = get_private_data<Bitmap>(self);
GFX_GUARD_EXC(SANDBOX_SLOT(1) = b->addFrame(*src, SANDBOX_SLOT(1));); GFX_GUARD_EXC(SANDBOX_SLOT(1) = b->addFrame(*src, SANDBOX_SLOT(1)););
} }
@ -666,7 +666,7 @@ static VALUE remove_frame(int32_t argc, wasm_ptr_t argv, VALUE self) {
if (argc < 2) { if (argc < 2) {
SANDBOX_SLOT(0) = -1; SANDBOX_SLOT(0) = -1;
} else { } else {
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (SANDBOX_SLOT(0) < 0) { if (SANDBOX_SLOT(0) < 0) {
SANDBOX_SLOT(0) = 0; SANDBOX_SLOT(0) = 0;
} }

View file

@ -47,13 +47,13 @@ struct color_binding_init : boost::asio::coroutine {
set_private_data(self, new Color); set_private_data(self, new Color);
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2dbl, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2dbl, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2dbl, sb()->ref<VALUE>(argv, 2));
if (argc <= 3) { if (argc <= 3) {
set_private_data(self, new Color(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2))); set_private_data(self, new Color(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2)));
} else { } else {
SANDBOX_AWAIT_S(3, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
set_private_data(self, new Color(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3))); set_private_data(self, new Color(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)));
} }
} }
@ -90,16 +90,16 @@ struct color_binding_init : boost::asio::coroutine {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) { if (argc == 1) {
*get_private_data<Color>(self) = *get_private_data<Color>(((VALUE *)(**sb() + argv))[0]); *get_private_data<Color>(self) = *get_private_data<Color>(sb()->ref<VALUE>(argv, 0));
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2dbl, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2dbl, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2dbl, sb()->ref<VALUE>(argv, 2));
if (argc <= 3) { if (argc <= 3) {
SANDBOX_SLOT(3) = 255; SANDBOX_SLOT(3) = 255;
} else { } else {
SANDBOX_AWAIT_S(3, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
} }
get_private_data<Color>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)); get_private_data<Color>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3));
} }
@ -180,13 +180,13 @@ struct tone_binding_init : boost::asio::coroutine {
set_private_data(self, new Tone); set_private_data(self, new Tone);
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2dbl, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2dbl, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2dbl, sb()->ref<VALUE>(argv, 2));
if (argc <= 3) { if (argc <= 3) {
set_private_data(self, new Tone(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2))); set_private_data(self, new Tone(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2)));
} else { } else {
SANDBOX_AWAIT_S(3, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
set_private_data(self, new Tone(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3))); set_private_data(self, new Tone(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)));
} }
} }
@ -223,16 +223,16 @@ struct tone_binding_init : boost::asio::coroutine {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) { if (argc == 1) {
*get_private_data<Tone>(self) = *get_private_data<Tone>(((VALUE *)(**sb() + argv))[0]); *get_private_data<Tone>(self) = *get_private_data<Tone>(sb()->ref<VALUE>(argv, 0));
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2dbl, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2dbl, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2dbl, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2dbl, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2dbl, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2dbl, sb()->ref<VALUE>(argv, 2));
if (argc <= 3) { if (argc <= 3) {
SANDBOX_SLOT(3) = 0; SANDBOX_SLOT(3) = 0;
} else { } else {
SANDBOX_AWAIT_S(3, rb_num2dbl, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2dbl, sb()->ref<VALUE>(argv, 3));
} }
get_private_data<Tone>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)); get_private_data<Tone>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3));
} }
@ -313,10 +313,10 @@ struct rect_binding_init : boost::asio::coroutine {
set_private_data(self, new Rect); set_private_data(self, new Rect);
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
set_private_data(self, new Rect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3))); set_private_data(self, new Rect(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)));
} }
} }
@ -352,13 +352,13 @@ struct rect_binding_init : boost::asio::coroutine {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
if (argc == 1) { if (argc == 1) {
*get_private_data<Rect>(self) = *get_private_data<Rect>(((VALUE *)(**sb() + argv))[0]); *get_private_data<Rect>(self) = *get_private_data<Rect>(sb()->ref<VALUE>(argv, 0));
} else { } else {
// TODO: make these optional // TODO: make these optional
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
get_private_data<Rect>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)); get_private_data<Rect>(self)->set(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3));
} }
} }

View file

@ -39,7 +39,7 @@ struct collect_strings : boost::asio::coroutine {
SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, obj, sb()->rb_cString()); SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, obj, sb()->rb_cString());
if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) { if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &obj); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &obj);
out.push_back((const char *)(**sb() + SANDBOX_SLOT(0))); out.push_back(sb()->str(SANDBOX_SLOT(0)));
} else { } else {
SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, obj, sb()->rb_cArray()); SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, obj, sb()->rb_cArray());
if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) { if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) {
@ -51,7 +51,7 @@ struct collect_strings : boost::asio::coroutine {
SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, SANDBOX_SLOT(4), sb()->rb_cString()); SANDBOX_AWAIT_S(3, rb_obj_is_kind_of, SANDBOX_SLOT(4), sb()->rb_cString());
if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) { if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(3))) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(4)); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &SANDBOX_SLOT(4));
out.push_back((const char *)(**sb() + SANDBOX_SLOT(0))); out.push_back(sb()->str(SANDBOX_SLOT(0)));
} }
} }
} }
@ -70,12 +70,12 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_AWAIT_S(0, rb_iv_get, font_class, "default_name"); SANDBOX_AWAIT_S(0, rb_iv_get, font_class, "default_name");
set_private_data(self, new Font); set_private_data(self, new Font);
} else if (argc == 1) { } else if (argc == 1) {
SANDBOX_SLOT(0) = ((VALUE *)(**sb() + argv))[0]; SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
SANDBOX_AWAIT(collect_strings, SANDBOX_SLOT(0), sb().font_names_buffer); SANDBOX_AWAIT(collect_strings, SANDBOX_SLOT(0), sb().font_names_buffer);
set_private_data(self, new Font(&sb().font_names_buffer)); set_private_data(self, new Font(&sb().font_names_buffer));
} else { } else {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_SLOT(0) = ((VALUE *)(**sb() + argv))[0]; SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
SANDBOX_AWAIT(collect_strings, SANDBOX_SLOT(0), sb().font_names_buffer); SANDBOX_AWAIT(collect_strings, SANDBOX_SLOT(0), sb().font_names_buffer);
set_private_data(self, new Font(&sb().font_names_buffer, SANDBOX_SLOT(1))); set_private_data(self, new Font(&sb().font_names_buffer, SANDBOX_SLOT(1)));
} }
@ -212,7 +212,7 @@ static VALUE exist(VALUE self, VALUE value) {
SANDBOX_AWAIT_S(1, rb_obj_is_kind_of, value, sb()->rb_cString()); SANDBOX_AWAIT_S(1, rb_obj_is_kind_of, value, sb()->rb_cString());
if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(1))) { if (SANDBOX_VALUE_TO_BOOL(SANDBOX_SLOT(1))) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value);
return SANDBOX_BOOL_TO_VALUE(Font::doesExist((const char *)(**sb() + SANDBOX_SLOT(0)))); return SANDBOX_BOOL_TO_VALUE(Font::doesExist(sb()->str(SANDBOX_SLOT(0))));
} else { } else {
return SANDBOX_BOOL_TO_VALUE(Font::doesExist(nullptr)); return SANDBOX_BOOL_TO_VALUE(Font::doesExist(nullptr));
} }

View file

@ -84,14 +84,14 @@ static VALUE transition(int32_t argc, wasm_ptr_t argv, VALUE self) {
} }
if (argc >= 1) { if (argc >= 1) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 1));
if (*(const char *)(**sb() + SANDBOX_SLOT(0))) { if (*sb()->str(SANDBOX_SLOT(0))) {
sb().trans_map = new Bitmap((const char *)(**sb() + SANDBOX_SLOT(0))); sb().trans_map = new Bitmap(sb()->str(SANDBOX_SLOT(0)));
} }
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
} }
} }
} }
@ -135,7 +135,7 @@ static VALUE screenshot(VALUE self, VALUE value) {
VALUE operator()(VALUE self, VALUE value) { VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value);
GFX_GUARD_EXC(shState->graphics().screenshot((const char *)(**sb() + SANDBOX_SLOT(0)));); GFX_GUARD_EXC(shState->graphics().screenshot(sb()->str(SANDBOX_SLOT(0))););
} }
return SANDBOX_NIL; return SANDBOX_NIL;
@ -287,11 +287,11 @@ static VALUE resize_window(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
// TODO: require at least 2 arguments // TODO: require at least 2 arguments
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
GFX_LOCK; GFX_LOCK;
if (argc >= 3) { if (argc >= 3) {
shState->graphics().resizeWindow(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_VALUE_TO_BOOL(((VALUE *)(**sb() + argv))[2])); shState->graphics().resizeWindow(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_VALUE_TO_BOOL(sb()->ref<VALUE>(argv, 2)));
} else { } else {
shState->graphics().resizeWindow(SANDBOX_SLOT(0), SANDBOX_SLOT(1)); shState->graphics().resizeWindow(SANDBOX_SLOT(0), SANDBOX_SLOT(1));
} }
@ -319,15 +319,15 @@ static VALUE play_movie(int32_t argc, wasm_ptr_t argv, VALUE self) {
VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) { VALUE operator()(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
// TODO: require at least 1 argument // TODO: require at least 1 argument
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
} else { } else {
SANDBOX_SLOT(1) = 100; SANDBOX_SLOT(1) = 100;
} }
SANDBOX_SLOT(2) = argc >= 3 ? SANDBOX_VALUE_TO_BOOL(((VALUE *)(**sb() + argv))[2]) : false; SANDBOX_SLOT(2) = argc >= 3 ? SANDBOX_VALUE_TO_BOOL(sb()->ref<VALUE>(argv, 2)) : false;
GFX_GUARD_EXC(sb().set_movie(shState->graphics().playMovie((const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2)));); GFX_GUARD_EXC(sb().set_movie(shState->graphics().playMovie(sb()->str(SANDBOX_SLOT(0)), SANDBOX_SLOT(1), SANDBOX_SLOT(2))););
while (sb().get_movie_from_main_thread() != nullptr) { while (sb().get_movie_from_main_thread() != nullptr) {
SANDBOX_YIELD; SANDBOX_YIELD;
GFX_GUARD_EXC(sb().set_movie(shState->graphics().playMovie(sb().get_movie_from_main_thread()));); GFX_GUARD_EXC(sb().set_movie(shState->graphics().playMovie(sb().get_movie_from_main_thread())););

View file

@ -589,7 +589,7 @@ static VALUE set_clipboard(VALUE self, VALUE value) {
VALUE operator()(VALUE self, VALUE value) { VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value); SANDBOX_AWAIT_S(0, rb_string_value_cstr, &value);
mkxp_retro::input->setClipboardText((const char *)(**sb() + SANDBOX_SLOT(0))); mkxp_retro::input->setClipboardText(sb()->str(SANDBOX_SLOT(0)));
} }
return value; return value;

View file

@ -152,7 +152,7 @@ void sandbox::set_movie(Movie *new_movie) {
const char *sandbox::getcwd() { const char *sandbox::getcwd() {
if (w2c_ruby_mkxp_sandbox_getcwd(ruby.get())) { if (w2c_ruby_mkxp_sandbox_getcwd(ruby.get())) {
return (const char *)(**bindings + ruby->w2c_mkxp_sandbox_cwd); return bindings->str(ruby->w2c_mkxp_sandbox_cwd);
} else { } else {
return "/game"; return "/game";
} }

View file

@ -34,7 +34,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_S(2, rb_obj_alloc, klass); SANDBOX_AWAIT_S(2, rb_obj_alloc, klass);
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &src); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &src);
SANDBOX_AWAIT_S(1, get_bytesize, src); SANDBOX_AWAIT_S(1, get_bytesize, src);
set_private_data(SANDBOX_SLOT(2), C::deserialize((const char *)(**sb() + SANDBOX_SLOT(0)), SANDBOX_SLOT(1))); /* TODO: free when sandbox is deallocated */ set_private_data(SANDBOX_SLOT(2), C::deserialize((const char *)sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1))); /* TODO: free when sandbox is deallocated */
} }
return SANDBOX_SLOT(2); return SANDBOX_SLOT(2);
@ -54,7 +54,7 @@ namespace mkxp_sandbox {
SANDBOX_AWAIT_S(2, rb_str_new_cstr, ""); SANDBOX_AWAIT_S(2, rb_str_new_cstr, "");
SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(2), SANDBOX_SLOT(1)); SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(2), SANDBOX_SLOT(1));
SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(2)); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(2));
get_private_data<C>(self)->serialize((char *)(**sb() + SANDBOX_SLOT(0))); get_private_data<C>(self)->serialize((char *)sb()->ptr(SANDBOX_SLOT(0)));
} }
return SANDBOX_SLOT(2); return SANDBOX_SLOT(2);

View file

@ -39,13 +39,13 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(1) = SANDBOX_SLOT(2) = 1; SANDBOX_SLOT(1) = SANDBOX_SLOT(2) = 1;
// TODO: throw error if too many or too few arguments // TODO: throw error if too many or too few arguments
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_SLOT(0) = std::max(SANDBOX_SLOT(0), (int32_t)0); SANDBOX_SLOT(0) = std::max(SANDBOX_SLOT(0), (int32_t)0);
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_SLOT(1) = std::max(SANDBOX_SLOT(1), (int32_t)0); SANDBOX_SLOT(1) = std::max(SANDBOX_SLOT(1), (int32_t)0);
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_SLOT(2) = std::max(SANDBOX_SLOT(2), (int32_t)0); SANDBOX_SLOT(2) = std::max(SANDBOX_SLOT(2), (int32_t)0);
} }
} }
@ -92,13 +92,13 @@ static VALUE resize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(1) = SANDBOX_SLOT(2) = 1; SANDBOX_SLOT(1) = SANDBOX_SLOT(2) = 1;
// TODO: throw error if too many or too few arguments // TODO: throw error if too many or too few arguments
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_SLOT(0) = std::max(SANDBOX_SLOT(0), (int32_t)0); SANDBOX_SLOT(0) = std::max(SANDBOX_SLOT(0), (int32_t)0);
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_SLOT(1) = std::max(SANDBOX_SLOT(1), (int32_t)0); SANDBOX_SLOT(1) = std::max(SANDBOX_SLOT(1), (int32_t)0);
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_SLOT(2) = std::max(SANDBOX_SLOT(2), (int32_t)0); SANDBOX_SLOT(2) = std::max(SANDBOX_SLOT(2), (int32_t)0);
} }
} }
@ -133,11 +133,11 @@ static VALUE get(int32_t argc, wasm_ptr_t argv, VALUE self) {
BOOST_ASIO_CORO_REENTER (this) { BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_SLOT(2) = SANDBOX_SLOT(3) = 0; SANDBOX_SLOT(2) = SANDBOX_SLOT(3) = 0;
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (argc >= 2) { if (argc >= 2) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 2));
// TODO: throw error if too many arguments // TODO: throw error if too many arguments
} }
} }
@ -166,18 +166,18 @@ static VALUE set(int32_t argc, wasm_ptr_t argv, VALUE self) {
// TODO: throw error if too few arguments // TODO: throw error if too few arguments
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
if (argc >= 3) { if (argc >= 3) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
if (argc >= 4) { if (argc >= 4) {
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
} }
} }
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[std::min(argc, (int32_t)4) - 1]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, std::min(argc, (int32_t)4) - 1));
get_private_data<Table>(self)->set(SANDBOX_SLOT(3), SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2)); get_private_data<Table>(self)->set(SANDBOX_SLOT(3), SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2));
return ((VALUE *)(**sb() + argv))[std::min(argc, (int32_t)4) - 1]; return sb()->ref<VALUE>(std::min(argc, (int32_t)4) - 1);
} }
return SANDBOX_UNDEF; return SANDBOX_UNDEF;

View file

@ -102,7 +102,7 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(0) = SANDBOX_NIL; SANDBOX_SLOT(0) = SANDBOX_NIL;
Viewport *viewport = nullptr; Viewport *viewport = nullptr;
if (argc > 0) { if (argc > 0) {
SANDBOX_SLOT(0) = *(VALUE *)(**sb() + argv); SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
if (SANDBOX_SLOT(0) != SANDBOX_NIL) { if (SANDBOX_SLOT(0) != SANDBOX_NIL) {
viewport = get_private_data<Viewport>(SANDBOX_SLOT(0)); viewport = get_private_data<Viewport>(SANDBOX_SLOT(0));
} }

View file

@ -101,7 +101,7 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
SANDBOX_SLOT(0) = SANDBOX_NIL; SANDBOX_SLOT(0) = SANDBOX_NIL;
Viewport *viewport = nullptr; Viewport *viewport = nullptr;
if (argc > 0) { if (argc > 0) {
SANDBOX_SLOT(0) = *(VALUE *)(**sb() + argv); SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
if (SANDBOX_SLOT(0) != SANDBOX_NIL) { if (SANDBOX_SLOT(0) != SANDBOX_NIL) {
viewport = get_private_data<Viewport>(SANDBOX_SLOT(0)); viewport = get_private_data<Viewport>(SANDBOX_SLOT(0));
} }

View file

@ -47,12 +47,12 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
viewport = new Viewport; viewport = new Viewport;
} else if (argc == 1) { } else if (argc == 1) {
GFX_LOCK; GFX_LOCK;
viewport = new Viewport(get_private_data<Rect>(((VALUE *)(**sb() + argv))[0])); viewport = new Viewport(get_private_data<Rect>(sb()->ref<VALUE>(argv, 0)));
} else { } else {
SANDBOX_AWAIT_S(0, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(0, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 3));
GFX_LOCK; GFX_LOCK;
viewport = new Viewport(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3)); viewport = new Viewport(SANDBOX_SLOT(0), SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3));
} }

View file

@ -37,7 +37,7 @@ namespace mkxp_sandbox {
{ {
Viewport *viewport = nullptr; Viewport *viewport = nullptr;
if (argc > 0) { if (argc > 0) {
SANDBOX_SLOT(0) = *(VALUE *)(**sb() + argv); SANDBOX_SLOT(0) = sb()->ref<VALUE>(argv, 0);
if (SANDBOX_SLOT(0) != SANDBOX_NIL) { if (SANDBOX_SLOT(0) != SANDBOX_NIL) {
viewport = get_private_data<Viewport>(SANDBOX_SLOT(0)); viewport = get_private_data<Viewport>(SANDBOX_SLOT(0));
} }

View file

@ -827,7 +827,7 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_open(wasi_t *wasi, u32 fd, u32
case PHYSFS_ERR_NO_WRITE_DIR: case PHYSFS_ERR_NO_WRITE_DIR:
return WASI_EROFS; return WASI_EROFS;
case PHYSFS_ERR_PERMISSION: case PHYSFS_ERR_PERMISSION:
return WASI_EPERM; return WASI_EACCES;
default: default:
return WASI_EIO; return WASI_EIO;
} }
@ -900,7 +900,7 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_remove_directory(wasi_t *wasi,
case PHYSFS_ERR_NO_WRITE_DIR: case PHYSFS_ERR_NO_WRITE_DIR:
return WASI_EROFS; return WASI_EROFS;
case PHYSFS_ERR_PERMISSION: case PHYSFS_ERR_PERMISSION:
return WASI_EPERM; return WASI_EACCES;
default: default:
return WASI_EIO; return WASI_EIO;
} }
@ -975,7 +975,7 @@ extern "C" u32 w2c_wasi__snapshot__preview1_path_unlink_file(wasi_t *wasi, u32 f
case PHYSFS_ERR_NO_WRITE_DIR: case PHYSFS_ERR_NO_WRITE_DIR:
return WASI_EROFS; return WASI_EROFS;
case PHYSFS_ERR_PERMISSION: case PHYSFS_ERR_PERMISSION:
return WASI_EPERM; return WASI_EACCES;
default: default:
return WASI_EIO; return WASI_EIO;
} }

View file

@ -45,10 +45,10 @@ static VALUE initialize(int32_t argc, wasm_ptr_t argv, VALUE self) {
GFX_LOCK; GFX_LOCK;
if (rgssVer >= 3) { if (rgssVer >= 3) {
if (argc == 4) { if (argc == 4) {
SANDBOX_AWAIT_S(1, rb_num2int, ((VALUE *)(**sb() + argv))[0]); SANDBOX_AWAIT_S(1, rb_num2int, sb()->ref<VALUE>(argv, 0));
SANDBOX_AWAIT_S(2, rb_num2int, ((VALUE *)(**sb() + argv))[1]); SANDBOX_AWAIT_S(2, rb_num2int, sb()->ref<VALUE>(argv, 1));
SANDBOX_AWAIT_S(3, rb_num2int, ((VALUE *)(**sb() + argv))[2]); SANDBOX_AWAIT_S(3, rb_num2int, sb()->ref<VALUE>(argv, 2));
SANDBOX_AWAIT_S(4, rb_num2int, ((VALUE *)(**sb() + argv))[3]); SANDBOX_AWAIT_S(4, rb_num2int, sb()->ref<VALUE>(argv, 3));
} }
WindowVX *window = new WindowVX(SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(4)); WindowVX *window = new WindowVX(SANDBOX_SLOT(1), SANDBOX_SLOT(2), SANDBOX_SLOT(3), SANDBOX_SLOT(4));
set_private_data(self, window); set_private_data(self, window);

View file

@ -49,21 +49,21 @@ ARG_HANDLERS = {
'const char *' => { 'const char *' => {
keep: true, keep: true,
buf_size: 'std::strlen(ARG) + 1', buf_size: 'std::strlen(ARG) + 1',
serialize: "std::strcpy((char *)(*bind + BUF), ARG);\n", serialize: "_sbindgen_strcpy((char *)bind.ptr(BUF), ARG);\n",
}, },
'const VALUE *' => { 'const VALUE *' => {
keep: true, keep: true,
condition: lambda { |func_name, args, arg_index| arg_index > 0 && args[arg_index - 1] == 'int' }, # Only handle arguments of type `const VALUE *` if the previous argument is of type `int` condition: lambda { |func_name, args, arg_index| arg_index > 0 && args[arg_index - 1] == 'int' }, # Only handle arguments of type `const VALUE *` if the previous argument is of type `int`
buf_size: 'PREV_ARG * sizeof(VALUE)', buf_size: 'PREV_ARG * sizeof(VALUE)',
serialize: <<~HEREDOC serialize: <<~HEREDOC
std::memcpy(*bind + BUF, ARG, PREV_ARG * sizeof(VALUE)); _sbindgen_value_array_copy((VALUE *)bind.ptr(BUF), ARG, PREV_ARG);
HEREDOC HEREDOC
}, },
'volatile VALUE *' => { 'volatile VALUE *' => {
keep: true, keep: true,
buf_size: 'sizeof(VALUE)', buf_size: 'sizeof(VALUE)',
serialize: <<~HEREDOC serialize: <<~HEREDOC
*(VALUE *)(*bind + BUF) = *ARG; bind.ref<VALUE>(BUF) = *ARG;
HEREDOC HEREDOC
}, },
'void *' => { 'void *' => {
@ -198,20 +198,6 @@ HEADER_START = <<~HEREDOC
// Autogenerated by sandbox-bindgen.rb. Don't manually modify this file - modify sandbox-bindgen.rb instead! // Autogenerated by sandbox-bindgen.rb. Don't manually modify this file - modify sandbox-bindgen.rb instead!
#if WABT_BIG_ENDIAN
# define SERIALIZE_32(value) __builtin_bswap32(value)
# define SERIALIZE_64(value) __builtin_bswap64(value)
#else
# define SERIALIZE_32(value) (value)
# define SERIALIZE_64(value) (value)
#endif
#ifdef MKXPZ_SANDBOX_MEMORY64
# define SERIALIZE_VALUE(value) SERIALIZE_64(value)
#else
# define SERIALIZE_VALUE(value) SERIALIZE_32(value)
#endif
namespace mkxp_sandbox { namespace mkxp_sandbox {
struct bindings : binding_base { struct bindings : binding_base {
bindings(std::shared_ptr<struct w2c_#{MODULE_NAME}> m); bindings(std::shared_ptr<struct w2c_#{MODULE_NAME}> m);
@ -232,10 +218,6 @@ HEREDOC
HEADER_END = <<~HEREDOC HEADER_END = <<~HEREDOC
} }
#undef SERIALIZE_32
#undef SERIALIZE_64
#undef SERIALIZE_VALUE
#endif // MKXP_SANDBOX_BINDGEN_H #endif // MKXP_SANDBOX_BINDGEN_H
HEREDOC HEREDOC
@ -266,23 +248,11 @@ PRELUDE = <<~HEREDOC
#include <cstdarg> #include <cstdarg>
#include "mkxp-sandbox-bindgen.h" #include "mkxp-sandbox-bindgen.h"
static_assert(alignof(VALUE) % sizeof(VALUE) == 0, "Alignment of `VALUE` must be divisible by size of `VALUE` for Ruby garbage collection to work. If you compiled Ruby for wasm64, try compiling it for wasm32 instead."); #define _SBINDGEN_SLOT(slot_index) (bind.ref<typename slot_type<(slot_index), slots>::type>(bind.stack_pointer() + slot_offset<(slot_index), slots>::value))
#define SLOT(slot_index) (*(typename slot_type<(slot_index), slots>::type *)(*bind + bind.stack_pointer() + slot_offset<(slot_index), slots>::value))
#if WABT_BIG_ENDIAN
# define SERIALIZE_32(value) __builtin_bswap32(value)
# define SERIALIZE_64(value) __builtin_bswap64(value)
#else
# define SERIALIZE_32(value) (value)
# define SERIALIZE_64(value) (value)
#endif
#ifdef MKXPZ_SANDBOX_MEMORY64 #ifdef MKXPZ_SANDBOX_MEMORY64
# define SERIALIZE_VALUE(value) SERIALIZE_64(value)
# define WASM_RT_ISIZE WASM_RT_I64 # define WASM_RT_ISIZE WASM_RT_I64
#else #else
# define SERIALIZE_VALUE(value) SERIALIZE_32(value)
# define WASM_RT_ISIZE WASM_RT_I32 # define WASM_RT_ISIZE WASM_RT_I32
#endif #endif
@ -299,6 +269,27 @@ PRELUDE = <<~HEREDOC
bindings::bindings(std::shared_ptr<struct w2c_#{MODULE_NAME}> m) : binding_base(m) {} bindings::bindings(std::shared_ptr<struct w2c_#{MODULE_NAME}> m) : binding_base(m) {}
static void _sbindgen_strcpy(char *dst, const char *src) {
#ifdef MKXPZ_BIG_ENDIAN
do {
*--dst = *src;
} while (*src++);
#else
std::strcpy(dst, src);
#endif
}
static void _sbindgen_value_array_copy(VALUE *dst, const VALUE *src, wasm_size_t num_values) {
#ifdef MKXPZ_BIG_ENDIAN
while (num_values > 0) {
*--dst = *src++;
--num_values;
};
#else
std::memcpy(dst, src, num_values * sizeof(VALUE));
#endif
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
HEREDOC HEREDOC
@ -319,41 +310,41 @@ POSTSCRIPT = <<~HEREDOC
throw std::bad_alloc(); throw std::bad_alloc();
} }
std::strcpy((char *)(**this + str), wrap_struct_name); _sbindgen_strcpy((char *)ptr(str), wrap_struct_name);
((wasm_ptr_t *)(**this + buf))[0] = SERIALIZE_VALUE(str); ref<wasm_ptr_t>(buf, 0) = str;
((wasm_ptr_t *)(**this + buf))[1] = dmark == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t { ref<wasm_ptr_t>(buf, 1) = dmark == NULL ? 0 : wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
.module_instance = (void *)dmark, .module_instance = (void *)dmark,
})); });
((wasm_ptr_t *)(**this + buf))[2] = dfree == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t { ref<wasm_ptr_t>(buf, 2) = dfree == NULL ? 0 : wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
.module_instance = (void *)dfree, .module_instance = (void *)dfree,
})); });
((wasm_ptr_t *)(**this + buf))[3] = dsize == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t { ref<wasm_ptr_t>(buf, 3) = dsize == NULL ? 0 : wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:size]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:size]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:size, [:value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:size, [:value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
.module_instance = (void *)dsize, .module_instance = (void *)dsize,
})); });
((wasm_ptr_t *)(**this + buf))[4] = dcompact == NULL ? 0 : SERIALIZE_VALUE(wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t { ref<wasm_ptr_t>(buf, 4) = dcompact == NULL ? 0 : wasm_rt_push_funcref(&instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(1, 0, #{FUNC_TYPE_TABLE[:ptr]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:void, [:value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
.module_instance = (void *)dcompact, .module_instance = (void *)dcompact,
})); });
((wasm_ptr_t *)(**this + buf))[5] = 0; ref<wasm_ptr_t>(buf, 5) = 0;
((wasm_ptr_t *)(**this + buf))[6] = SERIALIZE_VALUE(parent); ref<wasm_ptr_t>(buf, 6) = parent;
((wasm_ptr_t *)(**this + buf))[7] = SERIALIZE_VALUE(data); ref<wasm_ptr_t>(buf, 7) = data;
((wasm_ptr_t *)(**this + buf))[8] = SERIALIZE_VALUE(flags); ref<wasm_ptr_t>(buf, 8) = flags;
return buf; return buf;
} }
@ -376,7 +367,7 @@ for call_type in CALL_TYPES
call_bindings.append( call_bindings.append(
<<~HEREDOC <<~HEREDOC
static #{call_type[0] == :void ? 'void' : call_type[0] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[0]]} _sbindgen_call_#{call_type_hash(call_type)}(#{(["#{call_type[0] == :void ? 'void' : call_type[0] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[0]]} (*func)(#{(0...call_type[1].length).map { |i| call_type[1][i] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[1][i]] }.join(', ')})"] + (0...call_type[1].length).map { |i| "#{call_type[1][i] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[1][i]]} a#{i}" }).join(', ')}) { static #{call_type[0] == :void ? 'void' : call_type[0] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[0]]} _sbindgen_call_#{call_type_hash(call_type)}(#{(["#{call_type[0] == :void ? 'void' : call_type[0] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[0]]} (*func)(#{(0...call_type[1].length).map { |i| call_type[1][i] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[1][i]] }.join(', ')})"] + (0...call_type[1].length).map { |i| "#{call_type[1][i] == :value ? 'VALUE' : VAR_TYPE_TABLE[call_type[1][i]]} a#{i}" }).join(', ')}) {
#{call_type[0] == :void ? '' : 'return '}#{call_type[0] != :value ? '' : 'SERIALIZE_VALUE('}func(#{(0...call_type[1].length).map { |i| call_type[1][i] == :value ? "SERIALIZE_VALUE(a#{i})" : "a#{i}" }.join(', ')})#{call_type[0] != :value ? '' : ')'}; #{call_type[0] == :void ? '' : 'return '}func(#{(0...call_type[1].length).map { |i| "a#{i}" }.join(', ')});
} }
HEREDOC HEREDOC
) )
@ -451,7 +442,7 @@ File.readlines('tags', chomp: true).each do |line|
coroutine_initializer += <<~HEREDOC coroutine_initializer += <<~HEREDOC
switch (a#{args.length - 1}) { switch (a#{args.length - 1}) {
case -1: case -1:
SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t { _SBINDGEN_SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(3, 1, #{FUNC_TYPE_TABLE[:s32]}, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(3, 1, #{FUNC_TYPE_TABLE[:s32]}, #{FUNC_TYPE_TABLE[:ptr]}, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:s32, :ptr, :value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:s32, :ptr, :value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
@ -459,7 +450,7 @@ File.readlines('tags', chomp: true).each do |line|
}); });
break; break;
case -2: case -2:
SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t { _SBINDGEN_SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(2, 1, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(2, 1, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}, #{FUNC_TYPE_TABLE[:value]}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:value, :value]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:value, :value]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
@ -470,7 +461,7 @@ File.readlines('tags', chomp: true).each do |line|
for j in 0..16 for j in 0..16
case_str = <<~HEREDOC case_str = <<~HEREDOC
case #{j}: case #{j}:
SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t { _SBINDGEN_SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(#{j + 1}, 1, #{([FUNC_TYPE_TABLE[:value]] * (j + 2)).join(', ')}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(#{j + 1}, 1, #{([FUNC_TYPE_TABLE[:value]] * (j + 2)).join(', ')}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:value] * (j + 1)])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([:value, [:value] * (j + 1)])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
@ -487,7 +478,7 @@ File.readlines('tags', chomp: true).each do |line|
HEREDOC HEREDOC
else else
coroutine_initializer += <<~HEREDOC coroutine_initializer += <<~HEREDOC
SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t { _SBINDGEN_SLOT(#{num_slots}) = wasm_rt_push_funcref(&bind.instance().w2c_T0, wasm_rt_funcref_t {
.func_type = wasm2c_#{MODULE_NAME}_get_func_type(#{handler[:func_ptr_args].length}, #{handler[:func_ptr_rets].length}#{handler[:func_ptr_args].empty? && handler[:func_ptr_rets].empty? ? '' : ', ' + (handler[:func_ptr_args] + handler[:func_ptr_rets]).map { |type| FUNC_TYPE_TABLE[type] }.join(', ')}), .func_type = wasm2c_#{MODULE_NAME}_get_func_type(#{handler[:func_ptr_args].length}, #{handler[:func_ptr_rets].length}#{handler[:func_ptr_args].empty? && handler[:func_ptr_rets].empty? ? '' : ', ' + (handler[:func_ptr_args] + handler[:func_ptr_rets]).map { |type| FUNC_TYPE_TABLE[type] }.join(', ')}),
.func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([handler[:func_ptr_rets].empty? ? :void : handler[:func_ptr_rets][0], handler[:func_ptr_args]])}, .func = (wasm_rt_function_ptr_t)_sbindgen_call_#{call_type_hash([handler[:func_ptr_rets].empty? ? :void : handler[:func_ptr_rets][0], handler[:func_ptr_args]])},
.func_tailcallee = {.fn = NULL}, .func_tailcallee = {.fn = NULL},
@ -500,10 +491,10 @@ File.readlines('tags', chomp: true).each do |line|
num_slots += 1 num_slots += 1
elsif !handler[:buf_size].nil? elsif !handler[:buf_size].nil?
coroutine_initializer += <<~HEREDOC coroutine_initializer += <<~HEREDOC
SLOT(#{num_slots}) = bind.sandbox_malloc(#{handler[:buf_size].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}")}); _SBINDGEN_SLOT(#{num_slots}) = bind.sandbox_malloc(#{handler[:buf_size].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}")});
if (SLOT(#{num_slots}) == 0) throw std::bad_alloc(); if (_SBINDGEN_SLOT(#{num_slots}) == 0) throw std::bad_alloc();
HEREDOC HEREDOC
coroutine_initializer += handler[:serialize].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}").gsub('BUF', "SLOT(#{num_slots})") coroutine_initializer += handler[:serialize].gsub('PREV_ARG', "a#{i - 1}").gsub('ARG', "a#{i}").gsub('BUF', "_SBINDGEN_SLOT(#{num_slots})")
coroutine_initializer += "\n" coroutine_initializer += "\n"
transformed_args.add(i) transformed_args.add(i)
num_slots += 1 num_slots += 1
@ -525,13 +516,13 @@ File.readlines('tags', chomp: true).each do |line|
if (sp > fp) { if (sp > fp) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
SLOT(#{num_slots}) = sp; _SBINDGEN_SLOT(#{num_slots}) = sp;
SLOT(#{num_slots + 1}) = fp; _SBINDGEN_SLOT(#{num_slots + 1}) = fp;
w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), sp); w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), sp);
std::va_list a; std::va_list a;
va_start(a, a#{args.length - 2}); va_start(a, a#{args.length - 2});
for (long i = 0; i < a#{args.length - 2}; ++i) { for (long i = 0; i < a#{args.length - 2}; ++i) {
((VALUE *)(*bind + sp))[i] = va_arg(a, VALUE); bind.ref<VALUE>(sp, i) = va_arg(a, VALUE);
} }
va_end(a); va_end(a);
} }
@ -552,11 +543,11 @@ File.readlines('tags', chomp: true).each do |line|
if (sp > fp) { if (sp > fp) {
throw std::bad_alloc(); throw std::bad_alloc();
} }
SLOT(#{num_slots}) = sp; _SBINDGEN_SLOT(#{num_slots}) = sp;
SLOT(#{num_slots + 1}) = fp; _SBINDGEN_SLOT(#{num_slots + 1}) = fp;
w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), sp); w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), sp);
for (wasm_size_t i = 0; i < n; ++i) { for (wasm_size_t i = 0; i < n; ++i) {
((VALUE *)(*bind + sp))[i] = va_arg(a, VALUE); bind.ref<VALUE>(sp, i) = va_arg(a, VALUE);
} }
va_end(a); va_end(a);
} }
@ -575,10 +566,10 @@ File.readlines('tags', chomp: true).each do |line|
arg = args[i] arg = args[i]
if arg == '...' if arg == '...'
num_slots += 2 num_slots += 2
"SLOT(#{num_slots - 2}) = 0;\nSLOT(#{num_slots - 1}) = 0;" "_SBINDGEN_SLOT(#{num_slots - 2}) = 0;\n_SBINDGEN_SLOT(#{num_slots - 1}) = 0;"
elsif transformed_args.include?(i) elsif transformed_args.include?(i)
num_slots += 1 num_slots += 1
"SLOT(#{num_slots - 1}) = 0;" "_SBINDGEN_SLOT(#{num_slots - 1}) = 0;"
else else
nil nil
end end
@ -614,9 +605,9 @@ File.readlines('tags', chomp: true).each do |line|
#{handler[:primitive] == :void ? '' : 'r = '}w2c_#{MODULE_NAME}_#{func_name}(#{(['&bind.instance()'] + (0...args.length).map do |i| #{handler[:primitive] == :void ? '' : 'r = '}w2c_#{MODULE_NAME}_#{func_name}(#{(['&bind.instance()'] + (0...args.length).map do |i|
if args[i] == '...' || transformed_args.include?(i) if args[i] == '...' || transformed_args.include?(i)
j += 1 j += 1
"SLOT(#{j - 1})" "_SBINDGEN_SLOT(#{j - 1})"
else else
args[i] == 'VALUE' ? "SERIALIZE_VALUE(a#{i})" : args[i] == 'const rb_data_type_t *' ? "a#{i}.get()" : "a#{i}" args[i] == 'const rb_data_type_t *' ? "a#{i}.get()" : "a#{i}"
end end
end).join(', ')}); end).join(', ')});
if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break; if (w2c_#{MODULE_NAME}_asyncify_get_state(&bind.instance()) != 1) break;
@ -632,10 +623,10 @@ File.readlines('tags', chomp: true).each do |line|
arg = args[i] arg = args[i]
if arg == '...' if arg == '...'
num_slots -= 2 num_slots -= 2
" if (SLOT(#{num_slots + 1}) != 0) w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), SLOT(#{num_slots + 1}));" " if (_SBINDGEN_SLOT(#{num_slots + 1}) != 0) w2c_ruby_rb_wasm_set_stack_pointer(&bind.instance(), _SBINDGEN_SLOT(#{num_slots + 1}));"
elsif transformed_args.include?(i) elsif transformed_args.include?(i)
num_slots -= 1 num_slots -= 1
" if (SLOT(#{num_slots}) != 0) bind.sandbox_free(SLOT(#{num_slots}));" " if (_SBINDGEN_SLOT(#{num_slots}) != 0) bind.sandbox_free(_SBINDGEN_SLOT(#{num_slots}));"
else else
nil nil
end end
@ -653,7 +644,7 @@ File.readlines('tags', chomp: true).each do |line|
#{coroutine_initializer.empty? ? '' : (coroutine_initializer.split("\n").map { |line| " #{line}".rstrip }.join("\n") + "\n\n")} for (;;) { #{coroutine_initializer.empty? ? '' : (coroutine_initializer.split("\n").map { |line| " #{line}".rstrip }.join("\n") + "\n\n")} for (;;) {
#{coroutine_inner.split("\n").map { |line| " #{line}" }.join("\n")} #{coroutine_inner.split("\n").map { |line| " #{line}" }.join("\n")}
} }
}#{handler[:primitive] == :void ? '' : ret == 'VALUE' ? "\n\n return SERIALIZE_VALUE(r);" : "\n\n return r;"} }#{handler[:primitive] == :void ? '' : "\n\n return r;"}
}#{coroutine_destructor.empty? ? '' : ("\n" + coroutine_destructor)} }#{coroutine_destructor.empty? ? '' : ("\n" + coroutine_destructor)}
HEREDOC HEREDOC
@ -675,28 +666,16 @@ end
File.open('mkxp-sandbox-bindgen.h', 'w') do |file| File.open('mkxp-sandbox-bindgen.h', 'w') do |file|
file.write(HEADER_START) file.write(HEADER_START)
for global_name in globals for global_name in globals
file.write(" inline VALUE #{global_name}() const noexcept { return *(VALUE *)(**this + instance().w2c_#{global_name}); }\n") file.write(" inline VALUE #{global_name}() const noexcept { return ref<VALUE>(instance().w2c_#{global_name}); }\n")
end end
file.write(" };") file.write(" };")
for declaration in declarations for declaration in declarations
file.write("\n\n" + declaration.split("\n").map { |line| " #{line}" }.join("\n").rstrip) file.write("\n\n" + declaration.split("\n").map { |line| " #{line}" }.join("\n").rstrip)
end end
file.write("\n\n") file.write("\n\n")
file.write("#if WABT_BIG_ENDIAN\n")
file.write("# ifdef MKXPZ_SANDBOX_MEMORY64\n")
for const in consts for const in consts
file.write("# define SANDBOX_#{const[0]} 0x#{[const[1]].pack('Q<').unpack('H*')[0]}u\n") file.write("#define SANDBOX_#{const[0]} ((VALUE)#{const[1]}U)\n")
end end
file.write("# else\n")
for const in consts
file.write("# define SANDBOX_#{const[0]} 0x#{[const[1]].pack('L<').unpack('H*')[0]}u\n")
end
file.write("# endif\n")
file.write("#else\n")
for const in consts
file.write("# define SANDBOX_#{const[0]} 0x#{[const[1]].pack('L>').unpack('H*')[0]}u\n")
end
file.write("#endif\n")
file.write(HEADER_END) file.write(HEADER_END)
end end
File.open('mkxp-sandbox-bindgen.cpp', 'w') do |file| File.open('mkxp-sandbox-bindgen.cpp', 'w') do |file|

View file

@ -1941,6 +1941,10 @@ bool Bitmap::getRaw(void *output, int output_size)
Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality."; Debug() << "GAME BUG: Game is calling getRaw on low-res Bitmap; you may want to patch the game to improve graphics quality.";
} }
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
output -= output_size;
#endif
if (!p->animation.enabled && (p->surface || p->megaSurface)) { if (!p->animation.enabled && (p->surface || p->megaSurface)) {
void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels; void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels;
memcpy(output, src, output_size); memcpy(output, src, output_size);
@ -1949,6 +1953,11 @@ bool Bitmap::getRaw(void *output, int output_size)
FBO::bind(getGLTypes().fbo); FBO::bind(getGLTypes().fbo);
gl.ReadPixels(0,0,width(),height(),GL_RGBA,GL_UNSIGNED_BYTE,output); gl.ReadPixels(0,0,width(),height(),GL_RGBA,GL_UNSIGNED_BYTE,output);
} }
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
std::reverse((uint8_t *)output, (uint8_t *)output + output_size);
#endif
return true; return true;
} }
@ -1969,8 +1978,17 @@ void Bitmap::replaceRaw(void *pixel_data, int size)
if (size != w*h*4) if (size != w*h*4)
throw Exception(Exception::MKXPError, "Replacement bitmap data is not large enough (given %i bytes, need %i)", size, requiredsize); throw Exception(Exception::MKXPError, "Replacement bitmap data is not large enough (given %i bytes, need %i)", size, requiredsize);
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
output -= output_size;
std::reverse((uint8_t *)pixel_data, (uint8_t *)pixel_data + size);
#endif
TEX::bind(getGLTypes().tex); TEX::bind(getGLTypes().tex);
TEX::uploadImage(w, h, pixel_data, GL_RGBA); TEX::uploadImage(w, h, pixel_data, GL_RGBA);
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
std::reverse((uint8_t *)pixel_data, (uint8_t *)pixel_data + size);
#endif
taintArea(IntRect(0,0,w,h)); taintArea(IntRect(0,0,w,h));
p->onModified(); p->onModified();

View file

@ -115,7 +115,12 @@ void Table::serialize(char *buffer) const
writeInt32(&buffer, zs); writeInt32(&buffer, zs);
writeInt32(&buffer, size); writeInt32(&buffer, size);
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
for (const int16_t datum : data)
*(int16_t *)(buffer -= sizeof(int16_t)) = datum;
#else
memcpy(buffer, dataPtr(data), sizeof(int16_t)*size); memcpy(buffer, dataPtr(data), sizeof(int16_t)*size);
#endif
} }
@ -137,7 +142,13 @@ Table *Table::deserialize(const char *data, int len)
throw Exception(Exception::RGSSError, "Marshal: Table: bad file format"); throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
Table *t = new Table(x, y, z); Table *t = new Table(x, y, z);
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
for (int16_t &datum : t->data)
datum = *(int16_t *)(data -= sizeof(int16_t));
#else
memcpy(dataPtr(t->data), data, sizeof(int16_t)*size); memcpy(dataPtr(t->data), data, sizeof(int16_t)*size);
#endif
return t; return t;
} }

View file

@ -31,10 +31,15 @@ readInt32(const char **dataP)
{ {
int32_t result; int32_t result;
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
*dataP -= 4;
memcpy(&result, *dataP, 4);
#else
memcpy(&result, *dataP, 4); memcpy(&result, *dataP, 4);
*dataP += 4; *dataP += 4;
#endif
#ifdef MKXPZ_BIG_ENDIAN #if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
# ifdef _MSC_VER # ifdef _MSC_VER
static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits"); static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits");
result = (int32_t)_byteswap_ulong((unsigned long)result); result = (int32_t)_byteswap_ulong((unsigned long)result);
@ -49,7 +54,7 @@ readInt32(const char **dataP)
static inline double static inline double
readDouble(const char **dataP) readDouble(const char **dataP)
{ {
#ifdef MKXPZ_BIG_ENDIAN #if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
uint64_t result; uint64_t result;
memcpy(&result, *dataP, 8); memcpy(&result, *dataP, 8);
@ -65,8 +70,13 @@ readDouble(const char **dataP)
#else #else
double result; double result;
# if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
*dataP -= 8;
memcpy(&result, *dataP, 8);
# else
memcpy(&result, *dataP, 8); memcpy(&result, *dataP, 8);
*dataP += 8; *dataP += 8;
# endif
return result; return result;
#endif #endif
@ -75,7 +85,7 @@ readDouble(const char **dataP)
static inline void static inline void
writeInt32(char **dataP, int32_t value) writeInt32(char **dataP, int32_t value)
{ {
#ifdef MKXPZ_BIG_ENDIAN #if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
# ifdef _MSC_VER # ifdef _MSC_VER
static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits"); static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits");
value = (int32_t)_byteswap_ulong((unsigned long)value); value = (int32_t)_byteswap_ulong((unsigned long)value);
@ -84,14 +94,19 @@ writeInt32(char **dataP, int32_t value)
# endif # endif
#endif #endif
#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
*dataP -= 4;
memcpy(*dataP, &value, 4);
#else
memcpy(*dataP, &value, 4); memcpy(*dataP, &value, 4);
*dataP += 4; *dataP += 4;
#endif
} }
static inline void static inline void
writeDouble(char **dataP, double value) writeDouble(char **dataP, double value)
{ {
#ifdef MKXPZ_BIG_ENDIAN #if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
uint64_t valueUint = *(uint64_t *)&value; uint64_t valueUint = *(uint64_t *)&value;
# ifdef _MSC_VER # ifdef _MSC_VER
@ -101,10 +116,14 @@ writeDouble(char **dataP, double value)
# endif # endif
memcpy(*dataP, &valueUint, 8); memcpy(*dataP, &valueUint, 8);
*dataP += 8;
#elif defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN)
*dataP -= 8;
memcpy(*dataP, &value, 8);
#else #else
memcpy(*dataP, &value, 8); memcpy(*dataP, &value, 8);
#endif
*dataP += 8; *dataP += 8;
#endif
} }
#endif // SERIALUTIL_H #endif // SERIALUTIL_H