summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commitcb29a590d07d9d2c64964d475ced50e81e4e7bd3 (patch)
treebba92b6eb98726e26ab6acf715c14db4cf00608b
parent472be8055fc05670b5e37726130792b0472ec230 (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.lua2
-rw-r--r--src/frontend/mame/ui/state.cpp330
-rw-r--r--src/frontend/mame/ui/state.h90
-rw-r--r--src/frontend/mame/ui/ui.cpp121
-rw-r--r--src/frontend/mame/ui/ui.h1
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;