diff options
Diffstat (limited to 'src/emu/ioport.cpp')
-rw-r--r-- | src/emu/ioport.cpp | 105 |
1 files changed, 64 insertions, 41 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index bf241f30b57..d76804a9573 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -153,7 +153,7 @@ inline s64 recip_scale(s64 scale) inline s32 apply_scale(s32 value, s64 scale) { - return (s64(value) * scale) >> 24; + return (s64(value) * scale) / (1 << 24); } @@ -616,7 +616,9 @@ ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value def // reset sequences and chars for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; ++seqtype) m_seq[seqtype].set_default(); - std::fill(std::begin(m_chars), std::end(m_chars), char32_t(0)); + + for (int i = 0; i < ARRAY_LENGTH(m_chars); i++) + std::fill(std::begin(m_chars[i]), std::end(m_chars[i]), char32_t(0)); // for DIP switches and configs, look for a default value from the owner if (type == IPT_DIPSWITCH || type == IPT_CONFIG) @@ -755,16 +757,20 @@ ioport_type_class ioport_field::type_class() const //------------------------------------------------- -// keyboard_code - accesses a particular keyboard -// code +// keyboard_codes - accesses a particular keyboard +// code list //------------------------------------------------- -char32_t ioport_field::keyboard_code(int which) const +std::vector<char32_t> ioport_field::keyboard_codes(int which) const { if (which >= ARRAY_LENGTH(m_chars)) throw emu_fatalerror("Tried to access keyboard_code with out-of-range index %d\n", which); - return m_chars[which]; + std::vector<char32_t> result; + for (int i = 0; i < ARRAY_LENGTH(m_chars[which]) && m_chars[which] != 0; i++) + result.push_back(m_chars[which][i]); + + return result; } @@ -774,7 +780,8 @@ char32_t ioport_field::keyboard_code(int which) const std::string ioport_field::key_name(int which) const { - char32_t ch = keyboard_code(which); + std::vector<char32_t> codes = keyboard_codes(which); + char32_t ch = codes.empty() ? 0 : codes[0]; // attempt to get the string from the character info table switch (ch) @@ -1373,8 +1380,8 @@ ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog) // loop through each character on the field for (int which = 0; which < 4; which++) { - char32_t const ch = field.keyboard_code(which); - if (ch == 0) + std::vector<char32_t> const codes = field.keyboard_codes(which); + if (codes.empty()) break; name.append(string_format("%-*s ", std::max(SPACE_COUNT - 1, 0), field.key_name(which))); } @@ -3059,16 +3066,27 @@ ioport_configurer& ioport_configurer::field_alloc(ioport_type type, ioport_value // field_add_char - add a character to a field //------------------------------------------------- -ioport_configurer& ioport_configurer::field_add_char(char32_t ch) +ioport_configurer& ioport_configurer::field_add_char(std::initializer_list<char32_t> charlist) { for (int index = 0; index < ARRAY_LENGTH(m_curfield->m_chars); index++) - if (m_curfield->m_chars[index] == 0) + if (m_curfield->m_chars[index][0] == 0) { - m_curfield->m_chars[index] = ch; + const size_t char_count = ARRAY_LENGTH(m_curfield->m_chars[index]); + assert(charlist.size() > 0 && charlist.size() <= char_count); + + for (size_t i = 0; i < char_count; i++) + m_curfield->m_chars[index][i] = i < charlist.size() ? *(charlist.begin() + i) : 0; return *this; } - throw emu_fatalerror("PORT_CHAR(%d) could not be added - maximum amount exceeded\n", ch); + std::ostringstream s; + bool is_first = true; + for (char32_t ch : charlist) + { + util::stream_format(s, "%s%d", is_first ? "" : ",", (int)ch); + is_first = false; + } + throw emu_fatalerror("PORT_CHAR(%s) could not be added - maximum amount exceeded\n", s.str().c_str()); } @@ -3328,10 +3346,6 @@ analog_field::analog_field(ioport_field &field) // single axis that increases from default m_scalepos = compute_scale(m_adjmax - m_adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN); - // move from default - if (m_adjdefvalue == m_adjmax) - m_scalepos = -m_scalepos; - // make the scaling the same for easier coding when we need to scale m_scaleneg = m_scalepos; @@ -3370,7 +3384,13 @@ analog_field::analog_field(ioport_field &field) // relative controls reverse from 1 past their max range if (m_wraps) - m_reverse_val -= INPUT_RELATIVE_PER_PIXEL; + { + // FIXME: positional needs -1, using INPUT_RELATIVE_PER_PIXEL skips a position (and reads outside the table array) + if(field.type() == IPT_POSITIONAL || field.type() == IPT_POSITIONAL_V) + m_reverse_val --; + else + m_reverse_val -= INPUT_RELATIVE_PER_PIXEL; + } } } @@ -3392,25 +3412,11 @@ inline s32 analog_field::apply_min_max(s32 value) const s32 adjmin = apply_inverse_sensitivity(m_minimum); s32 adjmax = apply_inverse_sensitivity(m_maximum); - // for absolute devices, clamp to the bounds absolutely - if (!m_wraps) - { - if (value > adjmax) - value = adjmax; - else if (value < adjmin) - value = adjmin; - } - - // for relative devices, wrap around when we go past the edge - else - { - s32 range = adjmax - adjmin; - // rolls to other end when 1 position past end. - value = (value - adjmin) % range; - if (value < 0) - value += range; - value += adjmin; - } + // clamp to the bounds absolutely + if (value > adjmax) + value = adjmax; + else if (value < adjmin) + value = adjmin; return value; } @@ -3423,7 +3429,7 @@ inline s32 analog_field::apply_min_max(s32 value) const inline s32 analog_field::apply_sensitivity(s32 value) const { - return s32((s64(value) * m_sensitivity) / 100.0 + 0.5); + return lround((s64(value) * m_sensitivity) / 100.0); } @@ -3446,7 +3452,8 @@ inline s32 analog_field::apply_inverse_sensitivity(s32 value) const s32 analog_field::apply_settings(s32 value) const { // apply the min/max and then the sensitivity - value = apply_min_max(value); + if (!m_wraps) + value = apply_min_max(value); value = apply_sensitivity(value); // apply reversal if needed @@ -3464,6 +3471,18 @@ s32 analog_field::apply_settings(s32 value) const value = apply_scale(value, m_scaleneg); value += m_adjdefvalue; + // for relative devices, wrap around when we go past the edge + // (this is done last to prevent rounding errors) + if (m_wraps) + { + s32 range = m_adjmax - m_adjmin; + // rolls to other end when 1 position past end. + value = (value - m_adjmin) % range; + if (value < 0) + value += range; + value += m_adjmin; + } + return value; } @@ -3475,8 +3494,12 @@ s32 analog_field::apply_settings(s32 value) const void analog_field::frame_update(running_machine &machine) { - // clamp the previous value to the min/max range and remember it - m_previous = m_accum = apply_min_max(m_accum); + // clamp the previous value to the min/max range + if (!m_wraps) + m_accum = apply_min_max(m_accum); + + // remember the previous value in case we need to interpolate + m_previous = m_accum; // get the new raw analog value and its type input_item_class itemclass; |