summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Tomer Verona <tverona@hotmail.com>2016-09-12 18:35:36 -0700
committer Tomer Verona <tverona@hotmail.com>2016-09-12 18:35:36 -0700
commit2bd18d5fea66bedcde02da1b2c17d83c4640a782 (patch)
tree21a026c276f83cd6a3619d49ca85cba088485e5b /src
parent597626d0593e84868d5d9887c1f44b96222bdd49 (diff)
Support for configuring device to conrtoller id
This change adds support for configuring device to conrtoller id. This allows for stable controller ids even if USB devices are plugged / unplugged, system is rebooted, etc. See documentation for additional context.
Diffstat (limited to 'src')
-rw-r--r--src/emu/input.cpp103
-rw-r--r--src/emu/input.h8
-rw-r--r--src/emu/ioport.cpp18
-rw-r--r--src/osd/modules/input/input_rawinput.cpp12
4 files changed, 139 insertions, 2 deletions
diff --git a/src/emu/input.cpp b/src/emu/input.cpp
index bbae55fcd34..560e9271797 100644
--- a/src/emu/input.cpp
+++ b/src/emu/input.cpp
@@ -941,6 +941,21 @@ void input_device::apply_steadykey() const
}
}
+//-------------------------------------------------
+// match_device_name - match device name via
+// substring search
+//-------------------------------------------------
+
+bool input_device::match_device_name(const char *devicename)
+{
+ std::string devicenameupper(devicename);
+ std::string nameupper(m_name);
+
+ strmakeupper(devicenameupper);
+ strmakeupper(nameupper);
+
+ return std::string::npos == nameupper.find(devicenameupper) ? false : true;
+}
//**************************************************************************
@@ -1020,6 +1035,29 @@ 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
+ m_device[oldindex]->set_devindex(oldindex);
+ 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 +2096,71 @@ 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 *devicename = 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_name(devicename))
+ {
+ // remap devindex
+ input_devclass->remap_device_index(device->devindex(), devindex);
+ osd_printf_info("Mapped device '%s' to %s #%d\n", device->name(), (*devclass_string_table)[input_devclass->devclass()], devindex);
+ 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..1c4276fef3d 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
@@ -562,6 +564,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,6 +574,7 @@ public:
// helpers
INT32 apply_deadzone_and_saturation(INT32 value) const;
void apply_steadykey() const;
+ bool match_device_name(const char * devicename);
private:
// internal state
@@ -616,6 +622,7 @@ public:
// 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 +686,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..00dbedb8de8 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -2904,6 +2904,24 @@ 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, if any
+ 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"))
{
diff --git a/src/osd/modules/input/input_rawinput.cpp b/src/osd/modules/input/input_rawinput.cpp
index ee6dbf4a511..44fba696e2c 100644
--- a/src/osd/modules/input/input_rawinput.cpp
+++ b/src/osd/modules/input/input_rawinput.cpp
@@ -572,8 +572,16 @@ protected:
// improve the name and then allocate a device
std::wstring name = rawinput_device_improve_name(tname.get());
- // convert name to utf8
- std::string utf8_name = utf8_from_wstring(name.c_str());
+ // convert name to utf8. Preserve raw name as well (if different than improved name) to allow mapping of device to controller.
+ std::string utf8_name;
+ if (0 == name.compare(tname.get()))
+ {
+ utf8_name = utf8_from_wstring(name.c_str());
+ }
+ else
+ {
+ utf8_name = util::string_format("%s (%s)", utf8_from_wstring(name.c_str()), utf8_from_wstring(tname.get()));
+ }
devinfo = devicelist()->create_device<TDevice>(machine, utf8_name.c_str(), *this);