mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
Fix save/load states in Emscripten build (#2470)
* Fix save/load states in Emscripten build * Simplified Emscripten integration points * Moved standalone JS functions to be static member functions of running_machine * Improved Emscripten main loop * Use convenience functions for cleaner code As an added bonus, this now allows for proper shutdown of the running machine when running in the Emscripten environment - previously, attempts to exit the program were just being ignored.
This commit is contained in:
parent
6d634e0093
commit
15c2bb0c08
@ -1,8 +1,8 @@
|
|||||||
// MAME-JavaScript function mappings
|
// MAME-JavaScript function mappings
|
||||||
var JSMAME = JSMAME || {};
|
var JSMAME = JSMAME || {};
|
||||||
JSMAME.get_machine = Module.cwrap('_Z14js_get_machinev', 'number');
|
JSMAME.get_machine = Module.cwrap('_ZN15running_machine30emscripten_get_running_machineEv', 'number');
|
||||||
JSMAME.get_ui = Module.cwrap('_Z9js_get_uiv', 'number');
|
JSMAME.get_ui = Module.cwrap('_ZN15running_machine17emscripten_get_uiEv', 'number');
|
||||||
JSMAME.get_sound = Module.cwrap('_Z12js_get_soundv', 'number');
|
JSMAME.get_sound = Module.cwrap('_ZN15running_machine20emscripten_get_soundEv', 'number');
|
||||||
JSMAME.ui_set_show_fps = Module.cwrap('_ZN15mame_ui_manager12set_show_fpsEb', '', ['number', 'number']);
|
JSMAME.ui_set_show_fps = Module.cwrap('_ZN15mame_ui_manager12set_show_fpsEb', '', ['number', 'number']);
|
||||||
JSMAME.ui_get_show_fps = Module.cwrap('_ZNK15mame_ui_manager8show_fpsEv', 'number', ['number']);
|
JSMAME.ui_get_show_fps = Module.cwrap('_ZNK15mame_ui_manager8show_fpsEv', 'number', ['number']);
|
||||||
JSMAME.sound_manager_mute = Module.cwrap('_ZN13sound_manager4muteEbh', '', ['number', 'number', 'number']);
|
JSMAME.sound_manager_mute = Module.cwrap('_ZN13sound_manager4muteEbh', '', ['number', 'number', 'number']);
|
||||||
|
@ -157,7 +157,7 @@ end
|
|||||||
.. " -s TOTAL_MEMORY=268435456"
|
.. " -s TOTAL_MEMORY=268435456"
|
||||||
.. " -s DISABLE_EXCEPTION_CATCHING=2"
|
.. " -s DISABLE_EXCEPTION_CATCHING=2"
|
||||||
.. " -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\",\"__ZN12cli_frontend7executeEiPPc\"]'"
|
.. " -s EXCEPTION_CATCHING_WHITELIST='[\"__ZN15running_machine17start_all_devicesEv\",\"__ZN12cli_frontend7executeEiPPc\"]'"
|
||||||
.. " -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__Z14js_get_machinev', '__Z9js_get_uiv', '__Z12js_get_soundv', '__ZN15mame_ui_manager12set_show_fpsEb', '__ZNK15mame_ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio', '_SDL_SendKeyboardKey']\""
|
.. " -s EXPORTED_FUNCTIONS=\"['_main', '_malloc', '__ZN15running_machine30emscripten_get_running_machineEv', '__ZN15running_machine17emscripten_get_uiEv', '__ZN15running_machine20emscripten_get_soundEv', '__ZN15mame_ui_manager12set_show_fpsEb', '__ZNK15mame_ui_manager8show_fpsEv', '__ZN13sound_manager4muteEbh', '_SDL_PauseAudio', '_SDL_SendKeyboardKey']\""
|
||||||
.. " --pre-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/modules/sound/js_sound.js"
|
.. " --pre-js " .. _MAKE.esc(MAME_DIR) .. "src/osd/modules/sound/js_sound.js"
|
||||||
.. " --post-js " .. _MAKE.esc(MAME_DIR) .. "scripts/resources/emscripten/emscripten_post.js"
|
.. " --post-js " .. _MAKE.esc(MAME_DIR) .. "scripts/resources/emscripten/emscripten_post.js"
|
||||||
.. " --embed-file " .. _MAKE.esc(MAME_DIR) .. "bgfx/chains@bgfx/chains"
|
.. " --embed-file " .. _MAKE.esc(MAME_DIR) .. "bgfx/chains@bgfx/chains"
|
||||||
|
@ -89,8 +89,6 @@
|
|||||||
|
|
||||||
#if defined(EMSCRIPTEN)
|
#if defined(EMSCRIPTEN)
|
||||||
#include <emscripten.h>
|
#include <emscripten.h>
|
||||||
|
|
||||||
void js_set_main_loop(running_machine * machine);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -342,17 +340,18 @@ int running_machine::run(bool quiet)
|
|||||||
|
|
||||||
export_http_api();
|
export_http_api();
|
||||||
|
|
||||||
// run the CPUs until a reset or exit
|
|
||||||
m_hard_reset_pending = false;
|
m_hard_reset_pending = false;
|
||||||
|
|
||||||
|
#if defined(EMSCRIPTEN)
|
||||||
|
// break out to our async javascript loop and halt
|
||||||
|
emscripten_set_running_machine(this);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// run the CPUs until a reset or exit
|
||||||
while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != saveload_schedule::NONE)
|
while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != saveload_schedule::NONE)
|
||||||
{
|
{
|
||||||
g_profiler.start(PROFILER_EXTRA);
|
g_profiler.start(PROFILER_EXTRA);
|
||||||
|
|
||||||
#if defined(EMSCRIPTEN)
|
|
||||||
// break out to our async javascript loop and halt
|
|
||||||
js_set_main_loop(this);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// execute CPUs if not paused
|
// execute CPUs if not paused
|
||||||
if (!m_paused)
|
if (!m_paused)
|
||||||
m_scheduler.timeslice();
|
m_scheduler.timeslice();
|
||||||
@ -422,7 +421,6 @@ int running_machine::run(bool quiet)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// schedule_exit - schedule a clean exit
|
// schedule_exit - schedule a clean exit
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -1316,41 +1314,71 @@ device_memory_interface::space_config_vector dummy_space_device::memory_space_co
|
|||||||
|
|
||||||
#if defined(EMSCRIPTEN)
|
#if defined(EMSCRIPTEN)
|
||||||
|
|
||||||
static running_machine * jsmess_machine;
|
running_machine * running_machine::emscripten_running_machine;
|
||||||
|
|
||||||
void js_main_loop()
|
void running_machine::emscripten_main_loop()
|
||||||
{
|
{
|
||||||
if (jsmess_machine->paused()) {
|
running_machine *machine = emscripten_running_machine;
|
||||||
jsmess_machine->video().frame_update();
|
|
||||||
return;
|
g_profiler.start(PROFILER_EXTRA);
|
||||||
|
|
||||||
|
// execute CPUs if not paused
|
||||||
|
if (!machine->m_paused)
|
||||||
|
{
|
||||||
|
device_scheduler * scheduler;
|
||||||
|
scheduler = &(machine->scheduler());
|
||||||
|
|
||||||
|
// Emscripten will call this function at 60Hz, so step the simulation
|
||||||
|
// forward for the amount of time that has passed since the last frame
|
||||||
|
const attotime frametime(0,HZ_TO_ATTOSECONDS(60));
|
||||||
|
const attotime stoptime(scheduler->time() + frametime);
|
||||||
|
|
||||||
|
while (!machine->m_paused && !machine->scheduled_event_pending() && scheduler->time() < stoptime)
|
||||||
|
{
|
||||||
|
scheduler->timeslice();
|
||||||
|
// handle save/load
|
||||||
|
if (machine->m_saveload_schedule != saveload_schedule::NONE)
|
||||||
|
{
|
||||||
|
machine->handle_saveload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// otherwise, just pump video updates through
|
||||||
|
else
|
||||||
|
machine->m_video->frame_update();
|
||||||
|
|
||||||
|
// cancel the emscripten loop if the system has been told to exit
|
||||||
|
if (machine->exit_pending())
|
||||||
|
{
|
||||||
|
emscripten_cancel_main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
device_scheduler * scheduler;
|
g_profiler.stop();
|
||||||
scheduler = &(jsmess_machine->scheduler());
|
|
||||||
attotime stoptime(scheduler->time() + attotime(0,HZ_TO_ATTOSECONDS(60)));
|
|
||||||
while (scheduler->time() < stoptime) {
|
|
||||||
scheduler->timeslice();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void js_set_main_loop(running_machine * machine) {
|
void running_machine::emscripten_set_running_machine(running_machine *machine)
|
||||||
jsmess_machine = machine;
|
{
|
||||||
|
emscripten_running_machine = machine;
|
||||||
EM_ASM (
|
EM_ASM (
|
||||||
JSMESS.running = true;
|
JSMESS.running = true;
|
||||||
);
|
);
|
||||||
emscripten_set_main_loop(&js_main_loop, 0, 1);
|
emscripten_set_main_loop(&(emscripten_main_loop), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
running_machine * js_get_machine() {
|
running_machine * running_machine::emscripten_get_running_machine()
|
||||||
return jsmess_machine;
|
{
|
||||||
|
return emscripten_running_machine;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_manager * js_get_ui() {
|
ui_manager * running_machine::emscripten_get_ui()
|
||||||
return &(jsmess_machine->ui());
|
{
|
||||||
|
return &(emscripten_running_machine->ui());
|
||||||
}
|
}
|
||||||
|
|
||||||
sound_manager * js_get_sound() {
|
sound_manager * running_machine::emscripten_get_sound()
|
||||||
return &(jsmess_machine->sound());
|
{
|
||||||
|
return &(emscripten_running_machine->sound());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(EMSCRIPTEN) */
|
#endif /* defined(EMSCRIPTEN) */
|
||||||
|
@ -396,6 +396,17 @@ private:
|
|||||||
|
|
||||||
// configuration state
|
// configuration state
|
||||||
dummy_space_device m_dummy_space;
|
dummy_space_device m_dummy_space;
|
||||||
|
|
||||||
|
#if defined(EMSCRIPTEN)
|
||||||
|
private:
|
||||||
|
static running_machine *emscripten_running_machine;
|
||||||
|
static void emscripten_main_loop();
|
||||||
|
public:
|
||||||
|
static void emscripten_set_running_machine(running_machine *machine);
|
||||||
|
static running_machine * emscripten_get_running_machine();
|
||||||
|
static ui_manager * emscripten_get_ui();
|
||||||
|
static sound_manager * emscripten_get_sound();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user