diff options
Diffstat (limited to 'src/emu/input.cpp')
-rw-r--r-- | src/emu/input.cpp | 921 |
1 files changed, 48 insertions, 873 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp index 2abcfd9dac7..91ff3350750 100644 --- a/src/emu/input.cpp +++ b/src/emu/input.cpp @@ -18,7 +18,7 @@ ***************************************************************************/ #include "emu.h" -#include "emuopts.h" +#include "inputdev.h" @@ -44,63 +44,6 @@ const input_seq input_seq::empty_seq; // TYPE DEFINITIONS //************************************************************************** -// ======================> input_device_switch_item - -// derived input item representing a switch input -class input_device_switch_item : public input_device_item -{ -public: - // construction/destruction - input_device_switch_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate); - - // readers - virtual int32_t read_as_switch(input_item_modifier modifier) override; - virtual int32_t read_as_relative(input_item_modifier modifier) override; - virtual int32_t read_as_absolute(input_item_modifier modifier) override; - - // steadykey helper - bool steadykey_changed(); - void steadykey_update_to_current() { m_steadykey = m_current; } - -private: - // internal state - int32_t m_steadykey; // the live steadykey state - int32_t m_oldkey; // old live state -}; - - -// ======================> input_device_switch_item - -// derived input item representing a relative axis input -class input_device_relative_item : public input_device_item -{ -public: - // construction/destruction - input_device_relative_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate); - - // readers - virtual int32_t read_as_switch(input_item_modifier modifier) override; - virtual int32_t read_as_relative(input_item_modifier modifier) override; - virtual int32_t read_as_absolute(input_item_modifier modifier) override; -}; - - -// ======================> input_device_switch_item - -// derived input item representing an absolute axis input -class input_device_absolute_item : public input_device_item -{ -public: - // construction/destruction - input_device_absolute_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate); - - // readers - virtual int32_t read_as_switch(input_item_modifier modifier) override; - virtual int32_t read_as_relative(input_item_modifier modifier) override; - virtual int32_t read_as_absolute(input_item_modifier modifier) override; -}; - - // ======================> code_string_table // simple class to match codes to strings @@ -426,191 +369,6 @@ static const code_string_table itemid_token_table[] = //************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - -// standard joystick mappings -const char joystick_map_8way[] = "7778...4445"; -const char joystick_map_4way_diagonal[] = "4444s8888..444458888.444555888.ss5.222555666.222256666.2222s6666.2222s6666"; -// const char joystick_map_4way_sticky[] = "s8.4s8.44s8.4445"; - - -//************************************************************************** -// JOYSTICK MAP -//************************************************************************** - -//------------------------------------------------- -// joystick_map - constructor -//------------------------------------------------- - -joystick_map::joystick_map() - : m_lastmap(JOYSTICK_MAP_NEUTRAL) -{ - // parse the standard 8-way map as default - parse(joystick_map_8way); -} - - -//------------------------------------------------- -// parse - parse a string into a joystick map -//------------------------------------------------- - -bool joystick_map::parse(const char *mapstring) -{ - // save a copy of the original string - m_origstring = mapstring; - - // iterate over rows - for (int rownum = 0; rownum < 9; rownum++) - { - // if we're done, copy from another row - if (*mapstring == 0 || *mapstring == '.') - { - bool symmetric = (rownum >= 5 && *mapstring == 0); - const uint8_t *srcrow = &m_map[symmetric ? (8 - rownum) : (rownum - 1)][0]; - - // if this is row 0, we don't have a source row -- invalid - if (rownum == 0) - return false; - - // copy from the srcrow, applying up/down symmetry if in the bottom half - for (int colnum = 0; colnum < 9; colnum++) - { - uint8_t val = srcrow[colnum]; - if (symmetric) - val = (val & (JOYSTICK_MAP_LEFT | JOYSTICK_MAP_RIGHT)) | ((val & JOYSTICK_MAP_UP) << 1) | ((val & JOYSTICK_MAP_DOWN) >> 1); - m_map[rownum][colnum] = val; - } - } - - // otherwise, parse this column - else - { - for (int colnum = 0; colnum < 9; colnum++) - { - // if we're at the end of row, copy previous to the middle, then apply left/right symmetry - if (colnum > 0 && (*mapstring == 0 || *mapstring == '.')) - { - bool symmetric = (colnum >= 5); - uint8_t val = m_map[rownum][symmetric ? (8 - colnum) : (colnum - 1)]; - if (symmetric) - val = (val & (JOYSTICK_MAP_UP | JOYSTICK_MAP_DOWN)) | ((val & JOYSTICK_MAP_LEFT) << 1) | ((val & JOYSTICK_MAP_RIGHT) >> 1); - m_map[rownum][colnum] = val; - } - - // otherwise, convert the character to its value - else - { - static const uint8_t charmap[] = - { - JOYSTICK_MAP_UP | JOYSTICK_MAP_LEFT, - JOYSTICK_MAP_UP, - JOYSTICK_MAP_UP | JOYSTICK_MAP_RIGHT, - JOYSTICK_MAP_LEFT, - JOYSTICK_MAP_NEUTRAL, - JOYSTICK_MAP_RIGHT, - JOYSTICK_MAP_DOWN | JOYSTICK_MAP_LEFT, - JOYSTICK_MAP_DOWN, - JOYSTICK_MAP_DOWN | JOYSTICK_MAP_RIGHT, - JOYSTICK_MAP_STICKY - }; - static const char validchars[] = "789456123s"; - const char *ptr = strchr(validchars, *mapstring++); - - // invalid characters exit immediately - if (ptr == nullptr) - return false; - m_map[rownum][colnum] = charmap[ptr - validchars]; - } - } - } - - // if we ended with a period, advance to the next row - if (*mapstring == '.') - mapstring++; - } - return true; -} - - -//------------------------------------------------- -// to_string - output the map as a string for -// friendly display -//------------------------------------------------- - -std::string joystick_map::to_string() const -{ - std::string str(m_origstring); - str.append("\n"); - for (auto & elem : m_map) - { - str.append(" "); - for (auto & elem_colnum : elem) - switch (elem_colnum) - { - case JOYSTICK_MAP_UP | JOYSTICK_MAP_LEFT: str.append("7"); break; - case JOYSTICK_MAP_UP: str.append("8"); break; - case JOYSTICK_MAP_UP | JOYSTICK_MAP_RIGHT: str.append("9"); break; - case JOYSTICK_MAP_LEFT: str.append("4"); break; - case JOYSTICK_MAP_NEUTRAL: str.append("5"); break; - case JOYSTICK_MAP_RIGHT: str.append("6"); break; - case JOYSTICK_MAP_DOWN | JOYSTICK_MAP_LEFT: str.append("1"); break; - case JOYSTICK_MAP_DOWN: str.append("2"); break; - case JOYSTICK_MAP_DOWN | JOYSTICK_MAP_RIGHT:str.append("3"); break; - case JOYSTICK_MAP_STICKY: str.append("s"); break; - default: str.append("?"); break; - } - - str.append("\n"); - } - return str; -} - - -//------------------------------------------------- -// update - update the state of the joystick -// map based on the given X/Y axis values -//------------------------------------------------- - -uint8_t joystick_map::update(int32_t xaxisval, int32_t yaxisval) -{ - // now map the X and Y axes to a 9x9 grid using the raw values - xaxisval = ((xaxisval - INPUT_ABSOLUTE_MIN) * 9) / (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN + 1); - yaxisval = ((yaxisval - INPUT_ABSOLUTE_MIN) * 9) / (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN + 1); - uint8_t mapval = m_map[yaxisval][xaxisval]; - - // handle stickiness - if (mapval == JOYSTICK_MAP_STICKY) - mapval = m_lastmap; - else - m_lastmap = mapval; - - // return based on whether the appropriate bit is set - return mapval; -} - - - -//************************************************************************** -// INPUT CODE -//************************************************************************** - -//------------------------------------------------- -// input_code - construct an input code from a -// device/item pair -//------------------------------------------------- - -input_code::input_code(input_device &device, input_item_id itemid) -{ - assert(itemid < ITEM_ID_ABSOLUTE_MAXIMUM); - input_device_item *item = device.item(itemid); - assert(item != nullptr); - m_internal = ((device.devclass() & 0xf) << 28) | ((device.devindex() & 0xff) << 20) | ((item->itemclass() & 0xf) << 16) | (ITEM_MODIFIER_NONE << 12) | (item->itemid() & 0xfff); -} - - - -//************************************************************************** // INPUT SEQ //************************************************************************** @@ -791,326 +549,43 @@ void input_seq::replace(input_code oldcode, input_code newcode) //************************************************************************** -// INPUT DEVICE +// INPUT MANAGER //************************************************************************** //------------------------------------------------- -// input_device - constructor -//------------------------------------------------- - -input_device::input_device(input_class &_class, int devindex, const char *name, const char *id, void *internal) - : m_class(_class), - m_name(name), - m_id(id), - m_devindex(devindex), - m_maxitem(input_item_id(0)), - m_internal(internal), - m_joystick_deadzone((int32_t)(_class.manager().machine().options().joystick_deadzone() * INPUT_ABSOLUTE_MAX)), - m_joystick_saturation((int32_t)(_class.manager().machine().options().joystick_saturation() * INPUT_ABSOLUTE_MAX)), - m_steadykey_enabled(_class.manager().machine().options().steadykey()), - m_lightgun_reload_button(_class.manager().machine().options().offscreen_reload()) -{ - // additional work for joysticks - if (devclass() == DEVICE_CLASS_JOYSTICK) - { - // get the default joystick map - const char *mapstring = machine().options().joystick_map(); - if (mapstring[0] == 0 || strcmp(mapstring, "auto") == 0) - mapstring = joystick_map_8way; - - // parse it - if (!m_joymap.parse(mapstring)) - { - osd_printf_error("Invalid joystick map: %s\n", mapstring); - m_joymap.parse(joystick_map_8way); - } - else if (mapstring != joystick_map_8way) - osd_printf_verbose("Input: Default joystick map = %s\n", m_joymap.to_string().c_str()); - } -} - - -//------------------------------------------------- -// add_item - add a new item to an input device -//------------------------------------------------- - -input_item_id input_device::add_item(const char *name, input_item_id itemid, item_get_state_func getstate, void *internal) -{ - assert_always(machine().phase() == MACHINE_PHASE_INIT, "Can only call input_device::add_item at init time!"); - assert(name != nullptr); - assert(itemid > ITEM_ID_INVALID && itemid < ITEM_ID_MAXIMUM); - assert(getstate != nullptr); - - // if we have a generic ID, pick a new internal one - input_item_id originalid = itemid; - if (itemid >= ITEM_ID_OTHER_SWITCH && itemid <= ITEM_ID_OTHER_AXIS_RELATIVE) - for (itemid = (input_item_id)(ITEM_ID_MAXIMUM + 1); itemid <= ITEM_ID_ABSOLUTE_MAXIMUM; ++itemid) - if (m_item[itemid] == nullptr) - break; - assert(itemid <= ITEM_ID_ABSOLUTE_MAXIMUM); - - // make sure we don't have any overlap - assert(m_item[itemid] == nullptr); - - // determine the class and create the appropriate item class - switch (m_class.standard_item_class(originalid)) - { - case ITEM_CLASS_SWITCH: - m_item[itemid] = std::make_unique<input_device_switch_item>(*this, name, internal, itemid, getstate); - break; - - case ITEM_CLASS_RELATIVE: - m_item[itemid] = std::make_unique<input_device_relative_item>(*this, name, internal, itemid, getstate); - break; - - case ITEM_CLASS_ABSOLUTE: - m_item[itemid] = std::make_unique<input_device_absolute_item>(*this, name, internal, itemid, getstate); - break; - - default: - m_item[itemid] = nullptr; - assert(false); - } - - // assign the new slot and update the maximum - m_maxitem = std::max(m_maxitem, itemid); - return itemid; -} - - -//------------------------------------------------- -// apply_deadzone_and_saturation - apply global -// deadzone and saturation parameters to an -// absolute value +// input_manager - constructor //------------------------------------------------- -int32_t input_device::apply_deadzone_and_saturation(int32_t result) const +input_manager::input_manager(running_machine &machine) + : m_machine(machine), + m_poll_seq_last_ticks(0), + m_poll_seq_class(ITEM_CLASS_SWITCH) { - // ignore for non-joysticks - if (devclass() != DEVICE_CLASS_JOYSTICK) - return result; - - // properties are symmetric - bool negative = false; - if (result < 0) - { - negative = true; - result = -result; - } - - // if in the deadzone, return 0 - if (result < m_joystick_deadzone) - result = 0; - - // if saturated, return the max - else if (result > m_joystick_saturation) - result = INPUT_ABSOLUTE_MAX; - - // otherwise, scale - else - result = (int64_t)(result - m_joystick_deadzone) * (int64_t)INPUT_ABSOLUTE_MAX / (int64_t)(m_joystick_saturation - m_joystick_deadzone); - - // re-apply sign and return - return negative ? -result : result; -} - - -//------------------------------------------------- -// apply_steadykey - apply steadykey option if -// enabled -//------------------------------------------------- + // reset code memory + reset_memory(); -void input_device::apply_steadykey() const -{ - // ignore if not enabled - if (!m_steadykey_enabled) - return; + // create pointers for the classes + m_class[DEVICE_CLASS_KEYBOARD] = std::make_unique<input_class_keyboard>(*this); + m_class[DEVICE_CLASS_MOUSE] = std::make_unique<input_class_mouse>(*this); + m_class[DEVICE_CLASS_LIGHTGUN] = std::make_unique<input_class_lightgun>(*this); + m_class[DEVICE_CLASS_JOYSTICK] = std::make_unique<input_class_joystick>(*this); - // update the state of all the keys and see if any changed state - bool anything_changed = false; - for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= m_maxitem; ++itemid) +#ifdef MAME_DEBUG + for (input_device_class devclass = DEVICE_CLASS_FIRST_VALID; devclass <= DEVICE_CLASS_LAST_VALID; ++devclass) { - input_device_item *item = m_item[itemid].get(); - if (item != nullptr && item->itemclass() == ITEM_CLASS_SWITCH) - if (downcast<input_device_switch_item *>(item)->steadykey_changed()) - anything_changed = true; + assert(m_class[devclass] != nullptr); + assert(m_class[devclass]->devclass() == devclass); } - - // if the keyboard state is stable, flush the current state - if (!anything_changed) - for (input_item_id itemid = ITEM_ID_FIRST_VALID; itemid <= m_maxitem; ++itemid) - { - input_device_item *item = m_item[itemid].get(); - if (item != nullptr && item->itemclass() == ITEM_CLASS_SWITCH) - downcast<input_device_switch_item *>(item)->steadykey_update_to_current(); - } -} - -//------------------------------------------------- -// match_device_id - match device id via -// substring search -//------------------------------------------------- - -bool input_device::match_device_id(const char *deviceid) -{ - std::string deviceidupper(deviceid); - std::string idupper(m_id); - - strmakeupper(deviceidupper); - strmakeupper(idupper); - - return std::string::npos == idupper.find(deviceidupper) ? false : true; -} - - -//************************************************************************** -// INPUT CLASS -//************************************************************************** - -//------------------------------------------------- -// input_class - constructor -//------------------------------------------------- - -input_class::input_class(input_manager &manager, input_device_class devclass, bool enabled, bool multi) - : m_manager(manager), - m_devclass(devclass), - m_maxindex(0), - m_enabled(enabled), - m_multi(multi) -{ - // request a per-frame callback for the keyboard class - if (devclass == DEVICE_CLASS_KEYBOARD) - machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(input_class::frame_callback), this)); -} - - -//------------------------------------------------- -// add_device - add a new input device -//------------------------------------------------- - -input_device *input_class::add_device(const char *name, const char *id, void *internal) -{ - // find the next empty index - int devindex; - for (devindex = 0; devindex < DEVICE_INDEX_MAXIMUM; devindex++) - if (m_device[devindex] == nullptr) - break; - - // call through - return add_device(devindex, name, id, internal); -} - -input_device *input_class::add_device(int devindex, const char *name, const char *id, void *internal) -{ - assert_always(machine().phase() == MACHINE_PHASE_INIT, "Can only call input_class::add_device at init time!"); - assert(name != nullptr); - assert(id != nullptr); - assert(devindex >= 0 && devindex < DEVICE_INDEX_MAXIMUM); - assert(m_device[devindex] == nullptr); - - // allocate a new device - m_device[devindex] = std::make_unique<input_device>(*this, devindex, name, id, internal); - - // update the maximum index found - m_maxindex = std::max(m_maxindex, devindex); - - if (0 == strlen(id)) - osd_printf_verbose("Input: Adding %s #%d: %s\n", (*devclass_string_table)[m_devclass], devindex, name); - else - osd_printf_verbose("Input: Adding %s #%d: %s (device id: %s)\n", (*devclass_string_table)[m_devclass], devindex, name, id); - - return m_device[devindex].get(); -} - - -//------------------------------------------------- -// standard_item_class - return the class of a -// standard item -//------------------------------------------------- - -input_item_class input_class::standard_item_class(input_item_id itemid) -{ - // most everything standard is a switch, apart from the axes - if (itemid == ITEM_ID_OTHER_SWITCH || itemid < ITEM_ID_XAXIS || (itemid > ITEM_ID_SLIDER2 && itemid < ITEM_ID_ADD_ABSOLUTE1)) - return ITEM_CLASS_SWITCH; - - // standard mouse axes are relative - else if (m_devclass == DEVICE_CLASS_MOUSE || itemid == ITEM_ID_OTHER_AXIS_RELATIVE || (itemid >= ITEM_ID_ADD_RELATIVE1 && itemid <= ITEM_ID_ADD_RELATIVE16)) - return ITEM_CLASS_RELATIVE; - - // all other standard axes are absolute - else - return ITEM_CLASS_ABSOLUTE; -} - - -//------------------------------------------------- -// remap_device_index - remaps device index by -// mapping oldindex to newindex -//------------------------------------------------- - -void input_class::remap_device_index(int oldindex, int newindex) -{ - assert(oldindex >= 0 && oldindex < DEVICE_INDEX_MAXIMUM); - assert(newindex >= 0 && newindex < DEVICE_INDEX_MAXIMUM); - - // swap indexes in m_device array - m_device[oldindex].swap(m_device[newindex]); - - // update device indexes - if (nullptr != m_device[oldindex].get()) - m_device[oldindex]->set_devindex(oldindex); - - if (nullptr != m_device[newindex].get()) - m_device[newindex]->set_devindex(newindex); - - // update the maximum index found, since newindex may - // exceed current m_maxindex - m_maxindex = std::max(m_maxindex, newindex); +#endif } //------------------------------------------------- -// frame_callback - per-frame callback for various -// bookkeeping +// input_manager - destructor //------------------------------------------------- -void input_class::frame_callback() +input_manager::~input_manager() { - // iterate over all devices in our class - for (int devnum = 0; devnum <= m_maxindex; devnum++) - if (m_device[devnum] != nullptr) - m_device[devnum]->apply_steadykey(); -} - - - -//************************************************************************** -// INPUT MANAGER -//************************************************************************** - -//------------------------------------------------- -// input_manager - constructor -//------------------------------------------------- - -input_manager::input_manager(running_machine &machine) - : m_machine(machine), - m_keyboard_class(*this, DEVICE_CLASS_KEYBOARD, true, machine.options().multi_keyboard()), - m_mouse_class(*this, DEVICE_CLASS_MOUSE, machine.options().mouse(), machine.options().multi_mouse()), - m_joystick_class(*this, DEVICE_CLASS_JOYSTICK, machine.options().joystick(), true), - m_lightgun_class(*this, DEVICE_CLASS_LIGHTGUN, machine.options().lightgun(), true), - m_poll_seq_last_ticks(0), - m_poll_seq_class(ITEM_CLASS_SWITCH) -{ - // reset code memory - reset_memory(); - - // create pointers for the classes - memset(m_class, 0, sizeof(m_class)); - m_class[DEVICE_CLASS_KEYBOARD] = &m_keyboard_class; - m_class[DEVICE_CLASS_MOUSE] = &m_mouse_class; - m_class[DEVICE_CLASS_JOYSTICK] = &m_joystick_class; - m_class[DEVICE_CLASS_LIGHTGUN] = &m_lightgun_class; } @@ -1251,7 +726,7 @@ void input_manager::reset_polling() // 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(input_code(*device, itemid))); + item->set_memory(code_value(item->code())); } } } @@ -1278,7 +753,7 @@ input_code input_manager::poll_switches() input_device_item *item = device->item(itemid); if (item != nullptr) { - input_code code(*device, itemid); + input_code code = item->code(); // if the item is natively a switch, poll it if (item->itemclass() == ITEM_CLASS_SWITCH) @@ -1345,10 +820,11 @@ input_code input_manager::poll_switches() input_code input_manager::poll_keyboard_switches() { // iterate over devices within each class - for (int devnum = 0; devnum < m_keyboard_class.maxindex(); devnum++) + 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 = m_keyboard_class.device(devnum); + input_device *device = keyboard_class.device(devnum); if (device == nullptr) continue; @@ -1358,7 +834,7 @@ input_code input_manager::poll_keyboard_switches() input_device_item *item = device->item(itemid); if (item != nullptr && item->itemclass() == ITEM_CLASS_SWITCH) { - input_code code(*device, itemid); + input_code code = item->code(); if (code_pressed_once(code)) return code; } @@ -1432,7 +908,7 @@ input_code input_manager::poll_axes() input_device_item *item = device->item(itemid); if (item != nullptr && item->itemclass() != ITEM_CLASS_SWITCH) { - input_code code(*device, itemid); + input_code code = item->code(); if (code_check_axis(*item, code)) return code; } @@ -1503,8 +979,12 @@ input_code input_manager::code_from_itemid(input_item_id itemid) const for (int devnum = 0; devnum <= m_class[devclass]->maxindex(); devnum++) { input_device *device = m_class[devclass]->device(devnum); - if (device != nullptr && device->item(itemid) != nullptr) - return input_code(*device, itemid); + if (device != nullptr) + { + input_device_item *item = device->item(itemid); + if (item != nullptr) + return item->code(); + } } return INPUT_CODE_INVALID; @@ -1535,7 +1015,7 @@ std::string input_manager::code_name(input_code code) const // 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_keyboard_class.maxindex() == 0) + if (device_class == DEVICE_CLASS_KEYBOARD && m_class[device_class]->maxindex() == 0) { devclass = ""; devindex.clear(); @@ -1712,6 +1192,17 @@ input_code input_manager::code_from_token(const char *_token) //------------------------------------------------- +// standard_token - return the standard token for +// the given input item ID +//------------------------------------------------- + +const char *input_manager::standard_token(input_item_id itemid) const +{ + return itemid <= ITEM_ID_MAXIMUM ? (*itemid_token_table)[itemid] : nullptr; +} + + +//------------------------------------------------- // seq_pressed - return true if the given sequence // of switch inputs is "pressed" //------------------------------------------------- @@ -2157,7 +1648,7 @@ bool input_manager::map_device_to_controller(const devicemap_table_type *devicem return false; // enumerate through devices and look for a match - input_class *input_devclass = m_class[devclass]; + input_class *input_devclass = m_class[devclass].get(); for (int devnum = 0; devnum <= input_devclass->maxindex(); devnum++) { input_device *device = input_devclass->device(devnum); @@ -2165,7 +1656,7 @@ bool input_manager::map_device_to_controller(const devicemap_table_type *devicem { // remap devindex input_devclass->remap_device_index(device->devindex(), devindex); - osd_printf_verbose("Input: Remapped %s #%d: %s (device id: %s)\n", (*devclass_string_table)[input_devclass->devclass()], devindex, device->name(), device->id()); + osd_printf_verbose("Input: Remapped %s #%d: %s (device id: %s)\n", input_devclass->name(), devindex, device->name(), device->id()); break; } @@ -2174,319 +1665,3 @@ bool input_manager::map_device_to_controller(const devicemap_table_type *devicem return true; } - - -//------------------------------------------------- -// set_global_joystick_map - set the joystick map -// for all devices -//------------------------------------------------- - -bool input_manager::set_global_joystick_map(const char *mapstring) -{ - // parse the map - joystick_map map; - if (!map.parse(mapstring)) - return false; - - osd_printf_verbose("Input: Changing default joystick map = %s\n", map.to_string().c_str()); - - // iterate over joysticks and set the map - for (int joynum = 0; joynum <= m_joystick_class.maxindex(); joynum++) - { - input_device *device = m_joystick_class.device(joynum); - if (device != nullptr) - device->set_joystick_map(map); - } - return true; -} - - - -//************************************************************************** -// INPUT DEVICE ITEM -//************************************************************************** - -//------------------------------------------------- -// input_device_item - constructor -//------------------------------------------------- - -input_device_item::input_device_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass) - : m_device(device), - m_name(name), - m_internal(internal), - m_itemid(itemid), - m_itemclass(itemclass), - m_getstate(getstate), - m_current(0), - m_memory(0) -{ - // use a standard token name for know item IDs - if (itemid <= ITEM_ID_MAXIMUM && (*itemid_token_table)[itemid] != nullptr) - m_token.assign((*itemid_token_table)[itemid]); - - // otherwise, create a tokenized name - else { - m_token.assign(name); - strmakeupper(m_token); - strdelchr(m_token, ' '); - strdelchr(m_token, '_'); - } -} - - -//------------------------------------------------- -// input_device_item - destructor -//------------------------------------------------- - -input_device_item::~input_device_item() -{ -} - - - -//************************************************************************** -// INPUT DEVICE SWITCH ITEM -//************************************************************************** - -//------------------------------------------------- -// input_device_switch_item - constructor -//------------------------------------------------- - -input_device_switch_item::input_device_switch_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_SWITCH), - m_steadykey(0), - m_oldkey(0) -{ -} - - -//------------------------------------------------- -// read_as_switch - return the raw switch value, -// modified as necessary -//------------------------------------------------- - -int32_t input_device_switch_item::read_as_switch(input_item_modifier modifier) -{ - // if we're doing a lightgun reload hack, button 1 and 2 operate differently - input_device_class devclass = m_device.devclass(); - if (devclass == DEVICE_CLASS_LIGHTGUN && m_device.lightgun_reload_button()) - { - // button 1 is pressed if either button 1 or 2 are active - if (m_itemid == ITEM_ID_BUTTON1) - { - input_device_item *button2_item = m_device.item(ITEM_ID_BUTTON2); - if (button2_item != nullptr) - return button2_item->update_value() | update_value(); - } - - // button 2 is never officially pressed - if (m_itemid == ITEM_ID_BUTTON2) - return 0; - } - - // steadykey for keyboards - if (devclass == DEVICE_CLASS_KEYBOARD && m_device.steadykey_enabled()) - return m_steadykey; - - // everything else is just the current value as-is - return update_value(); -} - - -//------------------------------------------------- -// read_as_relative - return the switch input as -// a relative axis value -//------------------------------------------------- - -int32_t input_device_switch_item::read_as_relative(input_item_modifier modifier) -{ - // no translation to relative - return 0; -} - - -//------------------------------------------------- -// read_as_absolute - return the switch input as -// an absolute axis value -//------------------------------------------------- - -int32_t input_device_switch_item::read_as_absolute(input_item_modifier modifier) -{ - // no translation to absolute - return 0; -} - - -//------------------------------------------------- -// steadykey_changed - update for steadykey -// behavior, returning true if the current state -// has changed since the last call -//------------------------------------------------- - -bool input_device_switch_item::steadykey_changed() -{ - int32_t old = m_oldkey; - m_oldkey = update_value(); - if (((m_current ^ old) & 1) == 0) - return false; - - // if the keypress was missed, turn it on for one frame - if (((m_current | m_steadykey) & 1) == 0) - m_steadykey = 1; - return true; -} - - - -//************************************************************************** -// INPUT DEVICE RELATIVE ITEM -//************************************************************************** - -//------------------------------------------------- -// input_device_relative_item - constructor -//------------------------------------------------- - -input_device_relative_item::input_device_relative_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_RELATIVE) -{ -} - - -//------------------------------------------------- -// read_as_switch - return the relative value as -// a switch result based on the modifier -//------------------------------------------------- - -int32_t input_device_relative_item::read_as_switch(input_item_modifier modifier) -{ - // process according to modifiers - if (modifier == ITEM_MODIFIER_POS || modifier == ITEM_MODIFIER_RIGHT || modifier == ITEM_MODIFIER_DOWN) - return (update_value() > 0); - else if (modifier == ITEM_MODIFIER_NEG || modifier == ITEM_MODIFIER_LEFT || modifier == ITEM_MODIFIER_UP) - return (update_value() < 0); - - // all other cases just return 0 - return 0; -} - - -//------------------------------------------------- -// read_as_relative - return the relative input -// as a relative axis value -//------------------------------------------------- - -int32_t input_device_relative_item::read_as_relative(input_item_modifier modifier) -{ - // just return directly - return update_value(); -} - - -//------------------------------------------------- -// read_as_absolute - return the relative input -// as an absolute axis value -//------------------------------------------------- - -int32_t input_device_relative_item::read_as_absolute(input_item_modifier modifier) -{ - // no translation to absolute - return 0; -} - - - -//************************************************************************** -// INPUT DEVICE ABSOLUTE ITEM -//************************************************************************** - -//------------------------------------------------- -// input_device_absolute_item - constructor -//------------------------------------------------- - -input_device_absolute_item::input_device_absolute_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate) - : input_device_item(device, name, internal, itemid, getstate, ITEM_CLASS_ABSOLUTE) -{ -} - - -//------------------------------------------------- -// read_as_switch - return the absolute value as -// a switch result based on the modifier -//------------------------------------------------- - -int32_t input_device_absolute_item::read_as_switch(input_item_modifier modifier) -{ - // start with the current value - int32_t result = m_device.apply_deadzone_and_saturation(update_value()); - assert(result >= INPUT_ABSOLUTE_MIN && result <= INPUT_ABSOLUTE_MAX); - - // left/right/up/down: if this is a joystick, fetch the paired X/Y axis values and convert - if (m_device.devclass() == DEVICE_CLASS_JOYSTICK && modifier >= ITEM_MODIFIER_LEFT && modifier <= ITEM_MODIFIER_DOWN) - { - input_device_item *xaxis_item = m_device.item(ITEM_ID_XAXIS); - input_device_item *yaxis_item = m_device.item(ITEM_ID_YAXIS); - if (xaxis_item != nullptr && yaxis_item != nullptr) - { - // determine which item we didn't update, and update it - assert(this == xaxis_item || this == yaxis_item); - if (this == xaxis_item) - yaxis_item->update_value(); - else - xaxis_item->update_value(); - - // now map the X and Y axes to a 9x9 grid using the raw values - return (m_device.joymap().update(xaxis_item->current(), yaxis_item->current()) >> (modifier - ITEM_MODIFIER_LEFT)) & 1; - } - } - - // positive/negative: true if past the deadzone in either direction - if (modifier == ITEM_MODIFIER_POS || modifier == ITEM_MODIFIER_RIGHT || modifier == ITEM_MODIFIER_DOWN) - return (result > 0); - else if (modifier == ITEM_MODIFIER_NEG || modifier == ITEM_MODIFIER_LEFT || modifier == ITEM_MODIFIER_UP) - return (result < 0); - - // all other cases just return 0 - return 0; -} - - -//------------------------------------------------- -// read_as_relative - return the absolute input -// as a relative axis value -//------------------------------------------------- - -int32_t input_device_absolute_item::read_as_relative(input_item_modifier modifier) -{ - // no translation to relative - return 0; -} - - -//------------------------------------------------- -// read_as_absolute - return the absolute input -// as an absolute axis value, with appropriate -// tweaks -//------------------------------------------------- - -int32_t input_device_absolute_item::read_as_absolute(input_item_modifier modifier) -{ - // start with the current value - int32_t result = m_device.apply_deadzone_and_saturation(update_value()); - assert(result >= INPUT_ABSOLUTE_MIN && result <= INPUT_ABSOLUTE_MAX); - - // if we're doing a lightgun reload hack, override the value - if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN && m_device.lightgun_reload_button()) - { - // if it is pressed, return (min,max) - input_device_item *button2_item = m_device.item(ITEM_ID_BUTTON2); - if (button2_item != nullptr && button2_item->update_value()) - result = (m_itemid == ITEM_ID_XAXIS) ? INPUT_ABSOLUTE_MIN : INPUT_ABSOLUTE_MAX; - } - - // positive/negative: scale to full axis - if (modifier == ITEM_MODIFIER_POS) - result = std::max(result, 0) * 2 + INPUT_ABSOLUTE_MIN; - if (modifier == ITEM_MODIFIER_NEG) - result = std::max(-result, 0) * 2 + INPUT_ABSOLUTE_MIN; - return result; -} |