/* ** sandbox.h ** ** This file is part of mkxp. ** ** Copyright (C) 2013 - 2021 Amaryllis Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #ifndef MKXPZ_SANDBOX_H #define MKXPZ_SANDBOX_H #include #include #include #include #include #include #include #include "wasm-types.h" #include "audio.h" #include "etc.h" #include "graphics.h" namespace mkxp_sandbox { struct sandbox; } namespace mkxp_retro { extern boost::optional sandbox; } namespace mkxp_sandbox { struct sandbox { private: std::shared_ptr ruby; std::unique_ptr wasi; boost::optional bindings; std::atomic movie; bool yielding; wasm_ptr_t sandbox_malloc(wasm_size_t size); void sandbox_free(wasm_ptr_t ptr); public: Exception e; std::vector script_decode_buffer; std::vector font_names_buffer; Bitmap *trans_map; Color bitmap_pixel_buffer; AudioMutex movie_mutex; struct retro_device_power device_power; std::string convert_string_buffer; bool transitioning; inline struct mkxp_sandbox::bindings &operator*() noexcept { return *bindings; } inline struct mkxp_sandbox::bindings *operator->() noexcept { return &*bindings; } sandbox(); ~sandbox(); bool sandbox_serialize_wasi(void *&data, wasm_size_t &max_size) const; bool sandbox_deserialize_wasi(const void *&data, wasm_size_t &max_size); Movie *get_movie_from_main_thread(); Movie *get_movie_from_audio_thread(); void set_movie(Movie *new_movie); // Gets the current working directory in the sandbox. struct sandbox_str_guard getcwd(); // Internal utility method of the `SANDBOX_YIELD` macro. inline void _begin_yield() { yielding = true; w2c_ruby_asyncify_start_unwind(ruby.get(), ruby->w2c_mkxp_sandbox_async_buf); } // Internal utility method of the `SANDBOX_YIELD` macro. inline void _end_yield() { w2c_ruby_asyncify_stop_rewind(ruby.get()); } // Executes the given coroutine as the top-level coroutine. Don't call this from inside of another coroutine; use `sb()->bind()` instead. // Returns whether or not the coroutine completed execution. template inline bool run() { if (yielding) { w2c_ruby_asyncify_start_rewind(ruby.get(), ruby->w2c_mkxp_sandbox_async_buf); yielding = false; } for (;;) { { struct mkxp_sandbox::bindings::stack_frame_guard frame = bindings->bind(); frame()(); if (yielding || frame().is_complete()) break; } w2c_ruby_mkxp_sandbox_yield(ruby.get()); } return !yielding; } }; inline struct sandbox &sb() noexcept { return *mkxp_retro::sandbox; } } #endif // MKXPZ_SANDBOX_H