Refactor save jukebox handling into its own class

This commit is contained in:
Ilari Liusvaara 2014-06-08 15:13:01 +03:00
parent ae17d41df4
commit 4afda2550e
8 changed files with 219 additions and 77 deletions

View file

@ -27,6 +27,7 @@ class slotinfo_cache;
class lua_state;
class audioapi_instance;
class loaded_rom;
class save_jukebox;
namespace command { class group; }
namespace lua { class state; }
namespace settingvar { class group; }
@ -121,6 +122,7 @@ struct emulator_instance
slotinfo_cache* slotcache;
audioapi_instance* audio;
loaded_rom* rom;
save_jukebox* jukebox;
threads::id emu_thread;
time_t random_seed_value;
dtor_list D;

83
include/core/jukebox.hpp Normal file
View file

@ -0,0 +1,83 @@
#ifndef _jukebox__hpp__included__
#define _jukebox__hpp__included__
#include <functional>
#include <cstdlib>
#include <string>
namespace settingvar { class group; }
class save_jukebox_listener;
/**
* Save jukebox.
*/
class save_jukebox
{
public:
/**
* Ctor.
*/
save_jukebox(settingvar::group& _settings);
/**
* Dtor.
*/
~save_jukebox();
/**
* Get current slot.
*
* Throws std::runtime_exception: No slot selected.
*/
size_t get_slot();
/**
* Set current slot.
*
* Parameter slot: The slot to select.
* Throws std::runtime_exception: Slot out of range.
*/
void set_slot(size_t slot);
/**
* Cycle next slot.
*
* Throws std::runtime_exception: No slot selected.
*/
void cycle_next();
/**
* Cycle previous slot.
*
* Throws std::runtime_exception: No slot selected.
*/
void cycle_prev();
/**
* Get save as binary flag.
*/
bool save_binary();
/**
* Get name of current jukebox slot.
*
* Throws std::runtime_exception: No slot selected.
*/
std::string get_slot_name();
/**
* Set size of jukebox.
*
* Parameter size: The new size.
*/
void set_size(size_t size);
/**
* Set update function.
*/
void set_update(std::function<void()> _update);
/**
* Unset update function.
*/
void unset_update();
private:
settingvar::group& settings;
size_t current_slot;
size_t current_size;
std::function<void()> update;
save_jukebox_listener* listener;
};
#endif

View file

@ -33,7 +33,6 @@ void reload_current_rom();
void do_break_pause();
void convert_break_to_pause();
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary;

View file

@ -10,6 +10,7 @@
#include "core/framerate.hpp"
#include "core/instance.hpp"
#include "core/inthread.hpp"
#include "core/jukebox.hpp"
#include "core/keymapper.hpp"
#include "core/mbranch.hpp"
#include "core/memorymanip.hpp"
@ -81,6 +82,7 @@ emulator_instance::emulator_instance()
D.init(lua2, *lua, *command);
D.init(mwatch, *memory, *project, *fbuf);
D.init(settings);
D.init(jukebox, *settings);
D.init(setcache, *settings);
D.init(audio);
D.init(commentary, *settings, *dispatch, *audio);

106
src/core/jukebox.cpp Normal file
View file

@ -0,0 +1,106 @@
#include "core/jukebox.hpp"
#include "core/settings.hpp"
#include "library/settingvar.hpp"
#include <stdexcept>
namespace
{
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> SET_jukebox_dflt_binary(lsnes_setgrp,
"jukebox-default-binary", "Movie‣Saving‣Saveslots binary", true);
settingvar::supervariable<settingvar::model_int<0,999999999>> SET_jukebox_size(lsnes_setgrp, "jukebox-size",
"Movie‣Number of save slots", 12);
}
struct save_jukebox_listener : public settingvar::listener
{
save_jukebox_listener(settingvar::group& _grp, save_jukebox& _jukebox)
: grp(_grp), jukebox(_jukebox)
{
grp.add_listener(*this);
}
~save_jukebox_listener() throw() { grp.remove_listener(*this); };
void on_setting_change(settingvar::group& _grp, const settingvar::base& val)
{
if(val.get_iname() == "jukebox-size")
jukebox.set_size((size_t)SET_jukebox_size(_grp));
}
private:
settingvar::group& grp;
save_jukebox& jukebox;
};
save_jukebox::save_jukebox(settingvar::group& _settings)
: settings(_settings)
{
listener = new save_jukebox_listener(_settings, *this);
}
save_jukebox::~save_jukebox()
{
delete listener;
}
size_t save_jukebox::get_slot()
{
if(!current_size)
throw std::runtime_error("No save slots available");
return current_slot;
}
void save_jukebox::set_slot(size_t slot)
{
if(current_size >= slot)
throw std::runtime_error("Selected slot out of range");
current_slot = slot;
if(update) update();
}
void save_jukebox::cycle_next()
{
if(!current_size)
throw std::runtime_error("No save slots available");
current_slot++;
if(current_slot >= current_size)
current_slot = 0;
if(update) update();
}
void save_jukebox::cycle_prev()
{
if(!current_size)
throw std::runtime_error("No save slots available");
if(current_slot)
current_slot--;
else
current_slot = current_size - 1;
if(update) update();
}
bool save_jukebox::save_binary()
{
return SET_jukebox_dflt_binary(settings);
}
std::string save_jukebox::get_slot_name()
{
return (stringfmt() << "$SLOT:" << (get_slot() + 1)).str();
}
void save_jukebox::set_size(size_t size)
{
current_size = size;
if(current_slot >= current_size)
current_slot = 0;
if(update) update();
}
void save_jukebox::set_update(std::function<void()> _update)
{
update = _update;
}
void save_jukebox::unset_update()
{
update = std::function<void()>();
}

