mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-06 18:12:55 +02:00
Implement save state serialization for WASI file descriptors in libretro builds
This commit is contained in:
parent
057b6dc95d
commit
e957af931c
5 changed files with 57 additions and 7 deletions
|
@ -125,6 +125,10 @@ sandbox::~sandbox() {
|
|||
wasm2c_ruby_free(RB);
|
||||
}
|
||||
|
||||
bool sandbox::sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const {
|
||||
return wasi->sandbox_serialize(data, max_size);
|
||||
}
|
||||
|
||||
Movie *sandbox::get_movie_from_main_thread() {
|
||||
return movie.load(std::memory_order_relaxed); // No need for synchronization because we always set the movie from the main thread
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace mkxp_sandbox {
|
|||
inline struct mkxp_sandbox::bindings *operator->() noexcept { return &*bindings; }
|
||||
sandbox();
|
||||
~sandbox();
|
||||
bool sandbox_serialize_fdtable(void *&data, wasm_size_t &max_size) const;
|
||||
Movie *get_movie_from_main_thread();
|
||||
Movie *get_movie_from_audio_thread();
|
||||
void set_movie(Movie *new_movie);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "core.h"
|
||||
#include "wasi.h"
|
||||
#include "binding-base.h"
|
||||
#include "sandbox-serial-util.h"
|
||||
|
||||
using namespace mkxp_sandbox;
|
||||
|
||||
|
@ -36,11 +37,11 @@ static inline size_t strlen_safe(const char *str, size_t max_length) {
|
|||
return ptr == nullptr ? max_length : ptr - str;
|
||||
}
|
||||
|
||||
struct fs_dir *wasi_file_entry::dir_handle() {
|
||||
struct fs_dir *wasi_file_entry::dir_handle() const noexcept {
|
||||
return (struct fs_dir *)handle;
|
||||
}
|
||||
|
||||
struct FileSystem::File *wasi_file_entry::file_handle() {
|
||||
struct FileSystem::File *wasi_file_entry::file_handle() const noexcept {
|
||||
return (struct FileSystem::File *)handle;
|
||||
}
|
||||
|
||||
|
@ -128,6 +129,42 @@ const char *wasi_t::str(wasm_ptr_t address) const noexcept {
|
|||
return sandbox_str(*ruby, address);
|
||||
}
|
||||
|
||||
bool wasi_t::sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const {
|
||||
if (!::sandbox_serialize((wasm_size_t)fdtable.size(), data, max_size)) return false;
|
||||
|
||||
wasm_size_t num_free_handles = 0;
|
||||
|
||||
for (const struct wasi_file_entry &entry : fdtable) {
|
||||
if (entry.type == wasi_fd_type::FSDIR) {
|
||||
if (num_free_handles > 0) {
|
||||
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||
num_free_handles = 0;
|
||||
}
|
||||
if (!::sandbox_serialize((uint8_t)1, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(entry.dir_handle()->path, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(entry.dir_handle()->root->path, data, max_size)) return false;
|
||||
} else if (entry.type == wasi_fd_type::FSFILE) {
|
||||
if (num_free_handles > 0) {
|
||||
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||
num_free_handles = 0;
|
||||
}
|
||||
if (!::sandbox_serialize((uint8_t)2, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(entry.file_handle()->path(), data, max_size)) return false;
|
||||
} else {
|
||||
++num_free_handles;
|
||||
}
|
||||
}
|
||||
if (num_free_handles > 0) {
|
||||
if (!::sandbox_serialize((uint8_t)0, data, max_size)) return false;
|
||||
if (!::sandbox_serialize(num_free_handles, data, max_size)) return false;
|
||||
num_free_handles = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" uint32_t w2c_wasi__snapshot__preview1_args_get(wasi_t *wasi, wasm_ptr_t argv, wasm_ptr_t argv_buf) {
|
||||
return WASI_ESUCCESS;
|
||||
}
|
||||
|
|
|
@ -181,8 +181,8 @@ struct wasi_file_entry {
|
|||
// The file/directory handle that the file descriptor corresponds to. The exact type of this handle depends on the type of file descriptor.
|
||||
void *handle;
|
||||
|
||||
struct fs_dir *dir_handle();
|
||||
struct FileSystem::File *file_handle();
|
||||
struct fs_dir *dir_handle() const noexcept;
|
||||
struct FileSystem::File *file_handle() const noexcept;
|
||||
};
|
||||
|
||||
typedef struct w2c_wasi__snapshot__preview1 {
|
||||
|
@ -230,6 +230,8 @@ typedef struct w2c_wasi__snapshot__preview1 {
|
|||
template <typename T> void arycpy(mkxp_sandbox::wasm_ptr_t dst_address, const T *src, mkxp_sandbox::wasm_size_t num_elements) const noexcept {
|
||||
mkxp_sandbox::sandbox_arycpy(*ruby, dst_address, src, num_elements);
|
||||
}
|
||||
|
||||
bool sandbox_serialize(void *&data, mkxp_sandbox::wasm_size_t &max_size) const;
|
||||
} wasi_t;
|
||||
|
||||
#endif /* MKXPZ_SANDBOX_WASI_H */
|
||||
|
|
12
src/core.cpp
12
src/core.cpp
|
@ -1639,10 +1639,12 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
|||
if (!Graphics::sandbox_serialize_movie(sb().get_movie_from_main_thread(), data, max_size)) return false;
|
||||
}
|
||||
|
||||
// TODO: write the file descriptor table
|
||||
// Write the open WASI file descriptors
|
||||
if (!sb().sandbox_serialize_fdtable(data, max_size)) return false;
|
||||
|
||||
// Write each object
|
||||
// Write the number of objects, then each object
|
||||
OBJECTS_BEGIN;
|
||||
if (!sandbox_serialize((wasm_size_t)sb()->get_objects().size(), data, max_size)) OBJECTS_END_FAIL;
|
||||
wasm_size_t num_free_objects = 0;
|
||||
for (const auto &object : sb()->get_objects()) {
|
||||
if (object.typenum == 0) {
|
||||
|
@ -1665,7 +1667,10 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
|||
num_free_objects = 0;
|
||||
}
|
||||
|
||||
// Write each extra object that was found during serialization of the normal objects
|
||||
// Write the number of extra objects that were found during serialization of the normal objects, then each such object
|
||||
if (max_size < sizeof(wasm_size_t)) OBJECTS_END_FAIL;
|
||||
wasm_size_t *num_extra_objects_ptr = (wasm_size_t *)data;
|
||||
ADVANCE(sizeof(wasm_size_t));
|
||||
for (size_t i = 0; i < extra_objects.size(); ++i) { // More items can be added to this vector during iteration
|
||||
const void *ptr = std::get<0>(extra_objects[i]);
|
||||
wasm_size_t typenum = std::get<1>(extra_objects[i]);
|
||||
|
@ -1683,6 +1688,7 @@ extern "C" RETRO_API bool retro_serialize(void *data, size_t len) {
|
|||
if (!sandbox_serialize(num_free_objects, data, max_size)) OBJECTS_END_FAIL;
|
||||
num_free_objects = 0;
|
||||
}
|
||||
*num_extra_objects_ptr = (wasm_size_t)extra_objects.size();
|
||||
|
||||
OBJECTS_END;
|
||||
std::memset(data, 0, max_size);
|
||||
|
|
Loading…
Add table
Reference in a new issue