From 1048b6f20b0c71c680a8c39795de2ba33b931f50 Mon Sep 17 00:00:00 2001 From: Garrett Brown Date: Sun, 30 Jul 2017 20:04:54 -0700 Subject: [PATCH] Device subclass support --- src/client.cpp | 2 +- src/input/ButtonMapper.cpp | 16 ++++++++++++++++ src/input/ButtonMapper.h | 2 ++ src/input/InputDefinitions.h | 5 +---- src/input/InputManager.cpp | 35 +++++++++++++++++++++++++++-------- src/input/InputManager.h | 2 +- src/input/LibretroDevice.cpp | 13 +++++++++++++ src/input/LibretroDevice.h | 6 ++++++ 8 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index eb50e06a..eba175e5 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -441,7 +441,7 @@ void UpdatePort(int port, bool connected, const game_controller* controller) if (port >= GAME_INPUT_PORT_JOYSTICK_START) { - const unsigned int device = CInputManager::Get().GetDevice(port); + const unsigned int device = CInputManager::Get().GetDeviceType(port); if (CLIENT) CLIENT->retro_set_controller_port_device(port, device); diff --git a/src/input/ButtonMapper.cpp b/src/input/ButtonMapper.cpp index 773562bc..c4de5321 100644 --- a/src/input/ButtonMapper.cpp +++ b/src/input/ButtonMapper.cpp @@ -98,6 +98,22 @@ libretro_device_t CButtonMapper::GetLibretroType(const std::string& strControlle return deviceType; } +libretro_subclass_t CButtonMapper::GetSubclass(const std::string& strControllerId) +{ + libretro_subclass_t subclass = 0; + + for (auto& device : m_devices) + { + if (device->ControllerID() == strControllerId) + { + subclass = device->Subclass(); + break; + } + } + + return subclass; +} + int CButtonMapper::GetLibretroIndex(const std::string& strControllerId, const std::string& strFeatureName) { if (!strControllerId.empty() && !strFeatureName.empty()) diff --git a/src/input/ButtonMapper.h b/src/input/ButtonMapper.h index 5614e200..f8df0a59 100644 --- a/src/input/ButtonMapper.h +++ b/src/input/ButtonMapper.h @@ -40,6 +40,8 @@ namespace LIBRETRO libretro_device_t GetLibretroType(const std::string& strControllerId); + libretro_subclass_t GetSubclass(const std::string& strControllerId); + int GetLibretroIndex(const std::string& strControllerId, const std::string& strFeatureName); libretro_device_t GetLibretroDevice(const std::string& strControllerId, const std::string& strFeatureName) const; int GetAxisID(const std::string& strControllerId, const std::string& strFeatureName) const; diff --git a/src/input/InputDefinitions.h b/src/input/InputDefinitions.h index d823fd0a..282a8154 100644 --- a/src/input/InputDefinitions.h +++ b/src/input/InputDefinitions.h @@ -20,15 +20,12 @@ #pragma once #define BUTTONMAP_XML_ROOT "buttonmap" - #define BUTTONMAP_XML_ELM_CONTROLLER "controller" #define BUTTONMAP_XML_ELM_FEATURE "feature" - #define BUTTONMAP_XML_ATTR_VERSION "version" - #define BUTTONMAP_XML_ATTR_CONTROLLER_ID "id" #define BUTTONMAP_XML_ATTR_CONTROLLER_TYPE "type" - +#define BUTTONMAP_XML_ATTR_CONTROLLER_SUBCLASS "subclass" #define BUTTONMAP_XML_ATTR_FEATURE_NAME "name" #define BUTTONMAP_XML_ATTR_FEATURE_MAPTO "mapto" #define BUTTONMAP_XML_ATTR_FEATURE_AXIS "axis" diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp index c53f602a..e0afd668 100644 --- a/src/input/InputManager.cpp +++ b/src/input/InputManager.cpp @@ -58,12 +58,23 @@ void CInputManager::DeviceConnected(int port, bool bConnected, const game_contro m_devices[port].reset(); } -libretro_device_t CInputManager::GetDevice(unsigned int port) +libretro_device_t CInputManager::GetDeviceType(unsigned int port) const { - libretro_device_t deviceType = 0; + libretro_device_t deviceType = RETRO_DEVICE_NONE; - if (m_devices[port]) - deviceType = m_devices[port]->Type(); + auto it = m_devices.find(port); + if (it != m_devices.end()) + { + const auto &device = it->second; + if (device) + { + libretro_subclass_t subclass = device->Subclass(); + if (subclass == RETRO_SUBCLASS_NONE) + deviceType = device->Type(); + else + deviceType = RETRO_DEVICE_SUBCLASS(device->Type(), subclass); + } + } return deviceType; } @@ -331,12 +342,20 @@ void CInputManager::SetControllerInfo(const retro_controller_info* info) const retro_controller_description& type = info->types[i]; libretro_device_t baseType = type.id & RETRO_DEVICE_MASK; - std::string device = LibretroTranslator::GetDeviceName(baseType); - unsigned int subclass = type.id >> RETRO_DEVICE_TYPE_SHIFT; + std::string description = type.desc ? type.desc : ""; - dsyslog("Device: \"%s\" (%d), Subclass: %u, Description: \"%s\"", - device.c_str(), static_cast(baseType), subclass, description.c_str()); + if (type.id & ~RETRO_DEVICE_MASK) + { + libretro_subclass_t subclass = (type.id >> RETRO_DEVICE_TYPE_SHIFT) - 1; + dsyslog("Device: %s, Subclass: %u, Description: \"%s\"", + LibretroTranslator::GetDeviceName(baseType), subclass, description.c_str()); + } + else + { + dsyslog("Device: %s, Description: \"%s\"", + LibretroTranslator::GetDeviceName(baseType), description.c_str()); + } } dsyslog("------------------------------------------------------------"); diff --git a/src/input/InputManager.h b/src/input/InputManager.h index 139372da..e8b4f082 100644 --- a/src/input/InputManager.h +++ b/src/input/InputManager.h @@ -59,7 +59,7 @@ namespace LIBRETRO * \brief Get the libretro device abstraction for the device connected to * the specified port */ - libretro_device_t GetDevice(unsigned int port); + libretro_device_t GetDeviceType(unsigned int port) const; bool OpenPort(unsigned int port); DevicePtr GetPort(unsigned int port); diff --git a/src/input/LibretroDevice.cpp b/src/input/LibretroDevice.cpp index 64c16ca5..a5434af2 100644 --- a/src/input/LibretroDevice.cpp +++ b/src/input/LibretroDevice.cpp @@ -28,6 +28,8 @@ #include "tinyxml.h" +#include + using namespace LIBRETRO; CLibretroDevice::CLibretroDevice(const game_controller* controller) @@ -38,6 +40,7 @@ CLibretroDevice::CLibretroDevice(const game_controller* controller) { m_controllerId = controller->controller_id; m_type = CButtonMapper::Get().GetLibretroType(m_controllerId); + m_subclass = CButtonMapper::Get().GetSubclass(m_controllerId); } } @@ -50,6 +53,7 @@ bool CLibretroDevice::Deserialize(const TiXmlElement* pElement, unsigned int but if (!pElement) return false; + // Controller ID const char* controllerId = pElement->Attribute(BUTTONMAP_XML_ATTR_CONTROLLER_ID); if (!controllerId) { @@ -57,6 +61,7 @@ bool CLibretroDevice::Deserialize(const TiXmlElement* pElement, unsigned int but return false; } + // Device type const char* type = pElement->Attribute(BUTTONMAP_XML_ATTR_CONTROLLER_TYPE); if (!type) { @@ -77,6 +82,14 @@ bool CLibretroDevice::Deserialize(const TiXmlElement* pElement, unsigned int but return false; } + // Device subclass + const char* subclass = pElement->Attribute(BUTTONMAP_XML_ATTR_CONTROLLER_SUBCLASS); + if (subclass) + std::istringstream(subclass) >> m_subclass; + else + m_subclass = RETRO_SUBCLASS_NONE; + + // Features const TiXmlElement* pFeature = pElement->FirstChildElement(BUTTONMAP_XML_ELM_FEATURE); if (!pFeature) { diff --git a/src/input/LibretroDevice.h b/src/input/LibretroDevice.h index ef5ebe53..1c8fb7af 100644 --- a/src/input/LibretroDevice.h +++ b/src/input/LibretroDevice.h @@ -28,11 +28,15 @@ class TiXmlElement; +// No subclass +#define RETRO_SUBCLASS_NONE (-1) + namespace LIBRETRO { class CLibretroDevice; typedef std::shared_ptr DevicePtr; typedef unsigned int libretro_device_t; + using libretro_subclass_t = int; struct FeatureMapItem { @@ -52,6 +56,7 @@ namespace LIBRETRO std::string ControllerID(void) const { return m_controllerId; } libretro_device_t Type(void) const { return m_type; } + libretro_subclass_t Subclass() const { return m_subclass; } const FeatureMap& Features(void) const { return m_featureMap; } CLibretroDeviceInput& Input() { return *m_input; } @@ -60,6 +65,7 @@ namespace LIBRETRO private: std::string m_controllerId; libretro_device_t m_type; + libretro_subclass_t m_subclass = RETRO_SUBCLASS_NONE; FeatureMap m_featureMap; std::unique_ptr m_input; };