diff options
author | Brad Hughes <brad@hughesonline.us> | 2016-09-20 17:54:34 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-20 17:54:34 -0400 |
commit | 31a9c62d1f8d857a448d4e4f3a2194c0ddb4325d (patch) | |
tree | 38a6485d25e91132c791a5cb7286543f98c2e654 /src/emu | |
parent | 35aaa35f9f03ce0ab19ced0c67db2660532c16f6 (diff) | |
parent | 845b36dae268242ab4a103ceb39520efdfa89018 (diff) |
Merge pull request #1405 from tverona1/master
Adding support for stable controller id's
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/input.cpp | 125 | ||||
-rw-r--r-- | src/emu/input.h | 16 | ||||
-rw-r--r-- | src/emu/ioport.cpp | 21 |
3 files changed, 153 insertions, 9 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp index bbae55fcd34..4c8aad97307 100644 --- a/src/emu/input.cpp +++ b/src/emu/input.cpp @@ -794,9 +794,10 @@ void input_seq::replace(input_code oldcode, input_code newcode) // input_device - constructor //------------------------------------------------- -input_device::input_device(input_class &_class, int devindex, const char *name, void *internal) +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), @@ -941,6 +942,21 @@ void input_device::apply_steadykey() const } } +//------------------------------------------------- +// 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; +} //************************************************************************** @@ -968,7 +984,7 @@ input_class::input_class(input_manager &manager, input_device_class devclass, bo // add_device - add a new input device //------------------------------------------------- -input_device *input_class::add_device(const char *name, void *internal) +input_device *input_class::add_device(const char *name, const char *id, void *internal) { // find the next empty index int devindex; @@ -977,23 +993,28 @@ input_device *input_class::add_device(const char *name, void *internal) break; // call through - return add_device(devindex, name, internal); + return add_device(devindex, name, id, internal); } -input_device *input_class::add_device(int devindex, const char *name, void *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, internal); + 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); - osd_printf_verbose("Input: Adding %s #%d: %s\n", (*devclass_string_table)[m_devclass], devindex, name); + 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(); } @@ -1020,6 +1041,32 @@ input_item_class input_class::standard_item_class(input_item_id itemid) //------------------------------------------------- +// 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); +} + + +//------------------------------------------------- // frame_callback - per-frame callback for various // bookkeeping //------------------------------------------------- @@ -2058,6 +2105,72 @@ void input_manager::seq_from_tokens(input_seq &seq, const char *string) } } +//------------------------------------------------- +// map_device_to_controller - map device to +// controller based on device map table +//------------------------------------------------- + +bool input_manager::map_device_to_controller(const devicemap_table_type *devicemap_table) +{ + if (nullptr == devicemap_table) + return true; + + for (devicemap_table_type::const_iterator it = devicemap_table->begin(); it != devicemap_table->end(); it++) + { + const char *deviceid = it->first.c_str(); + const char *controllername = it->second.c_str(); + + // 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); ) + { + // make a token up to the next underscore + char *score = (char *)strchr(_token, '_'); + token[numtokens++].assign(_token, (score == nullptr) ? strlen(_token) : (score - _token)); + + // if we hit the end, we're done, else advance our pointer + if (score == nullptr) + break; + _token = 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)) + return false; + + // second token should be the devindex + int devindex = 0; + if (1 != sscanf(token[1].c_str(), "%d", &devindex)) + return false; + devindex--; + + if (devindex >= DEVICE_INDEX_MAXIMUM) + return false; + + // enumerate through devices and look for a match + input_class *input_devclass = m_class[devclass]; + for (int devnum = 0; devnum <= input_devclass->maxindex(); devnum++) + { + input_device *device = input_devclass->device(devnum); + if (device != nullptr && 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", (*devclass_string_table)[input_devclass->devclass()], devindex, device->name(), device->id()); + + break; + } + } + } + + return true; +} + //------------------------------------------------- // set_global_joystick_map - set the joystick map diff --git a/src/emu/input.h b/src/emu/input.h index d7012c1f779..dff829f5d54 100644 --- a/src/emu/input.h +++ b/src/emu/input.h @@ -352,6 +352,8 @@ class input_manager; // callback for getting the value of an item on a device typedef INT32 (*item_get_state_func)(void *device_internal, void *item_internal); +// controller alias table typedef +typedef std::map<std::string, std::string> devicemap_table_type; // ======================> joystick_map @@ -547,13 +549,14 @@ class input_device public: // construction/destruction - input_device(input_class &_class, int _devindex, const char *_name, void *_internal); + input_device(input_class &_class, int _devindex, const char *_name, const char *_id, void *_internal); // getters input_class &device_class() const { return m_class; } input_manager &manager() const; running_machine &machine() const; input_device_class devclass() const; const char *name() const { return m_name.c_str(); } + const char *id() const { return m_id.c_str(); } int devindex() const { return m_devindex; } input_device_item *item(input_item_id index) const { return m_item[index].get(); } input_item_id maxitem() const { return m_maxitem; } @@ -562,6 +565,9 @@ public: bool steadykey_enabled() const { return m_steadykey_enabled; } bool lightgun_reload_button() const { return m_lightgun_reload_button; } + // setters + void set_devindex(int devindex) { m_devindex = devindex; } + // item management input_item_id add_item(const char *name, input_item_id itemid, item_get_state_func getstate, void *internal = nullptr); void set_joystick_map(const joystick_map &map) { m_joymap = map; } @@ -569,11 +575,13 @@ public: // helpers INT32 apply_deadzone_and_saturation(INT32 value) const; void apply_steadykey() const; + bool match_device_id(const char * deviceid); private: // internal state input_class & m_class; // reference to our class std::string m_name; // string name of device + std::string m_id; // id of device int m_devindex; // device index of this device std::unique_ptr<input_device_item> m_item[ITEM_ID_ABSOLUTE_MAXIMUM+1]; // array of pointers to items input_item_id m_maxitem; // maximum item index @@ -611,11 +619,12 @@ public: void set_multi(bool multi = true) { m_multi = multi; } // device management - input_device *add_device(const char *name, void *internal = nullptr); - input_device *add_device(int devindex, const char *name, void *internal = nullptr); + input_device *add_device(const char *name, const char *id, void *internal = nullptr); + input_device *add_device(int devindex, const char *name, const char *id, void *internal = nullptr); // misc helpers input_item_class standard_item_class(input_item_id itemid); + void remap_device_index(int oldindex, int newindex); private: // internal helpers @@ -679,6 +688,7 @@ public: // misc bool set_global_joystick_map(const char *mapstring); + bool map_device_to_controller(const devicemap_table_type *devicemap_table = nullptr); private: // internal helpers diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 44e758b5752..bf6a4cd52c4 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -2904,6 +2904,27 @@ void ioport_manager::load_config(config_type cfg_type, xml_data_node *parentnode if (cfg_type == config_type::CONFIG_TYPE_CONTROLLER) load_remap_table(parentnode); + // load device map table for controller configs only + if (cfg_type == config_type::CONFIG_TYPE_CONTROLLER) + { + std::unique_ptr<devicemap_table_type> devicemap_table = std::make_unique<devicemap_table_type>(); + for (xml_data_node *mapdevice_node = xml_get_sibling(parentnode->child, "mapdevice"); mapdevice_node != nullptr; mapdevice_node = xml_get_sibling(mapdevice_node->next, "mapdevice")) + { + const char *devicename = xml_get_attribute_string(mapdevice_node, "device", nullptr); + const char *controllername = xml_get_attribute_string(mapdevice_node, "controller", nullptr); + if (devicename != nullptr && controllername != nullptr) + { + devicemap_table->insert(std::make_pair(std::string(devicename), std::string(controllername))); + } + } + + // map device to controller if we have a device map + if (!devicemap_table->empty()) + { + machine().input().map_device_to_controller(devicemap_table.get()); + } + } + // iterate over all the port nodes for (xml_data_node *portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port")) { |