Merge pull request #8150 from lioncash/kbd

IOS/USB_KBD: Minor cleanup
This commit is contained in:
Léo Lam 2019-06-14 15:25:10 +02:00 committed by GitHub
commit 59155b4d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 161 additions and 172 deletions

View File

@ -4,7 +4,7 @@
#include "Core/IOS/USB/USB_KBD.h"
#include <cstring>
#include <array>
#include <queue>
#include "Common/FileUtil.h"
@ -22,156 +22,11 @@
namespace IOS::HLE::Device
{
USB_KBD::SMessageData::SMessageData(u32 type, u8 modifiers, u8* pressed_keys)
namespace
{
MsgType = Common::swap32(type);
Unk1 = 0; // swapped
Modifiers = modifiers;
Unk2 = 0;
if (pressed_keys) // Doesn't need to be in a specific order
memcpy(PressedKeys, pressed_keys, sizeof(PressedKeys));
else
memset(PressedKeys, 0, sizeof(PressedKeys));
}
// TODO: support in netplay/movies.
USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
IPCCommandResult USB_KBD::Open(const OpenRequest& request)
{
INFO_LOG(IOS, "USB_KBD: Open");
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);
m_MessageQueue = std::queue<SMessageData>();
for (bool& pressed : m_OldKeyBuffer)
{
pressed = false;
}
m_OldModifiers = 0x00;
// m_MessageQueue.push(SMessageData(MSG_KBD_CONNECT, 0, nullptr));
return Device::Open(request);
}
IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request)
{
// Stubbed.
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() &&
ControlReference::InputGateOn() && !m_MessageQueue.empty())
{
Memory::CopyToEmu(request.buffer_out, &m_MessageQueue.front(), sizeof(SMessageData));
m_MessageQueue.pop();
}
return GetDefaultReply(IPC_SUCCESS);
}
bool USB_KBD::IsKeyPressed(int _Key)
{
#ifdef _WIN32
if (GetAsyncKeyState(_Key) & 0x8000)
return true;
else
return false;
#else
// TODO: do it for non-Windows platforms
return false;
#endif
}
void USB_KBD::Update()
{
if (!SConfig::GetInstance().m_WiiKeyboard || Core::WantsDeterminism() || !m_is_active)
return;
u8 Modifiers = 0x00;
u8 PressedKeys[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bool GotEvent = false;
int num_pressed_keys = 0;
for (int i = 0; i < 256; i++)
{
bool KeyPressedNow = IsKeyPressed(i);
bool KeyPressedBefore = m_OldKeyBuffer[i];
u8 KeyCode = 0;
if (KeyPressedNow ^ KeyPressedBefore)
{
if (KeyPressedNow)
{
switch (m_KeyboardLayout)
{
case KBD_LAYOUT_QWERTY:
KeyCode = m_KeyCodesQWERTY[i];
break;
case KBD_LAYOUT_AZERTY:
KeyCode = m_KeyCodesAZERTY[i];
break;
}
if (KeyCode == 0x00)
continue;
PressedKeys[num_pressed_keys] = KeyCode;
num_pressed_keys++;
if (num_pressed_keys == 6)
break;
}
GotEvent = true;
}
m_OldKeyBuffer[i] = KeyPressedNow;
}
#ifdef _WIN32
if (GetAsyncKeyState(VK_LCONTROL) & 0x8000)
Modifiers |= 0x01;
if (GetAsyncKeyState(VK_LSHIFT) & 0x8000)
Modifiers |= 0x02;
if (GetAsyncKeyState(VK_MENU) & 0x8000)
Modifiers |= 0x04;
if (GetAsyncKeyState(VK_LWIN) & 0x8000)
Modifiers |= 0x08;
if (GetAsyncKeyState(VK_RCONTROL) & 0x8000)
Modifiers |= 0x10;
if (GetAsyncKeyState(VK_RSHIFT) & 0x8000)
Modifiers |= 0x20;
if (GetAsyncKeyState(VK_MENU) &
0x8000) // TODO: VK_MENU is for ALT, not for ALT GR (ALT GR seems to work though...)
Modifiers |= 0x40;
if (GetAsyncKeyState(VK_RWIN) & 0x8000)
Modifiers |= 0x80;
#else
// TODO: modifiers for non-Windows platforms
#endif
if (Modifiers ^ m_OldModifiers)
{
GotEvent = true;
m_OldModifiers = Modifiers;
}
if (GotEvent)
m_MessageQueue.push(SMessageData(MSG_EVENT, Modifiers, PressedKeys));
}
// Crazy ugly
#ifdef _WIN32
u8 USB_KBD::m_KeyCodesQWERTY[256] = {
constexpr std::array<u8, 256> s_key_codes_qwerty{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
@ -241,11 +96,9 @@ u8 USB_KBD::m_KeyCodesQWERTY[256] = {
0x34, // '''
0x00, //
0x00, // Nothing interesting past this point.
};
u8 USB_KBD::m_KeyCodesAZERTY[256] = {
constexpr std::array<u8, 256> s_key_codes_azerty{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
@ -315,11 +168,143 @@ u8 USB_KBD::m_KeyCodesAZERTY[256] = {
0x00, // ' '
0x38, // '!'
0x00, // Nothing interesting past this point.
};
#else
u8 USB_KBD::m_KeyCodesQWERTY[256] = {0};
constexpr std::array<u8, 256> s_key_codes_qwerty{};
u8 USB_KBD::m_KeyCodesAZERTY[256] = {0};
constexpr std::array<u8, 256> s_key_codes_azerty{};
#endif
} // Anonymous namespace
USB_KBD::MessageData::MessageData(MessageType type, u8 modifiers, PressedKeyData pressed_keys)
: msg_type{Common::swap32(static_cast<u32>(type))}, modifiers{modifiers}, pressed_keys{
pressed_keys}
{
}
// TODO: support in netplay/movies.
USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
IPCCommandResult USB_KBD::Open(const OpenRequest& request)
{
INFO_LOG(IOS, "USB_KBD: Open");
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_keyboard_layout, KBD_LAYOUT_QWERTY);
m_message_queue = {};
m_old_key_buffer.fill(false);
m_old_modifiers = 0x00;
// m_message_queue.emplace(MessageType::KeyboardConnect, 0, PressedKeyData{});
return Device::Open(request);
}
IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request)
{
// Stubbed.
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() &&
ControlReference::InputGateOn() && !m_message_queue.empty())
{
Memory::CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData));
m_message_queue.pop();
}
return GetDefaultReply(IPC_SUCCESS);
}
bool USB_KBD::IsKeyPressed(int key) const
{
#ifdef _WIN32
return (GetAsyncKeyState(key) & 0x8000) != 0;
#else
// TODO: do it for non-Windows platforms
return false;
#endif
}
void USB_KBD::Update()
{
if (!SConfig::GetInstance().m_WiiKeyboard || Core::WantsDeterminism() || !m_is_active)
return;
u8 modifiers = 0x00;
PressedKeyData pressed_keys{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bool got_event = false;
size_t num_pressed_keys = 0;
for (size_t i = 0; i < m_old_key_buffer.size(); i++)
{
const bool key_pressed_now = IsKeyPressed(static_cast<int>(i));
const bool key_pressed_before = m_old_key_buffer[i];
u8 key_code = 0;
if (key_pressed_now ^ key_pressed_before)
{
if (key_pressed_now)
{
switch (m_keyboard_layout)
{
case KBD_LAYOUT_QWERTY:
key_code = s_key_codes_qwerty[i];
break;
case KBD_LAYOUT_AZERTY:
key_code = s_key_codes_azerty[i];
break;
}
if (key_code == 0x00)
continue;
pressed_keys[num_pressed_keys] = key_code;
num_pressed_keys++;
if (num_pressed_keys == pressed_keys.size())
break;
}
got_event = true;
}
m_old_key_buffer[i] = key_pressed_now;
}
#ifdef _WIN32
if (GetAsyncKeyState(VK_LCONTROL) & 0x8000)
modifiers |= 0x01;
if (GetAsyncKeyState(VK_LSHIFT) & 0x8000)
modifiers |= 0x02;
if (GetAsyncKeyState(VK_MENU) & 0x8000)
modifiers |= 0x04;
if (GetAsyncKeyState(VK_LWIN) & 0x8000)
modifiers |= 0x08;
if (GetAsyncKeyState(VK_RCONTROL) & 0x8000)
modifiers |= 0x10;
if (GetAsyncKeyState(VK_RSHIFT) & 0x8000)
modifiers |= 0x20;
// TODO: VK_MENU is for ALT, not for ALT GR (ALT GR seems to work though...)
if (GetAsyncKeyState(VK_MENU) & 0x8000)
modifiers |= 0x40;
if (GetAsyncKeyState(VK_RWIN) & 0x8000)
modifiers |= 0x80;
#else
// TODO: modifiers for non-Windows platforms
#endif
if (modifiers ^ m_old_modifiers)
{
got_event = true;
m_old_modifiers = modifiers;
}
if (got_event)
m_message_queue.emplace(MessageType::Event, modifiers, pressed_keys);
}
} // namespace IOS::HLE::Device

