[XAM/HID] Add keyboard_passthru cvar, allows XInputGetKeystroke to receive proper keyboard events

Maybe useful for debug games, or games modded to allow in-game consoles.
This commit is contained in:
emoose 2020-01-14 23:35:51 +00:00 committed by illusion
parent 51ba83d315
commit bf6d4dcda0
2 changed files with 147 additions and 107 deletions

View File

@ -9,11 +9,18 @@
#include "xenia/hid/winkey/winkey_input_driver.h" #include "xenia/hid/winkey/winkey_input_driver.h"
#include "xenia/base/cvar.h"
#include "xenia/base/platform_win.h" #include "xenia/base/platform_win.h"
#include "xenia/hid/hid_flags.h" #include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_system.h" #include "xenia/hid/input_system.h"
#include "xenia/ui/window.h" #include "xenia/ui/window.h"
DEFINE_bool(keyboard_passthru, false,
"Maybe useful for debug games, disables keyboard->gamepad "
"emulation and forwards exact keyboard events to game (note that "
"Xenia keybinds, eg. H to show FPS, will still be in effect!)",
"HID");
namespace xe { namespace xe {
namespace hid { namespace hid {
namespace winkey { namespace winkey {
@ -103,7 +110,7 @@ X_RESULT WinKeyInputDriver::GetCapabilities(uint32_t user_index, uint32_t flags,
X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
X_INPUT_STATE* out_state) { X_INPUT_STATE* out_state) {
if (user_index != user_index_) { if (user_index != user_index_ || cvars::keyboard_passthru) {
return X_ERROR_DEVICE_NOT_CONNECTED; return X_ERROR_DEVICE_NOT_CONNECTED;
} }
@ -252,7 +259,7 @@ X_RESULT WinKeyInputDriver::SetState(uint32_t user_index,
X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) { X_INPUT_KEYSTROKE* out_keystroke) {
if (user_index != user_index_) { if (!cvars::keyboard_passthru && user_index != user_index_) {
return X_ERROR_DEVICE_NOT_CONNECTED; return X_ERROR_DEVICE_NOT_CONNECTED;
} }
@ -275,118 +282,149 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
key_events_.pop(); key_events_.pop();
} }
// TODO(DrChat): Some other way to toggle this... if (cvars::keyboard_passthru) {
if (IS_KEY_TOGGLED(VK_CAPITAL)) { virtual_key = evt.vkey;
// dpad toggled } else {
if (evt.vkey == (0x41)) { // TODO(DrChat): Some other way to toggle this...
// A if (IS_KEY_TOGGLED(VK_CAPITAL)) {
virtual_key = 0x5812; // VK_PAD_DPAD_LEFT // dpad toggled
} else if (evt.vkey == (0x44)) { if (evt.vkey == (0x41)) {
// D // A
virtual_key = 0x5813; // VK_PAD_DPAD_RIGHT virtual_key = 0x5812; // VK_PAD_DPAD_LEFT
} else if (evt.vkey == (0x53)) { } else if (evt.vkey == (0x44)) {
// S // D
virtual_key = 0x5811; // VK_PAD_DPAD_DOWN virtual_key = 0x5813; // VK_PAD_DPAD_RIGHT
} else if (evt.vkey == (0x57)) { } else if (evt.vkey == (0x53)) {
// W // S
virtual_key = 0x5810; // VK_PAD_DPAD_UP virtual_key = 0x5811; // VK_PAD_DPAD_DOWN
} else if (evt.vkey == (0x57)) {
// W
virtual_key = 0x5810; // VK_PAD_DPAD_UP
}
} else {
// left stick
if (evt.vkey == (0x57)) {
// W
virtual_key = 0x5820; // VK_PAD_LTHUMB_UP
}
if (evt.vkey == (0x53)) {
// S
virtual_key = 0x5821; // VK_PAD_LTHUMB_DOWN
}
if (evt.vkey == (0x44)) {
// D
virtual_key = 0x5822; // VK_PAD_LTHUMB_RIGHT
}
if (evt.vkey == (0x41)) {
// A
virtual_key = 0x5823; // VK_PAD_LTHUMB_LEFT
}
}
// Right stick
if (evt.vkey == (0x26)) {
// Up
virtual_key = 0x5830;
}
if (evt.vkey == (0x28)) {
// Down
virtual_key = 0x5831;
}
if (evt.vkey == (0x27)) {
// Right
virtual_key = 0x5832;
}
if (evt.vkey == (0x25)) {
// Left
virtual_key = 0x5833;
}
if (evt.vkey == (0x4C)) {
// L
virtual_key = 0x5802; // VK_PAD_X
} else if (evt.vkey == (VK_OEM_7)) {
// '
virtual_key = 0x5801; // VK_PAD_B
} else if (evt.vkey == (VK_OEM_1)) {
// ;
virtual_key = 0x5800; // VK_PAD_A
} else if (evt.vkey == (0x50)) {
// P
virtual_key = 0x5803; // VK_PAD_Y
}
if (evt.vkey == (0x58)) {
// X
virtual_key = 0x5814; // VK_PAD_START
}
if (evt.vkey == (0x5A)) {
// Z
virtual_key = 0x5815; // VK_PAD_BACK
}
if (evt.vkey == (0x51) || evt.vkey == (0x49)) {
// Q / I
virtual_key = 0x5806; // VK_PAD_LTRIGGER
}
if (evt.vkey == (0x45) || evt.vkey == (0x4F)) {
// E / O
virtual_key = 0x5807; // VK_PAD_RTRIGGER
}
if (evt.vkey == (0x31)) {
// 1
virtual_key = 0x5805; // VK_PAD_LSHOULDER
}
if (evt.vkey == (0x33)) {
// 3
virtual_key = 0x5804; // VK_PAD_RSHOULDER
}
}
if (!cvars::keyboard_passthru) {
if (virtual_key != 0) {
if (evt.transition == true) {
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN
} else if (evt.transition == false) {
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
}
if (evt.prev_state == evt.transition) {
keystroke_flags |= 0x0004; // XINPUT_KEYSTROKE_REPEAT
}
result = X_ERROR_SUCCESS;
} }
} else { } else {
// left stick // Handle keydown/keyup for VK_SHIFT
if (evt.vkey == (0x57)) { if (virtual_key == VK_SHIFT) {
// W if (evt.transition == false) {
virtual_key = 0x5820; // VK_PAD_LTHUMB_UP keystroke_flags |= 0x0002;
} else if (evt.transition == true) {
keystroke_flags |= 0x0001;
}
} }
if (evt.vkey == (0x53)) {
// S // Only handle keydown for other keys, since some stupid games will count
virtual_key = 0x5821; // VK_PAD_LTHUMB_DOWN // keyup as another keypress (seen in SR1..)
if (virtual_key != 0 && virtual_key != 0x10) {
if (evt.transition) {
keystroke_flags |= 0x0001;
}
} }
if (evt.vkey == (0x44)) {
// D if (keystroke_flags != 0) {
virtual_key = 0x5822; // VK_PAD_LTHUMB_RIGHT result = X_ERROR_SUCCESS;
}
if (evt.vkey == (0x41)) {
// A
virtual_key = 0x5823; // VK_PAD_LTHUMB_LEFT
} }
} }
// Right stick if (!result) {
if (evt.vkey == (0x26)) { out_keystroke->virtual_key = virtual_key;
// Up out_keystroke->unicode = unicode;
virtual_key = 0x5830; out_keystroke->flags = keystroke_flags;
out_keystroke->user_index = user_index_;
out_keystroke->hid_code = hid_code;
} else {
memset(out_keystroke, 0, sizeof(X_INPUT_KEYSTROKE));
} }
if (evt.vkey == (0x28)) {
// Down
virtual_key = 0x5831;
}
if (evt.vkey == (0x27)) {
// Right
virtual_key = 0x5832;
}
if (evt.vkey == (0x25)) {
// Left
virtual_key = 0x5833;
}
if (evt.vkey == (0x4C)) {
// L
virtual_key = 0x5802; // VK_PAD_X
} else if (evt.vkey == (VK_OEM_7)) {
// '
virtual_key = 0x5801; // VK_PAD_B
} else if (evt.vkey == (VK_OEM_1)) {
// ;
virtual_key = 0x5800; // VK_PAD_A
} else if (evt.vkey == (0x50)) {
// P
virtual_key = 0x5803; // VK_PAD_Y
}
if (evt.vkey == (0x58)) {
// X
virtual_key = 0x5814; // VK_PAD_START
}
if (evt.vkey == (0x5A)) {
// Z
virtual_key = 0x5815; // VK_PAD_BACK
}
if (evt.vkey == (0x51) || evt.vkey == (0x49)) {
// Q / I
virtual_key = 0x5806; // VK_PAD_LTRIGGER
}
if (evt.vkey == (0x45) || evt.vkey == (0x4F)) {
// E / O
virtual_key = 0x5807; // VK_PAD_RTRIGGER
}
if (evt.vkey == (0x31)) {
// 1
virtual_key = 0x5805; // VK_PAD_LSHOULDER
}
if (evt.vkey == (0x33)) {
// 3
virtual_key = 0x5804; // VK_PAD_RSHOULDER
}
if (virtual_key != 0) {
if (evt.transition == true) {
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN
} else if (evt.transition == false) {
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
}
if (evt.prev_state == evt.transition) {
keystroke_flags |= 0x0004; // XINPUT_KEYSTROKE_REPEAT
}
result = X_ERROR_SUCCESS;
}
out_keystroke->virtual_key = virtual_key;
out_keystroke->unicode = unicode;
out_keystroke->flags = keystroke_flags;
out_keystroke->user_index = user_index_;
out_keystroke->hid_code = hid_code;
// X_ERROR_EMPTY if no new keys // X_ERROR_EMPTY if no new keys
// X_ERROR_DEVICE_NOT_CONNECTED if no device // X_ERROR_DEVICE_NOT_CONNECTED if no device

View File

@ -26,6 +26,7 @@ using xe::hid::X_INPUT_STATE;
using xe::hid::X_INPUT_VIBRATION; using xe::hid::X_INPUT_VIBRATION;
constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01; constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01;
constexpr uint32_t XINPUT_FLAG_KEYBOARD = 0x02;
constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30; constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30;
void XamResetInactivity() { void XamResetInactivity() {
@ -157,7 +158,8 @@ dword_result_t XamInputGetKeystrokeEx(lpdword_t user_index_ptr, dword_t flags,
return X_ERROR_BAD_ARGUMENTS; return X_ERROR_BAD_ARGUMENTS;
} }
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) { if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0 &&
(flags & XINPUT_FLAG_KEYBOARD) == 0) {
// Ignore any query for other types of devices. // Ignore any query for other types of devices.
return X_ERROR_DEVICE_NOT_CONNECTED; return X_ERROR_DEVICE_NOT_CONNECTED;
} }