summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/input.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-01-28 08:00:27 +1100
committer Vas Crabb <vas@vastheman.com>2023-01-28 08:16:53 +1100
commit2498f2b7cfb77f6a6d8d08f07075b7fa1c3ab63b (patch)
tree07f72639213d6ada8dd143be21e11178160a4894 /src/emu/input.cpp
parent536c6eeb55a7d5b69ef61cb79ec35c3e09a1458e (diff)
Miscellaneous fixes and refactoring:
ui/analogipt.cpp: Fixed bar graph display for fields with ranges that wrap through zero. emu/inputdev.cpp: Separateed analog axis deadzone and switch threshold settings, reduced default deadzone, and fixed a potential division by zero if the deadzone and saturation settings are equal. emu/ioport.cpp: Fixed behaviour of absolute analog fields where range passes through zero - it previously only worked for specific combinations of mask, minimum and default. Removed a workaround from universal/getaway.cpp that is no longer necessary. emu/input.cpp: Fixed unintuitive behaviour when an absolute field is assigned an OR combination of a relative control folled by an absolute control (e.g. Mouse X or Joy 1 LSX). Also fixed reading axis input sequences where an axis code is followed by a switch code (these can only be produced by manually editing configuration files, not through MAME's UI), and fixed the returned type when multiple relative axes sum to zero. osd/modules/input_dinput.cpp: Fixed hat switches being stuck in up position when input is suspended in the background taito/taitoio_yoke.cpp: Give throttle control a distinct type, and don't auto-centre. osd: Added option to select MIDI provider module (currently only PortMidi and the dummy module are available). Also put various things in namespaces, and fixed builds including SDL sound module with native Windows OSD. emu/validity.cpp: Added check to catch I/O port fields using UI input types. emu/inpttype.ipp: Renamed inputs that were causing confusion. "Bill" and "Track" were causing confusion for translators and hence likely causing confusion for many users, especially those who are not native English speakers. "Track" as an abbreviation for "Trackball" was frequently being mistranslated, e.g. in the sense of a CD track selection button or even in the sense of a railway track. There's no reason to abbreviate it. "Bill" in the US English sense as a banknote is too ambiguous and was causing confusion for translators. It's better to use the less ambiguous "Banknote". Corrected Greek translations of "Trackball". Don't run GitHub Actions on issue template changes.
Diffstat (limited to 'src/emu/input.cpp')
-rw-r--r--src/emu/input.cpp142
1 files changed, 89 insertions, 53 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp
index 6c3699a833a..d8029216624 100644
--- a/src/emu/input.cpp
+++ b/src/emu/input.cpp
@@ -24,6 +24,8 @@
+namespace {
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -49,8 +51,8 @@ struct code_string_table
return nullptr;
}
- u32 m_code;
- const char * m_string;
+ u32 m_code;
+ const char * m_string;
};
@@ -60,7 +62,7 @@ struct code_string_table
//**************************************************************************
// token strings for device classes
-static const code_string_table devclass_token_table[] =
+const code_string_table devclass_token_table[] =
{
{ DEVICE_CLASS_KEYBOARD, "KEYCODE" },
{ DEVICE_CLASS_MOUSE, "MOUSECODE" },
@@ -70,7 +72,7 @@ static const code_string_table devclass_token_table[] =
};
// friendly strings for device classes
-static const code_string_table devclass_string_table[] =
+const code_string_table devclass_string_table[] =
{
{ DEVICE_CLASS_KEYBOARD, "Kbd" },
{ DEVICE_CLASS_MOUSE, "Mouse" },
@@ -80,7 +82,7 @@ static const code_string_table devclass_string_table[] =
};
// token strings for item modifiers
-static const code_string_table modifier_token_table[] =
+const code_string_table modifier_token_table[] =
{
{ ITEM_MODIFIER_REVERSE, "REVERSE" },
{ ITEM_MODIFIER_POS, "POS" },
@@ -93,7 +95,7 @@ static const code_string_table modifier_token_table[] =
};
// friendly strings for item modifiers
-static const code_string_table modifier_string_table[] =
+const code_string_table modifier_string_table[] =
{
{ ITEM_MODIFIER_REVERSE, "Reverse" },
{ ITEM_MODIFIER_POS, "+" },
@@ -106,7 +108,7 @@ static const code_string_table modifier_string_table[] =
};
// token strings for item classes
-static const code_string_table itemclass_token_table[] =
+const code_string_table itemclass_token_table[] =
{
{ ITEM_CLASS_SWITCH, "SWITCH" },
{ ITEM_CLASS_ABSOLUTE, "ABSOLUTE" },
@@ -115,7 +117,7 @@ static const code_string_table itemclass_token_table[] =
};
// token strings for standard item ids
-static const code_string_table itemid_token_table[] =
+const code_string_table itemid_token_table[] =
{
// standard keyboard codes
{ ITEM_ID_A, "A" },
@@ -355,6 +357,48 @@ static const code_string_table itemid_token_table[] =
//**************************************************************************
+// UTILITY FUNCTIONS
+//**************************************************************************
+
+inline void accumulate_axis_value(
+ s32 &result,
+ input_item_class &resultclass,
+ input_item_class &resultclasszero,
+ s32 value,
+ input_item_class valueclass,
+ input_item_class valueclasszero)
+{
+ if (!value)
+ {
+ // track the highest-priority zero
+ if ((ITEM_CLASS_ABSOLUTE == valueclasszero) || (ITEM_CLASS_INVALID == resultclasszero))
+ resultclasszero = valueclasszero;
+ }
+ else if (ITEM_CLASS_ABSOLUTE == valueclass)
+ {
+ // absolute values override relative values
+ if (ITEM_CLASS_ABSOLUTE == resultclass)
+ result += value;
+ else
+ result = value;
+ resultclass = ITEM_CLASS_ABSOLUTE;
+ }
+ else if (ITEM_CLASS_RELATIVE == valueclass)
+ {
+ // relative values accumulate
+ if (resultclass != ITEM_CLASS_ABSOLUTE)
+ {
+ result += value;
+ resultclass = ITEM_CLASS_RELATIVE;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
// INPUT MANAGER
//**************************************************************************
@@ -861,91 +905,83 @@ bool input_manager::seq_pressed(const input_seq &seq)
s32 input_manager::seq_axis_value(const input_seq &seq, input_item_class &itemclass)
{
- // start with no valid classes
- input_item_class itemclasszero = ITEM_CLASS_INVALID;
+ // start with zero result and no valid classes
+ s32 result = 0;
itemclass = ITEM_CLASS_INVALID;
+ input_item_class itemclasszero = ITEM_CLASS_INVALID;
// iterate over all of the codes
- s32 result = 0;
+ s32 groupval = 0;
+ input_item_class groupclass = ITEM_CLASS_INVALID;
+ input_item_class groupclasszero = ITEM_CLASS_INVALID;
bool invert = false;
bool enable = true;
for (int codenum = 0; ; codenum++)
{
- input_code code = seq[codenum];
+ input_code const code = seq[codenum];
if (code == input_seq::not_code)
{
- // handle NOT
+ // handle NOT - invert the next code
invert = true;
}
else if (code == input_seq::end_code)
{
- // handle END
+ // handle END - commit group and break out of loop
+ accumulate_axis_value(
+ result, itemclass, itemclasszero,
+ groupval, groupclass, groupclasszero);
break;
}
else if (code == input_seq::or_code)
{
- // handle OR
-
- // reset invert and enable for the next group
+ // handle OR - commit group and reset for the next group
+ accumulate_axis_value(
+ result, itemclass, itemclasszero,
+ groupval, groupclass, groupclasszero);
+ groupval = 0;
+ groupclasszero = ITEM_CLASS_INVALID;
+ groupclass = ITEM_CLASS_INVALID;
invert = false;
enable = true;
}
else if (enable)
{
// handle everything else only if we're still enabled
+ input_item_class const codeclass = code.item_class();
// switch codes serve as enables
- if (code.item_class() == ITEM_CLASS_SWITCH)
+ if (ITEM_CLASS_SWITCH == codeclass)
{
// AND against previous digital codes
if (enable)
+ {
enable = code_pressed(code) ^ invert;
- // FIXME: need to clear current group value if enable became false
- // you can't create a sequence where this matters using the internal UI,
- // but you can by editing a CFG file (or controller config file)
+ if (!enable)
+ {
+ // clear current group if enable became false - only way out is an OR code
+ groupval = 0;
+ groupclasszero = ITEM_CLASS_INVALID;
+ groupclass = ITEM_CLASS_INVALID;
+ }
+ }
}
else
{
// non-switch codes are analog values
- s32 value = code_value(code);
-
- // if we got a 0 value, don't do anything except remember the first type
- if (value == 0)
- {
- if (itemclasszero == ITEM_CLASS_INVALID)
- itemclasszero = code.item_class();
- }
- else if (code.item_class() == ITEM_CLASS_ABSOLUTE)
- {
- // non-zero absolute values override relative values
- if (itemclass == ITEM_CLASS_ABSOLUTE)
- result += value;
- else
- result = value;
- itemclass = ITEM_CLASS_ABSOLUTE;
- }
- else if (code.item_class() == ITEM_CLASS_RELATIVE)
- {
- // non-zero relative values accumulate in the absence of absolute values
- if (itemclass != ITEM_CLASS_ABSOLUTE)
- {
- result += value;
- itemclass = ITEM_CLASS_RELATIVE;
- }
- }
+ accumulate_axis_value(
+ groupval, groupclass, groupclasszero,
+ code_value(code), codeclass, codeclass);
}
- // clear the invert flag
+ // clear the invert flag - it only applies to one item
invert = false;
}
}
- // saturate mixed absolute values
- if (itemclass == ITEM_CLASS_ABSOLUTE)
+ // saturate mixed absolute values, report neutral type
+ if (ITEM_CLASS_ABSOLUTE == itemclass)
result = std::clamp(result, osd::INPUT_ABSOLUTE_MIN, osd::INPUT_ABSOLUTE_MAX);
-
- // if the caller wants to know the type, provide it
- if (result == 0)
+ else if (ITEM_CLASS_INVALID == itemclass)
itemclass = itemclasszero;
return result;
}