diff options
author | Olivier Galibert <galibert@pobox.com> | 2017-06-01 18:41:21 +0200 |
---|---|---|
committer | Olivier Galibert <galibert@pobox.com> | 2017-06-01 18:41:21 +0200 |
commit | cb29a590d07d9d2c64964d475ced50e81e4e7bd3 (patch) | |
tree | bba92b6eb98726e26ab6acf715c14db4cf00608b | |
parent | 472be8055fc05670b5e37726130792b0472ec230 (diff) |
Revert "state: Turns the current state save feature to a menu [Nathan Woods]"
This breaks saving a state from a joystick button, e.g. the
joy%i-%i.sta states, which are rather useful when you don't have a
keyboard handy.
-rw-r--r-- | scripts/src/mame/frontend.lua | 2 | ||||
-rw-r--r-- | src/frontend/mame/ui/state.cpp | 330 | ||||
-rw-r--r-- | src/frontend/mame/ui/state.h | 90 | ||||
-rw-r--r-- | src/frontend/mame/ui/ui.cpp | 121 | ||||
-rw-r--r-- | src/frontend/mame/ui/ui.h | 1 |
5 files changed, 116 insertions, 428 deletions
diff --git a/scripts/src/mame/frontend.lua b/scripts/src/mame/frontend.lua index ac2746d1429..9e0144916a4 100644 --- a/scripts/src/mame/frontend.lua +++ b/scripts/src/mame/frontend.lua @@ -159,8 +159,6 @@ files { MAME_DIR .. "src/frontend/mame/ui/sndmenu.cpp", MAME_DIR .. "src/frontend/mame/ui/sndmenu.h", MAME_DIR .. "src/frontend/mame/ui/starimg.ipp", - MAME_DIR .. "src/frontend/mame/ui/state.cpp", - MAME_DIR .. "src/frontend/mame/ui/state.h", MAME_DIR .. "src/frontend/mame/ui/toolbar.ipp", MAME_DIR .. "src/frontend/mame/ui/utils.cpp", MAME_DIR .. "src/frontend/mame/ui/utils.h", diff --git a/src/frontend/mame/ui/state.cpp b/src/frontend/mame/ui/state.cpp deleted file mode 100644 index dd0720ec601..00000000000 --- a/src/frontend/mame/ui/state.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -/*************************************************************************** - - ui/state.cpp - - Menus for saving and loading state - -***************************************************************************/ - -#include "emu.h" -#include "machine.h" -#include "emuopts.h" -#include "ui/state.h" - - -/*************************************************************************** - ANONYMOUS NAMESPACE -***************************************************************************/ - -namespace { - -//------------------------------------------------- -// is_valid_state_char - is the specified character -// a valid state filename character? -//------------------------------------------------- - -bool is_valid_state_char(char32_t ch) -{ - return uchar_is_printable(ch) && osd_is_valid_filename_char(ch); -} - - -//------------------------------------------------- -// get_entry_char -//------------------------------------------------- - -char32_t get_entry_char(const osd::directory::entry &entry) -{ - char32_t result = 0; - - // first, is this a file that ends with *.sta? - if (entry.type == osd::directory::entry::entry_type::FILE - && core_filename_ends_with(entry.name, ".sta")) - { - std::string basename = core_filename_extract_base(entry.name); - - - char32_t ch; - if (uchar_from_utf8(&ch, basename.c_str(), basename.length() == basename.length()) && is_valid_state_char(ch)) - result = ch; - } - return result; -} - - -}; - -namespace ui { - -/*************************************************************************** - FILE ENTRY -***************************************************************************/ - -char32_t menu_load_save_state_base::s_last_file_selected; - -//------------------------------------------------- -// file_entry ctor -//------------------------------------------------- - -menu_load_save_state_base::file_entry::file_entry(char32_t entry_char, const std::chrono::system_clock::time_point &last_modified) - : m_entry_char(entry_char) - , m_last_modified(last_modified) -{ -} - - -/*************************************************************************** - BASE CLASS FOR LOAD AND SAVE -***************************************************************************/ - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -menu_load_save_state_base::menu_load_save_state_base(mame_ui_manager &mui, render_container &container, const char *header, const char *footer, bool must_exist) - : menu(mui, container) - , m_header(header) - , m_footer(footer) - , m_must_exist(must_exist) - , m_was_paused(false) -{ -} - - -//------------------------------------------------- -// dtor -//------------------------------------------------- - -menu_load_save_state_base::~menu_load_save_state_base() -{ - // resume if appropriate (is the destructor really the right place - // to do this sort of activity?) - if (!m_was_paused) - machine().resume(); -} - - -//------------------------------------------------- -// populate -//------------------------------------------------- - -void menu_load_save_state_base::populate(float &customtop, float &custombottom) -{ - // open the state directory - std::string statedir = state_directory(); - osd::directory::ptr dir = osd::directory::open(statedir); - - // create a separate vector, so we can add sorted entries to the menu - std::vector<const file_entry *> m_entries_vec; - - // populate all file entries - m_file_entries.clear(); - if (dir) - { - const osd::directory::entry *entry; - while ((entry = dir->read()) != nullptr) - { - char32_t entry_char = get_entry_char(*entry); - if (entry_char) - { - if (core_filename_ends_with(entry->name, ".sta")) - { - file_entry fileent(entry_char, entry->last_modified); - auto iter = m_file_entries.emplace(std::make_pair(entry_char, std::move(fileent))).first; - m_entries_vec.push_back(&iter->second); - } - } - } - } - - // sort the vector; put recently modified state files at the top - std::sort( - m_entries_vec.begin(), - m_entries_vec.end(), - [this](const file_entry *a, const file_entry *b) - { - return a->last_modified() > b->last_modified(); - }); - - // add the entries - for (const file_entry *entry : m_entries_vec) - { - // get the time as a local time string - char time_string[128]; - auto last_modified_time_t = std::chrono::system_clock::to_time_t(entry->last_modified()); - std::strftime(time_string, sizeof(time_string), "%c", std::localtime(&last_modified_time_t)); - - // format the text - std::string text = util::string_format("%s: %s", - utf8_from_uchar(entry->entry_char()), - time_string); - - // append the menu item - void *itemref = itemref_from_file_entry(*entry); - item_append(std::move(text), std::string(), 0, itemref); - - // is this item selected? - if (entry->entry_char() == s_last_file_selected) - set_selection(itemref); - } - - // set up custom render proc - customtop = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; - custombottom = ui().get_line_height() + 3.0f * UI_BOX_TB_BORDER; - - // pause if appropriate - m_was_paused = machine().paused(); - if (!m_was_paused) - machine().pause(); -} - - -//------------------------------------------------- -// handle -//------------------------------------------------- - -void menu_load_save_state_base::handle() -{ - // process the menu - const event *event = process(0); - - // process the event - if ((event != nullptr) && (event->iptkey == IPT_UI_SELECT)) - { - // user selected one of the entries - const file_entry &entry = file_entry_from_itemref(event->itemref); - slot_selected(entry.entry_char()); - } - else if ((event != nullptr) && (event->iptkey == IPT_SPECIAL) - && is_valid_state_char(event->unichar) - && (!m_must_exist || is_present(event->unichar))) - { - // user pressed a shortcut key - slot_selected(event->unichar); - } -} - - -//------------------------------------------------- -// slot_selected -//------------------------------------------------- - -void menu_load_save_state_base::slot_selected(char32_t entry_char) -{ - // handle it - process_file(utf8_from_uchar(entry_char)); - - // record the last slot touched - s_last_file_selected = entry_char; - - // no matter what, pop out - menu::stack_pop(machine()); -} - - -//------------------------------------------------- -// custom_render - perform our special rendering -//------------------------------------------------- - -void menu_load_save_state_base::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) -{ - extra_text_render(top, bottom, origx1, origy1, origx2, origy2, - m_header, - m_footer); -} - - -//------------------------------------------------- -// itemref_from_file_entry -//------------------------------------------------- - -void *menu_load_save_state_base::itemref_from_file_entry(const menu_load_save_state_base::file_entry &entry) -{ - return (void *)&entry; -} - - -//------------------------------------------------- -// file_entry_from_itemref -//------------------------------------------------- - -const menu_load_save_state_base::file_entry &menu_load_save_state_base::file_entry_from_itemref(void *itemref) -{ - return *((const file_entry *)itemref); -} - - -//------------------------------------------------- -// is_present -//------------------------------------------------- - -std::string menu_load_save_state_base::state_directory() const -{ - return util::string_format("%s%s%s", - machine().options().state_directory(), - PATH_SEPARATOR, - machine().system().name); -} - - -//------------------------------------------------- -// is_present -//------------------------------------------------- - -bool menu_load_save_state_base::is_present(char32_t entry_char) const -{ - return m_file_entries.find(entry_char) != m_file_entries.end(); -} - - -/*************************************************************************** - LOAD STATE -***************************************************************************/ - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -menu_load_state::menu_load_state(mame_ui_manager &mui, render_container &container) - : menu_load_save_state_base(mui, container, _("Load State"), _("Select position to load from"), true) -{ -} - - -//------------------------------------------------- -// process_file -//------------------------------------------------- - -void menu_load_state::process_file(std::string &&file_name) -{ - machine().schedule_load(std::move(file_name)); -} - - -/*************************************************************************** - SAVE STATE -***************************************************************************/ - -//------------------------------------------------- -// ctor -//------------------------------------------------- - -menu_save_state::menu_save_state(mame_ui_manager &mui, render_container &container) - : menu_load_save_state_base(mui, container, _("Save State"), _("Select position to save to"), false) -{ -} - - -//------------------------------------------------- -// process_file -//------------------------------------------------- - -void menu_save_state::process_file(std::string &&file_name) -{ - machine().schedule_save(std::move(file_name)); -} - - -} // namespace ui diff --git a/src/frontend/mame/ui/state.h b/src/frontend/mame/ui/state.h deleted file mode 100644 index 171ec960b0d..00000000000 --- a/src/frontend/mame/ui/state.h +++ /dev/null @@ -1,90 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -/*************************************************************************** - - ui/state.h - - Menus for saving and loading state - -***************************************************************************/ - -#pragma once - -#ifndef MAME_FRONTEND_UI_STATE_H -#define MAME_FRONTEND_UI_STATE_H - -#include "ui/menu.h" - -namespace ui { - -// ======================> menu_load_save_state_base - -class menu_load_save_state_base : public menu -{ -public: - virtual ~menu_load_save_state_base() override; - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; - virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - -protected: - menu_load_save_state_base(mame_ui_manager &mui, render_container &container, const char *header, const char *footer, bool must_exist); - virtual void process_file(std::string &&file_name) = 0; - -private: - class file_entry - { - public: - file_entry() = delete; - file_entry(const file_entry &) = delete; - file_entry(file_entry &&) = default; - file_entry(char32_t entry_char, const std::chrono::system_clock::time_point &last_modified); - - char32_t entry_char() const { return m_entry_char; } - const std::chrono::system_clock::time_point &last_modified() const { return m_last_modified; } - - private: - char32_t m_entry_char; - std::chrono::system_clock::time_point m_last_modified; - }; - - static char32_t s_last_file_selected; - - std::unordered_map<char32_t, file_entry> m_file_entries; - const char * m_header; - const char * m_footer; - bool m_must_exist; - bool m_was_paused; - - static void *itemref_from_file_entry(const file_entry &entry); - static const file_entry &file_entry_from_itemref(void *itemref); - void slot_selected(char32_t entry_char); - std::string state_directory() const; - bool is_present(char32_t entry_char) const; -}; - -// ======================> menu_load_state - -class menu_load_state : public menu_load_save_state_base -{ -public: - menu_load_state(mame_ui_manager &mui, render_container &container); - -protected: - virtual void process_file(std::string &&file_name) override; -}; - -// ======================> menu_save_state - -class menu_save_state : public menu_load_save_state_base -{ -public: - menu_save_state(mame_ui_manager &mui, render_container &container); - -protected: - virtual void process_file(std::string &&file_name) override; -}; - -}; - -#endif // MAME_FRONTEND_UI_STATE_H diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 5c942c803ba..4b570491d0f 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -27,7 +27,6 @@ #include "ui/mainmenu.h" #include "ui/filemngr.h" #include "ui/sliders.h" -#include "ui/state.h" #include "ui/viewgfx.h" #include "imagedev/cassette.h" @@ -184,7 +183,8 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) , m_show_profiler(false) , m_popup_text_end(0) , m_mouse_arrow_texture(nullptr) - , m_mouse_show(false) {} + , m_mouse_show(false) + , m_load_save_hold(false) {} mame_ui_manager::~mame_ui_manager() { @@ -988,8 +988,10 @@ void mame_ui_manager::draw_profiler(render_container &container) void mame_ui_manager::start_save_state() { - show_menu(); - ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container()); + machine().pause(); + m_load_save_hold = true; + using namespace std::placeholders; + set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_load_save, this, _1, uint32_t(LOADSAVE_SAVE))); } @@ -999,8 +1001,10 @@ void mame_ui_manager::start_save_state() void mame_ui_manager::start_load_state() { - show_menu(); - ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container()); + machine().pause(); + m_load_save_hold = true; + using namespace std::placeholders; + set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_load_save, this, _1, uint32_t(LOADSAVE_LOAD))); } @@ -1266,6 +1270,111 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) //------------------------------------------------- +// handler_load_save - leads the user through +// specifying a game to save or load +//------------------------------------------------- + +uint32_t mame_ui_manager::handler_load_save(render_container &container, uint32_t state) +{ + std::string filename; + char file = 0; + + // if we're not in the middle of anything, skip + if (state == LOADSAVE_NONE) + return 0; + + // okay, we're waiting for a key to select a slot; display a message + if (state == LOADSAVE_SAVE) + draw_message_window(container, _("Select position to save to")); + else + draw_message_window(container, _("Select position to load from")); + + // if load/save state sequence is still being pressed, do not read the filename yet + if (m_load_save_hold) { + bool seq_in_progress = false; + const input_seq &load_save_seq = state == LOADSAVE_SAVE ? + machine().ioport().type_seq(IPT_UI_SAVE_STATE) : + machine().ioport().type_seq(IPT_UI_LOAD_STATE); + + for (int i = 0; i < load_save_seq.length(); i++) + if (machine().input().code_pressed_once(load_save_seq[i])) + seq_in_progress = true; + + if (seq_in_progress) + return state; + else + m_load_save_hold = false; + } + + // check for cancel key + if (machine().ui_input().pressed(IPT_UI_CANCEL)) + { + // display a popup indicating things were cancelled + if (state == LOADSAVE_SAVE) + machine().popmessage(_("Save cancelled")); + else + machine().popmessage(_("Load cancelled")); + + // reset the state + machine().resume(); + return UI_HANDLER_CANCEL; + } + + // check for A-Z or 0-9 + for (input_item_id id = ITEM_ID_A; id <= ITEM_ID_Z; ++id) + if (machine().input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) + file = id - ITEM_ID_A + 'a'; + if (file == 0) + for (input_item_id id = ITEM_ID_0; id <= ITEM_ID_9; ++id) + if (machine().input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) + file = id - ITEM_ID_0 + '0'; + if (file == 0) + for (input_item_id id = ITEM_ID_0_PAD; id <= ITEM_ID_9_PAD; ++id) + if (machine().input().code_pressed_once(input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) + file = id - ITEM_ID_0_PAD + '0'; + if (file == 0) + { + bool found = false; + + for (int joy_index = 0; joy_index <= MAX_SAVED_STATE_JOYSTICK; joy_index++) + for (input_item_id id = ITEM_ID_BUTTON1; id <= ITEM_ID_BUTTON32; ++id) + if (machine().input().code_pressed_once(input_code(DEVICE_CLASS_JOYSTICK, joy_index, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, id))) + { + filename = util::string_format("joy%i-%i", joy_index, id - ITEM_ID_BUTTON1 + 1); + found = true; + break; + } + + if (!found) + return state; + } + else + { + filename = util::string_format("%c", file); + } + + // display a popup indicating that the save will proceed + if (state == LOADSAVE_SAVE) + { + machine().popmessage(_("Save to position %s"), filename); + machine().schedule_save(std::move(filename)); + } + else + { + machine().popmessage(_("Load from position %s"), filename); + machine().schedule_load(std::move(filename)); + } + + // avoid handling the name of the save state slot as a seperate input + machine().ui_input().mark_all_as_pressed(); + + // remove the pause and reset the state + machine().resume(); + return UI_HANDLER_CANCEL; +} + + +//------------------------------------------------- // request_quit //------------------------------------------------- diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index ce83bb692cc..8364fa69ec2 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -245,6 +245,7 @@ private: std::unique_ptr<uint8_t[]> m_non_char_keys_down; render_texture * m_mouse_arrow_texture; bool m_mouse_show; + bool m_load_save_hold; ui_options m_ui_options; std::unique_ptr<ui::machine_info> m_machine_info; |