Added support to MUs to input manager
This commit is contained in:
parent
9307f816ba
commit
2e9546a20a
|
@ -1 +1 @@
|
|||
Subproject commit c2fe7365adae51ffabd9fe318ecdfaeac2cbe097
|
||||
Subproject commit 9a411fea58d97f4abe49e08893c57d6d9ff7f666
|
|
@ -35,6 +35,7 @@
|
|||
#include "InputDevice.h"
|
||||
#include "common\util\CxbxUtil.h"
|
||||
#include <algorithm>
|
||||
#include <charconv>
|
||||
|
||||
|
||||
std::string GetInputDeviceName(int dev_type)
|
||||
|
@ -90,6 +91,33 @@ std::string GetInputDeviceName(int dev_type)
|
|||
return str;
|
||||
}
|
||||
|
||||
std::string PortUserFormat(std::string_view port)
|
||||
{
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
++port1;
|
||||
if (slot != PORT_INVALID) {
|
||||
++slot;
|
||||
return std::to_string(port1) + "." + std::to_string(slot);
|
||||
}
|
||||
else {
|
||||
return std::to_string(port1);
|
||||
}
|
||||
}
|
||||
|
||||
void PortStr2Int(std::string_view port, int *port1, int *slot)
|
||||
{
|
||||
*slot = PORT_INVALID;
|
||||
auto &ret = std::from_chars(port.data(), port.data() + port.size(), *port1);
|
||||
assert(ret.ec != std::errc::invalid_argument);
|
||||
if (ret.ptr != port.data() + port.size()) {
|
||||
++ret.ptr;
|
||||
ret = std::from_chars(ret.ptr, port.data() + port.size(), *slot);
|
||||
assert(ret.ec != std::errc::invalid_argument);
|
||||
assert(ret.ptr == port.data() + port.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor, delete all inputs/outputs on device destruction
|
||||
InputDevice::~InputDevice()
|
||||
{
|
||||
|
@ -130,3 +158,31 @@ const std::vector<InputDevice::IoControl*> InputDevice::GetIoControls()
|
|||
});
|
||||
return vec;
|
||||
}
|
||||
|
||||
void InputDevice::SetPort(std::string_view Port, bool Connect)
|
||||
{
|
||||
if (Connect) {
|
||||
m_XboxPort.emplace_back(Port);
|
||||
}
|
||||
else {
|
||||
const auto &it = FindPort(Port);
|
||||
if (it != m_XboxPort.end()) {
|
||||
m_XboxPort.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InputDevice::GetPort(std::string_view Port) const
|
||||
{
|
||||
return FindPort(Port) != m_XboxPort.end() ? true : false;
|
||||
}
|
||||
|
||||
const auto InputDevice::FindPort(std::string_view Port) const
|
||||
{
|
||||
return std::find_if(m_XboxPort.begin(), m_XboxPort.end(), [Port](std::string_view Port1) {
|
||||
if (Port1 == Port) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
#define PORT_3 2
|
||||
#define PORT_4 3
|
||||
|
||||
#define PORT_INC(port) ((port) + 1)
|
||||
#define PORT_DEC(port) ((port) - 1)
|
||||
|
||||
#define DIRECTION_IN 0
|
||||
#define DIRECTION_OUT 1
|
||||
|
||||
|
@ -75,8 +72,12 @@ inline bool g_bIsTrackingMoMove = false;
|
|||
// Lookup array used to translate a gui port to an xbox usb port and vice versa
|
||||
extern int Gui2XboxPortArray[4];
|
||||
|
||||
// Global function used to retrieve the printable name of a xid type
|
||||
// Retrieves the printable name of a xid type
|
||||
std::string GetInputDeviceName(int dev_type);
|
||||
// Converts the port number in the user format
|
||||
std::string PortUserFormat(std::string_view);
|
||||
// Extracts port and slot number from a port formatted as a string
|
||||
void PortStr2Int(std::string_view port, int *port1, int *slot);
|
||||
|
||||
/* Abstract class which represents a host device usable for input/output */
|
||||
class InputDevice
|
||||
|
@ -124,9 +125,9 @@ public:
|
|||
// sets the ID of this device
|
||||
void SetId(int ID) { m_ID = ID; }
|
||||
// retrieves the port this device is attached to
|
||||
bool GetPort(int Port) const { return m_XboxPort[Port]; }
|
||||
bool GetPort(std::string_view Port) const;
|
||||
// sets the port this device is attached to
|
||||
void SetPort(int Port, bool Connect) { m_XboxPort[Port] = Connect; }
|
||||
void SetPort(std::string_view Port, bool Connect);
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -134,6 +135,8 @@ protected:
|
|||
void AddInput(Input* const In);
|
||||
// adds an output control to the device
|
||||
void AddOutput(Output* const Out);
|
||||
// searches for a port
|
||||
const auto FindPort(std::string_view Port) const;
|
||||
// indicates that the device has new input data available
|
||||
bool m_bDirty;
|
||||
// lock for the bindings map
|
||||
|
@ -159,7 +162,7 @@ private:
|
|||
// all the output controls detected and usable on this device
|
||||
std::vector<Output*> m_Outputs;
|
||||
// xbox port(s) this device is attached to
|
||||
bool m_XboxPort[4] = { false, false, false, false };
|
||||
std::vector<std::string> m_XboxPort;
|
||||
// button bindings to the xbox device buttons
|
||||
std::map<int, IoControl*> m_Bindings;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "EmuShared.h"
|
||||
#include "devices\usb\OHCI.h"
|
||||
#include "core/common/video/RenderBase.hpp"
|
||||
#include <charconv>
|
||||
|
||||
// hle input specific
|
||||
#include "core\hle\XAPI\Xapi.h"
|
||||
|
@ -69,7 +70,7 @@ int dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)] = {
|
|||
XBOX_CTRL_NUM_BUTTONS, // ARCADE_STICK
|
||||
};
|
||||
|
||||
extern CXBX_CONTROLLER_HOST_BRIDGE g_XboxControllerHostBridge[4]; // hle xinput
|
||||
void UpdateXppState(DeviceState *dev, XBOX_INPUT_DEVICE type, std::string_view port);
|
||||
|
||||
|
||||
InputDeviceManager g_InputDeviceManager;
|
||||
|
@ -108,10 +109,41 @@ void InputDeviceManager::Initialize(bool is_gui, HWND hwnd)
|
|||
RefreshDevices();
|
||||
|
||||
if (!is_gui) {
|
||||
UpdateDevices(PORT_1, false);
|
||||
UpdateDevices(PORT_2, false);
|
||||
UpdateDevices(PORT_3, false);
|
||||
UpdateDevices(PORT_4, false);
|
||||
for (unsigned i = 0; i < 12; ++i) {
|
||||
g_devs[i].type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
|
||||
g_devs[i].port = std::to_string(PORT_INVALID);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 4; ++i) {
|
||||
int type;
|
||||
g_EmuShared->GetInputDevTypeSettings(&type, i);
|
||||
std::string port = std::to_string(i);
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
|
||||
ConstructHleInputDevice(&g_devs[CTRL_OFFSET + i], nullptr, type, port);
|
||||
for (unsigned slot = 0; slot < XBOX_CTRL_NUM_SLOTS; ++slot) {
|
||||
g_EmuShared->GetInputSlotTypeSettings(&type, i, slot);
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||
assert(type == to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT));
|
||||
ConstructHleInputDevice(&g_devs[MU_OFFSET + slot], &g_devs[CTRL_OFFSET + i], type, port + std::to_string(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
|
||||
ConstructHleInputDevice(&g_devs[CTRL_OFFSET + i], nullptr, type, port);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RawInput::IgnoreHotplug = false;
|
||||
|
@ -188,164 +220,107 @@ void InputDeviceManager::RemoveDevice(std::function<bool(const InputDevice*)> Ca
|
|||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::UpdateDevices(int port, bool ack)
|
||||
void InputDeviceManager::UpdateDevices(std::string_view port, bool ack)
|
||||
{
|
||||
if (port > PORT_4 || port < PORT_1) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "Invalid port number. The port was %d", PORT_INC(port));
|
||||
return;
|
||||
}
|
||||
int type;
|
||||
#if 0 // lle usb
|
||||
int usb_port = PORT_DEC(Gui2XboxPortArray[port]);
|
||||
#else
|
||||
int usb_port = port;
|
||||
#endif
|
||||
g_EmuShared->GetInputDevTypeSettings(&type, port);
|
||||
DeviceState *dev, *upstream;
|
||||
int port1, type, slot;
|
||||
dev = &g_devs[port1];
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
|
||||
if (slot == PORT_INVALID) { // Port references a device attached to an xbox port
|
||||
upstream = nullptr;
|
||||
g_EmuShared->GetInputDevTypeSettings(&type, port1);
|
||||
}
|
||||
else { // Port references a device attached to a slot port
|
||||
assert(dev->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE ||
|
||||
dev->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S);
|
||||
upstream = dev;
|
||||
dev = dev->info.ctrl.slots[slot];
|
||||
g_EmuShared->GetInputSlotTypeSettings(&type, port1, slot);
|
||||
}
|
||||
|
||||
// connect slot
|
||||
if (dev == nullptr) {
|
||||
ConnectDevice(&g_devs[MU_OFFSET + port1 + slot], upstream, type, port);
|
||||
}
|
||||
// connect
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
//g_XidDeviceObjArray[usb_port].xid_dev == nullptr) { lle usb
|
||||
g_XboxControllerHostBridge[usb_port].XboxType == XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
ConnectDevice(port, usb_port, type);
|
||||
else if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
dev->type == XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
ConnectDevice(dev, upstream, type, port);
|
||||
}
|
||||
// disconnect
|
||||
else if (type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
//g_XidDeviceObjArray[usb_port].xid_dev != nullptr) { lle usb
|
||||
g_XboxControllerHostBridge[usb_port].XboxType != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
DisconnectDevice(port, usb_port, ack);
|
||||
dev->type != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
// We don't need to check of we need to destroy child devices because the UpdateInputEvent_t message always
|
||||
// calls us on the entire slot connectivity if the device has slots available
|
||||
DisconnectDevice(dev, port, ack);
|
||||
}
|
||||
// update bindings
|
||||
else {
|
||||
auto dev = g_InputDeviceManager.FindDevice(usb_port, 0);
|
||||
if (dev != nullptr) {
|
||||
dev->SetPort(usb_port, false);
|
||||
auto dev1 = g_InputDeviceManager.FindDevice(port);
|
||||
if (dev1 != nullptr) {
|
||||
dev1->SetPort(port, false);
|
||||
}
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||
if (type != to_underlying(g_XboxControllerHostBridge[port].XboxType)) {
|
||||
// this will happen when the user changes the type of an existing xbox device type connected to a port
|
||||
if (g_XboxControllerHostBridge[port].bPendingRemoval == false) {
|
||||
g_XboxControllerHostBridge[port].bPendingRemoval = true;
|
||||
if (type != to_underlying(dev->type)) {
|
||||
// This will happen when the user changes the type of an existing xbox device type connected to a port.
|
||||
// We don't need to check of we need to destroy child devices because the UpdateInputEvent_t message always
|
||||
// calls us on the entire slot connectivity if the device has slots available
|
||||
if (dev->bPendingRemoval == false) {
|
||||
dev->bPendingRemoval = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
DestructHleInputDevice(port);
|
||||
if (!ConstructHleInputDevice(type, port)) {
|
||||
return;
|
||||
DestructHleInputDevice(dev);
|
||||
ConstructHleInputDevice(dev, upstream, type, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
BindHostDevice(port, usb_port, type);
|
||||
BindHostDevice(type, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::ConnectDevice(int port, int usb_port, int type)
|
||||
void InputDeviceManager::ConnectDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port)
|
||||
{
|
||||
#if 0 // lle usb
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE): {
|
||||
if (ConstructHub(usb_port)) {
|
||||
if (!ConstructXpadDuke(usb_port)) {
|
||||
DestructHub(usb_port);
|
||||
return;
|
||||
}
|
||||
g_XidDeviceObjArray[usb_port].xid_type = type;
|
||||
EmuLog(LOG_LEVEL::INFO, "Attached device %s to port %d", GetInputDeviceName(type).c_str(), PORT_INC(port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::LIGHT_GUN):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
|
||||
EmuLog(LOG_LEVEL::INFO, "%s: device %s is not yet supported", __func__, GetInputDeviceName(type).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
EmuLog(LOG_LEVEL::WARNING, "Attempted to attach an unknown device type (type was %d)", type);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!ConstructHleInputDevice(type, port)) {
|
||||
return;
|
||||
}
|
||||
EmuLog(LOG_LEVEL::INFO, "Attached device %s to port %d", GetInputDeviceName(type).c_str(), PORT_INC(port));
|
||||
#endif
|
||||
BindHostDevice(port, usb_port, type);
|
||||
ConstructHleInputDevice(dev, upstream, type, port);
|
||||
BindHostDevice(type, port);
|
||||
EmuLog(LOG_LEVEL::INFO, "Attached device %s to port %d", GetInputDeviceName(type).c_str(),
|
||||
PortUserFormat(port).c_str());
|
||||
}
|
||||
|
||||
void InputDeviceManager::DisconnectDevice(int port, int usb_port, bool ack)
|
||||
void InputDeviceManager::DisconnectDevice(DeviceState *dev, std::string_view port, bool ack)
|
||||
{
|
||||
#if 0 // lle usb
|
||||
if (g_XidDeviceObjArray[usb_port].xid_dev != nullptr) {
|
||||
int type = g_XidDeviceObjArray[usb_port].xid_type;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE): {
|
||||
if (ack) {
|
||||
assert(g_HubObjArray[usb_port] != nullptr);
|
||||
DestructHub(usb_port);
|
||||
DestructXpadDuke(usb_port);
|
||||
g_HostController->OHCI_SetRemovalFlag(usb_port, false);
|
||||
EmuLog(LOG_LEVEL::INFO, "Detached device %s from port %d", GetInputDeviceName(type).c_str(), PORT_INC(port));
|
||||
int type = to_underlying(dev->type);
|
||||
DestructHleInputDevice(dev);
|
||||
EmuLog(LOG_LEVEL::INFO, "Detached device %s from port %d", GetInputDeviceName(type).c_str(), PortUserFormat(port).c_str());
|
||||
}
|
||||
else {
|
||||
g_HostController->OHCI_SetRemovalFlag(usb_port, true);
|
||||
dev->bPendingRemoval = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::LIGHT_GUN):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
|
||||
EmuLog(LOG_LEVEL::INFO, "%s: device %s is not yet supported", __func__, GetInputDeviceName(type).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
EmuLog(LOG_LEVEL::WARNING, "Attempted to detach an unknown device type (type was %d)", type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (g_XboxControllerHostBridge[port].XboxType != XBOX_INPUT_DEVICE::DEVICE_INVALID) {
|
||||
if (ack) {
|
||||
int type = to_underlying(g_XboxControllerHostBridge[port].XboxType);
|
||||
DestructHleInputDevice(port);
|
||||
EmuLog(LOG_LEVEL::INFO, "Detached device %s from port %d", GetInputDeviceName(type).c_str(), PORT_INC(port));
|
||||
}
|
||||
else {
|
||||
g_XboxControllerHostBridge[port].bPendingRemoval = true;
|
||||
}
|
||||
auto dev = g_InputDeviceManager.FindDevice(usb_port, 0);
|
||||
if (dev != nullptr) {
|
||||
dev->SetPort(usb_port, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::WARNING, "Attempted to detach a device not attached to the emulated machine");
|
||||
auto dev1 = g_InputDeviceManager.FindDevice(port);
|
||||
if (dev1 != nullptr) {
|
||||
dev1->SetPort(port, false);
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::BindHostDevice(int port, int usb_port, int type)
|
||||
void InputDeviceManager::BindHostDevice(int type, std::string_view port)
|
||||
{
|
||||
if (type == to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT)) {
|
||||
// MUs don't have any host device bound, so we just return
|
||||
return;
|
||||
}
|
||||
|
||||
char dev_name[50];
|
||||
char dev_control_names[HIGHEST_NUM_BUTTONS][HOST_BUTTON_NAME_LENGTH];
|
||||
|
||||
g_EmuShared->GetInputDevNameSettings(dev_name, port);
|
||||
g_EmuShared->GetInputBindingsSettings(dev_control_names, dev_num_buttons[type], port);
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
g_EmuShared->GetInputDevNameSettings(dev_name, port1);
|
||||
g_EmuShared->GetInputBindingsSettings(dev_control_names, dev_num_buttons[type], port1);
|
||||
|
||||
auto dev = FindDevice(std::string(dev_name));
|
||||
if (dev != nullptr) {
|
||||
std::vector<InputDevice::IoControl*> controls = dev->GetIoControls();
|
||||
std::vector<InputDevice::IoControl *> controls = dev->GetIoControls();
|
||||
for (int index = 0; index < dev_num_buttons[type]; index++) {
|
||||
std::string dev_button(dev_control_names[index]);
|
||||
auto it = std::find_if(controls.begin(), controls.end(), [&dev_button](const auto control) {
|
||||
|
@ -356,54 +331,53 @@ void InputDeviceManager::BindHostDevice(int port, int usb_port, int type)
|
|||
});
|
||||
dev->SetBindings(index, (it != controls.end()) ? *it : nullptr);
|
||||
}
|
||||
dev->SetPort(usb_port, true);
|
||||
dev->SetPort(port, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool InputDeviceManager::UpdateXboxPortInput(int usb_port, void* Buffer, int Direction, int xid_type)
|
||||
bool InputDeviceManager::UpdateXboxPortInput(int port, void* buffer, int direction, int type)
|
||||
{
|
||||
assert(Direction == DIRECTION_IN || Direction == DIRECTION_OUT);
|
||||
assert(xid_type > to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
xid_type < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
|
||||
assert(direction == DIRECTION_IN || direction == DIRECTION_OUT);
|
||||
assert(type > to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) &&
|
||||
type < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
|
||||
bool has_changed = false;
|
||||
|
||||
// First check if ImGui is focus, then ignore any input update occur.
|
||||
// If somebody else is currently holding the lock, we won't wait and instead report no input changes
|
||||
if (!g_renderbase->IsImGuiFocus() && m_Mtx.try_lock()) {
|
||||
for (auto &dev_ptr : m_Devices) {
|
||||
if (dev_ptr->GetPort(usb_port)) {
|
||||
switch (xid_type)
|
||||
for (auto &dev : m_Devices) {
|
||||
if (dev->GetPort(std::to_string(port))) {
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK): {
|
||||
has_changed = UpdateInputXpad(dev_ptr, Buffer, Direction);
|
||||
}
|
||||
break;
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
|
||||
has_changed = UpdateInputXpad(dev, buffer, direction);
|
||||
m_Mtx.unlock();
|
||||
return has_changed;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
|
||||
has_changed = UpdateInputSBC(dev_ptr, Buffer, Direction, usb_port);
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
|
||||
has_changed = UpdateInputSBC(dev, buffer, direction, port);
|
||||
m_Mtx.unlock();
|
||||
return has_changed;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::LIGHT_GUN):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE): {
|
||||
EmuLog(LOG_LEVEL::WARNING, "An unsupported device is attached at port %d! The device was %s",
|
||||
Gui2XboxPortArray[usb_port], GetInputDeviceName(xid_type).c_str());
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE):
|
||||
EmuLog(LOG_LEVEL::ERROR2, "An unsupported device is attached at port %d! The device was %s",
|
||||
Gui2XboxPortArray[port], GetInputDeviceName(type).c_str());
|
||||
break;
|
||||
|
||||
default: {
|
||||
EmuLog(LOG_LEVEL::WARNING, "An unknown device attached at port %d! The type was %s",
|
||||
Gui2XboxPortArray[usb_port], GetInputDeviceName(xid_type).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_Mtx.unlock();
|
||||
}
|
||||
|
||||
return has_changed;
|
||||
}
|
||||
|
||||
|
@ -690,18 +664,12 @@ std::shared_ptr<InputDevice> InputDeviceManager::FindDevice(SDL_JoystickID id) c
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<InputDevice> InputDeviceManager::FindDevice(int usb_port, int dummy) const
|
||||
std::shared_ptr<InputDevice> InputDeviceManager::FindDevice(std::string_view port) const
|
||||
{
|
||||
// Ignore dummy, it's just used to overload the function
|
||||
|
||||
if (usb_port == PORT_INVALID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lck(m_Mtx);
|
||||
|
||||
auto it = std::find_if(m_Devices.begin(), m_Devices.end(), [usb_port](const auto& Device) {
|
||||
return Device->GetPort(usb_port);
|
||||
auto it = std::find_if(m_Devices.begin(), m_Devices.end(), [port](const auto& Device) {
|
||||
return Device->GetPort(port);
|
||||
});
|
||||
if (it != m_Devices.end()) {
|
||||
return *it;
|
||||
|
@ -762,7 +730,7 @@ void InputDeviceManager::HotplugHandler(bool is_sdl)
|
|||
int type;
|
||||
g_EmuShared->GetInputDevTypeSettings(&type, port);
|
||||
if (type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
|
||||
BindHostDevice(port, port, type);
|
||||
BindHostDevice(type, std::to_string(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#define SLOT_TOP 0
|
||||
#define SLOT_BOTTOM 1
|
||||
|
||||
#define CTRL_OFFSET 0
|
||||
#define MU_OFFSET 4
|
||||
|
||||
extern int dev_num_buttons[to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)];
|
||||
|
||||
inline XBOX_INPUT_DEVICE input_support_list[] = {
|
||||
|
@ -100,36 +103,51 @@ struct SBCOutput {
|
|||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
// hle specific input types
|
||||
typedef struct _CXBX_XINPUT_DEVICE_INFO {
|
||||
uint8_t ucType; // xbox controller type
|
||||
uint8_t ucSubType; // xbox controller subtype
|
||||
uint8_t ucInputStateSize; // xbox controller input state size in bytes, not include dwPacketNumber
|
||||
uint8_t ucFeedbackSize; // xbox controller feedback size in bytes, not include FeedbackHeader
|
||||
uint32_t dwPacketNumber;
|
||||
}
|
||||
CXBX_XINPUT_DEVICE_INFO, *PCXBX_XINPUT_DEVICE_INFO;
|
||||
|
||||
union CXBX_XINPUT_IN_STATE {
|
||||
XpadInput Gamepad;
|
||||
SBCInput SBC;
|
||||
};
|
||||
|
||||
// this structure is for use of tracking the xbox controllers assigned to 4 ports.
|
||||
typedef struct _CXBX_CONTROLLER_HOST_BRIDGE {
|
||||
HANDLE hXboxDevice; // xbox device handle to this device, we use the address of this bridge as the handle, only set after opened. cleared after closed.
|
||||
int XboxPort; // xbox port# for this xbox controller
|
||||
XBOX_INPUT_DEVICE XboxType; // xbox device type
|
||||
CXBX_XINPUT_IN_STATE *InState;
|
||||
bool bPendingRemoval;
|
||||
bool bSignaled;
|
||||
bool bIoInProgress;
|
||||
struct CommonCtrlInfo {
|
||||
xbox::HANDLE hhandle; // device handle returned by xapi
|
||||
bool bAutoPoll; // autopoll on/off, as instructed by the title in XInputOpen
|
||||
bool bAutoPollDefault; // default autopoll value, depending on device type
|
||||
CXBX_XINPUT_DEVICE_INFO XboxDeviceInfo;
|
||||
}
|
||||
CXBX_CONTROLLER_HOST_BRIDGE, *PCXBX_CONTROLLER_HOST_BRIDGE;
|
||||
uint8_t ucType; // xapi type
|
||||
uint8_t ucSubType; // xapi subtype
|
||||
uint8_t ucInputStateSize; // input state size in bytes, does not include dwPacketNumber
|
||||
uint8_t ucFeedbackSize; // feedback size in bytes, does not include FeedbackHeader
|
||||
uint32_t dwPacketNumber;
|
||||
};
|
||||
|
||||
struct DeviceState;
|
||||
struct CtrlInfo {
|
||||
CommonCtrlInfo common;
|
||||
XpadInput in_buffer;
|
||||
DeviceState *slots[XBOX_CTRL_NUM_SLOTS];
|
||||
};
|
||||
|
||||
struct ArcadeCtrlInfo {
|
||||
CommonCtrlInfo common;
|
||||
XpadInput in_buffer;
|
||||
};
|
||||
|
||||
struct SbcInfo {
|
||||
CommonCtrlInfo common;
|
||||
SBCInput in_buffer;
|
||||
};
|
||||
|
||||
union DeviceInfo {
|
||||
CtrlInfo ctrl;
|
||||
ArcadeCtrlInfo arcade;
|
||||
SbcInfo sbc;
|
||||
};
|
||||
|
||||
struct DeviceState {
|
||||
DeviceState *upstream;
|
||||
std::string port;
|
||||
XBOX_INPUT_DEVICE type;
|
||||
bool bPendingRemoval;
|
||||
bool bSignaled;
|
||||
DeviceInfo info;
|
||||
};
|
||||
|
||||
extern DeviceState g_devs[4 + 8];
|
||||
|
||||
|
||||
class InputDeviceManager
|
||||
{
|
||||
|
@ -137,7 +155,7 @@ public:
|
|||
void Initialize(bool is_gui, HWND hwnd);
|
||||
void Shutdown();
|
||||
// read/write the input/output from/to the device attached to the supplied xbox port
|
||||
bool UpdateXboxPortInput(int usb_port, void* Buffer, int Direction, int xid_type);
|
||||
bool UpdateXboxPortInput(int port, void *buffer, int direction, int type);
|
||||
// add the device to the list of availble devices
|
||||
void AddDevice(std::shared_ptr<InputDevice> Device);
|
||||
// remove the device from the list of availble devices
|
||||
|
@ -151,9 +169,9 @@ public:
|
|||
// find device from its sdl id
|
||||
std::shared_ptr<InputDevice> FindDevice(SDL_JoystickID id) const;
|
||||
// find device from its xbox port
|
||||
std::shared_ptr<InputDevice> FindDevice(int usb_port, int dummy) const;
|
||||
std::shared_ptr<InputDevice> FindDevice(std::string_view port) const;
|
||||
// attach/detach guest devices to the emulated machine
|
||||
void UpdateDevices(int port, bool ack);
|
||||
void UpdateDevices(std::string_view port, bool ack);
|
||||
// update input options
|
||||
void UpdateOpt(bool is_gui);
|
||||
// device hotplug event handler
|
||||
|
@ -166,11 +184,11 @@ private:
|
|||
// update input for a Steel Battalion controller
|
||||
bool UpdateInputSBC(std::shared_ptr<InputDevice>& Device, void* Buffer, int Direction, int Port);
|
||||
// bind a host device to an emulated device
|
||||
void BindHostDevice(int port, int usb_port, int type);
|
||||
void BindHostDevice(int type, std::string_view port);
|
||||
// connect a device to the emulated machine
|
||||
void ConnectDevice(int port, int usb_port, int type);
|
||||
void ConnectDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port);
|
||||
// disconnect a device from the emulated machine
|
||||
void DisconnectDevice(int port, int usb_port, bool ack);
|
||||
void DisconnectDevice(DeviceState *dev, std::string_view port, bool ack);
|
||||
|
||||
// all enumerated devices currently detected and supported
|
||||
std::vector<std::shared_ptr<InputDevice>> m_Devices;
|
||||
|
@ -189,7 +207,7 @@ private:
|
|||
extern InputDeviceManager g_InputDeviceManager;
|
||||
|
||||
// hle input functions
|
||||
bool ConstructHleInputDevice(int Type, int Port);
|
||||
void DestructHleInputDevice(int Port);
|
||||
void ConstructHleInputDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port);
|
||||
void DestructHleInputDevice(DeviceState *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -160,7 +160,15 @@ namespace Sdl
|
|||
else {
|
||||
XInput::GetDeviceChanges();
|
||||
DInput::GetDeviceChanges();
|
||||
g_InputDeviceManager.UpdateDevices(*static_cast<int *>(Event.user.data1), false);
|
||||
std::string port = std::to_string(*static_cast<int *>(Event.user.data1));
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
if (g_devs[port1].type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE || g_devs[port1].type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S) {
|
||||
// Force an update of the entire slot connectivity of this port
|
||||
g_InputDeviceManager.UpdateDevices(port + ".0", false);
|
||||
g_InputDeviceManager.UpdateDevices(port + ".1", false);
|
||||
}
|
||||
g_InputDeviceManager.UpdateDevices(port, false);
|
||||
}
|
||||
|
||||
delete Event.user.data1;
|
||||
|
|
|
@ -43,6 +43,12 @@ namespace Sdl
|
|||
}
|
||||
SDL_INIT_STATUS;
|
||||
|
||||
struct UPDATE_INPUT_DATA {
|
||||
int Port;
|
||||
int Slot;
|
||||
bool Opt;
|
||||
};
|
||||
|
||||
extern uint32_t ExitEvent_t;
|
||||
extern uint32_t PopulateEvent_t;
|
||||
extern uint32_t UpdateInputEvent_t;
|
||||
|
|
|
@ -43,23 +43,25 @@
|
|||
#include "Windef.h"
|
||||
#include <vector>
|
||||
#include "core\hle\XAPI\Xapi.h"
|
||||
#include "distorm.h"
|
||||
#include "mnemonics.h"
|
||||
#include <charconv>
|
||||
|
||||
|
||||
xbox::PXPP_DEVICE_TYPE g_DeviceType_Gamepad = nullptr;
|
||||
xbox::PXPP_DEVICE_TYPE g_DeviceType_SBC = nullptr;
|
||||
xbox::PXPP_DEVICE_TYPE g_DeviceType_MU = nullptr;
|
||||
|
||||
// Flag is unset after initialize devices is done by simulate LLE USB thread.
|
||||
std::atomic<bool> g_bIsDevicesInitializing = true;
|
||||
std::atomic<bool> g_bIsDevicesEmulating = false;
|
||||
static CXBX_XINPUT_IN_STATE g_InState[4];
|
||||
|
||||
// Global bridge for xbox controller to host, 4 elements for 4 ports.
|
||||
CXBX_CONTROLLER_HOST_BRIDGE g_XboxControllerHostBridge[4] = {
|
||||
{ NULL, PORT_INVALID, XBOX_INPUT_DEVICE::DEVICE_INVALID, &g_InState[0], false, false, false, false, false, { 0, 0, 0, 0, 0 } },
|
||||
{ NULL, PORT_INVALID, XBOX_INPUT_DEVICE::DEVICE_INVALID, &g_InState[1], false, false, false, false, false, { 0, 0, 0, 0, 0 } },
|
||||
{ NULL, PORT_INVALID, XBOX_INPUT_DEVICE::DEVICE_INVALID, &g_InState[2], false, false, false, false, false, { 0, 0, 0, 0, 0 } },
|
||||
{ NULL, PORT_INVALID, XBOX_INPUT_DEVICE::DEVICE_INVALID, &g_InState[3], false, false, false, false, false, { 0, 0, 0, 0, 0 } },
|
||||
};
|
||||
// Protects access to xpp types
|
||||
std::atomic<bool> g_bXppGuard = false;
|
||||
|
||||
// allocate enough memory for the max number of devices we can support simultaneously
|
||||
// 4 duke / S / sbc / arcade jpystick (mutually exclusive) + 8 memory units
|
||||
DeviceState g_devs[4 + 8];
|
||||
|
||||
|
||||
bool operator==(xbox::PXPP_DEVICE_TYPE XppType, XBOX_INPUT_DEVICE XidType)
|
||||
|
@ -82,9 +84,15 @@ bool operator==(xbox::PXPP_DEVICE_TYPE XppType, XBOX_INPUT_DEVICE XidType)
|
|||
}
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::MEMORY_UNIT: {
|
||||
if (XppType == g_DeviceType_MU) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::LIGHT_GUN:
|
||||
case XBOX_INPUT_DEVICE::STEERING_WHEEL:
|
||||
case XBOX_INPUT_DEVICE::MEMORY_UNIT:
|
||||
case XBOX_INPUT_DEVICE::IR_DONGLE:
|
||||
default:
|
||||
break;
|
||||
|
@ -93,15 +101,9 @@ bool operator==(xbox::PXPP_DEVICE_TYPE XppType, XBOX_INPUT_DEVICE XidType)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(xbox::PXPP_DEVICE_TYPE XppType, XBOX_INPUT_DEVICE XidType)
|
||||
{
|
||||
return !(XppType == XidType);
|
||||
}
|
||||
|
||||
bool ConstructHleInputDevice(int Type, int Port)
|
||||
void ConstructHleInputDevice(DeviceState *dev, DeviceState *upstream, int type, std::string_view port)
|
||||
{
|
||||
g_bIsDevicesEmulating = true;
|
||||
bool ret = true;
|
||||
|
||||
if (g_bIsChihiro) {
|
||||
// Don't emulate XID devices during Chihiro Emulation
|
||||
|
@ -110,105 +112,153 @@ bool ConstructHleInputDevice(int Type, int Port)
|
|||
}
|
||||
|
||||
// NOTE: initialize bAutoPollDefault to its default state, which varies depending on the device type
|
||||
switch (Type)
|
||||
switch (type)
|
||||
{
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE): {
|
||||
g_XboxControllerHostBridge[Port].XboxPort = Port;
|
||||
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE;
|
||||
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
|
||||
g_XboxControllerHostBridge[Port].bSignaled = false;
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
g_XboxControllerHostBridge[Port].bAutoPollDefault = true;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = sizeof(XpadInput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = sizeof(XpadOutput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
|
||||
dev->upstream = nullptr;
|
||||
dev->port = port;
|
||||
dev->type = XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE;
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
dev->info.ctrl.common.bAutoPollDefault = true;
|
||||
dev->info.ctrl.common.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
dev->info.ctrl.common.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
|
||||
dev->info.ctrl.common.ucInputStateSize = sizeof(XpadInput);
|
||||
dev->info.ctrl.common.ucFeedbackSize = sizeof(XpadOutput);
|
||||
dev->info.ctrl.common.dwPacketNumber = 0;
|
||||
dev->info.ctrl.slots[SLOT_TOP] = dev->info.ctrl.slots[SLOT_BOTTOM] = nullptr;
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
|
||||
g_XboxControllerHostBridge[Port].XboxPort = Port;
|
||||
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::MS_CONTROLLER_S;
|
||||
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
|
||||
g_XboxControllerHostBridge[Port].bSignaled = false;
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
g_XboxControllerHostBridge[Port].bAutoPollDefault = true;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD_ALT;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = sizeof(XpadInput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = sizeof(XpadOutput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S):
|
||||
dev->upstream = nullptr;
|
||||
dev->port = port;
|
||||
dev->type = XBOX_INPUT_DEVICE::MS_CONTROLLER_S;
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
dev->info.ctrl.common.bAutoPollDefault = true;
|
||||
dev->info.ctrl.common.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
dev->info.ctrl.common.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD_ALT;
|
||||
dev->info.ctrl.common.ucInputStateSize = sizeof(XpadInput);
|
||||
dev->info.ctrl.common.ucFeedbackSize = sizeof(XpadOutput);
|
||||
dev->info.ctrl.common.dwPacketNumber = 0;
|
||||
dev->info.ctrl.slots[SLOT_TOP] = dev->info.ctrl.slots[SLOT_BOTTOM] = nullptr;
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER): {
|
||||
g_XboxControllerHostBridge[Port].XboxPort = Port;
|
||||
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER;
|
||||
g_XboxControllerHostBridge[Port].InState->SBC.ucGearLever = 8;
|
||||
g_XboxControllerHostBridge[Port].InState->SBC.sAimingX = static_cast<uint8_t>(0x7F);
|
||||
g_XboxControllerHostBridge[Port].InState->SBC.sAimingY = static_cast<uint8_t>(0x7F);
|
||||
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
|
||||
g_XboxControllerHostBridge[Port].bSignaled = false;
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
g_XboxControllerHostBridge[Port].bAutoPollDefault = true;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucType = XINPUT_DEVTYPE_STEELBATTALION;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD_ALT;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = sizeof(SBCInput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = sizeof(SBCOutput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER):
|
||||
dev->upstream = nullptr;
|
||||
dev->port = port;
|
||||
dev->type = XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER;
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
dev->info.sbc.in_buffer.ucGearLever = 8;
|
||||
dev->info.sbc.in_buffer.sAimingX = static_cast<uint8_t>(0x7F);
|
||||
dev->info.sbc.in_buffer.sAimingY = static_cast<uint8_t>(0x7F);
|
||||
dev->info.sbc.common.bAutoPollDefault = true;
|
||||
dev->info.sbc.common.ucType = XINPUT_DEVTYPE_STEELBATTALION;
|
||||
dev->info.sbc.common.ucSubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD_ALT;
|
||||
dev->info.sbc.common.ucInputStateSize = sizeof(SBCInput);
|
||||
dev->info.sbc.common.ucFeedbackSize = sizeof(SBCOutput);
|
||||
dev->info.sbc.common.dwPacketNumber = 0;
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK): {
|
||||
g_XboxControllerHostBridge[Port].XboxPort = Port;
|
||||
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::ARCADE_STICK;
|
||||
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
|
||||
g_XboxControllerHostBridge[Port].bSignaled = false;
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
g_XboxControllerHostBridge[Port].bAutoPollDefault = true;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType = XINPUT_DEVSUBTYPE_GC_ARCADE_STICK;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = sizeof(XpadInput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = sizeof(XpadOutput);
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
|
||||
}
|
||||
case to_underlying(XBOX_INPUT_DEVICE::ARCADE_STICK):
|
||||
dev->upstream = nullptr;
|
||||
dev->port = port;
|
||||
dev->type = XBOX_INPUT_DEVICE::ARCADE_STICK;
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
dev->info.arcade.common.bAutoPollDefault = true;
|
||||
dev->info.arcade.common.ucType = XINPUT_DEVTYPE_GAMEPAD;
|
||||
dev->info.arcade.common.ucSubType = XINPUT_DEVSUBTYPE_GC_ARCADE_STICK;
|
||||
dev->info.arcade.common.ucInputStateSize = sizeof(XpadInput);
|
||||
dev->info.arcade.common.ucFeedbackSize = sizeof(XpadOutput);
|
||||
dev->info.arcade.common.dwPacketNumber = 0;
|
||||
break;
|
||||
|
||||
case to_underlying(XBOX_INPUT_DEVICE::LIGHT_GUN):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::STEERING_WHEEL):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT):
|
||||
case to_underlying(XBOX_INPUT_DEVICE::IR_DONGLE):
|
||||
EmuLog(LOG_LEVEL::INFO, "%s: device %s is not yet supported", __func__, GetInputDeviceName(Type).c_str());
|
||||
ret = false;
|
||||
case to_underlying(XBOX_INPUT_DEVICE::MEMORY_UNIT): {
|
||||
assert(upstream != nullptr);
|
||||
dev->upstream = upstream;
|
||||
dev->port = port;
|
||||
dev->type = XBOX_INPUT_DEVICE::MEMORY_UNIT;
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
assert(slot != PORT_INVALID);
|
||||
dev->upstream->info.ctrl.slots[slot] = dev;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
EmuLog(LOG_LEVEL::WARNING, "Attempted to attach an unknown device type (type was %d)", Type);
|
||||
ret = false;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
UpdateXppState(dev, static_cast<XBOX_INPUT_DEVICE>(type), port);
|
||||
|
||||
g_bIsDevicesEmulating = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DestructHleInputDevice(int Port)
|
||||
void DestructHleInputDevice(DeviceState *dev)
|
||||
{
|
||||
g_bIsDevicesEmulating = true;
|
||||
|
||||
g_XboxControllerHostBridge[Port].XboxType = XBOX_INPUT_DEVICE::DEVICE_INVALID;
|
||||
g_XboxControllerHostBridge[Port].XboxPort = PORT_INVALID;
|
||||
while (g_XboxControllerHostBridge[Port].bIoInProgress) {}
|
||||
g_XboxControllerHostBridge[Port].bPendingRemoval = false;
|
||||
g_XboxControllerHostBridge[Port].bSignaled = false;
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
g_XboxControllerHostBridge[Port].bAutoPollDefault = false;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucType = 0;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType = 0;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize = 0;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize = 0;
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber = 0;
|
||||
std::memset(&g_InState[Port], 0, sizeof(CXBX_XINPUT_IN_STATE));
|
||||
XBOX_INPUT_DEVICE type = dev->type;
|
||||
std::string port = dev->port;
|
||||
dev->type = XBOX_INPUT_DEVICE::DEVICE_INVALID;
|
||||
dev->port = std::to_string(PORT_INVALID);
|
||||
dev->bPendingRemoval = false;
|
||||
dev->bSignaled = false;
|
||||
|
||||
switch (dev->type)
|
||||
{
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE:
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_S:
|
||||
dev->info.ctrl.common.bAutoPollDefault = false;
|
||||
dev->info.ctrl.common.ucType = 0;
|
||||
dev->info.ctrl.common.ucSubType = 0;
|
||||
dev->info.ctrl.common.ucInputStateSize = 0;
|
||||
dev->info.ctrl.common.ucFeedbackSize = 0;
|
||||
dev->info.ctrl.common.dwPacketNumber = 0;
|
||||
dev->info.ctrl.slots[SLOT_TOP] = dev->info.ctrl.slots[SLOT_BOTTOM] = nullptr;
|
||||
std::memset(&dev->info.sbc.in_buffer, 0, sizeof(XpadInput));
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER:
|
||||
dev->info.sbc.common.bAutoPollDefault = false;
|
||||
dev->info.sbc.common.ucType = 0;
|
||||
dev->info.sbc.common.ucSubType = 0;
|
||||
dev->info.sbc.common.ucInputStateSize = 0;
|
||||
dev->info.sbc.common.ucFeedbackSize = 0;
|
||||
dev->info.sbc.common.dwPacketNumber = 0;
|
||||
std::memset(&dev->info.sbc.in_buffer, 0, sizeof(SBCInput));
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::ARCADE_STICK:
|
||||
dev->info.arcade.common.bAutoPollDefault = false;
|
||||
dev->info.arcade.common.ucType = 0;
|
||||
dev->info.arcade.common.ucSubType = 0;
|
||||
dev->info.arcade.common.ucInputStateSize = 0;
|
||||
dev->info.arcade.common.ucFeedbackSize = 0;
|
||||
dev->info.arcade.common.dwPacketNumber = 0;
|
||||
std::memset(&dev->info.sbc.in_buffer, 0, sizeof(XpadInput));
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::MEMORY_UNIT: {
|
||||
assert(dev->upstream != nullptr && (dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE ||
|
||||
dev->upstream->type == XBOX_INPUT_DEVICE::MS_CONTROLLER_S));
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
assert(slot != PORT_INVALID);
|
||||
dev->upstream->info.ctrl.slots[slot] = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
UpdateXppState(dev, type, port);
|
||||
dev->upstream = nullptr;
|
||||
|
||||
g_bIsDevicesEmulating = false;
|
||||
}
|
||||
|
@ -280,8 +330,143 @@ void SetupXboxDeviceTypes()
|
|||
return;
|
||||
}
|
||||
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_GAMEPAD Found at 0x%08X", (uintptr_t)g_DeviceType_Gamepad);
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_GAMEPAD found at 0x%08X", (uintptr_t)g_DeviceType_Gamepad);
|
||||
}
|
||||
|
||||
// The MU device type is not present in the xpp table, because that only holds the types that XInputOpen supports, and MUs are not
|
||||
// one of those. Insted, this type is referenced by MU_Init, the main MU initialization function, so we can derive it from that.
|
||||
// Unfortunately, the offset of the MU type varies slightly between xdk revisions, so we cannot just read from a fixed offset. What's
|
||||
// constant is that the type is always hardcoded in a push instruction immediately followed by a call, and there are no other push - call
|
||||
// instructions between the start of MU_Init and the offset of interest.
|
||||
|
||||
if (uint8_t *start = reinterpret_cast<uint8_t *>(g_SymbolAddresses["MU_Init"])) {
|
||||
_CodeInfo ci;
|
||||
ci.code = start;
|
||||
ci.codeLen = 100;
|
||||
ci.codeOffset = 0;
|
||||
ci.dt = Decode32Bits;
|
||||
ci.features = DF_NONE;
|
||||
std::array<_DInst, 50> info;
|
||||
unsigned i;
|
||||
|
||||
distorm_decompose(&ci, info.data(), 50, &i);
|
||||
|
||||
i = 0;
|
||||
const auto &it = std::find_if(info.begin(), info.end(), [&info, &i](_DInst &op) {
|
||||
if (!(op.opcode == I_PUSH)) {
|
||||
++i;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((i + 1) <= 49) && (info[i + 1].opcode == I_CALL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
++i;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (it == info.end()) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "XDEVICE_TYPE_MEMORY_UNIT was not found inside MU_Init");
|
||||
}
|
||||
else {
|
||||
g_DeviceType_MU = reinterpret_cast<xbox::PXPP_DEVICE_TYPE>(*reinterpret_cast<uint32_t *>((it->addr + start + 1)));
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT found at 0x%08X", reinterpret_cast<uintptr_t>(g_DeviceType_MU));
|
||||
}
|
||||
}
|
||||
else {
|
||||
EmuLog(LOG_LEVEL::INFO, "XDEVICE_TYPE_MEMORY_UNIT was not found because MU_Init could not be found");
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateXppState(DeviceState *dev, XBOX_INPUT_DEVICE type, std::string_view port)
|
||||
{
|
||||
xbox::PXPP_DEVICE_TYPE xpp;
|
||||
switch (type)
|
||||
{
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE:
|
||||
case XBOX_INPUT_DEVICE::MS_CONTROLLER_S:
|
||||
case XBOX_INPUT_DEVICE::ARCADE_STICK:
|
||||
xpp = g_DeviceType_Gamepad;
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::STEEL_BATTALION_CONTROLLER:
|
||||
xpp = g_DeviceType_SBC;
|
||||
break;
|
||||
|
||||
case XBOX_INPUT_DEVICE::MEMORY_UNIT:
|
||||
xpp = g_DeviceType_MU;
|
||||
break;
|
||||
|
||||
default:
|
||||
xpp = nullptr;
|
||||
}
|
||||
|
||||
assert(xpp != nullptr);
|
||||
|
||||
int port1, slot;
|
||||
PortStr2Int(port, &port1, &slot);
|
||||
xbox::ulong_xt port_mask = 1 << port1;
|
||||
|
||||
// Guard against the unfortunate case where XGetDevices or XGetDeviceChanges have already checked for g_bIsDevicesInitializing
|
||||
// and g_bIsDevicesEmulating and a thread switch happens to this function
|
||||
while (g_bXppGuard) {}
|
||||
|
||||
if (xpp == g_DeviceType_MU) {
|
||||
if ((dev->upstream->type != XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE) ||
|
||||
(dev->upstream->type != XBOX_INPUT_DEVICE::MS_CONTROLLER_S) ||
|
||||
dev->upstream->bPendingRemoval) {
|
||||
xpp->CurrentConnected &= ~port_mask;
|
||||
xpp->CurrentConnected &= ~(port_mask << 16);
|
||||
}
|
||||
else {
|
||||
for (unsigned i = 0, j = 0; i < XBOX_CTRL_NUM_SLOTS; ++i, j += 16) {
|
||||
if (xpp == dev->type && !dev->bPendingRemoval) {
|
||||
xpp->CurrentConnected |= (port_mask << j);
|
||||
}
|
||||
else {
|
||||
xpp->CurrentConnected &= ~(port_mask << j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (xpp == dev->type && !dev->bPendingRemoval) {
|
||||
xpp->CurrentConnected |= port_mask;
|
||||
}
|
||||
else {
|
||||
xpp->CurrentConnected &= ~port_mask;
|
||||
}
|
||||
}
|
||||
|
||||
xpp->ChangeConnected = xpp->PreviousConnected ^ xpp->CurrentConnected;
|
||||
}
|
||||
|
||||
template<bool IsXInputPoll>
|
||||
xbox::dword_xt CxbxImpl_XInputHandler(xbox::HANDLE hDevice, xbox::PXINPUT_STATE pState)
|
||||
{
|
||||
xbox::dword_xt status = ERROR_DEVICE_NOT_CONNECTED;
|
||||
PXBOX_DEV_CONNECTIVITY Device = (PXBOX_DEV_CONNECTIVITY)hDevice;
|
||||
int Port = Device->XboxPort;
|
||||
|
||||
if ((g_XboxDevices[Port].hXboxDevice == hDevice) && !g_XboxDevices[Port].bPendingRemoval) {
|
||||
if (g_XboxDevices[Port].bAutoPoll != IsXInputPoll) {
|
||||
g_XboxDevices[Port].bIoInProgress = true;
|
||||
if (g_InputDeviceManager.UpdateXboxPortInput(Port, g_XboxDevices[Port].InState, DIRECTION_IN, to_underlying(g_XboxDevices[Port].XboxType))) {
|
||||
g_XboxDevices[Port].XboxDeviceInfo.dwPacketNumber++;
|
||||
}
|
||||
g_XboxDevices[Port].bIoInProgress = false;
|
||||
}
|
||||
|
||||
if constexpr (!IsXInputPoll) {
|
||||
std::memcpy((void *)&pState->Gamepad, g_XboxDevices[Port].InState, g_XboxDevices[Port].XboxDeviceInfo.ucInputStateSize);
|
||||
pState->dwPacketNumber = g_XboxDevices[Port].XboxDeviceInfo.dwPacketNumber;
|
||||
}
|
||||
|
||||
status = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -312,63 +497,6 @@ xbox::void_xt WINAPI xbox::EMUPATCH(XInitDevices)
|
|||
}).detach();
|
||||
}
|
||||
|
||||
// This is called to emulate async for both XGetDevices and XGetDeviceChanges
|
||||
void UpdateConnectedDeviceState(xbox::PXPP_DEVICE_TYPE DeviceType) {
|
||||
|
||||
// Do not process the queries until initialize delay and device emulating are complete.
|
||||
if (g_bIsDevicesInitializing || g_bIsDevicesEmulating){
|
||||
return;
|
||||
}
|
||||
|
||||
int Port, PortMask;
|
||||
for (Port = PORT_1, PortMask = 1; Port <= PORT_4; Port++, PortMask <<= 1) {
|
||||
if (DeviceType == g_XboxControllerHostBridge[Port].XboxType && !g_XboxControllerHostBridge[Port].bPendingRemoval) {
|
||||
DeviceType->CurrentConnected |= PortMask;
|
||||
}
|
||||
else {
|
||||
DeviceType->CurrentConnected &= ~PortMask;
|
||||
}
|
||||
|
||||
if (static_cast<uint8_t>(g_XboxControllerHostBridge[Port].bPendingRemoval) &
|
||||
~(static_cast<uint8_t>(g_XboxControllerHostBridge[Port].bSignaled))) {
|
||||
g_XboxControllerHostBridge[Port].bSignaled = true;
|
||||
SDL_Event DeviceRemoveEvent;
|
||||
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
|
||||
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
|
||||
DeviceRemoveEvent.user.data1 = new int(Port);
|
||||
SDL_PushEvent(&DeviceRemoveEvent);
|
||||
}
|
||||
}
|
||||
DeviceType->ChangeConnected = DeviceType->PreviousConnected ^ DeviceType->CurrentConnected;
|
||||
}
|
||||
|
||||
template<bool IsXInputPoll>
|
||||
xbox::dword_xt CxbxImpl_XInputHandler(xbox::HANDLE hDevice, xbox::PXINPUT_STATE pState)
|
||||
{
|
||||
xbox::dword_xt status = ERROR_DEVICE_NOT_CONNECTED;
|
||||
PCXBX_CONTROLLER_HOST_BRIDGE Device = (PCXBX_CONTROLLER_HOST_BRIDGE)hDevice;
|
||||
int Port = Device->XboxPort;
|
||||
|
||||
if ((g_XboxControllerHostBridge[Port].hXboxDevice == hDevice) && !g_XboxControllerHostBridge[Port].bPendingRemoval) {
|
||||
if (g_XboxControllerHostBridge[Port].bAutoPoll != IsXInputPoll) {
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = true;
|
||||
if (g_InputDeviceManager.UpdateXboxPortInput(Port, g_XboxControllerHostBridge[Port].InState, DIRECTION_IN, to_underlying(g_XboxControllerHostBridge[Port].XboxType))) {
|
||||
g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber++;
|
||||
}
|
||||
g_XboxControllerHostBridge[Port].bIoInProgress = false;
|
||||
}
|
||||
|
||||
if constexpr (!IsXInputPoll) {
|
||||
std::memcpy((void *)&pState->Gamepad, g_XboxControllerHostBridge[Port].InState, g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize);
|
||||
pState->dwPacketNumber = g_XboxControllerHostBridge[Port].XboxDeviceInfo.dwPacketNumber;
|
||||
}
|
||||
|
||||
status = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XGetDevices
|
||||
// * Note: This could be unpatched however,
|
||||
|
@ -383,18 +511,38 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XGetDevices)
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(DeviceType);
|
||||
|
||||
UpdateConnectedDeviceState(DeviceType);
|
||||
g_bXppGuard = true;
|
||||
static dword_xt last_connected = 0;
|
||||
if (g_bIsDevicesInitializing || g_bIsDevicesEmulating) {
|
||||
g_bXppGuard = false;
|
||||
RETURN(last_connected);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 12; ++i) {
|
||||
if (static_cast<uint8_t>(g_devs[i].bPendingRemoval) &
|
||||
~(static_cast<uint8_t>(g_devs[i].bSignaled))) {
|
||||
g_devs[i].bSignaled = true;
|
||||
SDL_Event DeviceRemoveEvent;
|
||||
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
|
||||
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
|
||||
DeviceRemoveEvent.user.data1 = new char[g_devs[i].port.size()];
|
||||
std::strcpy(static_cast<char *>(DeviceRemoveEvent.user.data1), g_devs[i].port.c_str());
|
||||
SDL_PushEvent(&DeviceRemoveEvent);
|
||||
}
|
||||
}
|
||||
|
||||
UCHAR oldIrql = xbox::KeRaiseIrqlToDpcLevel();
|
||||
|
||||
dword_xt ret = DeviceType->CurrentConnected;
|
||||
last_connected = DeviceType->CurrentConnected;
|
||||
|
||||
DeviceType->ChangeConnected = 0;
|
||||
DeviceType->PreviousConnected = DeviceType->CurrentConnected;
|
||||
|
||||
xbox::KfLowerIrql(oldIrql);
|
||||
|
||||
RETURN(ret);
|
||||
g_bXppGuard = false;
|
||||
|
||||
RETURN(last_connected);
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -417,11 +565,29 @@ xbox::bool_xt WINAPI xbox::EMUPATCH(XGetDeviceChanges)
|
|||
LOG_FUNC_ARG(pdwRemovals)
|
||||
LOG_FUNC_END;
|
||||
|
||||
UpdateConnectedDeviceState(DeviceType);
|
||||
g_bXppGuard = true;
|
||||
if (g_bIsDevicesInitializing || g_bIsDevicesEmulating) {
|
||||
*pdwInsertions = 0;
|
||||
*pdwRemovals = 0;
|
||||
g_bXppGuard = false;
|
||||
RETURN(FALSE);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 12; ++i) {
|
||||
if (static_cast<uint8_t>(g_devs[i].bPendingRemoval) &
|
||||
~(static_cast<uint8_t>(g_devs[i].bSignaled))) {
|
||||
g_devs[i].bSignaled = true;
|
||||
SDL_Event DeviceRemoveEvent;
|
||||
SDL_memset(&DeviceRemoveEvent, 0, sizeof(SDL_Event));
|
||||
DeviceRemoveEvent.type = Sdl::DeviceRemoveAck_t;
|
||||
DeviceRemoveEvent.user.data1 = new char[g_devs[i].port.size()];
|
||||
std::strcpy(static_cast<char *>(DeviceRemoveEvent.user.data1), g_devs[i].port.c_str());
|
||||
SDL_PushEvent(&DeviceRemoveEvent);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL ret = FALSE;
|
||||
|
||||
|
||||
if(!DeviceType->ChangeConnected)
|
||||
{
|
||||
*pdwInsertions = 0;
|
||||
|
@ -448,6 +614,7 @@ xbox::bool_xt WINAPI xbox::EMUPATCH(XGetDeviceChanges)
|
|||
|
||||
xbox::KfLowerIrql(oldIrql);
|
||||
}
|
||||
g_bXppGuard = false;
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
@ -470,12 +637,17 @@ xbox::HANDLE WINAPI xbox::EMUPATCH(XInputOpen)
|
|||
LOG_FUNC_ARG(pPollingParameters)
|
||||
LOG_FUNC_END;
|
||||
|
||||
if (DeviceType == g_DeviceType_MU) {
|
||||
// MUs cannot be opened with XInputOpen
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
if (dwPort >= PORT_1 && dwPort <= PORT_4) {
|
||||
if (DeviceType == g_XboxControllerHostBridge[dwPort].XboxType) {
|
||||
g_XboxControllerHostBridge[dwPort].bAutoPoll = pPollingParameters != xbox::zeroptr ?
|
||||
pPollingParameters->fAutoPoll : g_XboxControllerHostBridge[dwPort].bAutoPollDefault;
|
||||
g_XboxControllerHostBridge[dwPort].hXboxDevice = &g_XboxControllerHostBridge[dwPort];
|
||||
RETURN(g_XboxControllerHostBridge[dwPort].hXboxDevice);
|
||||
if (DeviceType == g_XboxDevices[dwPort].XboxType) {
|
||||
g_XboxDevices[dwPort].bAutoPoll = pPollingParameters != xbox::zeroptr ?
|
||||
pPollingParameters->fAutoPoll : g_XboxDevices[dwPort].bAutoPollDefault;
|
||||
g_XboxDevices[dwPort].hXboxDevice = &g_XboxDevices[dwPort];
|
||||
RETURN(g_XboxDevices[dwPort].hXboxDevice);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,9 +664,9 @@ xbox::void_xt WINAPI xbox::EMUPATCH(XInputClose)
|
|||
{
|
||||
LOG_FUNC_ONE_ARG(hDevice);
|
||||
|
||||
PCXBX_CONTROLLER_HOST_BRIDGE Device = (PCXBX_CONTROLLER_HOST_BRIDGE)hDevice;
|
||||
PXBOX_DEV_CONNECTIVITY Device = (PXBOX_DEV_CONNECTIVITY)hDevice;
|
||||
int Port = Device->XboxPort;
|
||||
if (g_XboxControllerHostBridge[Port].hXboxDevice == hDevice) {
|
||||
if (g_XboxDevices[Port].hXboxDevice == hDevice) {
|
||||
Device->hXboxDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -530,12 +702,12 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XInputGetCapabilities)
|
|||
LOG_FUNC_END;
|
||||
|
||||
dword_xt ret = ERROR_DEVICE_NOT_CONNECTED;
|
||||
PCXBX_CONTROLLER_HOST_BRIDGE Device = (PCXBX_CONTROLLER_HOST_BRIDGE)hDevice;
|
||||
PXBOX_DEV_CONNECTIVITY Device = (PXBOX_DEV_CONNECTIVITY)hDevice;
|
||||
int Port = Device->XboxPort;
|
||||
if (g_XboxControllerHostBridge[Port].hXboxDevice == hDevice && !g_XboxControllerHostBridge[Port].bPendingRemoval) {
|
||||
pCapabilities->SubType = g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucSubType;
|
||||
if (g_XboxDevices[Port].hXboxDevice == hDevice && !g_XboxDevices[Port].bPendingRemoval) {
|
||||
pCapabilities->SubType = g_XboxDevices[Port].XboxDeviceInfo.ucSubType;
|
||||
UCHAR* pCap = (UCHAR*)(&pCapabilities->In);
|
||||
memset(pCap, 0xFF, g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucInputStateSize + g_XboxControllerHostBridge[Port].XboxDeviceInfo.ucFeedbackSize);
|
||||
memset(pCap, 0xFF, g_XboxDevices[Port].XboxDeviceInfo.ucInputStateSize + g_XboxDevices[Port].XboxDeviceInfo.ucFeedbackSize);
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -579,11 +751,11 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XInputSetState)
|
|||
LOG_FUNC_ARG(pFeedback)
|
||||
LOG_FUNC_END;
|
||||
|
||||
PCXBX_CONTROLLER_HOST_BRIDGE Device = (PCXBX_CONTROLLER_HOST_BRIDGE)hDevice;
|
||||
PXBOX_DEV_CONNECTIVITY Device = (PXBOX_DEV_CONNECTIVITY)hDevice;
|
||||
int Port = Device->XboxPort;
|
||||
if (g_XboxControllerHostBridge[Port].hXboxDevice == hDevice && !g_XboxControllerHostBridge[Port].bPendingRemoval) {
|
||||
if (g_XboxDevices[Port].hXboxDevice == hDevice && !g_XboxDevices[Port].bPendingRemoval) {
|
||||
pFeedback->Header.dwStatus = ERROR_IO_PENDING;
|
||||
g_InputDeviceManager.UpdateXboxPortInput(Port, (void*)&pFeedback->Rumble, DIRECTION_OUT, to_underlying(g_XboxControllerHostBridge[Port].XboxType));
|
||||
g_InputDeviceManager.UpdateXboxPortInput(Port, (void*)&pFeedback->Rumble, DIRECTION_OUT, to_underlying(g_XboxDevices[Port].XboxType));
|
||||
pFeedback->Header.dwStatus = ERROR_SUCCESS;
|
||||
if (pFeedback->Header.hEvent != NULL &&
|
||||
ObReferenceObjectByHandle(pFeedback->Header.hEvent, &xbox::ExEventObjectType, (PVOID*)&pFeedback->Header.IoCompletedEvent) == ERROR_SUCCESS) {
|
||||
|
|
|
@ -79,12 +79,8 @@ void SyncInputSettings(int port_num, int dev_type, bool is_opt)
|
|||
g_EmuShared->SetInputGeneralSettings(&g_Settings->m_input_general);
|
||||
port_num = PORT_INVALID;
|
||||
}
|
||||
#if 0 // lle usb
|
||||
ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_INPUT_SYNC, PORT_DEC(Gui2XboxPortArray[port_num]),
|
||||
reinterpret_cast<std::uintptr_t>(g_ChildWnd));
|
||||
#else
|
||||
|
||||
ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_INPUT_SYNC, port_num, reinterpret_cast<std::uintptr_t>(g_ChildWnd));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,6 +161,13 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
|
|||
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + port);
|
||||
int DeviceType = SendMessage(hHandle, CB_GETITEMDATA, SendMessage(hHandle, CB_GETCURSEL, 0, 0), 0);
|
||||
g_Settings->m_input_port[port].Type = DeviceType;
|
||||
if (DeviceType != to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE) ||
|
||||
DeviceType != to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S)) {
|
||||
// Forcefully set the child devices to none. This will happen if the user sets MUs in the controller dialog but
|
||||
// then they set the parent device to a device that cannot support them in the input dialog
|
||||
g_Settings->m_input_port[port].TopSlotType = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
|
||||
g_Settings->m_input_port[port].BottomSlotType = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
|
||||
}
|
||||
SyncInputSettings(port, DeviceType, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ void DukeInputWindow::Initialize(HWND hwnd, int port_num, int dev_type)
|
|||
|
||||
}
|
||||
SendMessage(m_hwnd_window, WM_SETTEXT, 0,
|
||||
reinterpret_cast<LPARAM>((title + std::to_string(PORT_INC(m_port_num))).c_str()));
|
||||
reinterpret_cast<LPARAM>((title + PortUserFormat(std::to_string(m_port_num))).c_str()));
|
||||
|
||||
// Set the maximum profile name lenght the user can enter in the profile combobox
|
||||
SendMessage(m_hwnd_profile_list, CB_LIMITTEXT, 49, 0);
|
||||
|
|
|
@ -54,7 +54,7 @@ void SbcInputWindow::Initialize(HWND hwnd, int port_num, int dev_type)
|
|||
// Set window title
|
||||
std::string title("Steel Battalion Controller at port ");
|
||||
SendMessage(m_hwnd_window, WM_SETTEXT, 0,
|
||||
reinterpret_cast<LPARAM>((title + std::to_string(PORT_INC(m_port_num))).c_str()));
|
||||
reinterpret_cast<LPARAM>((title + PortUserFormat(std::to_string(m_port_num))).c_str()));
|
||||
|
||||
// Set the maximum profile name lenght the user can enter in the profile combobox
|
||||
SendMessage(m_hwnd_profile_list, CB_LIMITTEXT, 49, 0);
|
||||
|
|
Loading…
Reference in New Issue