[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/base/cvar.h"
#include "xenia/base/platform_win.h"
#include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_system.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 hid {
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_INPUT_STATE* out_state) {
if (user_index != user_index_) {
if (user_index != user_index_ || cvars::keyboard_passthru) {
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_INPUT_KEYSTROKE* out_keystroke) {
if (user_index != user_index_) {
if (!cvars::keyboard_passthru && user_index != user_index_) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
@ -275,6 +282,9 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
key_events_.pop();
}
if (cvars::keyboard_passthru) {
virtual_key = evt.vkey;
} else {
// TODO(DrChat): Some other way to toggle this...
if (IS_KEY_TOGGLED(VK_CAPITAL)) {
// dpad toggled
@ -367,7 +377,9 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
// 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
@ -381,12 +393,38 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
result = X_ERROR_SUCCESS;
}
} else {
// Handle keydown/keyup for VK_SHIFT
if (virtual_key == VK_SHIFT) {
if (evt.transition == false) {
keystroke_flags |= 0x0002;
} else if (evt.transition == true) {
keystroke_flags |= 0x0001;
}
}
// Only handle keydown for other keys, since some stupid games will count
// keyup as another keypress (seen in SR1..)
if (virtual_key != 0 && virtual_key != 0x10) {
if (evt.transition) {
keystroke_flags |= 0x0001;
}
}
if (keystroke_flags != 0) {
result = X_ERROR_SUCCESS;
}
}
if (!result) {
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;
} else {
memset(out_keystroke, 0, sizeof(X_INPUT_KEYSTROKE));
}
// X_ERROR_EMPTY if no new keys
// 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;
constexpr uint32_t XINPUT_FLAG_GAMEPAD = 0x01;
constexpr uint32_t XINPUT_FLAG_KEYBOARD = 0x02;
constexpr uint32_t XINPUT_FLAG_ANY_USER = 1 << 30;
void XamResetInactivity() {
@ -157,7 +158,8 @@ dword_result_t XamInputGetKeystrokeEx(lpdword_t user_index_ptr, dword_t flags,
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.
return X_ERROR_DEVICE_NOT_CONNECTED;
}