Refactor unsafe rewinding a bit now that state is its own subobject

This commit is contained in:
Ilari Liusvaara 2015-04-25 13:04:05 +03:00
parent 653f44e353
commit 39286f820a
7 changed files with 29 additions and 43 deletions

View file

@ -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<char>& 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);

View file

@ -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<char>& 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<std::string>& args);

View file

@ -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<char> 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<uint32_t> pollcounters;
std::vector<char> hostmemory;
std::string print()
{
return (stringfmt() << "to frame " << frame).str();
return (stringfmt() << "to frame " << console_state.save_frame).str();
}
};

View file

@ -712,8 +712,7 @@ jumpback:
if(!*core.mlogic)
return 0;
uint64_t t = framerate_regulator::get_utime();
std::vector<char> 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<char> 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;

View file

@ -885,16 +885,14 @@ bool do_load_state(const std::string& filename, int lmode)
return true;
}
void mainloop_restore_state(const std::vector<char>& 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()

View file

@ -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<char>& 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<char>& 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<lua::objpin<lua_unsaferewind>*>(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<lua_unsaferewind>::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;
}));
}

View file

@ -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<lua_unsaferewind>::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())