diff --git a/include/core/moviedata.hpp b/include/core/moviedata.hpp index 90eaed1e..11e9b153 100644 --- a/include/core/moviedata.hpp +++ b/include/core/moviedata.hpp @@ -51,7 +51,7 @@ extern std::string last_save; * Parameter secs: The seconds counter. * Parameter ssecs: The subsecond counter. */ -void mainloop_restore_state(const std::vector& state, uint64_t secs, uint64_t ssecs); +void mainloop_restore_state(const dynamic_state& state); std::string get_mprefix_for_project(); void set_mprefix_for_project(const std::string& pfx); diff --git a/include/lua/lua.hpp b/include/lua/lua.hpp index 7003d333..dc6bb0eb 100644 --- a/include/lua/lua.hpp +++ b/include/lua/lua.hpp @@ -73,8 +73,7 @@ struct lua_state void callback_snoop_input(uint32_t port, uint32_t controller, uint32_t index, short value) throw(); void callback_quit() throw(); void callback_keyhook(const std::string& key, keyboard::key& p) throw(); - void callback_do_unsafe_rewind(const std::vector& save, uint64_t secs, uint64_t ssecs, movie& mov, - void* u); + void callback_do_unsafe_rewind(movie& mov, void* u); bool callback_do_button(uint32_t port, uint32_t controller, uint32_t index, const char* type); void callback_movie_lost(const char* what); void callback_do_latch(std::list& args); diff --git a/include/lua/unsaferewind.hpp b/include/lua/unsaferewind.hpp index b3c94905..e834c496 100644 --- a/include/lua/unsaferewind.hpp +++ b/include/lua/unsaferewind.hpp @@ -3,22 +3,19 @@ #include "library/lua-base.hpp" #include "library/string.hpp" +#include "core/moviefile.hpp" struct lua_unsaferewind { lua_unsaferewind(lua::state& L); static size_t overcommit() { return 0; } - std::vector state; - uint64_t frame; - uint64_t lag; + //The console state. + dynamic_state console_state; + //Extra state variable involved in fast movie restore. It is not part of normal console state. uint64_t ptr; - uint64_t secs; - uint64_t ssecs; - std::vector pollcounters; - std::vector hostmemory; std::string print() { - return (stringfmt() << "to frame " << frame).str(); + return (stringfmt() << "to frame " << console_state.save_frame).str(); } }; diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index e9b3d453..e5aebaf4 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -712,8 +712,7 @@ jumpback: if(!*core.mlogic) return 0; uint64_t t = framerate_regulator::get_utime(); - std::vector s; - core.lua2->callback_do_unsafe_rewind(s, 0, 0, core.mlogic->get_movie(), unsafe_rewind_obj); + core.lua2->callback_do_unsafe_rewind(core.mlogic->get_movie(), unsafe_rewind_obj); core.dispatch->mode_change(false); do_unsafe_rewind = false; core.mlogic->get_mfile().dyn.is_savestate = true; @@ -805,11 +804,8 @@ nothing_to_do: } if(do_unsafe_rewind && !unsafe_rewind_obj) { uint64_t t = framerate_regulator::get_utime(); - std::vector s = core.rom->save_core_state(true); - uint64_t secs = core.mlogic->get_mfile().dyn.rtc_second; - uint64_t ssecs = core.mlogic->get_mfile().dyn.rtc_subsecond; - core.lua2->callback_do_unsafe_rewind(s, secs, ssecs, core.mlogic->get_movie(), - NULL); + core.mlogic->get_mfile().dyn.savestate = core.rom->save_core_state(true); + core.lua2->callback_do_unsafe_rewind(core.mlogic->get_movie(), NULL); do_unsafe_rewind = false; messages << "Rewind point set in " << (framerate_regulator::get_utime() - t) << " usec." << std::endl; diff --git a/src/core/moviedata.cpp b/src/core/moviedata.cpp index 9a1f1ffb..73644deb 100644 --- a/src/core/moviedata.cpp +++ b/src/core/moviedata.cpp @@ -885,16 +885,14 @@ bool do_load_state(const std::string& filename, int lmode) return true; } -void mainloop_restore_state(const std::vector& state, uint64_t secs, uint64_t ssecs) +void mainloop_restore_state(const dynamic_state& state) { auto& core = CORE(); //Force unlazy rrdata. core.mlogic->get_rrdata().read_base(rrdata::filename(core.mlogic->get_mfile().projectid), false); core.mlogic->get_rrdata().add((*core.nrrdata)()); - core.mlogic->get_mfile().dyn.rtc_second = secs; - core.mlogic->get_mfile().dyn.rtc_subsecond = ssecs; - core.rom->load_core_state(state, true); + core.rom->load_core_state(state.savestate, true); } rrdata::rrdata() diff --git a/src/lua/lua.cpp b/src/lua/lua.cpp index 123d8e28..00580282 100644 --- a/src/lua/lua.cpp +++ b/src/lua/lua.cpp @@ -418,8 +418,7 @@ uint64_t lua_state::timed_hook(int timer) throw() return 0; } -void lua_state::callback_do_unsafe_rewind(const std::vector& save, uint64_t secs, uint64_t ssecs, movie& mov, - void* u) +void lua_state::callback_do_unsafe_rewind(movie& mov, void* u) { auto& core = CORE(); if(u) { @@ -428,24 +427,26 @@ void lua_state::callback_do_unsafe_rewind(const std::vector& save, uint64_ try { run_callback(*on_pre_rewind); run_callback(*on_movie_lost, "unsaferewind"); - mainloop_restore_state(u2->state, u2->secs, u2->ssecs); - mov.fast_load(u2->frame, u2->ptr, u2->lag, u2->pollcounters); - try { core.mlogic->get_mfile().dyn.host_memory = u2->hostmemory; } catch(...) {} + mainloop_restore_state(u2->console_state); + mov.fast_load(u2->console_state.save_frame, u2->ptr, u2->console_state.lagged_frames, + u2->console_state.pollcounters); + core.mlogic->get_mfile().dyn = u2->console_state; run_callback(*on_post_rewind); delete reinterpret_cast*>(u); + } catch(std::bad_alloc& e) { + OOM_panic(); } catch(...) { return; } } else { //Save - run_callback(*on_set_rewind, lua::state::fn_tag([&core, save, secs, ssecs, &mov](lua::state& L) -> + run_callback(*on_set_rewind, lua::state::fn_tag([&core, &mov](lua::state& L) -> int { lua_unsaferewind* u2 = lua::_class::create(*core.lua); - u2->state = save; - u2->secs = secs, - u2->ssecs = ssecs; - u2->hostmemory = core.mlogic->get_mfile().dyn.host_memory; - mov.fast_save(u2->frame, u2->ptr, u2->lag, u2->pollcounters); + u2->console_state = core.mlogic->get_mfile().dyn; + u2->console_state.is_savestate = true; + mov.fast_save(u2->console_state.save_frame, u2->ptr, u2->console_state.lagged_frames, + u2->console_state.pollcounters); return 1; })); } diff --git a/src/lua/movie.cpp b/src/lua/movie.cpp index c40277ff..ea78a7cd 100644 --- a/src/lua/movie.cpp +++ b/src/lua/movie.cpp @@ -112,20 +112,15 @@ namespace if(!mfile.dyn.is_savestate) throw std::runtime_error("movie.to_rewind only allows savestates"); lua_unsaferewind* u2 = lua::_class::create(L); - u2->state = mfile.dyn.savestate; - if(u2->state.size() >= 32) - u2->state.resize(u2->state.size() - 32); - u2->secs = mfile.dyn.rtc_second; - u2->ssecs = mfile.dyn.rtc_subsecond; - u2->pollcounters = mfile.dyn.pollcounters; - u2->lag = mfile.dyn.lagged_frames; - u2->frame = mfile.dyn.save_frame; - u2->hostmemory = mfile.dyn.host_memory; + u2->console_state = mfile.dyn; + //Cut off the hash. + if(u2->console_state.savestate.size() >= 32) + u2->console_state.savestate.resize(u2->console_state.savestate.size() - 32); //Now the remaining field ptr is somewhat nastier. uint64_t f = 0; uint64_t s = mfile.input->size(); u2->ptr = 0; - while(++f < u2->frame) { + while(++f < u2->console_state.save_frame) { if(u2->ptr < s) u2->ptr++; while(u2->ptr < s && !(*mfile.input)[u2->ptr].sync())