diff --git a/binding-sandbox/binding-base.cpp b/binding-sandbox/binding-base.cpp index d9763930..120afafb 100644 --- a/binding-sandbox/binding-base.cpp +++ b/binding-sandbox/binding-base.cpp @@ -122,28 +122,24 @@ void binding_base::copy_memory_from(const void *ptr, wasm_size_t size, wasm_size } } -void *mkxp_sandbox::sandbox_ptr(struct w2c_ruby &instance, wasm_ptr_t address) noexcept { - if (address >= instance.w2c_memory.size) { - std::abort(); - } -#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 -} - wasm_size_t mkxp_sandbox::sandbox_strlen(struct w2c_ruby &instance, wasm_ptr_t address) noexcept { - const char *ptr = (char *)sandbox_ptr(instance, address); + const char *ptr = &sandbox_ref(instance, address); #ifdef MKXPZ_BIG_ENDIAN wasm_size_t size = 0; - while ((uint8_t *)ptr != instance.w2c_memory.data && *--ptr) { + while (*ptr) { + if ((uint8_t *)ptr == instance.w2c_memory.data) { + std::abort(); + } ++size; + --ptr; } return size; #else const char *end = (const char *)std::memchr(ptr, 0, instance.w2c_memory.size - address); - return ptr == nullptr ? instance.w2c_memory.size - address : end - ptr; + if (ptr == nullptr) { + std::abort(); + } + return end - ptr; #endif } @@ -151,62 +147,24 @@ struct sandbox_str_guard mkxp_sandbox::sandbox_str(struct w2c_ruby &instance, wa #ifdef MKXPZ_BIG_ENDIAN std::string str; str.reserve(sandbox_strlen(instance, address)); - const char *ptr = (const char *)sandbox_ptr(instance, address); - while ((uint8_t *)ptr != instance.w2c_memory.data && *--ptr) { + for (const char *ptr = &sandbox_ref(instance, address); *ptr; --ptr) { str.push_back(*ptr); } return str; #else - if (instance.w2c_memory.size - address <= sandbox_strlen(instance, address)) { + if (address >= instance.w2c_memory.size || instance.w2c_memory.size - address <= sandbox_strlen(instance, address)) { std::abort(); } - return (const char *)sandbox_ptr(instance, address); + return &sandbox_ref(instance, address); #endif // MKXPZ_BIG_ENDIAN } void mkxp_sandbox::sandbox_strcpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src) noexcept { -#ifdef MKXPZ_BIG_ENDIAN - char *dst = (char *)sandbox_ptr(instance, dst_address); - while (*src) { - if ((uint8_t *)dst == instance.w2c_memory.data) { - std::abort(); - } - *--dst = *src++; - } - *dst = 0; -#else - if (instance.w2c_memory.size - dst_address <= std::strlen(src)) { - std::abort(); - } - char *dst = (char *)sandbox_ptr(instance, dst_address); - std::strcpy(dst, src); -#endif + sandbox_arycpy(instance, dst_address, src, (wasm_size_t)std::strlen(src) + 1); } -void mkxp_sandbox::sandbox_strncpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept { -#ifdef MKXPZ_BIG_ENDIAN - char *dst = (char *)sandbox_ptr(instance, dst_address); - while (max_size && *src) { - if ((uint8_t *)dst == instance.w2c_memory.data) { - std::abort(); - } - *--dst = *src++; - --max_size; - } - if (max_size) { - *dst = 0; - } -#else - if (instance.w2c_memory.size - dst_address <= std::strlen(src)) { - std::abort(); - } - char *dst = (char *)sandbox_ptr(instance, dst_address); - std::strncpy(dst, src, max_size); -#endif -} - -void *binding_base::ptr(wasm_ptr_t address) const noexcept { - return sandbox_ptr(instance(), address); +void mkxp_sandbox::sandbox_strncpy_s(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept { + sandbox_arycpy(instance, dst_address, src, std::min((wasm_size_t)std::strlen(src) + 1, max_size)); } wasm_size_t binding_base::strlen(wasm_ptr_t address) const noexcept { @@ -221,8 +179,8 @@ void binding_base::strcpy(wasm_ptr_t dst_address, const char *src) const noexcep sandbox_strcpy(instance(), dst_address, src); } -void binding_base::strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept { - sandbox_strncpy(instance(), dst_address, src, max_size); +void binding_base::strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept { + sandbox_strncpy_s(instance(), dst_address, src, max_size); } binding_base::object::object() : ptr(nullptr), typenum(0) {} diff --git a/binding-sandbox/binding-base.h b/binding-sandbox/binding-base.h index 3685a2f2..378bbd8f 100644 --- a/binding-sandbox/binding-base.h +++ b/binding-sandbox/binding-base.h @@ -151,11 +151,31 @@ namespace mkxp_sandbox { }; // Gets a pointer to the given address in sandbox memory. - void *sandbox_ptr(struct w2c_ruby &instance, wasm_ptr_t address) noexcept; + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *sandbox_ptr_unaligned(struct w2c_ruby &instance, wasm_ptr_t address) noexcept { + static_assert(std::is_arithmetic::value, "can only get references to numeric values in the sandbox"); + if (address + (wasm_ptr_t)sizeof(T) < address || address + (wasm_ptr_t)sizeof(T) > instance.w2c_memory.size) { + std::abort(); + } +#ifdef MKXPZ_BIG_ENDIAN + return instance.w2c_memory.data + instance.w2c_memory.size - address - sizeof(T); +#else + return instance.w2c_memory.data + address; +#endif // MKXPZ_BIG_ENDIAN + } + + // Gets a pointer to the given index in the array at a given address in sandbox memory. + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *sandbox_ptr_unaligned(struct w2c_ruby &instance, wasm_ptr_t array_address, wasm_size_t array_index) noexcept { + if (array_address + array_index < array_address) { + std::abort(); + } + return sandbox_ptr_unaligned(instance, array_address + array_index * sizeof(T)); + } // Gets a reference to the value stored at a given address in sandbox memory. + // Make sure the address is aligned, or this function will abort. template T &sandbox_ref(struct w2c_ruby &instance, wasm_ptr_t address) noexcept { - static_assert(std::is_arithmetic::value, "can only get references to numeric values in the sandbox"); if (address % sizeof(T) != 0) { #ifdef MKXPZ_RETRO_MEMORY64 std::fprintf(stderr, "unaligned memory access of size %u at address 0x%016llx in `mkxp_sandbox::sandbox_ref()`\n", (unsigned int)sizeof(T), (unsigned long long)address); @@ -165,16 +185,14 @@ namespace mkxp_sandbox { std::fflush(stderr); std::abort(); } - assert(address % sizeof(T) == 0); -#ifdef MKXPZ_BIG_ENDIAN - return *(T *)sandbox_ptr(instance, address + sizeof(T)); -#else - return *(T *)sandbox_ptr(instance, address); -#endif // MKXPZ_BIG_ENDIAN + return *(T *)sandbox_ptr_unaligned(instance, address); } // Gets a reference to the value stored at the given index in the array at a given address in sandbox memory. template T &sandbox_ref(struct w2c_ruby &instance, wasm_ptr_t array_address, wasm_size_t array_index) noexcept { + if (array_address + array_index < array_address) { + std::abort(); + } return sandbox_ref(array_address + array_index * sizeof(T)); } @@ -218,26 +236,20 @@ namespace mkxp_sandbox { void sandbox_strcpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src) noexcept; // Copies a string into a sandbox memory address. - void sandbox_strncpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept; + void sandbox_strncpy_s(struct w2c_ruby &instance, wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) noexcept; // Copies an array of length `num_elements` into a sandbox memory address. template void sandbox_arycpy(struct w2c_ruby &instance, wasm_ptr_t dst_address, const T *src, wasm_size_t num_elements) noexcept { -#ifdef MKXPZ_BIG_ENDIAN - T *dst = (T *)sandbox_ptr(instance, dst_address); - while (num_elements > 0) { - if ((uint8_t *)dst - instance.w2c_memory.data < sizeof(T)) { - std::abort(); - } - *--dst = *src++; - --num_elements; - } -#else - if (instance.w2c_memory.size - dst_address < num_elements * sizeof(T)) { + if (dst_address >= instance.w2c_memory.size || instance.w2c_memory.size - dst_address < num_elements * sizeof(T)) { std::abort(); } - T *dst = (T *)sandbox_ptr(instance, dst_address); +#ifdef MKXPZ_BIG_ENDIAN + for (wasm_size_t i = 0; i < num_elements; ++i) { + std::memcpy(sandbox_ptr_unaligned(instance, dst_address, i), src + i, sizeof(T)); + } +#else if (num_elements > 0) { - std::memcpy(dst, src, num_elements * sizeof(T)); + std::memcpy(sandbox_ptr_unaligned(instance, dst_address), src, num_elements * sizeof(T)); } #endif } @@ -351,14 +363,25 @@ namespace mkxp_sandbox { void copy_memory_from(const void *ptr, wasm_size_t size, wasm_size_t capacity, bool swap_bytes) noexcept; // Gets a pointer to the given address in sandbox memory. - void *ptr(wasm_ptr_t address) const noexcept; + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *ptr_unaligned(wasm_ptr_t address) const noexcept { + return sandbox_ptr_unaligned(instance(), address); + } + + // Gets a pointer to the given index in the array at a given address in sandbox memory. + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *ptr_unaligned(wasm_ptr_t array_address, wasm_size_t array_index) const noexcept { + return sandbox_ptr_unaligned(instance(), array_address, array_index); + } // Gets a reference to the value stored at a given address in sandbox memory. + // Make sure the address is aligned, or this function will abort. template T &ref(wasm_ptr_t address) const noexcept { return sandbox_ref(instance(), address); } // Gets a reference to the value stored at the given index in the array at a given address in sandbox memory. + // Make sure the address is aligned, or this function will abort. template T &ref(wasm_ptr_t array_address, wasm_size_t array_index) const noexcept { return ref(array_address + array_index * sizeof(T)); } @@ -373,7 +396,7 @@ namespace mkxp_sandbox { void strcpy(wasm_ptr_t dst_address, const char *src) const noexcept; // Copies a string into a sandbox memory address. - void strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept; + void strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept; // Copies an array of length `num_elements` into a sandbox memory address. template void arycpy(wasm_ptr_t dst_address, const T *src, wasm_size_t num_elements) const noexcept { diff --git a/binding-sandbox/bitmap-binding.cpp b/binding-sandbox/bitmap-binding.cpp index 8835f011..4df54393 100644 --- a/binding-sandbox/bitmap-binding.cpp +++ b/binding-sandbox/bitmap-binding.cpp @@ -19,6 +19,7 @@ ** along with mkxp. If not, see . */ +#include #include "bitmap-binding.h" #include "disposable-binding.h" #include "etc-binding.h" @@ -406,7 +407,12 @@ static VALUE get_raw_data(VALUE self) { SANDBOX_AWAIT_S(1, rb_str_new_cstr, ""); SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(1), SANDBOX_SLOT(2)); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(1)); - SANDBOX_GUARD_L(bitmap->getRaw(sb().e, sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(2))); +#ifdef MKXPZ_BIG_ENDIAN + SANDBOX_GUARD_L(bitmap->getRaw(sb().e, &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1), SANDBOX_SLOT(2))); + std::reverse(&sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1), &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(2), (int32_t)1) - 1) + SANDBOX_SLOT(2)); +#else + SANDBOX_GUARD_L(bitmap->getRaw(sb().e, &sb()->ref(SANDBOX_SLOT(0)), SANDBOX_SLOT(2))); +#endif // MKXPZ_BIG_ENDIAN } return SANDBOX_SLOT(1); @@ -418,13 +424,18 @@ static VALUE get_raw_data(VALUE self) { static VALUE set_raw_data(VALUE self, VALUE value) { struct coro : boost::asio::coroutine { - typedef decl_slots slots; + typedef decl_slots slots; VALUE operator()(VALUE self, VALUE value) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_S(0, rb_string_value_ptr, &value); SANDBOX_AWAIT_S(1, get_bytesize, value); - SANDBOX_GUARD_L(get_private_data(self)->replaceRaw(sb().e, sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1))); +#ifdef MKXPZ_BIG_ENDIAN + SANDBOX_GUARD_L(get_private_data(self)->replaceRaw(sb().e, &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1), SANDBOX_SLOT(1))); + std::reverse(&sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1), &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (int32_t)1) - 1) + SANDBOX_SLOT(1)); +#else + SANDBOX_GUARD_L(get_private_data(self)->replaceRaw(sb().e, &sb()->ref(SANDBOX_SLOT(0)), SANDBOX_SLOT(1))); +#endif // MKXPZ_BIG_ENDIAN } return self; diff --git a/binding-sandbox/serializable-binding.h b/binding-sandbox/serializable-binding.h index a94420f4..25ef0ef3 100644 --- a/binding-sandbox/serializable-binding.h +++ b/binding-sandbox/serializable-binding.h @@ -22,6 +22,7 @@ #ifndef MKXPZ_SANDBOX_SERIALIZABLE_BINDING_H #define MKXPZ_SANDBOX_SERIALIZABLE_BINDING_H +#include #include "binding-util.h" namespace mkxp_sandbox { @@ -34,7 +35,12 @@ namespace mkxp_sandbox { SANDBOX_AWAIT_S(2, rb_obj_alloc, klass); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &src); SANDBOX_AWAIT_S(1, get_bytesize, src); - SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, (const char *)sb()->ptr(SANDBOX_SLOT(0)), SANDBOX_SLOT(1)))); +#ifdef MKXPZ_BIG_ENDIAN + SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), SANDBOX_SLOT(1)))); + std::reverse(&sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1) + SANDBOX_SLOT(1)); +#else + SANDBOX_GUARD(set_private_data(sb().e, SANDBOX_SLOT(2), C::deserialize(sb().e, &sb()->ref(SANDBOX_SLOT(0)), SANDBOX_SLOT(1)))); +#endif // MKXPZ_BIG_ENDIAN } return SANDBOX_SLOT(2); @@ -54,7 +60,12 @@ namespace mkxp_sandbox { SANDBOX_AWAIT_S(2, rb_str_new_cstr, ""); SANDBOX_AWAIT(rb_str_resize, SANDBOX_SLOT(2), SANDBOX_SLOT(1)); SANDBOX_AWAIT_S(0, rb_string_value_ptr, &SANDBOX_SLOT(2)); - get_private_data(self)->serialize((char *)sb()->ptr(SANDBOX_SLOT(0))); +#ifdef MKXPZ_BIG_ENDIAN + get_private_data(self)->serialize(&sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1)); + std::reverse(&sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1), &sb()->ref(SANDBOX_SLOT(0), std::max(SANDBOX_SLOT(1), (wasm_size_t)1) - 1) + SANDBOX_SLOT(1)); +#else + get_private_data(self)->serialize(&sb()->ref(SANDBOX_SLOT(0))); +#endif // MKXPZ_BIG_ENDIAN } return SANDBOX_SLOT(2); diff --git a/binding-sandbox/wasi.cpp b/binding-sandbox/wasi.cpp index b7163279..50771e7a 100644 --- a/binding-sandbox/wasi.cpp +++ b/binding-sandbox/wasi.cpp @@ -138,10 +138,6 @@ void wasi_t::deallocate_file_descriptor(uint32_t fd) { } } -void *wasi_t::ptr(wasm_ptr_t address) const noexcept { - return sandbox_ptr(*ruby, address); -} - wasm_size_t wasi_t::strlen(wasm_ptr_t address) const noexcept { return sandbox_strlen(*ruby, address); } @@ -150,8 +146,8 @@ void wasi_t::strcpy(wasm_ptr_t dst_address, const char *src) const noexcept { sandbox_strcpy(*ruby, dst_address, src); } -void wasi_t::strncpy(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept { - sandbox_strncpy(*ruby, dst_address, src, max_size); +void wasi_t::strncpy_s(wasm_ptr_t dst_address, const char *src, wasm_size_t max_size) const noexcept { + sandbox_strncpy_s(*ruby, dst_address, src, max_size); } struct mkxp_sandbox::sandbox_str_guard wasi_t::str(wasm_ptr_t address) const noexcept { @@ -550,7 +546,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_prestat_dir_name(wasi_t *was return WASI_EBADF; case wasi_fd_type::FS: - wasi->strncpy(path, wasi->fdtable[fd].dir_handle()->path.c_str(), path_len + 1); + wasi->strncpy_s(path, wasi->fdtable[fd].dir_handle()->path.c_str(), path_len + 1); return WASI_ESUCCESS; case wasi_fd_type::STDIN: @@ -621,17 +617,21 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_read(wasi_t *wasi, uint32_t { uint32_t size = 0; while (iovs_len > 0) { - uint8_t *ptr = (uint8_t *)wasi->ptr(wasi->ref(iovs)); + uint32_t ptr = wasi->ref(iovs); uint32_t length = wasi->ref(iovs + 4); + if (length > 0) { #ifdef MKXPZ_BIG_ENDIAN - ptr -= length; + uint8_t *buffer = &wasi->ref(ptr, length - 1); +#else + uint8_t *buffer = &wasi->ref(ptr); #endif // MKXPZ_BIG_ENDIAN - PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->file.get(), ptr, length); + PHYSFS_sint64 n = PHYSFS_readBytes(wasi->fdtable[fd].file_handle()->file.get(), buffer, length); #ifdef MKXPZ_BIG_ENDIAN - std::reverse(ptr, ptr + length); + std::reverse(buffer, buffer + length); #endif // MKXPZ_BIG_ENDIAN - if (n < 0) return WASI_EIO; - size += n; + if (n < 0) return WASI_EIO; + size += n; + } iovs += 8; --iovs_len; } @@ -694,29 +694,13 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, uint32 if (edata->buf - edata->original_buf + 8 > edata->buf_len) { return PHYSFS_ENUM_STOP; } - std::memcpy( -#ifdef MKXPZ_BIG_ENDIAN - wasi->ptr(edata->buf + 8), -#else - wasi->ptr(edata->buf), -#endif // MKXPZ_BIG_ENDIAN - &edata->cookie, - 8 - ); + std::memcpy(wasi->ptr_unaligned(edata->buf), &edata->cookie, 8); edata->buf += 8; if (edata->buf - edata->original_buf + 8 > edata->buf_len) { return PHYSFS_ENUM_STOP; } - std::memset( -#ifdef MKXPZ_BIG_ENDIAN - wasi->ptr(edata->buf + 8), -#else - wasi->ptr(edata->buf), -#endif // MKXPZ_BIG_ENDIAN - 0, - 8 - ); + std::memset(wasi->ptr_unaligned(edata->buf), 0, 8); edata->buf += 8; if (edata->buf - edata->original_buf + 4 > edata->buf_len) { @@ -724,15 +708,7 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_readdir(wasi_t *wasi, uint32 } { const uint32_t value = std::strlen(filename); - std::memcpy( -#ifdef MKXPZ_BIG_ENDIAN - wasi->ptr(edata->buf + 8), -#else - wasi->ptr(edata->buf), -#endif // MKXPZ_BIG_ENDIAN - &value, - 4 - ); + std::memcpy(wasi->ptr_unaligned(edata->buf), &value, 4); } edata->buf += 4; @@ -908,18 +884,21 @@ extern "C" uint32_t w2c_wasi__snapshot__preview1_fd_write(wasi_t *wasi, uint32_t } uint32_t size = 0; while (iovs_len > 0) { - uint8_t *ptr = (uint8_t *)wasi->ptr(wasi->ref(iovs)); + uint32_t ptr = wasi->ref(iovs); uint32_t length = wasi->ref(iovs + 4); + if (length > 0) { #ifdef MKXPZ_BIG_ENDIAN - ptr -= length; - std::reverse(ptr, ptr + length); + uint8_t *buffer = &wasi->ref(ptr, length - 1); +#else + uint8_t *buffer = &wasi->ref(ptr); #endif // MKXPZ_BIG_ENDIAN - PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->file.get_write(), ptr, length); + PHYSFS_sint64 n = PHYSFS_writeBytes(wasi->fdtable[fd].file_handle()->file.get_write(), buffer, length); #ifdef MKXPZ_BIG_ENDIAN - std::reverse(ptr, ptr + length); + std::reverse(buffer, buffer + length); #endif // MKXPZ_BIG_ENDIAN - if (n >= 0) { - size += n; + if (n > 0) { + size += n; + } } iovs += 8; --iovs_len; diff --git a/binding-sandbox/wasi.h b/binding-sandbox/wasi.h index c2064902..7c6a0bd1 100644 --- a/binding-sandbox/wasi.h +++ b/binding-sandbox/wasi.h @@ -210,14 +210,25 @@ typedef struct w2c_wasi__snapshot__preview1 { void deallocate_file_descriptor(uint32_t fd); // Gets a pointer to the given address in sandbox memory. - void *ptr(mkxp_sandbox::wasm_ptr_t address) const noexcept; + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t address) const noexcept { + return mkxp_sandbox::sandbox_ptr_unaligned(*ruby, address); + } + + // Gets a pointer to the given index in the array at a given address in sandbox memory. + // Unlike `sandbox_ref`, the address does not need to be aligned. + template void *ptr_unaligned(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept { + return mkxp_sandbox::sandbox_ptr_unaligned(*ruby, array_address, array_index); + } // Gets a reference to the value stored at a given address in sandbox memory. + // Make sure the address is aligned, or this function will abort. template T &ref(mkxp_sandbox::wasm_ptr_t address) const noexcept { return mkxp_sandbox::sandbox_ref(*ruby, address); } // Gets a reference to the value stored at the given index in the array at a given address in sandbox memory. + // Make sure the address is aligned, or this function will abort. template T &ref(mkxp_sandbox::wasm_ptr_t array_address, mkxp_sandbox::wasm_size_t array_index) const noexcept { return ref(array_address + array_index * sizeof(T)); } @@ -232,7 +243,7 @@ typedef struct w2c_wasi__snapshot__preview1 { void strcpy(mkxp_sandbox::wasm_ptr_t dst_address, const char *src) const noexcept; // Copies a string into a sandbox memory address. - void strncpy(mkxp_sandbox::wasm_ptr_t dst_address, const char *src, mkxp_sandbox::wasm_size_t max_size) const noexcept; + void strncpy_s(mkxp_sandbox::wasm_ptr_t dst_address, const char *src, mkxp_sandbox::wasm_size_t max_size) const noexcept; // Copies an array of length `num_elements` into a sandbox memory address. template void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept { diff --git a/src/display/bitmap.cpp b/src/display/bitmap.cpp index 77cf9604..f13e9382 100644 --- a/src/display/bitmap.cpp +++ b/src/display/bitmap.cpp @@ -2306,10 +2306,6 @@ bool Bitmap::getRaw(Exception &exception, 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."; } -#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - output = (uint8_t *)output - output_size; -#endif - if (!p->animation.enabled && (p->surface || p->megaSurface)) { void *src = (p->megaSurface) ? p->megaSurface->pixels : p->surface->pixels; memcpy(output, src, output_size); @@ -2319,10 +2315,6 @@ bool Bitmap::getRaw(Exception &exception, void *output, int output_size) 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; } @@ -2345,18 +2337,9 @@ void Bitmap::replaceRaw(Exception &exception, void *pixel_data, int size) return; } -#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - pixel_data = (uint8_t *)pixel_data - size; - std::reverse((uint8_t *)pixel_data, (uint8_t *)pixel_data + size); -#endif - TEX::bind(getGLTypes().tex); 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 - #ifdef MKXPZ_RETRO p->pushDiff(pixel_data, rect()); #endif // MKXPZ_RETRO diff --git a/src/etc/table.cpp b/src/etc/table.cpp index 79aa8c86..36179ff5 100644 --- a/src/etc/table.cpp +++ b/src/etc/table.cpp @@ -129,13 +129,8 @@ void Table::serialize(char *buffer) const writeInt32(&buffer, zs); 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 if (size > 0) memcpy(buffer, dataPtr(data), sizeof(int16_t)*size); -#endif } @@ -167,13 +162,8 @@ Table *Table::deserialize(Exception &exception, const char *data, int len) 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 if (size > 0) memcpy(dataPtr(t->data), data, sizeof(int16_t)*size); -#endif return t; } diff --git a/src/util/serial-util.h b/src/util/serial-util.h index c8a7eeba..07ea977e 100644 --- a/src/util/serial-util.h +++ b/src/util/serial-util.h @@ -31,15 +31,10 @@ readInt32(const char **dataP) { int32_t result; -#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - *dataP -= 4; - memcpy(&result, *dataP, 4); -#else memcpy(&result, *dataP, 4); *dataP += 4; -#endif -#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) +#ifdef MKXPZ_BIG_ENDIAN # ifdef _MSC_VER static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits"); result = (int32_t)_byteswap_ulong((unsigned long)result); @@ -54,7 +49,7 @@ readInt32(const char **dataP) static inline double readDouble(const char **dataP) { -#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) +#ifdef MKXPZ_BIG_ENDIAN uint64_t result; memcpy(&result, *dataP, 8); @@ -70,13 +65,8 @@ readDouble(const char **dataP) #else double result; -# if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - *dataP -= 8; - memcpy(&result, *dataP, 8); -# else memcpy(&result, *dataP, 8); *dataP += 8; -# endif return result; #endif @@ -85,7 +75,7 @@ readDouble(const char **dataP) static inline void writeInt32(char **dataP, int32_t value) { -#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) +#ifdef MKXPZ_BIG_ENDIAN # ifdef _MSC_VER static_assert(sizeof(unsigned long) == sizeof(int32_t), "unsigned long should be 32 bits"); value = (int32_t)_byteswap_ulong((unsigned long)value); @@ -94,19 +84,14 @@ writeInt32(char **dataP, int32_t value) # endif #endif -#if defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - *dataP -= 4; - memcpy(*dataP, &value, 4); -#else memcpy(*dataP, &value, 4); *dataP += 4; -#endif } static inline void writeDouble(char **dataP, double value) { -#if !defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) +#ifdef MKXPZ_BIG_ENDIAN uint64_t valueUint = *(uint64_t *)&value; # ifdef _MSC_VER @@ -116,14 +101,10 @@ writeDouble(char **dataP, double value) # endif memcpy(*dataP, &valueUint, 8); - *dataP += 8; -#elif defined(MKXPZ_RETRO) && defined(MKXPZ_BIG_ENDIAN) - *dataP -= 8; - memcpy(*dataP, &value, 8); #else memcpy(*dataP, &value, 8); - *dataP += 8; #endif + *dataP += 8; } #endif // SERIALUTIL_H