mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
fix(keyboard): preserve raw keys and ignore the Kana LED
This commit is contained in:
1 parent
e2b9700a98
commit
aaa33a3f3e
3 files changed
+69
-10
No files matched your search
@@ -175,17 +175,15 @@ int GetKey2Char(std::int32_t handle, std::int32_t arrange, std::uint32_t ledStat
|
||||
{
|
||||
std::lock_guard lock(keyboardMutex);
|
||||
if (!initialized) return KEYBOARD_ERROR_NOT_INITIALIZED;
|
||||
if (keyCode < 4 || keyCode > 231) return KEYBOARD_ERROR_INVALID_ARG;
|
||||
if (handle != KEYBOARD_HANDLE || !opened) return KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (charData == nullptr) return KEYBOARD_ERROR_INVALID_ARG;
|
||||
if (arrange != KEYBOARD_ARRANGEMENT_101 && arrange != KEYBOARD_ARRANGEMENT_106) return KEYBOARD_ERROR_INVALID_ARG;
|
||||
if (arrange == KEYBOARD_ARRANGEMENT_106 && (ledState & KEYBOARD_LED_KANA) != 0) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return KEYBOARD_ERROR_INVALID_ARG;
|
||||
}
|
||||
*charData = {};
|
||||
charData->char_code = character(arrange == KEYBOARD_ARRANGEMENT_106, ledState, modifierKey, keyCode);
|
||||
charData->processed = charData->char_code != 0;
|
||||
const std::uint16_t converted = character(arrange == KEYBOARD_ARRANGEMENT_106, ledState, modifierKey, keyCode);
|
||||
charData->char_code = converted != 0 ? converted : keyCode;
|
||||
charData->processed = converted != 0;
|
||||
charData->length = charData->processed ? 1 : 0;
|
||||
return KEYBOARD_OK;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_keyboard.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <source_location>
|
||||
#include <stdexcept>
|
||||
|
||||
extern "C" {
|
||||
@@ -19,7 +23,11 @@ int APS5_VABI sceKeyboardConnectPort(void);
|
||||
int APS5_VABI sceKeyboardDisconnectAll(void);
|
||||
}
|
||||
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
static void Require(bool value, std::source_location location = std::source_location::current()) {
|
||||
if (value) return;
|
||||
std::fprintf(stderr, "%s:%u: keyboard assertion failed\n", location.file_name(), location.line());
|
||||
std::abort();
|
||||
}
|
||||
|
||||
static SDL_Event KeyEvent(Uint32 type, SDL_Scancode scancode, Uint16 mod = 0, Uint8 repeat = 0) {
|
||||
SDL_Event event{};
|
||||
@@ -34,14 +42,63 @@ static SDL_Event KeyEvent(Uint32 type, SDL_Scancode scancode, Uint16 mod = 0, Ui
|
||||
static std::uint16_t Char(std::uint32_t led, std::uint32_t modifierKey, std::uint16_t keyCode, std::int32_t arrange = KEYBOARD_ARRANGEMENT_101) {
|
||||
KeyboardCharData data{};
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, arrange, led, modifierKey, keyCode, &data) == KEYBOARD_OK);
|
||||
Require(data.processed == (data.char_code != 0) && data.length == (data.processed ? 1 : 0));
|
||||
return data.char_code;
|
||||
Require(data.processed ? data.char_code != 0 : data.char_code == keyCode);
|
||||
Require(data.length == (data.processed ? 1 : 0));
|
||||
return data.processed ? data.char_code : 0;
|
||||
}
|
||||
|
||||
static std::uint16_t Jis(std::uint32_t modifierKey, std::uint16_t keyCode, std::uint32_t led = 0) {
|
||||
return Char(led, modifierKey, keyCode, KEYBOARD_ARRANGEMENT_106);
|
||||
}
|
||||
|
||||
static void CheckInvalidKeys(bool opened) {
|
||||
constexpr std::uint16_t invalidKeys[] = {0, 1, 2, 3, 232, 255, 256, 65535};
|
||||
for (const auto key : invalidKeys) {
|
||||
for (const auto handle : {KEYBOARD_HANDLE, 42}) {
|
||||
KeyboardCharData data;
|
||||
std::memset(&data, 0xa5, sizeof(data));
|
||||
unsigned char before[sizeof(data)];
|
||||
std::memcpy(before, &data, sizeof(data));
|
||||
Require(sceKeyboardGetKey2Char(handle, KEYBOARD_ARRANGEMENT_101, 0, 0, key, &data) == KEYBOARD_ERROR_INVALID_ARG);
|
||||
Require(std::memcmp(&data, before, sizeof(data)) == 0);
|
||||
Require(sceKeyboardGetKey2Char(handle, KEYBOARD_ARRANGEMENT_106, KEYBOARD_LED_KANA, 0, key, nullptr) == KEYBOARD_ERROR_INVALID_ARG);
|
||||
}
|
||||
}
|
||||
for (const auto key : {std::uint16_t{4}, std::uint16_t{231}}) {
|
||||
KeyboardCharData data{};
|
||||
const auto expected = opened ? KEYBOARD_OK : KEYBOARD_ERROR_INVALID_HANDLE;
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, KEYBOARD_ARRANGEMENT_101, 0, 0, key, &data) == expected);
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckUnconvertedKeys() {
|
||||
constexpr std::uint16_t unconvertedKeys[] = {0x29, 0x39, 0x3a, 0x4f, 0x59, 0x88, 0xe0, 0xe7};
|
||||
for (const auto arrange : {KEYBOARD_ARRANGEMENT_101, KEYBOARD_ARRANGEMENT_106}) {
|
||||
for (const auto key : unconvertedKeys) {
|
||||
KeyboardCharData data{};
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, arrange, 0, 0, key, &data) == KEYBOARD_OK);
|
||||
Require(!data.processed && data.char_code == key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckKanaLed() {
|
||||
for (const auto arrange : {KEYBOARD_ARRANGEMENT_101, KEYBOARD_ARRANGEMENT_106}) {
|
||||
for (const auto modifier : {std::uint8_t{0}, std::uint8_t{KEYBOARD_MOD_LEFT_SHIFT}, std::uint8_t{KEYBOARD_MOD_RIGHT_SHIFT}}) {
|
||||
for (const auto led : {std::uint8_t{0}, std::uint8_t{KEYBOARD_LED_NUM_LOCK | KEYBOARD_LED_CAPS_LOCK}}) {
|
||||
for (std::uint16_t key = 4; key <= 231; ++key) {
|
||||
KeyboardCharData withoutKana{};
|
||||
KeyboardCharData withKana{};
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, arrange, led, modifier, key, &withoutKana) == KEYBOARD_OK);
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, arrange, led | KEYBOARD_LED_KANA, modifier, key, &withKana) == KEYBOARD_OK);
|
||||
Require(withKana.processed == withoutKana.processed);
|
||||
Require(withKana.length == withoutKana.length && withKana.char_code == withoutKana.char_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
KeyboardData data[16]{};
|
||||
KeyboardCharData charData{};
|
||||
@@ -50,11 +107,15 @@ int main() {
|
||||
Require(sceKeyboardGetConnection(KEYBOARD_HANDLE, &connected) == KEYBOARD_ERROR_NOT_INITIALIZED);
|
||||
Require(sceKeyboardInit() == KEYBOARD_OK);
|
||||
Require(sceKeyboardInit() == KEYBOARD_OK);
|
||||
CheckInvalidKeys(false);
|
||||
Require(sceKeyboardOpen(1, 0, 1, nullptr) == KEYBOARD_ERROR_INVALID_ARG);
|
||||
Require(sceKeyboardOpen(1, 1, 0, nullptr) == KEYBOARD_ERROR_INVALID_ARG);
|
||||
Require(sceKeyboardGetKey2Char(KEYBOARD_HANDLE, KEYBOARD_ARRANGEMENT_101, 0, 0, 0x04, &charData) == KEYBOARD_ERROR_INVALID_HANDLE);
|
||||
Require(sceKeyboardGetConnection(KEYBOARD_HANDLE, &connected) == KEYBOARD_ERROR_INVALID_HANDLE);
|
||||
Require(sceKeyboardOpen(1, 0, 0, nullptr) == KEYBOARD_HANDLE);
|
||||
CheckInvalidKeys(true);
|
||||
CheckUnconvertedKeys();
|
||||
CheckKanaLed();
|
||||
Require(sceKeyboardOpen(1, 0, 0, nullptr) == KEYBOARD_ERROR_ALREADY_OPENED);
|
||||
Require(sceKeyboardGetConnection(42, &connected) == KEYBOARD_ERROR_INVALID_HANDLE);
|
||||
Require(sceKeyboardGetConnection(KEYBOARD_HANDLE, nullptr) == KEYBOARD_ERROR_INVALID_ARG);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Functional
|
||||
|
||||
- [sceKeyboardGetKey2Char](../../../core/libs/prx/libSceKeyboard/src/keyboard_impl.cpp): the original validates HID usages 4 through 231 before the handle and preserves unconverted HID usages in the output with `processed == 0`. The host instead accepts out-of-range usages and writes zero for unconverted keys. The original ignores the Kana LED, while the host throws for it. This partially implemented function contains `NotImplemented_nid_no_patch(__func__)`; its body is preserved under the requested restriction. One title (PPSA15246) disassembled for this entry calls it once with an output buffer cleared to 24 bytes, uses a character only when the result is 0 and the first output byte is nonzero, and then reads the 16-bit value at offset 8, which agrees with `processed` and `char_code` as laid out here. Which other output fields it reads and what its other arguments mean are not shown.
|
||||
- [sceKeyboardGetKey2Char](../../../core/libs/prx/libSceKeyboard/src/keyboard_impl.cpp): initialization, output length and reserved bytes remain unverified on a console; unconverted keys retain the host's length of 0. One title (PPSA15246) disassembled for this entry checks the first output byte and reads the 16-bit value at offset 8. Which other output fields it reads and what its other arguments mean are not shown.
|
||||
|
||||
### Unknown function info
|
||||
|
||||
|
||||
Reference in new issue
Block a user