View File

@ -4,8 +4,10 @@
#pragma once
#include <array>
#include <queue>
#include <string>
#include <type_traits>
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
@ -24,31 +26,35 @@ public:
void Update() override;
private:
enum
enum class MessageType : u32
{
MSG_KBD_CONNECT = 0,
MSG_KBD_DISCONNECT = 1,
MSG_EVENT = 2
KeyboardConnect = 0,
KeyboardDisconnect = 1,
Event = 2
};
using PressedKeyData = std::array<u8, 6>;
#pragma pack(push, 1)
struct SMessageData
struct MessageData
{
u32 MsgType;
u32 Unk1;
u8 Modifiers;
u8 Unk2;
u8 PressedKeys[6];
MessageType msg_type{};
u32 unk1 = 0;
u8 modifiers = 0;
u8 unk2 = 0;
PressedKeyData pressed_keys{};
SMessageData(u32 msg_type, u8 modifiers, u8* pressed_keys);
MessageData(MessageType msg_type, u8 modifiers, PressedKeyData pressed_keys);
};
static_assert(std::is_trivially_copyable_v<MessageData>,
"MessageData must be trivially copyable, as it's copied into emulated memory.");
#pragma pack(pop)
std::queue<SMessageData> m_MessageQueue;
std::queue<MessageData> m_message_queue;
bool m_OldKeyBuffer[256];
u8 m_OldModifiers;
std::array<bool, 256> m_old_key_buffer{};
u8 m_old_modifiers = 0;
virtual bool IsKeyPressed(int _Key);
bool IsKeyPressed(int key) const;
// This stuff should probably die
enum
@ -56,8 +62,6 @@ private:
KBD_LAYOUT_QWERTY = 0,
KBD_LAYOUT_AZERTY = 1
};
int m_KeyboardLayout;
static u8 m_KeyCodesQWERTY[256];
static u8 m_KeyCodesAZERTY[256];
int m_keyboard_layout = KBD_LAYOUT_QWERTY;
};
} // namespace IOS::HLE::Device