From 4afda2550e99f64c3ddcd723fc2c9ccafd9f5f41 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Sun, 8 Jun 2014 15:13:01 +0300 Subject: [PATCH] Refactor save jukebox handling into its own class --- include/core/instance.hpp | 2 + include/core/jukebox.hpp | 83 ++++++++++++++++++++++++++++++++++++ include/core/mainloop.hpp | 1 - src/core/instance.cpp | 2 + src/core/jukebox.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/mainloop.cpp | 97 ++++++++++-------------------------------- src/core/moviedata.cpp | 3 +- src/library/command.cpp | 2 +- 8 files changed, 219 insertions(+), 77 deletions(-) create mode 100644 include/core/jukebox.hpp create mode 100644 src/core/jukebox.cpp diff --git a/include/core/instance.hpp b/include/core/instance.hpp index 24c409e4..d854821f 100644 --- a/include/core/instance.hpp +++ b/include/core/instance.hpp @@ -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; diff --git a/include/core/jukebox.hpp b/include/core/jukebox.hpp new file mode 100644 index 00000000..191e09f1 --- /dev/null +++ b/include/core/jukebox.hpp @@ -0,0 +1,83 @@ +#ifndef _jukebox__hpp__included__ +#define _jukebox__hpp__included__ + +#include +#include +#include + +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 _update); +/** + * Unset update function. + */ + void unset_update(); +private: + settingvar::group& settings; + size_t current_slot; + size_t current_size; + std::function update; + save_jukebox_listener* listener; +}; + +#endif diff --git a/include/core/mainloop.hpp b/include/core/mainloop.hpp index 3234976e..0d0712a5 100644 --- a/include/core/mainloop.hpp +++ b/include/core/mainloop.hpp @@ -33,7 +33,6 @@ void reload_current_rom(); void do_break_pause(); void convert_break_to_pause(); -extern settingvar::supervariable> jukebox_dflt_binary; extern settingvar::supervariable> movie_dflt_binary; extern settingvar::supervariable> save_dflt_binary; diff --git a/src/core/instance.cpp b/src/core/instance.cpp index 7d518436..cba6b92f 100644 --- a/src/core/instance.cpp +++ b/src/core/instance.cpp @@ -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); diff --git a/src/core/jukebox.cpp b/src/core/jukebox.cpp new file mode 100644 index 00000000..2ace9bb5 --- /dev/null +++ b/src/core/jukebox.cpp @@ -0,0 +1,106 @@ +#include "core/jukebox.hpp" +#include "core/settings.hpp" +#include "library/settingvar.hpp" + +#include + +namespace +{ + settingvar::supervariable> SET_jukebox_dflt_binary(lsnes_setgrp, + "jukebox-default-binary", "Movie‣Saving‣Saveslots binary", true); + settingvar::supervariable> 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 _update) +{ + update = _update; +} + +void save_jukebox::unset_update() +{ + update = std::function(); +} diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index d35c1828..f7f50702 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -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> jukebox_dflt_binary(lsnes_setgrp, - "jukebox-default-binary", "Movie‣Saving‣Saveslots binary", true); settingvar::supervariable> movie_dflt_binary(lsnes_setgrp, "movie-default-binary", "Movie‣Saving‣Movies binary", false); settingvar::supervariable> save_dflt_binary(lsnes_setgrp, @@ -65,8 +64,6 @@ namespace "advance-subframe-timeout", "Delays‣Subframe advance", 100); settingvar::supervariable> SET_pause_on_end(lsnes_setgrp, "pause-on-end", "Movie‣Pause on end", false); - settingvar::supervariable> 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> 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 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(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; diff --git a/src/core/moviedata.cpp b/src/core/moviedata.cpp index f2eeef68..113df474 100644 --- a/src/core/moviedata.cpp +++ b/src/core/moviedata.cpp @@ -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; diff --git a/src/library/command.cpp b/src/library/command.cpp index 2bc3367b..66666ade 100644 --- a/src/library/command.cpp +++ b/src/library/command.cpp @@ -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; } -- 2.11.4.GIT