summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
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
commit31a9c62d1f8d857a448d4e4f3a2194c0ddb4325d (patch)
tree38a6485d25e91132c791a5cb7286543f98c2e654 /src/emu
parent35aaa35f9f03ce0ab19ced0c67db2660532c16f6 (diff)
parent845b36dae268242ab4a103ceb39520efdfa89018 (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.cpp125
-rw-r--r--src/emu/input.h16
-rw-r--r--src/emu/ioport.cpp21
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"))
{