diff options
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/input.cpp | 214 | ||||
-rw-r--r-- | src/emu/input.h | 131 | ||||
-rw-r--r-- | src/emu/ioport.cpp | 2 |
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()); } |