summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/input.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/input.cpp')
-rw-r--r--src/emu/input.cpp1085
1 files changed, 307 insertions, 778 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp
index 0265b021e9a..5eeee806f9d 100644
--- a/src/emu/input.cpp
+++ b/src/emu/input.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- input.c
+ input.cpp
Handle input from the user.
@@ -20,25 +20,11 @@
#include "emu.h"
#include "inputdev.h"
+#include "corestr.h"
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// invalid memory value for axis polling
-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);
-
-// constant sequences
-const input_seq input_seq::empty_seq;
-
+namespace {
//**************************************************************************
// TYPE DEFINITIONS
@@ -49,24 +35,26 @@ const input_seq input_seq::empty_seq;
// simple class to match codes to strings
struct code_string_table
{
- u32 operator[](const char *string) const
+ static inline constexpr u32 SENTINEL = ~u32(0);
+
+ u32 operator[](std::string_view string) const
{
- for (const code_string_table *current = this; current->m_code != ~0; current++)
- if (strcmp(current->m_string, string) == 0)
+ for (const code_string_table *current = this; current->m_code != SENTINEL; current++)
+ if (current->m_string == string)
return current->m_code;
- return ~0;
+ return SENTINEL;
}
const char *operator[](u32 code) const
{
- for (const code_string_table *current = this; current->m_code != ~0; current++)
+ for (const code_string_table *current = this; current->m_code != SENTINEL; current++)
if (current->m_code == code)
return current->m_string;
return nullptr;
}
- u32 m_code;
- const char * m_string;
+ u32 m_code;
+ const char * m_string;
};
@@ -76,60 +64,62 @@ 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" },
- { DEVICE_CLASS_LIGHTGUN, "GUNCODE" },
- { DEVICE_CLASS_JOYSTICK, "JOYCODE" },
- { ~0U, "UNKCODE" }
+ { DEVICE_CLASS_KEYBOARD, "KEYCODE" },
+ { DEVICE_CLASS_MOUSE, "MOUSECODE" },
+ { DEVICE_CLASS_LIGHTGUN, "GUNCODE" },
+ { DEVICE_CLASS_JOYSTICK, "JOYCODE" },
+ { code_string_table::SENTINEL, "UNKCODE" }
};
// 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" },
- { DEVICE_CLASS_LIGHTGUN, "Gun" },
- { DEVICE_CLASS_JOYSTICK, "Joy" },
- { ~0U, "Unk" }
+ { DEVICE_CLASS_KEYBOARD, "Kbd" },
+ { DEVICE_CLASS_MOUSE, "Mouse" },
+ { DEVICE_CLASS_LIGHTGUN, "Gun" },
+ { DEVICE_CLASS_JOYSTICK, "Joy" },
+ { code_string_table::SENTINEL, "Unk" }
};
// token strings for item modifiers
-static const code_string_table modifier_token_table[] =
+const code_string_table modifier_token_table[] =
{
- { ITEM_MODIFIER_POS, "POS" },
- { ITEM_MODIFIER_NEG, "NEG" },
- { ITEM_MODIFIER_LEFT, "LEFT" },
- { ITEM_MODIFIER_RIGHT, "RIGHT" },
- { ITEM_MODIFIER_UP, "UP" },
- { ITEM_MODIFIER_DOWN, "DOWN" },
- { ~0U, "" }
+ { ITEM_MODIFIER_REVERSE, "REVERSE" },
+ { ITEM_MODIFIER_POS, "POS" },
+ { ITEM_MODIFIER_NEG, "NEG" },
+ { ITEM_MODIFIER_LEFT, "LEFT" },
+ { ITEM_MODIFIER_RIGHT, "RIGHT" },
+ { ITEM_MODIFIER_UP, "UP" },
+ { ITEM_MODIFIER_DOWN, "DOWN" },
+ { code_string_table::SENTINEL, "" }
};
// friendly strings for item modifiers
-static const code_string_table modifier_string_table[] =
+const code_string_table modifier_string_table[] =
{
- { ITEM_MODIFIER_POS, "+" },
- { ITEM_MODIFIER_NEG, "-" },
- { ITEM_MODIFIER_LEFT, "Left" },
- { ITEM_MODIFIER_RIGHT, "Right" },
- { ITEM_MODIFIER_UP, "Up" },
- { ITEM_MODIFIER_DOWN, "Down" },
- { ~0U, "" }
+ { ITEM_MODIFIER_REVERSE, "Reverse" },
+ { ITEM_MODIFIER_POS, "+" },
+ { ITEM_MODIFIER_NEG, "-" },
+ { ITEM_MODIFIER_LEFT, "Left" },
+ { ITEM_MODIFIER_RIGHT, "Right" },
+ { ITEM_MODIFIER_UP, "Up" },
+ { ITEM_MODIFIER_DOWN, "Down" },
+ { code_string_table::SENTINEL, "" }
};
// 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" },
- { ITEM_CLASS_RELATIVE, "RELATIVE" },
- { ~0U, "" }
+ { ITEM_CLASS_SWITCH, "SWITCH" },
+ { ITEM_CLASS_ABSOLUTE, "ABSOLUTE" },
+ { ITEM_CLASS_RELATIVE, "RELATIVE" },
+ { code_string_table::SENTINEL, "" }
};
// 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" },
@@ -363,188 +353,50 @@ static const code_string_table itemid_token_table[] =
{ ITEM_ID_ADD_RELATIVE15,"ADDREL15" },
{ ITEM_ID_ADD_RELATIVE16,"ADDREL16" },
- { ~0U, nullptr }
+ { code_string_table::SENTINEL, nullptr }
};
//**************************************************************************
-// INPUT SEQ
+// UTILITY FUNCTIONS
//**************************************************************************
-//-------------------------------------------------
-// operator+= - append a code to the end of an
-// input sequence
-//-------------------------------------------------
-
-input_seq &input_seq::operator+=(input_code code)
+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 not enough room, return false
- int curlength = length();
- if (curlength < ARRAY_LENGTH(m_code) - 1)
+ if (!value)
{
- m_code[curlength++] = code;
- m_code[curlength] = end_code;
+ // track the highest-priority zero
+ if ((ITEM_CLASS_ABSOLUTE == valueclasszero) || (ITEM_CLASS_INVALID == resultclasszero))
+ resultclasszero = valueclasszero;
}
- return *this;
-}
-
-
-//-------------------------------------------------
-// operator|= - append a code to a sequence; if
-// the sequence is non-empty, insert an OR
-// before the new code
-//-------------------------------------------------
-
-input_seq &input_seq::operator|=(input_code code)
-{
- // overwrite end/default with the new code
- if (m_code[0] == end_code || m_code[0] == default_code)
- m_code[0] = code;
-
- // otherwise, append an OR token and then the new code
- else
+ else if (ITEM_CLASS_ABSOLUTE == valueclass)
{
- *this += or_code;
- *this += code;
+ // absolute values override relative values
+ if (ITEM_CLASS_ABSOLUTE == resultclass)
+ result += value;
+ else
+ result = value;
+ resultclass = ITEM_CLASS_ABSOLUTE;
}
- return *this;
-}
-
-
-//-------------------------------------------------
-// length - return the length of the sequence
-//-------------------------------------------------
-
-int input_seq::length() const
-{
- // find the end token; error if none found
- for (int seqnum = 0; seqnum < ARRAY_LENGTH(m_code); seqnum++)
- if (m_code[seqnum] == end_code)
- return seqnum;
- return ARRAY_LENGTH(m_code);
-}
-
-
-//-------------------------------------------------
-// is_valid - return true if a given sequence is
-// valid
-//-------------------------------------------------
-
-bool input_seq::is_valid() const
-{
- // "default" can only be of length 1
- if (m_code[0] == default_code)
- return (length() == 1);
-
- // 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)
+ else if (ITEM_CLASS_RELATIVE == valueclass)
{
- // invalid codes are never permitted
-
- if (code == INPUT_CODE_INVALID)
- return false;
-
- // if we hit an OR or the end, validate the previous chunk
- if (code == or_code || code == end_code)
- {
- // must be at least one positive code
- if (positive_code_count == 0)
- return false;
-
- // last code must not have been an internal code
- if (lastcode.internal())
- return false;
-
- // if this is the end, we're ok
- if (code == end_code)
- return true;
-
- // reset the state for the next chunk
- 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)
+ // relative values accumulate
+ if (resultclass != ITEM_CLASS_ABSOLUTE)
{
- if (lastcode == not_code)
- return false;
+ result += value;
+ resultclass = ITEM_CLASS_RELATIVE;
}
-
- // anything else
- else
- {
- // count positive codes
- if (lastcode != not_code)
- positive_code_count++;
-
- // non-switch items can't have a NOT
- input_item_class itemclass = code.item_class();
- if (itemclass != ITEM_CLASS_SWITCH && lastcode == not_code)
- return false;
-
- // absolute/relative items must all be the same class
- if ((lastclass == ITEM_CLASS_ABSOLUTE && itemclass != ITEM_CLASS_ABSOLUTE) ||
- (lastclass == ITEM_CLASS_RELATIVE && itemclass != ITEM_CLASS_RELATIVE))
- return false;
- }
-
- // remember the last code
- lastcode = code;
}
-
- // if we got here, we were missing an END token; fail
- return false;
-}
-
-
-//-------------------------------------------------
-// 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()
-{
- // if we have at least one entry, remove it
- int curlength = length();
- if (curlength > 0)
- m_code[curlength - 1] = end_code;
}
-
-//-------------------------------------------------
-// replace - replace all instances of oldcode
-// with newcode in a sequence
-//-------------------------------------------------
-
-void input_seq::replace(input_code oldcode, input_code newcode)
-{
- for (auto & elem : m_code)
- if (elem == oldcode)
- elem = newcode;
-}
+} // anonymous namespace
@@ -556,10 +408,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();
@@ -590,72 +439,89 @@ input_manager::~input_manager()
//-------------------------------------------------
+// class_enabled - return whether input device
+// class is enabled
+//-------------------------------------------------
+
+bool input_manager::class_enabled(input_device_class devclass) const
+{
+ assert(devclass >= DEVICE_CLASS_FIRST_VALID && devclass <= DEVICE_CLASS_LAST_VALID);
+ return m_class[devclass]->enabled();
+}
+
+
+//-------------------------------------------------
+// add_device - add a representation of a host
+// input device
+//-------------------------------------------------
+
+osd::input_device &input_manager::add_device(input_device_class devclass, std::string_view name, std::string_view id, void *internal)
+{
+ return device_class(devclass).add_device(name, id, internal);
+}
+
+
+//-------------------------------------------------
// code_value - return the value of a given
// input code
//-------------------------------------------------
s32 input_manager::code_value(input_code code)
{
- g_profiler.start(PROFILER_INPUT);
- s32 result = 0;
-
- // dummy loop to allow clean early exits
- do
+ auto profile = g_profiler.start(PROFILER_INPUT);
+
+ // return 0 for any invalid devices
+ input_device *const device = device_from_code(code);
+ if (!device)
+ return 0;
+
+ // also return 0 if the device class is disabled
+ input_class &devclass = *m_class[code.device_class()];
+ if (!devclass.enabled())
+ return 0;
+
+ // if this is not a multi device, only return data for item 0 and iterate over all
+ int startindex = code.device_index();
+ int stopindex = startindex;
+ if (!devclass.multi())
{
- // return 0 for any invalid devices
- input_device *device = device_from_code(code);
- if (device == nullptr)
- break;
-
- // also return 0 if the device class is disabled
- input_class &devclass = *m_class[code.device_class()];
- if (!devclass.enabled())
- break;
-
- // if this is not a multi device, only return data for item 0 and iterate over all
- int startindex = code.device_index();
- int stopindex = startindex;
- if (!devclass.multi())
- {
- if (startindex != 0)
- break;
- stopindex = devclass.maxindex();
- }
+ if (startindex != 0)
+ return 0;
+ stopindex = devclass.maxindex();
+ }
- // iterate over all device indices
- input_item_class targetclass = code.item_class();
- for (int curindex = startindex; curindex <= stopindex; curindex++)
+ // iterate over all device indices
+ s32 result = 0;
+ input_item_class targetclass = code.item_class();
+ for (int curindex = startindex; curindex <= stopindex; curindex++)
+ {
+ // lookup the item for the appropriate index
+ code.set_device_index(curindex);
+ input_device_item *const item = item_from_code(code);
+ if (item)
{
- // lookup the item for the appropriate index
- code.set_device_index(curindex);
- input_device_item *item = item_from_code(code);
- if (item == nullptr)
- continue;
-
// process items according to their native type
switch (targetclass)
{
- case ITEM_CLASS_ABSOLUTE:
- if (result == 0)
- result = item->read_as_absolute(code.item_modifier());
- break;
+ case ITEM_CLASS_ABSOLUTE:
+ if (result == 0)
+ result = item->read_as_absolute(code.item_modifier());
+ break;
- case ITEM_CLASS_RELATIVE:
- result += item->read_as_relative(code.item_modifier());
- break;
+ case ITEM_CLASS_RELATIVE:
+ result += item->read_as_relative(code.item_modifier());
+ break;
- case ITEM_CLASS_SWITCH:
- result |= item->read_as_switch(code.item_modifier());
- break;
+ case ITEM_CLASS_SWITCH:
+ result |= item->read_as_switch(code.item_modifier());
+ break;
- default:
- break;
+ default:
+ break;
}
}
- } while (0);
+ }
- // stop the profiler before exiting
- g_profiler.stop();
return result;
}
@@ -671,13 +537,13 @@ bool input_manager::code_pressed_once(input_code code)
// look for the code in the memory
bool curvalue = code_pressed(code);
int empty = -1;
- for (int memnum = 0; memnum < ARRAY_LENGTH(m_switch_memory); memnum++)
+ for (int memnum = 0; memnum < std::size(m_switch_memory); memnum++)
{
// were we previous pressed on the last time through here?
if (m_switch_memory[memnum] == code)
{
// if no longer pressed, clear entry
- if (curvalue == false)
+ if (!curvalue)
m_switch_memory[memnum] = INPUT_CODE_INVALID;
// always return false
@@ -689,11 +555,11 @@ bool input_manager::code_pressed_once(input_code code)
empty = memnum;
}
- // if we get here, we were not previously pressed; if still not pressed, return 0
- if (curvalue == false)
+ // if we get here, we were not previously pressed; if still not pressed, return false
+ if (!curvalue)
return false;
- // otherwise, add ourself to the memory and return 1
+ // otherwise, add the code to the memory and return true
assert(empty != -1);
if (empty != -1)
m_switch_memory[empty] = code;
@@ -702,225 +568,6 @@ bool input_manager::code_pressed_once(input_code code)
//-------------------------------------------------
-// reset_polling - reset memories in preparation
-// for polling
-//-------------------------------------------------
-
-void input_manager::reset_polling()
-{
- // reset switch memory
- reset_memory();
-
- // iterate over device classes and devices
- for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass)
- for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
- {
- // fetch the device; ignore if nullptr
- input_device *device = m_class[devclass]->device(devnum);
- if (device == nullptr)
- continue;
-
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
- {
- // for any non-switch items, set memory equal to the current value
- input_device_item *item = device->item(itemid);
- if (item != nullptr && item->itemclass() != ITEM_CLASS_SWITCH)
- item->set_memory(code_value(item->code()));
- }
- }
-}
-
-
-//-------------------------------------------------
-// poll_switches - poll for any input
-//-------------------------------------------------
-
-input_code input_manager::poll_switches()
-{
- // iterate over device classes and devices
- for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass)
- for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
- {
- // fetch the device; ignore if nullptr
- input_device *device = m_class[devclass]->device(devnum);
- if (device == nullptr)
- continue;
-
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
- {
- input_device_item *item = device->item(itemid);
- if (item != nullptr)
- {
- input_code code = item->code();
-
- // if the item is natively a switch, poll it
- if (item->itemclass() == ITEM_CLASS_SWITCH)
- {
- if (code_pressed_once(code))
- return code;
- else
- continue;
- }
-
- // skip if there is not enough axis movement
- if (!code_check_axis(*item, code))
- continue;
-
- // otherwise, poll axes digitally
- code.set_item_class(ITEM_CLASS_SWITCH);
-
- // if this is a joystick X axis, check with left/right modifiers
- if (devclass == DEVICE_CLASS_JOYSTICK && code.item_id() == ITEM_ID_XAXIS)
- {
- code.set_item_modifier(ITEM_MODIFIER_LEFT);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_RIGHT);
- if (code_pressed_once(code))
- return code;
- }
-
- // if this is a joystick Y axis, check with up/down modifiers
- else if (devclass == DEVICE_CLASS_JOYSTICK && code.item_id() == ITEM_ID_YAXIS)
- {
- code.set_item_modifier(ITEM_MODIFIER_UP);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_DOWN);
- if (code_pressed_once(code))
- return code;
- }
-
- // any other axis, check with pos/neg modifiers
- else
- {
- code.set_item_modifier(ITEM_MODIFIER_POS);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_NEG);
- if (code_pressed_once(code))
- return code;
- }
- }
- }
- }
-
- // if nothing, return an invalid code
- return INPUT_CODE_INVALID;
-}
-
-
-//-------------------------------------------------
-// poll_keyboard_switches - poll for any
-// keyboard-specific input
-//-------------------------------------------------
-
-input_code input_manager::poll_keyboard_switches()
-{
- // iterate over devices within each class
- input_class &keyboard_class = device_class(DEVICE_CLASS_KEYBOARD);
- for (int devnum = 0; devnum < keyboard_class.maxindex(); devnum++)
- {
- // fetch the device; ignore if nullptr
- input_device *device = keyboard_class.device(devnum);
- if (device == nullptr)
- continue;
-
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
- {
- input_device_item *item = device->item(itemid);
- if (item != nullptr && item->itemclass() == ITEM_CLASS_SWITCH)
- {
- input_code code = item->code();
- if (code_pressed_once(code))
- return code;
- }
- }
- }
-
- // if nothing, return an invalid code
- return INPUT_CODE_INVALID;
-}
-
-
-//-------------------------------------------------
-// code_check_axis - see if axis has moved far
-// enough to trigger a read when polling
-//-------------------------------------------------
-
-bool input_manager::code_check_axis(input_device_item &item, input_code code)
-{
- // if we've already reported this one, don't bother
- if (item.memory() == INVALID_AXIS_VALUE)
- return false;
-
- // ignore min/max for lightguns
- // so the selection will not be affected by a gun going out of range
- s32 curval = code_value(code);
- if (code.device_class() == DEVICE_CLASS_LIGHTGUN &&
- (code.item_id() == ITEM_ID_XAXIS || code.item_id() == ITEM_ID_YAXIS) &&
- (curval == INPUT_ABSOLUTE_MAX || curval == INPUT_ABSOLUTE_MIN))
- return false;
-
- // compute the diff against memory
- s32 diff = curval - item.memory();
- if (diff < 0)
- diff = -diff;
-
- // for absolute axes, look for 25% of maximum
- if (item.itemclass() == ITEM_CLASS_ABSOLUTE && diff > (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4)
- {
- item.set_memory(INVALID_AXIS_VALUE);
- return true;
- }
-
- // for relative axes, look for ~20 pixels movement
- if (item.itemclass() == ITEM_CLASS_RELATIVE && diff > 20 * INPUT_RELATIVE_PER_PIXEL)
- {
- item.set_memory(INVALID_AXIS_VALUE);
- return true;
- }
- return false;
-}
-
-
-//-------------------------------------------------
-// poll_axes - poll for any input
-//-------------------------------------------------
-
-input_code input_manager::poll_axes()
-{
- // iterate over device classes and devices
- for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass)
- for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++)
- {
- // fetch the device; ignore if nullptr
- input_device *device = m_class[devclass]->device(devnum);
- if (device == nullptr)
- continue;
-
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
- {
- input_device_item *item = device->item(itemid);
- if (item != nullptr && item->itemclass() != ITEM_CLASS_SWITCH)
- {
- input_code code = item->code();
- if (code_check_axis(*item, code))
- return code;
- }
- }
- }
-
- // if nothing, return an invalid code
- return INPUT_CODE_INVALID;
-}
-
-
-//-------------------------------------------------
// device_from_code - given an input_code return
// a pointer to the associated device
//-------------------------------------------------
@@ -999,50 +646,44 @@ input_code input_manager::code_from_itemid(input_item_id itemid) const
std::string input_manager::code_name(input_code code) const
{
// if nothing there, return an empty string
- input_device_item *item = item_from_code(code);
- if (item == nullptr)
+ input_device_item const *const item = item_from_code(code);
+ if (!item)
return std::string();
- // determine the devclass part
- const char *devclass = (*devclass_string_table)[code.device_class()];
-
- // determine the devindex part
- std::string devindex = string_format("%d", code.device_index() + 1);
-
- // if we're unifying all devices, don't display a number
- if (!m_class[code.device_class()]->multi())
- devindex.clear();
+ std::string str;
// keyboard 0 doesn't show a class or index if it is the only one
- input_device_class device_class = item->device().devclass();
- if (device_class == DEVICE_CLASS_KEYBOARD && m_class[device_class]->maxindex() == 0)
+ input_device_class const device_class = item->device().devclass();
+ if ((device_class != DEVICE_CLASS_KEYBOARD) || (m_class[device_class]->maxindex() > 0))
{
- devclass = "";
- devindex.clear();
- }
-
- // devcode part comes from the item name
- const char *devcode = item->name();
+ // determine the devclass part
+ str = (*devclass_string_table)[code.device_class()];
- // determine the modifier part
- const char *modifier = (*modifier_string_table)[code.item_modifier()];
-
- // devcode is redundant with joystick switch left/right/up/down
- if (device_class == DEVICE_CLASS_JOYSTICK && code.item_class() == ITEM_CLASS_SWITCH)
- if (code.item_modifier() >= ITEM_MODIFIER_LEFT && code.item_modifier() <= ITEM_MODIFIER_DOWN)
- devcode = "";
+ // if we're unifying all devices, don't display a number
+ if (m_class[code.device_class()]->multi())
+ str.append(util::string_format(" %d ", code.device_index() + 1));
+ else
+ str.append(" ");
+ }
- // concatenate the strings
- std::string str(devclass);
- if (!devindex.empty())
- str.append(" ").append(devindex);
- if (devcode[0] != 0)
- str.append(" ").append(devcode);
- if (modifier != nullptr)
- str.append(" ").append(modifier);
+ // append item name - redundant with joystick switch left/right/up/down
+ bool const joydir =
+ (device_class == DEVICE_CLASS_JOYSTICK) &&
+ (code.item_class() == ITEM_CLASS_SWITCH) &&
+ (code.item_modifier() >= ITEM_MODIFIER_LEFT) &&
+ (code.item_modifier() <= ITEM_MODIFIER_DOWN);
+ if (joydir)
+ {
+ str.append((*modifier_string_table)[code.item_modifier()]);
+ }
+ else
+ {
+ str.append(item->name());
+ char const *const modifier = (*modifier_string_table)[code.item_modifier()];
+ if (modifier && *modifier)
+ str.append(" ").append(modifier);
+ }
- // delete any leading spaces
- strtrimspace(str);
return str;
}
@@ -1053,8 +694,12 @@ std::string input_manager::code_name(input_code code) const
std::string input_manager::code_to_token(input_code code) const
{
+ using namespace std::literals;
+
// determine the devclass part
const char *devclass = (*devclass_token_table)[code.device_class()];
+ if (!devclass)
+ return "INVALID";
// determine the devindex part; keyboard 0 doesn't show an index
std::string devindex = string_format("%d", code.device_index() + 1);
@@ -1063,25 +708,25 @@ std::string input_manager::code_to_token(input_code code) const
// determine the itemid part; look up in the table if we don't have a token
input_device_item *item = item_from_code(code);
- const char *devcode = (item != nullptr) ? item->token() : "UNKNOWN";
+ std::string_view devcode = item ? item->token() : "UNKNOWN"sv;
// determine the modifier part
const char *modifier = (*modifier_token_table)[code.item_modifier()];
// determine the itemclass part; if we match the native class, we don't include this
const char *itemclass = "";
- if (item == nullptr || item->itemclass() != code.item_class())
+ if (!item || (item->itemclass() != code.item_class()))
itemclass = (*itemclass_token_table)[code.item_class()];
// concatenate the strings
std::string str(devclass);
if (!devindex.empty())
str.append("_").append(devindex);
- if (devcode[0] != 0)
+ if (!devcode.empty())
str.append("_").append(devcode);
if (modifier != nullptr)
str.append("_").append(modifier);
- if (itemclass[0] != 0)
+ if (itemclass != nullptr && itemclass[0] != 0)
str.append("_").append(itemclass);
return str;
}
@@ -1092,27 +737,27 @@ std::string input_manager::code_to_token(input_code code) const
// token
//-------------------------------------------------
-input_code input_manager::code_from_token(const char *_token)
+input_code input_manager::code_from_token(std::string_view _token)
{
// copy the token and break it into pieces
std::string token[6];
- int numtokens;
- for (numtokens = 0; numtokens < ARRAY_LENGTH(token); )
+ int numtokens = 0;
+ while (numtokens < std::size(token))
{
// make a token up to the next underscore
- char *score = (char *)strchr(_token, '_');
- token[numtokens++].assign(_token, (score == nullptr) ? strlen(_token) : (score - _token));
+ std::string_view::size_type score = _token.find('_');
+ token[numtokens++].assign(_token, 0, (std::string_view::npos == score) ? _token.length() : score);
// if we hit the end, we're done, else advance our pointer
- if (score == nullptr)
+ if (std::string_view::npos == score)
break;
- _token = score + 1;
+ _token.remove_prefix(score + 1);
}
// first token should be the devclass
int curtok = 0;
- input_device_class devclass = input_device_class((*devclass_token_table)[token[curtok++].c_str()]);
- if (devclass == ~input_device_class(0))
+ input_device_class const devclass = input_device_class((*devclass_token_table)[token[curtok++]]);
+ if (devclass == input_device_class(code_string_table::SENTINEL))
return INPUT_CODE_INVALID;
// second token might be index; look for number
@@ -1126,27 +771,29 @@ input_code input_manager::code_from_token(const char *_token)
return INPUT_CODE_INVALID;
// next token is the item ID
- input_item_id itemid = input_item_id((*itemid_token_table)[token[curtok].c_str()]);
- bool standard = (itemid != ~input_item_id(0));
+ input_item_id itemid = input_item_id((*itemid_token_table)[token[curtok]]);
+ bool const standard = (itemid != input_item_id(code_string_table::SENTINEL));
- // if we're a standard code, default the itemclass based on it
input_item_class itemclass = ITEM_CLASS_INVALID;
if (standard)
+ {
+ // if we're a standard code, default the itemclass based on it
itemclass = m_class[devclass]->standard_item_class(itemid);
-
- // otherwise, keep parsing
+ }
else
{
+ // otherwise, keep parsing
+
// if this is an invalid device, we have nothing to look up
input_device *device = m_class[devclass]->device(devindex);
- if (device == nullptr)
+ if (!device)
return INPUT_CODE_INVALID;
// if not a standard code, look it up in the device specific codes
for (itemid = ITEM_ID_FIRST_VALID; itemid <= device->maxitem(); ++itemid)
{
input_device_item *item = device->item(itemid);
- if (item != nullptr && token[curtok].compare(item->token()) == 0)
+ if (item && !token[curtok].compare(item->token()))
{
// take the itemclass from the item
itemclass = item->itemclass();
@@ -1164,8 +811,8 @@ input_code input_manager::code_from_token(const char *_token)
input_item_modifier modifier = ITEM_MODIFIER_NONE;
if (curtok < numtokens)
{
- modifier = input_item_modifier((*modifier_token_table)[token[curtok].c_str()]);
- if (modifier != ~input_item_modifier(0))
+ modifier = input_item_modifier((*modifier_token_table)[token[curtok]]);
+ if (modifier != input_item_modifier(code_string_table::SENTINEL))
curtok++;
else
modifier = ITEM_MODIFIER_NONE;
@@ -1174,8 +821,8 @@ input_code input_manager::code_from_token(const char *_token)
// if we have another token, it is the item class
if (curtok < numtokens)
{
- u32 temp = (*itemclass_token_table)[token[curtok].c_str()];
- if (temp != ~0)
+ u32 const temp = (*itemclass_token_table)[token[curtok]];
+ if (temp != code_string_table::SENTINEL)
{
curtok++;
itemclass = input_item_class(temp);
@@ -1198,7 +845,7 @@ input_code input_manager::code_from_token(const char *_token)
const char *input_manager::standard_token(input_item_id itemid) const
{
- return itemid <= ITEM_ID_MAXIMUM ? (*itemid_token_table)[itemid] : nullptr;
+ return (itemid <= ITEM_ID_MAXIMUM) ? (*itemid_token_table)[itemid] : nullptr;
}
@@ -1215,14 +862,16 @@ bool input_manager::seq_pressed(const input_seq &seq)
bool first = true;
for (int codenum = 0; ; codenum++)
{
- // handle NOT
input_code code = seq[codenum];
if (code == input_seq::not_code)
+ {
+ // handle NOT
invert = true;
-
- // handle OR and END
+ }
else if (code == input_seq::or_code || code == input_seq::end_code)
{
+ // handle OR and END
+
// if we have a positive result from the previous set, we're done
if (result || code == input_seq::end_code)
break;
@@ -1232,10 +881,10 @@ bool input_manager::seq_pressed(const input_seq &seq)
invert = false;
first = true;
}
-
- // handle everything else as a series of ANDs
else
{
+ // handle everything else as a series of ANDs
+
// if this is the first in the sequence, result is set equal
if (first)
result = code_pressed(code) ^ invert;
@@ -1261,233 +910,117 @@ 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++)
{
- // handle NOT
- input_code code = seq[codenum];
+ input_code const code = seq[codenum];
if (code == input_seq::not_code)
+ {
+ // handle NOT - invert the next code
invert = true;
-
- // handle OR and END
- else if (code == input_seq::or_code || code == input_seq::end_code)
+ }
+ else if (code == input_seq::end_code)
{
- // if we have a positive result from the previous set, we're done
- if (itemclass != ITEM_CLASS_INVALID || code == input_seq::end_code)
- break;
-
- // otherwise, reset our state
- result = 0;
+ // 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 - 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;
}
-
- // handle everything else only if we're still enabled
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;
+ {
+ enable = code_pressed(code) ^ invert;
+ 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;
+ }
+ }
}
-
- // non-switch codes are analog values
else
{
- 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();
- }
-
- // non-zero absolute values stick
- else if (code.item_class() == ITEM_CLASS_ABSOLUTE)
- {
- itemclass = ITEM_CLASS_ABSOLUTE;
- result = value;
- }
-
- // non-zero relative values accumulate
- else if (code.item_class() == ITEM_CLASS_RELATIVE)
- {
- itemclass = ITEM_CLASS_RELATIVE;
- result += value;
- }
+ // non-switch codes are analog values
+ 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;
}
}
- // if the caller wants to know the type, provide it
- if (result == 0)
+ // saturate mixed absolute values, report neutral type
+ if (ITEM_CLASS_ABSOLUTE == itemclass)
+ result = std::clamp(result, osd::input_device::ABSOLUTE_MIN, osd::input_device::ABSOLUTE_MAX);
+ else if (ITEM_CLASS_INVALID == itemclass)
itemclass = itemclasszero;
return result;
}
//-------------------------------------------------
-// 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()
-{
- int curlen = m_poll_seq.length();
- input_code lastcode = m_poll_seq[curlen - 1];
-
- // switch case: see if we have a new code to process
- input_code newcode;
- if (m_poll_seq_class == ITEM_CLASS_SWITCH)
- {
- 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;
- }
- }
- }
-
- // absolute/relative case: see if we have an analog change of sufficient amount
- else
- {
- 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
//-------------------------------------------------
input_seq input_manager::seq_clean(const input_seq &seq) const
{
+ // make a copy of our sequence, removing any invalid bits
+ input_seq clean_codes;
int clean_index = 0;
for (int codenum = 0; seq[codenum] != input_seq::end_code; codenum++)
{
// if this is a code item which is not valid, don't copy it and remove any preceding ORs/NOTs
input_code code = seq[codenum];
- if (!code.internal() && code_name(code).empty())
+ if (!code.internal() && (((code.device_index() > 0) && !m_class[code.device_class()]->multi()) || !item_from_code(code)))
{
- while (clean_index > 0 && seq[clean_index - 1].internal())
+ while (clean_index > 0 && clean_codes[clean_index - 1].internal())
+ {
+ clean_codes.backspace();
clean_index--;
+ }
}
- else if (clean_index > 0 || !code.internal())
+ else if (clean_index > 0 || !code.internal() || code == input_seq::not_code)
+ {
+ clean_codes += code;
clean_index++;
+ }
}
-
- input_seq cleaned_seq;
- for (int i = 0; i < clean_index; i++)
- cleaned_seq += seq[i];
- return cleaned_seq;
+ return clean_codes;
}
@@ -1503,7 +1036,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;
@@ -1569,53 +1102,52 @@ std::string input_manager::seq_to_tokens(const input_seq &seq) const
// of a sequence
//-------------------------------------------------
-void input_manager::seq_from_tokens(input_seq &seq, const char *string)
+void input_manager::seq_from_tokens(input_seq &seq, std::string_view string)
{
// start with a blank sequence
seq.reset();
// loop until we're done
- std::vector<char> strcopy(string, string + std::strlen(string) + 1);
- char *str = &strcopy[0];
unsigned operators = 0;
while (1)
{
// trim any leading spaces
- while (*str != 0 && isspace(u8(*str)))
- str++;
+ while (!string.empty() && isspace(u8(string[0])))
+ string.remove_prefix(1);
// bail if we're done
- if (*str == 0)
+ if (string.empty())
return;
// find the end of the token and make it upper-case along the way
- char *strtemp;
- for (strtemp = str; *strtemp != 0 && !isspace(u8(*strtemp)); strtemp++)
- *strtemp = toupper(u8(*strtemp));
- char origspace = *strtemp;
- *strtemp = 0;
+ std::string token;
+ while (!string.empty() && !isspace(u8(string[0])))
+ {
+ token.push_back(toupper(u8(string[0])));
+ string.remove_prefix(1);
+ }
// look for common stuff
input_code code;
bool is_operator;
- if (strcmp(str, "OR") == 0)
+ if (token == "OR")
{
code = input_seq::or_code;
is_operator = true;
}
- else if (strcmp(str, "NOT") == 0)
+ else if (token == "NOT")
{
code = input_seq::not_code;
is_operator = true;
}
- else if (strcmp(str, "DEFAULT") == 0)
+ else if (token == "DEFAULT")
{
code = input_seq::default_code;
is_operator = false;
}
else
{
- code = code_from_token(str);
+ code = code_from_token(token);
is_operator = false;
}
@@ -1629,7 +1161,7 @@ void input_manager::seq_from_tokens(input_seq &seq, const char *string)
{
if (code.device_class() < DEVICE_CLASS_FIRST_VALID)
{
- osd_printf_warning("Input: Dropping invalid input token %s\n", str);
+ osd_printf_warning("Input: Dropping invalid input token %s\n", token);
while (operators)
{
seq.backspace();
@@ -1644,9 +1176,9 @@ void input_manager::seq_from_tokens(input_seq &seq, const char *string)
}
// advance
- if (origspace == 0)
+ if (string.empty())
return;
- str = strtemp + 1;
+ string.remove_prefix(1);
}
}
@@ -1655,37 +1187,34 @@ void input_manager::seq_from_tokens(input_seq &seq, const char *string)
// controller based on device map table
//-------------------------------------------------
-bool input_manager::map_device_to_controller(const devicemap_table_type *devicemap_table)
+bool input_manager::map_device_to_controller(const devicemap_table &table)
{
- if (nullptr == devicemap_table)
- return true;
-
- for (devicemap_table_type::const_iterator it = devicemap_table->begin(); it != devicemap_table->end(); it++)
+ for (const auto &it : table)
{
- const char *deviceid = it->first.c_str();
- const char *controllername = it->second.c_str();
+ std::string_view deviceid = it.first;
+ std::string_view controllername = it.second;
// tokenize the controller name into device class and index (i.e. controller name should be of the form "GUNCODE_1")
std::string token[2];
- int numtokens;
- const char *_token = controllername;
- for (numtokens = 0; numtokens < ARRAY_LENGTH(token); )
+ int numtokens = 0;
+ std::string_view _token = controllername;
+ while (numtokens < std::size(token))
{
// make a token up to the next underscore
- char *score = (char *)strchr(_token, '_');
- token[numtokens++].assign(_token, (score == nullptr) ? strlen(_token) : (score - _token));
+ std::string_view::size_type score = _token.find('_');
+ token[numtokens++].assign(_token, 0, (std::string_view::npos == score) ? _token.length() : score);
// if we hit the end, we're done, else advance our pointer
- if (score == nullptr)
+ if (std::string_view::npos == score)
break;
- _token = score + 1;
+ _token.remove_prefix(score + 1);
}
if (2 != numtokens)
return false;
// first token should be the devclass
- input_device_class devclass = input_device_class((*devclass_token_table)[strmakeupper(token[0]).c_str()]);
- if (devclass == ~input_device_class(0))
+ input_device_class const devclass = input_device_class((*devclass_token_table)[strmakeupper(token[0])]);
+ if (devclass == input_device_class(code_string_table::SENTINEL))
return false;
// second token should be the devindex
@@ -1702,11 +1231,11 @@ bool input_manager::map_device_to_controller(const devicemap_table_type *devicem
for (int devnum = 0; devnum <= input_devclass->maxindex(); devnum++)
{
input_device *device = input_devclass->device(devnum);
- if (device != nullptr && device->match_device_id(deviceid))
+ if (device && device->match_device_id(deviceid))
{
// remap devindex
input_devclass->remap_device_index(device->devindex(), devindex);
- osd_printf_verbose("Input: Remapped %s #%d: %s (device id: %s)\n", input_devclass->name(), devindex, device->name(), device->id());
+ osd_printf_verbose("Input: Remapped %s #%d: %s (device id: %s)\n", input_devclass->name(), devindex + 1, device->name(), device->id());
break;
}