View file

@ -10,6 +10,7 @@
#include "core/framerate.hpp"
#include "core/instance.hpp"
#include "core/inthread.hpp"
#include "core/jukebox.hpp"
#include "core/keymapper.hpp"
#include "core/mainloop.hpp"
#include "core/memorymanip.hpp"
@ -50,8 +51,6 @@
void update_movie_state();
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> jukebox_dflt_binary(lsnes_setgrp,
"jukebox-default-binary", "Movie‣Saving‣Saveslots binary", true);
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary(lsnes_setgrp,
"movie-default-binary", "Movie‣Saving‣Movies binary", false);
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary(lsnes_setgrp,
@ -65,8 +64,6 @@ namespace
"advance-subframe-timeout", "Delays‣Subframe advance", 100);
settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> SET_pause_on_end(lsnes_setgrp,
"pause-on-end", "Movie‣Pause on end", false);
settingvar::supervariable<settingvar::model_int<0,999999999>> SET_jukebox_size(lsnes_setgrp, "jukebox-size",
"Movie‣Number of save slots", 12);
enum advance_mode
{
@ -95,8 +92,6 @@ namespace
std::string pending_new_project;
//Queued saves (all savestates).
std::set<std::pair<std::string, int>> queued_saves;
//Save jukebox.
size_t save_jukebox_pointer;
//Special subframe location. One of SPECIAL_* constants.
int location_special;
//Unsafe rewind.
@ -126,11 +121,6 @@ namespace
}
return false;
}
std::string save_jukebox_name(size_t i)
{
return (stringfmt() << "$SLOT:" << (i + 1)).str();
}
}
void mainloop_signal_need_rewind(void* ptr)
@ -263,22 +253,6 @@ namespace
queued_saves.insert(std::make_pair(filename, binary));
messages << "Pending save on '" << filename << "'" << std::endl;
}
struct jukebox_size_listener : public settingvar::listener
{
jukebox_size_listener(settingvar::group& _grp) : grp(_grp) { grp.add_listener(*this); }
~jukebox_size_listener() throw() { grp.remove_listener(*this); };
void on_setting_change(settingvar::group& _grp, const settingvar::base& val)
{
if(val.get_iname() == "jukebox-size") {
if(save_jukebox_pointer >= (size_t)SET_jukebox_size(_grp))
save_jukebox_pointer = 0;
}
update_movie_state();
}
private:
settingvar::group& grp;
};
}
void update_movie_state()
@ -336,13 +310,13 @@ void update_movie_state()
else
_status.mode = 'F';
}
if(SET_jukebox_size(*core.settings) > 0) {
try {
_status.saveslot_valid = true;
int tmp = -1;
std::string sfilen = translate_name_mprefix(save_jukebox_name(save_jukebox_pointer), tmp, -1);
_status.saveslot = save_jukebox_pointer + 1;
std::string sfilen = translate_name_mprefix(core.jukebox->get_slot_name(), tmp, -1);
_status.saveslot = core.jukebox->get_slot() + 1;
_status.slotinfo = utf8::to32(core.slotcache->get(sfilen));
} else {
} catch(...) {
_status.saveslot_valid = false;
}
_status.branch_valid = (p != NULL);
@ -590,31 +564,15 @@ namespace
command::fnptr<> CMD_save_jukebox_prev(lsnes_cmds, "cycle-jukebox-backward", "Cycle save jukebox backwards",
"Syntax: cycle-jukebox-backward\nCycle save jukebox backwards\n",
[]() throw(std::bad_alloc, std::runtime_error) {
size_t jbsize = SET_jukebox_size(*CORE().settings);
if(jbsize == 0)
return;
if(save_jukebox_pointer == 0)
save_jukebox_pointer = jbsize - 1;
else
save_jukebox_pointer--;
if(save_jukebox_pointer >= (size_t)jbsize)
save_jukebox_pointer = 0;
update_movie_state();
auto& core = CORE();
core.jukebox->cycle_prev();
});
command::fnptr<> CMD_save_jukebox_next(lsnes_cmds, "cycle-jukebox-forward", "Cycle save jukebox forwards",
"Syntax: cycle-jukebox-forward\nCycle save jukebox forwards\n",
[]() throw(std::bad_alloc, std::runtime_error) {
size_t jbsize = SET_jukebox_size(*CORE().settings);
if(jbsize == 0)
return;
if(save_jukebox_pointer + 1 >= (size_t)jbsize)
save_jukebox_pointer = 0;
else
save_jukebox_pointer++;
if(save_jukebox_pointer >= (size_t)jbsize)
save_jukebox_pointer = 0;
update_movie_state();
auto& core = CORE();
core.jukebox->cycle_next();
});
command::fnptr<const std::string&> CMD_save_jukebox_set(lsnes_cmds, "set-jukebox-slot", "Set jukebox slot",
@ -623,58 +581,50 @@ namespace
if(!regex_match("[1-9][0-9]{0,8}", args))
throw std::runtime_error("Bad slot number");
uint32_t slot = parse_value<uint32_t>(args);
if(slot >= (size_t)SET_jukebox_size(*CORE().settings))
throw std::runtime_error("Bad slot number");
save_jukebox_pointer = slot - 1;
update_movie_state();
auto& core = CORE();
core.jukebox->set_slot(slot);
});
command::fnptr<> CMD_load_jukebox(lsnes_cmds, "load-jukebox", "Load save from jukebox",
"Syntax: load-jukebox\nLoad save from jukebox\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_CURRENT);
auto& core = CORE();
mark_pending_load(core.jukebox->get_slot_name(), LOAD_STATE_CURRENT);
});
command::fnptr<> CMD_load_jukebox_readwrite(lsnes_cmds, "load-jukebox-readwrite", "Load save from jukebox in"
" recording mode", "Syntax: load-jukebox-readwrite\nLoad save from jukebox in recording mode\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_RW);
auto& core = CORE();
mark_pending_load(core.jukebox->get_slot_name(), LOAD_STATE_RW);
});
command::fnptr<> CMD_load_jukebox_readonly(lsnes_cmds, "load-jukebox-readonly", "Load save from jukebox in "
"playback mode", "Syntax: load-jukebox-readonly\nLoad save from jukebox in playback mode\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_RO);
auto& core = CORE();
mark_pending_load(core.jukebox->get_slot_name(), LOAD_STATE_RO);
});
command::fnptr<> CMD_load_jukebox_preserve(lsnes_cmds, "load-jukebox-preserve", "Load save from jukebox, "
"preserving input", "Syntax: load-jukebox-preserve\nLoad save from jukebox, preserving input\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_PRESERVE);
auto& core = CORE();
mark_pending_load(core.jukebox->get_slot_name(), LOAD_STATE_PRESERVE);
});
command::fnptr<> CMD_load_jukebox_movie(lsnes_cmds, "load-jukebox-movie", "Load save from jukebox as movie",
"Syntax: load-jukebox-movie\nLoad save from jukebox as movie\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_load(save_jukebox_name(save_jukebox_pointer), LOAD_STATE_MOVIE);
auto& core = CORE();
mark_pending_load(core.jukebox->get_slot_name(), LOAD_STATE_MOVIE);
});
command::fnptr<> CMD_save_jukebox_c(lsnes_cmds, "save-jukebox", "Save save to jukebox",
"Syntax: save-jukebox\nSave save to jukebox\n",
[]() throw(std::bad_alloc, std::runtime_error) {
if(SET_jukebox_size(*CORE().settings) == 0)
throw std::runtime_error("No slot selected");
mark_pending_save(save_jukebox_name(save_jukebox_pointer), SAVE_STATE, -1);
auto& core = CORE();
mark_pending_save(core.jukebox->get_slot_name(), SAVE_STATE, -1);
});
command::fnptr<> CMD_padvance_frame(lsnes_cmds, "+advance-frame", "Advance one frame",
@ -1219,7 +1169,6 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_
mywindowcallbacks mywcb(*core.dispatch);
core.iqueue->system_thread_available = true;
//Basic initialization.
jukebox_size_listener jlistener(*core.settings);
core.commentary->init();
core.fbuf->init_special_screens();
*core.rom = rom;

View file

@ -6,6 +6,7 @@
#include "core/framebuffer.hpp"
#include "core/framerate.hpp"
#include "core/instance.hpp"
#include "core/jukebox.hpp"
#include "core/mainloop.hpp"
#include "core/messages.hpp"
#include "core/moviedata.hpp"
@ -152,7 +153,7 @@ std::string translate_name_mprefix(std::string original, int& binary, int save)
regex_results r = regex("\\$SLOT:(.*)", original);
if(r) {
if(binary < 0)
binary = jukebox_dflt_binary(*core.settings) ? 1 : 0;
binary = core.jukebox->save_binary() ? 1 : 0;
if(p) {
uint64_t branch = p->get_current_branch();
std::string branch_str;

View file

@ -321,7 +321,7 @@ not_alias:
} catch(std::bad_alloc& e) {
oom_panic_routine();
} catch(std::exception& e) {
(*output) << "Error: " << e.what() << std::endl;
(*output) << "Error[" << cmd2 << "]: " << e.what() << std::endl;
command_stack.erase(cmd2);
return;
}