summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-11-03 05:18:06 +1100
committer Vas Crabb <vas@vastheman.com>2021-11-03 05:18:06 +1100
commitdd43f801a1839b526de1f3b0196d27073c0ebd7a (patch)
tree5dc3f56fdc8bc157c386e106cf659f997fc68f00 /src/emu
parente1863f8c6a023951090eca7a9d3a727f632c424e (diff)
-emu/ioport.cpp: Fixed "MAME lost my joystick settings!!!1!11!
-plugins: Gave the timecode plugin an option to count emulated frames.
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/ioport.cpp148
-rw-r--r--src/emu/ioport.h30
2 files changed, 109 insertions, 69 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 736d68e5967..eb9ed623a02 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -695,7 +695,7 @@ const char *ioport_field::name() const
const input_seq &ioport_field::seq(input_seq_type seqtype) const noexcept
{
// if no live state, return default
- if (m_live == nullptr)
+ if (!m_live)
return defseq(seqtype);
// if the sequence is the special default code, return the expanded default value
@@ -736,7 +736,7 @@ void ioport_field::set_defseq(input_seq_type seqtype, const input_seq &newseq)
m_seq[seqtype] = newseq;
// also update live state unless previously customized
- if (m_live != nullptr && !was_changed)
+ if (m_live && !was_changed)
m_live->seq[seqtype] = newseq;
}
@@ -875,14 +875,18 @@ std::string ioport_field::key_name(int which) const
// settings for the given input field
//-------------------------------------------------
-void ioport_field::get_user_settings(user_settings &settings) const noexcept
+void ioport_field::get_user_settings(user_settings &settings) const
{
// zap the entire structure
settings = user_settings();
// copy the basics
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
+ {
settings.seq[seqtype] = seq(seqtype);
+ if (m_live)
+ settings.cfg[seqtype] = m_live->cfg[seqtype];
+ }
// if there's a list of settings or we're an adjuster, copy the current value
if (!m_settinglist.empty() || m_type == IPT_ADJUSTER)
@@ -909,16 +913,16 @@ void ioport_field::get_user_settings(user_settings &settings) const noexcept
// settings for the given input field
//-------------------------------------------------
-void ioport_field::set_user_settings(const user_settings &settings) noexcept
+void ioport_field::set_user_settings(const user_settings &settings)
{
// copy the basics
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
- const input_seq &defseq = manager().type_seq(m_type, m_player, input_seq_type(seqtype));
- if (defseq == settings.seq[seqtype])
+ if (settings.seq[seqtype].is_default())
m_live->seq[seqtype].set_default();
else
m_live->seq[seqtype] = settings.seq[seqtype];
+ m_live->cfg[seqtype] = settings.cfg[seqtype];
}
// if there's a list of settings or we're an adjuster, copy the current value
@@ -1898,7 +1902,21 @@ void ioport_manager::set_type_seq(ioport_type type, int player, input_seq_type s
{
input_type_entry *const entry = m_type_to_entry[type][player];
if (entry)
- entry->set_seq(seqtype, newseq);
+ {
+ if (newseq.is_default())
+ {
+ entry->set_seq(seqtype, entry->defseq(seqtype));
+ entry->set_cfg(seqtype, "");
+ }
+ else
+ {
+ entry->set_seq(seqtype, newseq);
+ if (!newseq.length())
+ entry->set_cfg(seqtype, "NONE");
+ else
+ entry->set_cfg(seqtype, machine().input().seq_to_tokens(newseq));
+ }
+ }
}
@@ -2086,9 +2104,12 @@ void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, u
int type = token_to_input_type(portnode->get_attribute_string("type", ""), player);
// initialize sequences to invalid defaults
- input_seq newseq[SEQ_TYPE_TOTAL];
- for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
- newseq[seqtype].set(INPUT_CODE_INVALID);
+ std::pair<input_seq, char const *> newseq[SEQ_TYPE_TOTAL];
+ for (auto &seq : newseq)
+ {
+ seq.first.set(INPUT_CODE_INVALID);
+ seq.second = "";
+ }
// loop over new sequences
for (util::xml::data_node const *seqnode = portnode->get_child("newseq"); seqnode; seqnode = seqnode->get_next_sibling("newseq"))
@@ -2098,19 +2119,28 @@ void ioport_manager::load_config(config_type cfg_type, config_level cfg_level, u
if ((seqtype != -1) && seqnode->get_value())
{
if (!strcmp(seqnode->get_value(), "NONE"))
- newseq[seqtype].reset();
+ newseq[seqtype].first.reset();
else
- machine().input().seq_from_tokens(newseq[seqtype], seqnode->get_value());
+ machine().input().seq_from_tokens(newseq[seqtype].first, seqnode->get_value());
+ newseq[seqtype].second = seqnode->get_value();
}
}
// load into the appropriate place for the config type/level
if (config_type::SYSTEM == cfg_type)
+ {
load_system_config(*portnode, type, player, newseq);
+ }
else if ((config_type::CONTROLLER == cfg_type) && (config_level::DEFAULT != cfg_level))
+ {
+ for (auto &seq : newseq)
+ seq.second = "";
load_controller_config(*portnode, type, player, newseq);
+ }
else
+ {
load_default_config(type, player, newseq);
+ }
}
// after applying the controller config, push that back into the backup, since that is
@@ -2230,7 +2260,10 @@ void ioport_manager::load_remap_table(util::xml::data_node const &parentnode)
// to defaults for all systems
//-------------------------------------------------
-bool ioport_manager::load_default_config(int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
+bool ioport_manager::load_default_config(
+ int type,
+ int player,
+ const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL])
{
// find a matching port in the list
for (input_type_entry &entry : m_typelist)
@@ -2238,8 +2271,11 @@ bool ioport_manager::load_default_config(int type, int player, const input_seq (
if (entry.type() == type && entry.player() == player)
{
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
- if (newseq[seqtype][0] != INPUT_CODE_INVALID)
- entry.set_seq(seqtype, newseq[seqtype]);
+ {
+ if (newseq[seqtype].first[0] != INPUT_CODE_INVALID)
+ entry.set_seq(seqtype, newseq[seqtype].first);
+ entry.set_cfg(seqtype, newseq[seqtype].second);
+ }
return true;
}
}
@@ -2252,7 +2288,11 @@ bool ioport_manager::load_default_config(int type, int player, const input_seq (
// profile settings to defaults
//-------------------------------------------------
-bool ioport_manager::load_controller_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
+bool ioport_manager::load_controller_config(
+ util::xml::data_node const &portnode,
+ int type,
+ int player,
+ const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL])
{
// without a tag, apply to the defaults for all systems
char const *const tag = portnode.get_attribute_string("tag", nullptr);
@@ -2278,8 +2318,8 @@ bool ioport_manager::load_controller_config(util::xml::data_node const &portnode
// if a sequence was specified, override the developer-specified default for the field
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
- if (newseq[seqtype][0] != INPUT_CODE_INVALID)
- field.set_defseq(seqtype, newseq[seqtype]);
+ if (newseq[seqtype].first[0] != INPUT_CODE_INVALID)
+ field.set_defseq(seqtype, newseq[seqtype].first);
}
// fetch configurable attributes
@@ -2342,7 +2382,11 @@ bool ioport_manager::load_controller_config(util::xml::data_node const &portnode
// configuration for the current system
//-------------------------------------------------
-void ioport_manager::load_system_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL])
+void ioport_manager::load_system_config(
+ util::xml::data_node const &portnode,
+ int type,
+ int player,
+ const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL])
{
// system-specific configuration should always apply by port/field
char const *const tag = portnode.get_attribute_string("tag", nullptr);
@@ -2364,8 +2408,9 @@ void ioport_manager::load_system_config(util::xml::data_node const &portnode, in
// if a sequence was specified, copy it in
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
{
- if (newseq[seqtype][0] != INPUT_CODE_INVALID)
- field.live().seq[seqtype] = newseq[seqtype];
+ if (newseq[seqtype].first[0] != INPUT_CODE_INVALID)
+ field.live().seq[seqtype] = newseq[seqtype].first;
+ field.live().cfg[seqtype] = newseq[seqtype].second;
}
// fetch configurable attributes
@@ -2461,27 +2506,6 @@ void ioport_manager::save_config(config_type cfg_type, util::xml::data_node *par
//-------------------------------------------------
-// save_sequence - add a node for an input
-// sequence
-//-------------------------------------------------
-
-void ioport_manager::save_sequence(util::xml::data_node &parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq)
-{
- // get the string for the sequence
- std::string seqstring;
- if (seq.length() == 0)
- seqstring.assign("NONE");
- else
- seqstring = machine().input().seq_to_tokens(seq);
-
- // add the new node
- util::xml::data_node *const seqnode = parentnode.add_child("newseq", seqstring.c_str());
- if (seqnode != nullptr)
- seqnode->set_attribute("type", seqtypestrings[type]);
-}
-
-
-//-------------------------------------------------
// save_this_input_field_type - determine if the
// given port type is worth saving
//-------------------------------------------------
@@ -2519,7 +2543,7 @@ void ioport_manager::save_default_inputs(util::xml::data_node &parentnode)
// see if any of the sequences have changed
input_seq_type seqtype;
for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
- if (entry.seq(seqtype) != entry.defseq(seqtype))
+ if (!entry.cfg(seqtype).empty())
break;
// if so, we need to add a node
@@ -2527,15 +2551,21 @@ void ioport_manager::save_default_inputs(util::xml::data_node &parentnode)
{
// add a new port node
util::xml::data_node *const portnode = parentnode.add_child("port", nullptr);
- if (portnode != nullptr)
+ if (portnode)
{
// add the port information and attributes
portnode->set_attribute("type", input_type_to_token(entry.type(), entry.player()).c_str());
// add only the sequences that have changed from the defaults
for (input_seq_type type = SEQ_TYPE_STANDARD; type < SEQ_TYPE_TOTAL; ++type)
- if (entry.seq(type) != entry.defseq(type))
- save_sequence(*portnode, type, entry.type(), entry.seq(type));
+ {
+ if (!entry.cfg(type).empty())
+ {
+ util::xml::data_node *const seqnode = portnode->add_child("newseq", entry.cfg(type).c_str());
+ if (seqnode)
+ seqnode->set_attribute("type", seqtypestrings[type]);
+ }
+ }
}
}
}
@@ -2566,22 +2596,22 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
{
// determine if we changed
bool changed = false;
- for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
- changed |= (field.seq(seqtype) != field.defseq(seqtype));
+ for (input_seq_type seqtype = SEQ_TYPE_STANDARD; (seqtype < SEQ_TYPE_TOTAL) && !changed; ++seqtype)
+ changed = !field.live().cfg[seqtype].empty();
if (!field.is_analog())
{
// non-analog changes
- changed |= ((field.live().value & field.mask()) != (field.defvalue() & field.mask()));
- changed |= (field.live().toggle != field.toggle());
+ changed = changed || ((field.live().value & field.mask()) != (field.defvalue() & field.mask()));
+ changed = changed || (field.live().toggle != field.toggle());
}
else
{
// analog changes
- changed |= (field.live().analog->m_delta != field.delta());
- changed |= (field.live().analog->m_centerdelta != field.centerdelta());
- changed |= (field.live().analog->m_sensitivity != field.sensitivity());
- changed |= (field.live().analog->m_reverse != field.analog_reverse());
+ changed = changed || (field.live().analog->m_delta != field.delta());
+ changed = changed || (field.live().analog->m_centerdelta != field.centerdelta());
+ changed = changed || (field.live().analog->m_sensitivity != field.sensitivity());
+ changed = changed || (field.live().analog->m_reverse != field.analog_reverse());
}
// if we did change, add a new node
@@ -2599,8 +2629,14 @@ void ioport_manager::save_game_inputs(util::xml::data_node &parentnode)
// add sequences if changed
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype)
- if (field.seq(seqtype) != field.defseq(seqtype))
- save_sequence(*portnode, seqtype, field.type(), field.seq(seqtype));
+ {
+ if (!field.live().cfg[seqtype].empty())
+ {
+ util::xml::data_node *const seqnode = portnode->add_child("newseq", field.live().cfg[seqtype].c_str());
+ if (seqnode)
+ seqnode->set_attribute("type", seqtypestrings[seqtype]);
+ }
+ }
if (!field.is_analog())
{
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 01fffab02d8..39cfbc42205 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -802,22 +802,25 @@ public:
input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) noexcept { return m_defseq[seqtype]; }
const input_seq &defseq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_defseq[seqtype]; }
const input_seq &seq(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_seq[seqtype]; }
+ const std::string &cfg(input_seq_type seqtype = SEQ_TYPE_STANDARD) const noexcept { return m_cfg[seqtype]; }
// setters
void restore_default_seq() noexcept;
void set_seq(input_seq_type seqtype, const input_seq &seq) noexcept { m_seq[seqtype] = seq; }
+ template <typename... T> void set_cfg(input_seq_type seqtype, T &&... cfg) { m_cfg[seqtype].assign(std::forward<T>(cfg)...); }
void replace_code(input_code oldcode, input_code newcode) noexcept;
void configure_osd(const char *token, const char *name) noexcept;
private:
// internal state
- ioport_type m_type; // IPT_* for this entry
- ioport_group m_group; // which group the port belongs to
- u8 m_player; // player number (0 is player 1)
- const char * m_token; // token used to store settings
- const char * m_name; // user-friendly name
- std::array<input_seq, SEQ_TYPE_TOTAL> m_defseq; // default input sequence
- std::array<input_seq, SEQ_TYPE_TOTAL> m_seq; // currently configured sequences
+ ioport_type m_type; // IPT_* for this entry
+ ioport_group m_group; // which group the port belongs to
+ u8 m_player; // player number (0 is player 1)
+ const char * m_token; // token used to store settings
+ const char * m_name; // user-friendly name
+ std::array<input_seq, SEQ_TYPE_TOTAL> m_defseq; // default input sequence
+ std::array<input_seq, SEQ_TYPE_TOTAL> m_seq; // currently configured sequences
+ std::array<std::string, SEQ_TYPE_TOTAL> m_cfg; // configuration strings
};
@@ -1087,14 +1090,15 @@ public:
{
ioport_value value = 0; // for DIP switches
input_seq seq[SEQ_TYPE_TOTAL]; // sequences of all types
+ std::string cfg[SEQ_TYPE_TOTAL]; // configuration strings of all types
s32 sensitivity = 0; // for analog controls
s32 delta = 0; // for analog controls
s32 centerdelta = 0; // for analog controls
bool reverse = false; // for analog controls
bool toggle = false; // for non-analog controls
};
- void get_user_settings(user_settings &settings) const noexcept;
- void set_user_settings(const user_settings &settings) noexcept;
+ void get_user_settings(user_settings &settings) const;
+ void set_user_settings(const user_settings &settings);
private:
void expand_diplocation(const char *location, std::string &errorbuf);
@@ -1163,6 +1167,7 @@ struct ioport_field_live
digital_joystick::direction_t joydir; // digital joystick direction index
bool lockout; // user lockout
std::string name; // overridden name
+ std::string cfg[SEQ_TYPE_TOTAL];// configuration strings
};
@@ -1405,12 +1410,11 @@ private:
void load_config(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode);
void load_remap_table(util::xml::data_node const &parentnode);
- bool load_default_config(int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
- bool load_controller_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
- void load_system_config(util::xml::data_node const &portnode, int type, int player, const input_seq (&newseq)[SEQ_TYPE_TOTAL]);
+ bool load_default_config(int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]);
+ bool load_controller_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]);
+ void load_system_config(util::xml::data_node const &portnode, int type, int player, const std::pair<input_seq, char const *> (&newseq)[SEQ_TYPE_TOTAL]);
void save_config(config_type cfg_type, util::xml::data_node *parentnode);
- void save_sequence(util::xml::data_node &parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq);
bool save_this_input_field_type(ioport_type type);
void save_default_inputs(util::xml::data_node &parentnode);
void save_game_inputs(util::xml::data_node &parentnode);