Reload mode for movies

This commit is contained in:
Ilari Liusvaara 2013-03-20 01:24:11 +02:00
parent c1c9c1d2b2
commit 3a80e18300
5 changed files with 101 additions and 3 deletions

View file

@ -268,6 +268,18 @@ public:
* Adjust frame count.
*/
void adjust_frame_count(int64_t adjust) { frames_in_movie += adjust; }
/**
* Set reload mode flag (only effective in readonly mode).
*/
void set_reload_mode(bool newstate) throw() { reload_mode = newstate; }
/**
* Get reload mode flag.
*/
bool get_reload_mode() const throw() { return reload_mode; }
/**
* Read the current subframe.
*/
controller_frame current_subframe() throw(std::bad_alloc);
private:
//TRUE if readonly mode is active.
bool readonly;
@ -296,6 +308,8 @@ private:
uint32_t count_changes(uint64_t first_subframe) throw();
//Sequence number.
uint64_t seqno;
//Reload mode flag.
bool reload_mode;
};
/**

View file

@ -173,7 +173,14 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
controls.reset(pending_reset_cycles);
else if(!subframe)
controls.reset(-1);
controller_frame tmp = controls.commit(movb.get_movie().get_current_frame());
auto& mov = movb.get_movie();
controller_frame tmp = controls.commit(mov.get_current_frame());
if(mov.get_reload_mode() && mov.readonly_mode()) {
//In reload mode, read the present frame and XOR it.
controller_frame pframe;
pframe = mov.current_subframe();
tmp = tmp ^ pframe;
}
lua_callback_do_input(tmp, subframe);
return tmp;
}
@ -270,6 +277,8 @@ void update_movie_state()
x << "C";
else if(!mo.readonly_mode())
x << "R";
else if(mo.get_reload_mode())
x << "L";
else if(mo.get_frame_count() >= mo.get_current_frame())
x << "P";
else
@ -636,6 +645,20 @@ namespace
information_dispatch::do_status_update();
});
function_ptr_command<> toggle_rlmode("toggle-rlmode", "Toggle reload mode",
"Syntax: toggle-rlmode\nToggles reload mode\n",
[]() throw(std::bad_alloc, std::runtime_error) {
bool c = movb.get_movie().get_reload_mode();
if(!c && !movb.get_movie().readonly_mode()) {
//If in read-write mode, set readonly mode.
movb.get_movie().readonly_mode(true);
information_dispatch::do_mode_change(true);
}
movb.get_movie().set_reload_mode(!c);
update_movie_state();
information_dispatch::do_status_update();
});
function_ptr_command<> repaint("repaint", "Redraw the screen",
"Syntax: repaint\nRedraws the screen\n",
[]() throw(std::bad_alloc, std::runtime_error) {
@ -700,6 +723,7 @@ namespace
inverse_key iset_rwmode("set-rwmode", "Movie‣Switch to read/write");
inverse_key itoggle_romode("set-romode", "Movie‣Switch to read-only");
inverse_key itoggle_rwmode("toggle-rwmode", "Movie‣Toggle read-only");
inverse_key itoggle_rlmode("toggle-rlmode", "Movie‣Toggle reload mode");
inverse_key irepaint("repaint", "System‣Repaint screen");
inverse_key itogglepause("toggle-pause-on-end", "Movie‣Toggle pause-on-end");
inverse_key irewind_movie("rewind-movie", "Movie‣Rewind movie");

View file

@ -220,11 +220,32 @@ bool movie::get_DRDY(unsigned pid, unsigned ctrl) throw(std::logic_error)
return pollcounters.get_DRDY(pid, ctrl);
}
controller_frame movie::current_subframe() throw(std::bad_alloc)
{
//Reload mode works like readwrite once movie end is reached.
if(readonly && (!reload_mode || current_frame_first_subframe < movie_data.size())) {
//In readonly mode...
//If at the end of the movie, return released / neutral...
//Before the beginning? Somebody screwed up (but return released / neutral anyway)...
if(current_frame_first_subframe >= movie_data.size() || current_frame == 0)
return movie_data.blank_frame(false);
//Otherwise find the last valid frame of input.
uint32_t changes = count_changes(current_frame_first_subframe);
uint32_t polls = pollcounters.max_polls();
uint32_t index = (changes >= polls) ? polls : changes - 1;
return movie_data[current_frame_first_subframe + index].copy(index == 0);
} else {
//Readwrite mode. The frame is always empty.
return movie_data.blank_frame(false);
}
}
short movie::next_input(unsigned pid, unsigned ctrl) throw(std::bad_alloc, std::logic_error)
{
pollcounters.clear_DRDY(pid, ctrl);
if(readonly) {
//Reload mode works like readwrite once movie end is reached.
if(readonly && (!reload_mode || current_frame_first_subframe < movie_data.size())) {
//In readonly mode...
//If at the end of the movie, return released / neutral (but also record the poll)...
if(current_frame_first_subframe >= movie_data.size()) {
@ -237,8 +258,11 @@ short movie::next_input(unsigned pid, unsigned ctrl) throw(std::bad_alloc, std::
//Otherwise find the last valid frame of input.
uint32_t changes = count_changes(current_frame_first_subframe);
uint32_t polls = pollcounters.increment_polls(pid, ctrl);
uint32_t index = (changes > polls) ? polls : changes - 1;
uint32_t index = (changes >= polls) ? polls : changes - 1;
//debuglog << "Frame=" << current_frame << " Subframe=" << polls << " control=" << controlindex << " value=" << movie_data[current_frame_first_subframe + index](controlindex) << " fetchrow=" << current_frame_first_subframe + index << std::endl << std::flush;
//Reload mode reloads the frames.
if(reload_mode && changes < polls)
movie_data[current_frame_first_subframe + index] = current_controls.copy(index == 0);
return movie_data[current_frame_first_subframe + index].axis(pid, ctrl);
} else {
//Readwrite mode.
@ -283,6 +307,7 @@ movie::movie() throw(std::bad_alloc)
{
seqno = 0;
readonly = false;
reload_mode = false;
rerecords = "0";
_project_id = "";
current_frame = 0;
@ -548,6 +573,7 @@ movie& movie::operator=(const movie& m)
{
seqno++;
readonly = m.readonly;
reload_mode = m.reload_mode;
rerecords = m.rerecords;
_project_id = m._project_id;
movie_data = m.movie_data;

View file

@ -338,6 +338,7 @@ void do_load_beginning(bool reload) throw(std::bad_alloc, std::runtime_error)
void do_load_state(struct moviefile& _movie, int lmode)
{
bool current_mode = movb.get_movie().readonly_mode();
bool in_reload = movb.get_movie().get_reload_mode();
if(_movie.force_corrupt)
throw std::runtime_error("Movie file invalid");
bool will_load_state = _movie.is_savestate && lmode != LOAD_STATE_MOVIE;
@ -457,6 +458,9 @@ void do_load_state(struct moviefile& _movie, int lmode)
if(lmode == LOAD_STATE_CURRENT && !current_mode)
movb.get_movie().readonly_mode(false);
information_dispatch::do_mode_change(movb.get_movie().readonly_mode());
//Anything except load_state_preserve disenages reload mode.
if(lmode != LOAD_STATE_PRESERVE)
movb.get_movie().set_reload_mode(false);
if(our_rom->rtype)
messages << "ROM Type " << our_rom->rtype->get_hname() << " region " << our_rom->region->get_hname()
<< std::endl;

View file

@ -35,9 +35,39 @@ namespace
function_ptr_luafun mrw("movie.readwrite", [](lua_State* LS, const std::string& fname) -> int {
auto& m = get_movie();
m.readonly_mode(false);
m.set_reload_mode(false);
return 0;
});
function_ptr_luafun mgm("movie.getmode", [](lua_State* LS, const std::string& fname) -> int {
auto& m = get_movie();
if(m.readonly_mode())
if(m.get_reload_mode())
lua_pushstring(LS, "reload");
else
lua_pushstring(LS, "readonly");
else
lua_pushstring(LS, "readwrite");
return 1;
});
function_ptr_luafun msm("movie.setmode", [](lua_State* LS, const std::string& fname) -> int {
auto& m = get_movie();
std::string mod = get_string_argument(LS, 1, fname.c_str());
if(mod == "reload") {
m.readonly_mode(true);
m.set_reload_mode(true);
} else if(mod == "readonly") {
m.readonly_mode(true);
m.set_reload_mode(false);
} else if(mod == "readwrite") {
m.readonly_mode(false);
m.set_reload_mode(false);
}
return 0;
});
function_ptr_luafun mfs("movie.frame_subframes", [](lua_State* LS, const std::string& fname) -> int {
uint64_t frame = get_numeric_argument<uint64_t>(LS, 1, "movie.frame_subframes");
auto& m = get_movie();