diff options
author | 2017-11-13 17:12:47 -0500 | |
---|---|---|
committer | 2017-11-13 18:13:58 -0500 | |
commit | dcfdab2735a60c03e2e34cd7a076a3f14b631b49 (patch) | |
tree | cb761f395579be2940191caa36b537710cfafe6d | |
parent | 65c4ad8e90c589779e59782e450bec1c53d3a1b8 (diff) |
Better wraparound handling for relative inputs
-rw-r--r-- | src/emu/ioport.cpp | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 82f4c4d8030..0538207b46b 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); } @@ -3346,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; @@ -3416,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; } @@ -3470,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 @@ -3488,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; } @@ -3499,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; |