summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/input.cpp214
-rw-r--r--src/emu/input.h131
-rw-r--r--src/emu/ioport.cpp2
3 files changed, 122 insertions, 225 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp
index 64aa4382c97..0d829b84bc5 100644
--- a/src/emu/input.cpp
+++ b/src/emu/input.cpp
@@ -30,10 +30,10 @@
const s32 INVALID_AXIS_VALUE = 0x7fffffff;
// additional expanded input codes for sequences
-const input_code input_seq::end_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_END);
-const input_code input_seq::default_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_DEFAULT);
-const input_code input_seq::not_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_NOT);
-const input_code input_seq::or_code(DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_OR);
+constexpr input_code input_seq::end_code;
+constexpr input_code input_seq::default_code;
+constexpr input_code input_seq::not_code;
+constexpr input_code input_seq::or_code;
// constant sequences
const input_seq input_seq::empty_seq;
@@ -377,14 +377,15 @@ static const code_string_table itemid_token_table[] =
// input sequence
//-------------------------------------------------
-input_seq &input_seq::operator+=(input_code code)
+input_seq &input_seq::operator+=(input_code code) noexcept
{
// if not enough room, return false
- int curlength = length();
- if (curlength < ARRAY_LENGTH(m_code) - 1)
+ const int curlength = length();
+ if (curlength < m_code.size())
{
- m_code[curlength++] = code;
- m_code[curlength] = end_code;
+ m_code[curlength] = code;
+ if ((curlength + 1) < m_code.size())
+ m_code[curlength + 1] = end_code;
}
return *this;
}
@@ -396,17 +397,25 @@ input_seq &input_seq::operator+=(input_code code)
// before the new code
//-------------------------------------------------
-input_seq &input_seq::operator|=(input_code code)
+input_seq &input_seq::operator|=(input_code code) noexcept
{
// overwrite end/default with the new code
- if (m_code[0] == end_code || m_code[0] == default_code)
+ if (m_code[0] == default_code)
+ {
m_code[0] = code;
-
- // otherwise, append an OR token and then the new code
+ m_code[1] = end_code;
+ }
else
{
- *this += or_code;
- *this += code;
+ // otherwise, append an OR token and then the new code
+ const int curlength = length();
+ if ((curlength + 1) < m_code.size())
+ {
+ m_code[curlength] = or_code;
+ m_code[curlength + 1] = code;
+ if ((curlength + 2) < m_code.size())
+ m_code[curlength + 2] = end_code;
+ }
}
return *this;
}
@@ -416,13 +425,13 @@ input_seq &input_seq::operator|=(input_code code)
// length - return the length of the sequence
//-------------------------------------------------
-int input_seq::length() const
+int input_seq::length() const noexcept
{
// find the end token; error if none found
- for (int seqnum = 0; seqnum < ARRAY_LENGTH(m_code); seqnum++)
+ for (int seqnum = 0; seqnum < m_code.size(); seqnum++)
if (m_code[seqnum] == end_code)
return seqnum;
- return ARRAY_LENGTH(m_code);
+ return m_code.size();
}
@@ -431,17 +440,17 @@ int input_seq::length() const
// valid
//-------------------------------------------------
-bool input_seq::is_valid() const
+bool input_seq::is_valid() const noexcept
{
// "default" can only be of length 1
if (m_code[0] == default_code)
- return (length() == 1);
+ return m_code[1] == end_code;
// scan the sequence for valid codes
input_item_class lastclass = ITEM_CLASS_INVALID;
input_code lastcode = INPUT_CODE_INVALID;
int positive_code_count = 0;
- for (auto code : m_code)
+ for (input_code code : m_code)
{
// invalid codes are never permitted
if (code == INPUT_CODE_INVALID)
@@ -451,7 +460,7 @@ bool input_seq::is_valid() const
if (code == or_code || code == end_code)
{
// must be at least one positive code
- if (positive_code_count == 0)
+ if (!positive_code_count)
return false;
// last code must not have been an internal code
@@ -466,15 +475,12 @@ bool input_seq::is_valid() const
positive_code_count = 0;
lastclass = ITEM_CLASS_INVALID;
}
-
- // if we hit a NOT, make sure we don't have a double
else if (code == not_code)
{
+ // if we hit a NOT, make sure we don't have a double
if (lastcode == not_code)
return false;
}
-
- // anything else
else
{
// count positive codes
@@ -502,32 +508,14 @@ bool input_seq::is_valid() const
//-------------------------------------------------
-// set - directly set up to the first 7 codes
-//-------------------------------------------------
-
-void input_seq::set(input_code code0, input_code code1, input_code code2, input_code code3, input_code code4, input_code code5, input_code code6)
-{
- m_code[0] = code0;
- m_code[1] = code1;
- m_code[2] = code2;
- m_code[3] = code3;
- m_code[4] = code4;
- m_code[5] = code5;
- m_code[6] = code6;
- for (int codenum = 7; codenum < ARRAY_LENGTH(m_code); codenum++)
- m_code[codenum] = end_code;
-}
-
-
-//-------------------------------------------------
// backspace - "backspace" over the last entry in
// a sequence
//-------------------------------------------------
-void input_seq::backspace()
+void input_seq::backspace() noexcept
{
// if we have at least one entry, remove it
- int curlength = length();
+ const int curlength = length();
if (curlength > 0)
m_code[curlength - 1] = end_code;
}
@@ -538,9 +526,9 @@ void input_seq::backspace()
// with newcode in a sequence
//-------------------------------------------------
-void input_seq::replace(input_code oldcode, input_code newcode)
+void input_seq::replace(input_code oldcode, input_code newcode) noexcept
{
- for (auto & elem : m_code)
+ for (input_code &elem : m_code)
if (elem == oldcode)
elem = newcode;
}
@@ -555,10 +543,7 @@ void input_seq::replace(input_code oldcode, input_code newcode)
// input_manager - constructor
//-------------------------------------------------
-input_manager::input_manager(running_machine &machine)
- : m_machine(machine),
- m_poll_seq_last_ticks(0),
- m_poll_seq_class(ITEM_CLASS_SWITCH)
+input_manager::input_manager(running_machine &machine) : m_machine(machine)
{
// reset code memory
reset_memory();
@@ -1339,129 +1324,6 @@ s32 input_manager::seq_axis_value(const input_seq &seq, input_item_class &itemcl
//-------------------------------------------------
-// seq_poll_start - begin polling for a new
-// sequence of the given itemclass
-//-------------------------------------------------
-
-void input_manager::seq_poll_start(input_item_class itemclass, const input_seq *startseq)
-{
- assert(itemclass == ITEM_CLASS_SWITCH || itemclass == ITEM_CLASS_ABSOLUTE || itemclass == ITEM_CLASS_RELATIVE);
-
- // reset the recording count and the clock
- m_poll_seq_last_ticks = 0;
- m_poll_seq_class = itemclass;
- m_poll_seq.reset();
-
- // grab the starting sequence to append to, and append an OR
- if (startseq != nullptr)
- {
- m_poll_seq = *startseq;
- if (m_poll_seq.length() > 0)
- m_poll_seq += input_seq::or_code;
- }
-
- // flush out any goobers
- reset_polling();
- input_code dummycode = KEYCODE_ENTER;
- while (dummycode != INPUT_CODE_INVALID)
- dummycode = (m_poll_seq_class == ITEM_CLASS_SWITCH) ? poll_switches() : poll_axes();
-}
-
-
-//-------------------------------------------------
-// input_seq_poll - continue polling
-//-------------------------------------------------
-
-bool input_manager::seq_poll()
-{
- const int curlen = m_poll_seq.length();
- input_code lastcode = m_poll_seq[curlen - 1];
-
- input_code newcode;
- if (m_poll_seq_class == ITEM_CLASS_SWITCH)
- {
- // switch case: see if we have a new code to process
- newcode = poll_switches();
- if (newcode != INPUT_CODE_INVALID)
- {
- // if code is duplicate, toggle the NOT state on the code
- if (curlen > 0 && newcode == lastcode)
- {
- // back up over the existing code
- m_poll_seq.backspace();
-
- // if there was a NOT preceding it, delete it as well, otherwise append a fresh one
- if (m_poll_seq[curlen - 2] == input_seq::not_code)
- m_poll_seq.backspace();
- else
- m_poll_seq += input_seq::not_code;
- }
- }
- }
- else
- {
- // absolute/relative case: see if we have an analog change of sufficient amount
- bool has_or = false;
- if (lastcode == input_seq::or_code)
- {
- lastcode = m_poll_seq[curlen - 2];
- has_or = true;
- }
- newcode = poll_axes();
-
- // if the last code doesn't match absolute/relative of this code, ignore the new one
- if ((lastcode.item_class() == ITEM_CLASS_ABSOLUTE && newcode.item_class() != ITEM_CLASS_ABSOLUTE) ||
- (lastcode.item_class() == ITEM_CLASS_RELATIVE && newcode.item_class() != ITEM_CLASS_RELATIVE))
- newcode = INPUT_CODE_INVALID;
-
- // if the new code is valid, check for half-axis toggles on absolute controls
- if (newcode != INPUT_CODE_INVALID && curlen > 0 && newcode.item_class() == ITEM_CLASS_ABSOLUTE)
- {
- input_code last_nomodifier = lastcode;
- last_nomodifier.set_item_modifier(ITEM_MODIFIER_NONE);
- if (newcode == last_nomodifier)
- {
- // increment the modifier, wrapping back to none
- switch (lastcode.item_modifier())
- {
- case ITEM_MODIFIER_NONE: newcode.set_item_modifier(ITEM_MODIFIER_POS); break;
- case ITEM_MODIFIER_POS: newcode.set_item_modifier(ITEM_MODIFIER_NEG); break;
- default:
- case ITEM_MODIFIER_NEG: newcode.set_item_modifier(ITEM_MODIFIER_NONE); break;
- }
-
- // back up over the previous code so we can re-append
- if (has_or)
- m_poll_seq.backspace();
- m_poll_seq.backspace();
- }
- }
- }
-
- // if we got a new code to append it, append it and reset the timer
- if (newcode != INPUT_CODE_INVALID)
- {
- m_poll_seq += newcode;
- m_poll_seq_last_ticks = osd_ticks();
- }
-
- // if we're recorded at least one item and 2/3 of a second has passed, we're done
- if (m_poll_seq_last_ticks != 0 && osd_ticks() > m_poll_seq_last_ticks + osd_ticks_per_second() * 2 / 3)
- {
- // if the final result is invalid, reset to nothing
- if (!m_poll_seq.is_valid())
- m_poll_seq.reset();
-
- // return true to indicate that we are finished
- return true;
- }
-
- // return false to indicate we are still polling
- return false;
-}
-
-
-//-------------------------------------------------
// seq_clean - clean the sequence, removing
// any invalid bits
//-------------------------------------------------
@@ -1505,7 +1367,7 @@ std::string input_manager::seq_name(const input_seq &seq) const
// special case: empty
if (cleaned_seq[0] == input_seq::end_code)
- return std::string((seq.length() == 0) ? "None" : "n/a");
+ return std::string(seq.empty() ? "None" : "n/a");
// start with an empty buffer
std::string str;
diff --git a/src/emu/input.h b/src/emu/input.h
index 3ca97ae1e99..24b6dd062d2 100644
--- a/src/emu/input.h
+++ b/src/emu/input.h
@@ -17,6 +17,10 @@
#ifndef MAME_EMU_INPUT_H
#define MAME_EMU_INPUT_H
+#include <algorithm>
+#include <array>
+#include <iterator>
+
//**************************************************************************
// CONSTANTS
@@ -358,7 +362,12 @@ class input_code
{
public:
// construction/destruction
- input_code(input_device_class devclass = DEVICE_CLASS_INVALID, int devindex = 0, input_item_class itemclass = ITEM_CLASS_INVALID, input_item_modifier modifier = ITEM_MODIFIER_NONE, input_item_id itemid = ITEM_ID_INVALID)
+ constexpr input_code(
+ input_device_class devclass = DEVICE_CLASS_INVALID,
+ int devindex = 0,
+ input_item_class itemclass = ITEM_CLASS_INVALID,
+ input_item_modifier modifier = ITEM_MODIFIER_NONE,
+ input_item_id itemid = ITEM_ID_INVALID) noexcept
: m_internal(((devclass & 0xf) << 28) | ((devindex & 0xff) << 20) | ((itemclass & 0xf) << 16) | ((modifier & 0xf) << 12) | (itemid & 0xfff))
{
assert(devclass >= 0 && devclass < DEVICE_CLASS_MAXIMUM);
@@ -367,30 +376,48 @@ public:
assert(modifier >= 0 && modifier < ITEM_MODIFIER_MAXIMUM);
assert(itemid >= 0 && itemid < ITEM_ID_ABSOLUTE_MAXIMUM);
}
- input_code(const input_code &src)
- : m_internal(src.m_internal) { }
+ constexpr input_code(const input_code &src) noexcept = default;
// operators
- bool operator==(const input_code &rhs) const { return m_internal == rhs.m_internal; }
- bool operator!=(const input_code &rhs) const { return m_internal != rhs.m_internal; }
+ constexpr bool operator==(const input_code &rhs) const noexcept { return m_internal == rhs.m_internal; }
+ constexpr bool operator!=(const input_code &rhs) const noexcept { return m_internal != rhs.m_internal; }
// getters
- bool internal() const { return device_class() == DEVICE_CLASS_INTERNAL; }
- input_device_class device_class() const { return input_device_class((m_internal >> 28) & 0xf); }
- int device_index() const { return ((m_internal >> 20) & 0xff); }
- input_item_class item_class() const { return input_item_class((m_internal >> 16) & 0xf); }
- input_item_modifier item_modifier() const { return input_item_modifier((m_internal >> 12) & 0xf); }
- input_item_id item_id() const { return input_item_id(m_internal & 0xfff); }
+ constexpr bool internal() const noexcept { return device_class() == DEVICE_CLASS_INTERNAL; }
+ constexpr input_device_class device_class() const noexcept { return input_device_class((m_internal >> 28) & 0xf); }
+ constexpr int device_index() const noexcept { return ((m_internal >> 20) & 0xff); }
+ constexpr input_item_class item_class() const noexcept { return input_item_class((m_internal >> 16) & 0xf); }
+ constexpr input_item_modifier item_modifier() const noexcept { return input_item_modifier((m_internal >> 12) & 0xf); }
+ constexpr input_item_id item_id() const noexcept { return input_item_id(m_internal & 0xfff); }
// setters
- void set_device_class(input_device_class devclass) { assert(devclass >= 0 && devclass <= 0xf); m_internal = (m_internal & ~(0xf << 28)) | ((devclass & 0xf) << 28); }
- void set_device_index(int devindex) { assert(devindex >= 0 && devindex <= 0xff); m_internal = (m_internal & ~(0xff << 20)) | ((devindex & 0xff) << 20); }
- void set_item_class(input_item_class itemclass) { assert(itemclass >= 0 && itemclass <= 0xf); m_internal = (m_internal & ~(0xf << 16)) | ((itemclass & 0xf) << 16); }
- void set_item_modifier(input_item_modifier modifier) { assert(modifier >= 0 && modifier <= 0xf); m_internal = (m_internal & ~(0xf << 12)) | ((modifier & 0xf) << 12); }
- void set_item_id(input_item_id itemid) { assert(itemid >= 0 && itemid <= 0xfff); m_internal = (m_internal & ~0xfff) | (itemid & 0xfff); }
+ void set_device_class(input_device_class devclass) noexcept
+ {
+ assert(devclass >= 0 && devclass <= 0xf);
+ m_internal = (m_internal & ~(0xf << 28)) | ((devclass & 0xf) << 28);
+ }
+ void set_device_index(int devindex) noexcept
+ {
+ assert(devindex >= 0 && devindex <= 0xff);
+ m_internal = (m_internal & ~(0xff << 20)) | ((devindex & 0xff) << 20);
+ }
+ void set_item_class(input_item_class itemclass) noexcept
+ {
+ assert(itemclass >= 0 && itemclass <= 0xf);
+ m_internal = (m_internal & ~(0xf << 16)) | ((itemclass & 0xf) << 16);
+ }
+ void set_item_modifier(input_item_modifier modifier) noexcept
+ {
+ assert(modifier >= 0 && modifier <= 0xf);
+ m_internal = (m_internal & ~(0xf << 12)) | ((modifier & 0xf) << 12);
+ }
+ void set_item_id(input_item_id itemid) noexcept
+ {
+ assert(itemid >= 0 && itemid <= 0xfff);
+ m_internal = (m_internal & ~0xfff) | (itemid & 0xfff);
+ }
private:
- // internal state
u32 m_internal;
};
@@ -402,41 +429,59 @@ class input_seq
{
public:
// construction/destruction
- input_seq(input_code code0 = input_seq::end_code, input_code code1 = input_seq::end_code, input_code code2 = input_seq::end_code, input_code code3 = input_seq::end_code, input_code code4 = input_seq::end_code, input_code code5 = input_seq::end_code, input_code code6 = input_seq::end_code)
- { set(code0, code1, code2, code3, code4, code5, code6); }
- input_seq(const input_seq &rhs) { memcpy(m_code, rhs.m_code, sizeof(m_code)); }
+ template <typename... T> constexpr input_seq(input_code code_0 = end_code, T... code_n) noexcept
+ {
+ set(code_0, code_n...);
+ }
+ constexpr input_seq(const input_seq &rhs) noexcept = default;
// operators
- bool operator==(const input_seq &rhs) const { return (memcmp(m_code, rhs.m_code, sizeof(m_code)) == 0); }
- bool operator!=(const input_seq &rhs) const { return (memcmp(m_code, rhs.m_code, sizeof(m_code)) != 0); }
- input_code operator[](int index) const { return (index >= 0 && index < ARRAY_LENGTH(m_code)) ? m_code[index] : input_seq::end_code; }
- input_seq &operator+=(input_code code);
- input_seq &operator|=(input_code code);
+ bool operator==(const input_seq &rhs) const noexcept { return m_code == rhs.m_code; }
+ bool operator!=(const input_seq &rhs) const noexcept { return m_code != rhs.m_code; }
+ constexpr input_code operator[](int index) const noexcept { return (index >= 0 && index < m_code.size()) ? m_code[index] : end_code; }
+ input_seq &operator+=(input_code code) noexcept;
+ input_seq &operator|=(input_code code) noexcept;
// getters
- int length() const;
- bool is_valid() const;
- bool is_default() const { return m_code[0] == default_code; }
+ constexpr bool empty() const noexcept { return m_code[0] == end_code; }
+ constexpr int max_size() const noexcept { return std::tuple_size<decltype(m_code)>::value; }
+ int length() const noexcept;
+ bool is_valid() const noexcept;
+ constexpr bool is_default() const noexcept { return m_code[0] == default_code; }
// setters
- void set(input_code code0 = input_seq::end_code, input_code code1 = input_seq::end_code, input_code code2 = input_seq::end_code, input_code code3 = input_seq::end_code, input_code code4 = input_seq::end_code, input_code code5 = input_seq::end_code, input_code code6 = input_seq::end_code);
- void reset() { set(); }
- void set_default() { set(default_code); }
- void backspace();
- void replace(input_code oldcode, input_code newcode);
+ template <typename... T> void set(input_code code_0, T... code_n) noexcept
+ {
+ static_assert(sizeof...(T) < std::tuple_size<decltype(m_code)>::value, "too many codes for input_seq");
+ set<0>(code_0, code_n...);
+ }
+ void reset() noexcept { set(end_code); }
+ void set_default() noexcept { set(default_code); }
+ void backspace() noexcept;
+ void replace(input_code oldcode, input_code newcode) noexcept;
// constant codes used in sequences
- static const input_code end_code;
- static const input_code default_code;
- static const input_code not_code;
- static const input_code or_code;
+ static constexpr input_code end_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_END };
+ static constexpr input_code default_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_DEFAULT };
+ static constexpr input_code not_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_NOT };
+ static constexpr input_code or_code { DEVICE_CLASS_INTERNAL, 0, ITEM_CLASS_INVALID, ITEM_MODIFIER_NONE, ITEM_ID_SEQ_OR };
// constant sequences
static const input_seq empty_seq;
private:
+ template <unsigned N> void set() noexcept
+ {
+ std::fill(std::next(m_code.begin(), N), m_code.end(), end_code);
+ }
+ template <unsigned N, typename... T> void set(input_code code_0, T... code_n) noexcept
+ {
+ m_code[N] = code_0;
+ set<N + 1>(code_n...);
+ }
+
// internal state
- input_code m_code[16];
+ std::array<input_code, 16> m_code;
};
@@ -478,11 +523,6 @@ public:
bool seq_pressed(const input_seq &seq);
s32 seq_axis_value(const input_seq &seq, input_item_class &itemclass);
- // input sequence polling
- void seq_poll_start(input_item_class itemclass, const input_seq *startseq = nullptr);
- bool seq_poll();
- const input_seq &seq_poll_final() const { return m_poll_seq; }
-
// input sequence helpers
input_seq seq_clean(const input_seq &seq) const;
std::string seq_name(const input_seq &seq) const;
@@ -503,11 +543,6 @@ private:
// classes
std::array<std::unique_ptr<input_class>, DEVICE_CLASS_MAXIMUM> m_class;
-
- // sequence polling state
- input_seq m_poll_seq;
- osd_ticks_t m_poll_seq_last_ticks;
- input_item_class m_poll_seq_class;
};
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 0d7fe96e5b5..6b75a1289f4 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -2133,7 +2133,7 @@ void ioport_manager::load_config(config_type cfg_type, util::xml::data_node cons
if (seqtype != -1 && seqnode->get_value() != nullptr)
{
if (strcmp(seqnode->get_value(), "NONE") == 0)
- newseq[seqtype].set();
+ newseq[seqtype].reset();
else
machine().input().seq_from_tokens(newseq[seqtype], seqnode->get_value());
}