mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 10:04:39 +00:00
Ime lib fixes
- Updated functions to consistently use the Error enum type for return values. - Added detailed logging to aid future IME/OSK development and debugging. - Now use OrbisUserServiceUserId (s32) and OrbisImeKeycodeState in relevant functions and structs. - Introduced a generic template method to generate full bitmasks for all Orbis flag-style enums, simplifying validation and mask creation. - Implemented additional parameter validations in sceImeOpen. - Added missing enums: OrbisDisableDevice, OrbisImeInputMethodState, OrbisImeInitExtKeyboardMode, OrbisImeKeycodeState, and other USB keyboard-related enums. - Fixed incorrect usage of format specifiers in calls to logging macros (LOG_*).
This commit is contained in:
parent
ee1424186e
commit
7881bd352b
@ -144,17 +144,17 @@ int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_INFO(Lib_Ime, "(STUBBED) called");
|
||||
Error PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
|
||||
g_ime_handler.release();
|
||||
g_ime_ui = ImeUi();
|
||||
g_ime_state = ImeState();
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeConfigGet() {
|
||||
@ -223,32 +223,68 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() {
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize called");
|
||||
|
||||
if (!width || !height) {
|
||||
if (!param) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: param is NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
if (!width) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: width pointer is NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
if (!height) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: height pointer is NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (static_cast<u32>(param->option) & ~0x7BFF) { // Basic check for invalid options
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid option 0x{:X}",
|
||||
static_cast<u32>(param->option));
|
||||
return Error::INVALID_OPTION;
|
||||
}
|
||||
|
||||
switch (param->type) {
|
||||
case OrbisImeType::Default:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Default ({})",
|
||||
static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::BasicLatin:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type BasicLatin ({})",
|
||||
static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Url:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Url ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Mail:
|
||||
// We set our custom sizes, commented sizes are the original ones
|
||||
*width = 500; // 793
|
||||
*height = 100; // 408
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Mail ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Number:
|
||||
*width = 370;
|
||||
*height = 402;
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Number ({})",
|
||||
static_cast<u32>(param->type));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid IME type ({})",
|
||||
static_cast<u32>(param->type));
|
||||
return Error::INVALID_TYPE;
|
||||
}
|
||||
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) {
|
||||
LOG_INFO(Lib_Ime, "(STUBBED) called");
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(OrbisUserServiceUserId userId) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!g_keyboard_handler) {
|
||||
return Error::NOT_OPENED;
|
||||
@ -268,9 +304,12 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(OrbisUserServiceUserId userId,
|
||||
const OrbisImeKeyboardParam* param) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
LOG_INFO(Lib_Ime, "kValidImeDialogExtOptionMask=0x{:X}", kValidImeDialogExtOptionMask);
|
||||
|
||||
if (!param) {
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
@ -308,13 +347,169 @@ Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExt
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!param) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: param is null");
|
||||
return Error::INVALID_ADDRESS;
|
||||
} else {
|
||||
// LOG_DEBUG values for debugging purposes
|
||||
LOG_DEBUG(Lib_Ime, "param: user_id={}", param->user_id);
|
||||
LOG_DEBUG(Lib_Ime, "param: type={}", static_cast<u32>(param->type));
|
||||
LOG_DEBUG(Lib_Ime, "param: supported_languages={:064b}",
|
||||
static_cast<u64>(param->supported_languages));
|
||||
LOG_DEBUG(Lib_Ime, "param: enter_label={}", static_cast<u32>(param->enter_label));
|
||||
LOG_DEBUG(Lib_Ime, "param: input_method={}", static_cast<u32>(param->input_method));
|
||||
LOG_DEBUG(Lib_Ime, "param: filter={:p}", reinterpret_cast<void*>(param->filter));
|
||||
LOG_DEBUG(Lib_Ime, "param: option={:032b}", static_cast<u32>(param->option));
|
||||
LOG_DEBUG(Lib_Ime, "param: maxTextLength={}", param->maxTextLength);
|
||||
LOG_DEBUG(Lib_Ime, "param: inputTextBuffer={:p}",
|
||||
static_cast<const void*>(param->inputTextBuffer));
|
||||
LOG_DEBUG(Lib_Ime, "param: posx={}", param->posx);
|
||||
LOG_DEBUG(Lib_Ime, "param: posy={}", param->posy);
|
||||
LOG_DEBUG(Lib_Ime, "param: horizontal_alignment={}",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
LOG_DEBUG(Lib_Ime, "param: vertical_alignment={}",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
LOG_DEBUG(Lib_Ime, "param: work={:p}", param->work);
|
||||
LOG_DEBUG(Lib_Ime, "param: arg={:p}", param->arg);
|
||||
LOG_DEBUG(Lib_Ime, "param: handler={:p}", reinterpret_cast<void*>(param->handler));
|
||||
}
|
||||
|
||||
if (!extended) {
|
||||
LOG_INFO(Lib_Ime, "sceImeOpen: extended is null");
|
||||
} else {
|
||||
// LOG_DEBUG values for debugging purposes
|
||||
LOG_DEBUG(Lib_Ime, "extended: option={:032b}", static_cast<u32>(extended->option));
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_base={{{},{},{},{}}}", extended->color_base.r,
|
||||
extended->color_base.g, extended->color_base.b, extended->color_base.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_line={{{},{},{},{}}}", extended->color_line.r,
|
||||
extended->color_line.g, extended->color_line.b, extended->color_line.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_text_field={{{},{},{},{}}}",
|
||||
extended->color_text_field.r, extended->color_text_field.g,
|
||||
extended->color_text_field.b, extended->color_text_field.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_preedit={{{},{},{},{}}}", extended->color_preedit.r,
|
||||
extended->color_preedit.g, extended->color_preedit.b, extended->color_preedit.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_button_default={{{},{},{},{}}}",
|
||||
extended->color_button_default.r, extended->color_button_default.g,
|
||||
extended->color_button_default.b, extended->color_button_default.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_button_function={{{},{},{},{}}}",
|
||||
extended->color_button_function.r, extended->color_button_function.g,
|
||||
extended->color_button_function.b, extended->color_button_function.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_button_symbol={{{},{},{},{}}}",
|
||||
extended->color_button_symbol.r, extended->color_button_symbol.g,
|
||||
extended->color_button_symbol.b, extended->color_button_symbol.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_text={{{},{},{},{}}}", extended->color_text.r,
|
||||
extended->color_text.g, extended->color_text.b, extended->color_text.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: color_special={{{},{},{},{}}}", extended->color_special.r,
|
||||
extended->color_special.g, extended->color_special.b, extended->color_special.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended: priority={}", static_cast<u32>(extended->priority));
|
||||
LOG_DEBUG(Lib_Ime, "extended: additional_dictionary_path={:p}",
|
||||
static_cast<const void*>(extended->additional_dictionary_path));
|
||||
LOG_DEBUG(Lib_Ime, "extended: ext_keyboard_filter={:p}",
|
||||
reinterpret_cast<void*>(extended->ext_keyboard_filter));
|
||||
LOG_DEBUG(Lib_Ime, "extended: disable_device={:032b}",
|
||||
static_cast<u32>(extended->disable_device));
|
||||
LOG_DEBUG(Lib_Ime, "extended: ext_keyboard_mode={}", extended->ext_keyboard_mode);
|
||||
}
|
||||
|
||||
if (param->user_id < 1 || param->user_id > 4) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid user_id ({})", static_cast<u32>(param->user_id));
|
||||
return Error::INVALID_USER_ID;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->type)) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid type ({})", static_cast<u32>(param->type));
|
||||
return Error::INVALID_TYPE;
|
||||
}
|
||||
|
||||
if (static_cast<u64>(param->supported_languages) & ~kValidOrbisImeLanguageMask) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: supported_languages has invalid bits (0x{:016X})",
|
||||
static_cast<u64>(param->supported_languages));
|
||||
return Error::INVALID_SUPPORTED_LANGUAGES;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->enter_label)) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid enter_label ({})",
|
||||
static_cast<u32>(param->enter_label));
|
||||
return Error::INVALID_ENTER_LABEL;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->input_method)) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid input_method ({})",
|
||||
static_cast<u32>(param->input_method));
|
||||
return Error::INVALID_INPUT_METHOD;
|
||||
}
|
||||
|
||||
if (static_cast<u32>(param->option) & ~kValidImeOptionMask) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: option has invalid bits set (0x{:X}), mask=(0x{:X})",
|
||||
static_cast<u32>(param->option), kValidImeOptionMask);
|
||||
return Error::INVALID_OPTION;
|
||||
}
|
||||
|
||||
if (param->maxTextLength == 0 || param->maxTextLength > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: maxTextLength invalid ({})", param->maxTextLength);
|
||||
return Error::INVALID_MAX_TEXT_LENGTH;
|
||||
}
|
||||
|
||||
if (!param->inputTextBuffer) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: inputTextBuffer is NULL");
|
||||
return Error::INVALID_INPUT_TEXT_BUFFER;
|
||||
}
|
||||
|
||||
bool useHighRes = True(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES);
|
||||
const float maxWidth = useHighRes ? 3840.0f : 1920.0f;
|
||||
const float maxHeight = useHighRes ? 2160.0f : 1080.0f;
|
||||
|
||||
if (param->posx < 0.0f || param->posx >= maxWidth) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: posx out of range (%.2f), max allowed %.0f", param->posx,
|
||||
maxWidth);
|
||||
return Error::INVALID_POSX;
|
||||
}
|
||||
if (param->posy < 0.0f || param->posy >= maxHeight) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: posy out of range (%.2f), max allowed %.0f", param->posy,
|
||||
maxHeight);
|
||||
return Error::INVALID_POSY;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->horizontal_alignment)) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid horizontal_alignment ({})",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
return Error::INVALID_HORIZONTALIGNMENT;
|
||||
}
|
||||
if (!magic_enum::enum_contains(param->vertical_alignment)) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid vertical_alignment ({})",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
return Error::INVALID_VERTICALALIGNMENT;
|
||||
}
|
||||
|
||||
if (extended) {
|
||||
u32 ext_option_value = static_cast<u32>(extended->option);
|
||||
if (ext_option_value & ~kValidImeExtOptionMask) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: extended->option has invalid bits set (0x{:X})",
|
||||
ext_option_value);
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!param->work) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: work buffer is NULL");
|
||||
return Error::INVALID_WORK;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < sizeof(param->reserved); ++i) {
|
||||
if (param->reserved[i] != 0) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: reserved field must be zeroed");
|
||||
return Error::INVALID_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: validate arg and handler
|
||||
|
||||
if (g_ime_handler) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeOpen: Error BUSY");
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
g_ime_handler = std::make_unique<ImeHandler>(param);
|
||||
LOG_INFO(Lib_Ime, "sceImeOpen: OK");
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
@ -324,7 +519,7 @@ int PS4_SYSV_ABI sceImeOpenInternal() {
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
LOG_INFO(Lib_Ime, "sceImeParamInit called");
|
||||
|
||||
if (!param) {
|
||||
return;
|
||||
|
@ -18,7 +18,7 @@ int PS4_SYSV_ABI InitializeImeModule();
|
||||
int PS4_SYSV_ABI sceImeCheckFilterText();
|
||||
int PS4_SYSV_ABI sceImeCheckRemoteEventParam();
|
||||
int PS4_SYSV_ABI sceImeCheckUpdateTextInfo();
|
||||
int PS4_SYSV_ABI sceImeClose();
|
||||
Error PS4_SYSV_ABI sceImeClose();
|
||||
int PS4_SYSV_ABI sceImeConfigGet();
|
||||
int PS4_SYSV_ABI sceImeConfigSet();
|
||||
int PS4_SYSV_ABI sceImeConfirmCandidate();
|
||||
@ -33,10 +33,11 @@ int PS4_SYSV_ABI sceImeFilterText();
|
||||
int PS4_SYSV_ABI sceImeForTestFunction();
|
||||
int PS4_SYSV_ABI sceImeGetPanelPositionAndForm();
|
||||
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height);
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(s32 userId);
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(OrbisUserServiceUserId userId);
|
||||
int PS4_SYSV_ABI sceImeKeyboardGetInfo();
|
||||
int PS4_SYSV_ABI sceImeKeyboardGetResourceId();
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param);
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(OrbisUserServiceUserId userId,
|
||||
const OrbisImeKeyboardParam* param);
|
||||
int PS4_SYSV_ABI sceImeKeyboardOpenInternal();
|
||||
int PS4_SYSV_ABI sceImeKeyboardSetMode();
|
||||
int PS4_SYSV_ABI sceImeKeyboardUpdate();
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "common/enum.h"
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/rtc/rtc.h"
|
||||
@ -10,8 +11,28 @@
|
||||
constexpr u32 ORBIS_IME_MAX_TEXT_LENGTH = 2048;
|
||||
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
|
||||
|
||||
using OrbisUserServiceUserId = s32;
|
||||
|
||||
template <typename E>
|
||||
constexpr std::underlying_type_t<E> generate_full_mask() {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum type.");
|
||||
static_assert(magic_enum::customize::enum_range<E>::is_flags,
|
||||
"E must be marked as is_flags = true.");
|
||||
|
||||
using U = std::underlying_type_t<E>;
|
||||
U mask = 0;
|
||||
|
||||
for (E value : magic_enum::enum_values<E>()) {
|
||||
mask |= static_cast<U>(value);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
enum class Error : u32 {
|
||||
OK = 0x0,
|
||||
|
||||
// ImeDialog library
|
||||
BUSY = 0x80bc0001,
|
||||
NOT_OPENED = 0x80bc0002,
|
||||
NO_MEMORY = 0x80bc0003,
|
||||
@ -46,6 +67,8 @@ enum class Error : u32 {
|
||||
INVALID_RESERVED = 0x80bc0032,
|
||||
INVALID_TIMING = 0x80bc0033,
|
||||
INTERNAL = 0x80bc00ff,
|
||||
|
||||
// Ime library
|
||||
DIALOG_INVALID_TITLE = 0x80bc0101,
|
||||
DIALOG_NOT_RUNNING = 0x80bc0105,
|
||||
DIALOG_NOT_FINISHED = 0x80bc0106,
|
||||
@ -67,9 +90,44 @@ enum class OrbisImeOption : u32 {
|
||||
DISABLE_POSITION_ADJUSTMENT = 2048,
|
||||
EXPANDED_PREEDIT_BUFFER = 4096,
|
||||
USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192,
|
||||
USE_2K_COORDINATES = 16384,
|
||||
USE_OVER_2K_COORDINATES = 16384,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidImeOptionMask = generate_full_mask<OrbisImeOption>();
|
||||
|
||||
enum class OrbisImeExtOption : u32 {
|
||||
DEFAULT = 0x00000000,
|
||||
SET_PRIORITY = 0x00000002,
|
||||
PRIORITY_FULL_WIDTH = 0x00000008,
|
||||
PRIORITY_FIXED_PANEL = 0x00000010,
|
||||
DISABLE_POINTER = 0x00000040,
|
||||
ENABLE_ADDITIONAL_DICTIONARY = 0x00000080,
|
||||
DISABLE_STARTUP_SE = 0x00000100,
|
||||
DISABLE_LIST_FOR_EXT_KEYBOARD = 0x00000200,
|
||||
HIDE_KEYPANEL_IF_EXT_KEYBOARD = 0x00000400,
|
||||
INIT_EXT_KEYBOARD_MODE = 0x00000800,
|
||||
|
||||
ENABLE_ACCESSIBILITY = 0x00001000, // ImeDialog unly
|
||||
ADDITIONAL_DICTIONARY_PRIORITY_MODE = 0x00004000, // ImeDialog only
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeExtOption);
|
||||
|
||||
constexpr u32 kValidImeExtOptionMask = static_cast<u32>(
|
||||
OrbisImeExtOption::SET_PRIORITY | OrbisImeExtOption::PRIORITY_FULL_WIDTH |
|
||||
OrbisImeExtOption::PRIORITY_FIXED_PANEL | OrbisImeExtOption::DISABLE_POINTER |
|
||||
OrbisImeExtOption::ENABLE_ADDITIONAL_DICTIONARY | OrbisImeExtOption::DISABLE_STARTUP_SE |
|
||||
OrbisImeExtOption::DISABLE_LIST_FOR_EXT_KEYBOARD |
|
||||
OrbisImeExtOption::HIDE_KEYPANEL_IF_EXT_KEYBOARD | OrbisImeExtOption::INIT_EXT_KEYBOARD_MODE);
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeExtOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidImeDialogExtOptionMask = generate_full_mask<OrbisImeExtOption>();
|
||||
|
||||
enum class OrbisImeLanguage : u64 {
|
||||
DANISH = 0x0000000000000001,
|
||||
@ -105,6 +163,113 @@ enum class OrbisImeLanguage : u64 {
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeLanguage);
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeLanguage> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u64 kValidOrbisImeLanguageMask = generate_full_mask<OrbisImeLanguage>();
|
||||
|
||||
enum class OrbisImeDisableDevice : u32 {
|
||||
DEFAULT = 0x00000000,
|
||||
CONTROLLER = 0x00000001,
|
||||
EXT_KEYBOARD = 0x00000002,
|
||||
REMOTE_OSK = 0x00000004,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDisableDevice);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeDisableDevice> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidOrbisImeDisableDeviceMask = generate_full_mask<OrbisImeDisableDevice>();
|
||||
|
||||
enum class OrbisImeInputMethodState : u32 {
|
||||
PREEDIT = 0x01000000,
|
||||
SELECTED = 0x02000000,
|
||||
NATIVE = 0x04000000,
|
||||
NATIVE2 = 0x08000000,
|
||||
FULL_WIDTH = 0x10000000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInputMethodState);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeInputMethodState> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidOrbisImeInputMethodStateMask = generate_full_mask<OrbisImeInputMethodState>();
|
||||
|
||||
enum class OrbisImeInitExtKeyboardMode : u32 {
|
||||
ISABLE_ARABIC_INDIC_NUMERALS = 0x00000001,
|
||||
ENABLE_FORMAT_CHARACTERS = 0x00000002,
|
||||
INPUT_METHOD_STATE_NATIVE = 0x04000000,
|
||||
INPUT_METHOD_STATE_NATIVE2 = 0x08000000,
|
||||
INPUT_METHOD_STATE_FULL_WIDTH = 0x10000000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInitExtKeyboardMode);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeInitExtKeyboardMode> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidOrbisImeInitExtKeyboardModeMask =
|
||||
generate_full_mask<OrbisImeInitExtKeyboardMode>();
|
||||
|
||||
enum class OrbisImeKeycodeState : u32 {
|
||||
KEYCODE_VALID = 0x00000001,
|
||||
CHARACTER_VALID = 0x00000002,
|
||||
WITH_IME = 0x00000004,
|
||||
FROM_OSK = 0x00000008,
|
||||
FROM_OSK_SHORTCUT = 0x00000010,
|
||||
FROM_IME_OPERATION = 0x00000020,
|
||||
REPLACE_CHARACTER = 0x00000040,
|
||||
CONTINUOUS_EVENT = 0x00000080,
|
||||
MODIFIER_L_CTRL = 0x00000100,
|
||||
MODIFIER_L_SHIFT = 0x00000200,
|
||||
MODIFIER_L_ALT = 0x00000400,
|
||||
MODIFIER_L_GUI = 0x00000800,
|
||||
MODIFIER_R_CTRL = 0x00001000,
|
||||
MODIFIER_R_SHIFT = 0x00002000,
|
||||
MODIFIER_R_ALT = 0x00004000,
|
||||
MODIFIER_R_GUI = 0x00008000,
|
||||
LED_NUM_LOCK = 0x00010000,
|
||||
LED_CAPS_LOCK = 0x00020000,
|
||||
LED_SCROLL_LOCK = 0x00040000,
|
||||
RESERVED1 = 0x00080000,
|
||||
RESERVED2 = 0x00100000,
|
||||
FROM_IME_INPUT = 0x00200000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeycodeState);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeKeycodeState> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidOrbisImeKeycodeStateMask = generate_full_mask<OrbisImeKeycodeState>();
|
||||
|
||||
enum class OrbisImeKeyboardOption : u32 {
|
||||
Default = 0,
|
||||
Repeat = 1,
|
||||
RepeatEachKey = 2,
|
||||
AddOsk = 4,
|
||||
EffectiveWithIme = 8,
|
||||
DisableResume = 16,
|
||||
DisableCapslockWithoutShift = 32,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeKeyboardOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
constexpr u32 kValidOrbisImeKeyboardOptionMask = generate_full_mask<OrbisImeKeyboardOption>();
|
||||
|
||||
enum class OrbisImeKeyboardMode : u32 {
|
||||
Auto = 0,
|
||||
Manual = 1,
|
||||
Alphabet = 0,
|
||||
Native = 2,
|
||||
Part = 4,
|
||||
Katakana = 8,
|
||||
Hkana = 16,
|
||||
ArabicIndicNumerals = 32,
|
||||
DisableFormatCharacters = 64,
|
||||
};
|
||||
|
||||
enum class OrbisImeType : u32 {
|
||||
Default = 0,
|
||||
BasicLatin = 1,
|
||||
@ -260,13 +425,13 @@ struct OrbisImeKeycode {
|
||||
char16_t character;
|
||||
u32 status;
|
||||
OrbisImeKeyboardType type;
|
||||
s32 user_id; // Todo: switch to OrbisUserServiceUserId
|
||||
OrbisUserServiceUserId user_id;
|
||||
u32 resource_id;
|
||||
Libraries::Rtc::OrbisRtcTick timestamp;
|
||||
};
|
||||
|
||||
struct OrbisImeKeyboardResourceIdArray {
|
||||
s32 user_id; // Todo: switch to OrbisUserServiceUserId
|
||||
OrbisUserServiceUserId user_id;
|
||||
u32 resource_id[5];
|
||||
};
|
||||
|
||||
@ -322,17 +487,6 @@ using OrbisImeTextFilter = PS4_SYSV_ABI int (*)(char16_t* outText, u32* outTextL
|
||||
|
||||
using OrbisImeEventHandler = PS4_SYSV_ABI void (*)(void* arg, const OrbisImeEvent* e);
|
||||
|
||||
enum class OrbisImeKeyboardOption : u32 {
|
||||
Default = 0,
|
||||
Repeat = 1,
|
||||
RepeatEachKey = 2,
|
||||
AddOsk = 4,
|
||||
EffectiveWithIme = 8,
|
||||
DisableResume = 16,
|
||||
DisableCapslockWithoutShift = 32,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
|
||||
|
||||
struct OrbisImeKeyboardParam {
|
||||
OrbisImeKeyboardOption option;
|
||||
s8 reserved1[4];
|
||||
@ -342,9 +496,9 @@ struct OrbisImeKeyboardParam {
|
||||
};
|
||||
|
||||
struct OrbisImeParam {
|
||||
s32 user_id; // Todo: switch to OrbisUserServiceUserId
|
||||
OrbisUserServiceUserId user_id;
|
||||
OrbisImeType type;
|
||||
u64 supported_languages; // OrbisImeLanguage flags
|
||||
OrbisImeLanguage supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
@ -369,9 +523,9 @@ struct OrbisImeCaret {
|
||||
};
|
||||
|
||||
struct OrbisImeDialogParam {
|
||||
s32 user_id;
|
||||
OrbisUserServiceUserId user_id;
|
||||
OrbisImeType type;
|
||||
u64 supported_languages; // OrbisImeLanguage flags
|
||||
OrbisImeLanguage supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
@ -388,7 +542,7 @@ struct OrbisImeDialogParam {
|
||||
};
|
||||
|
||||
struct OrbisImeParamExtended {
|
||||
u32 option; // OrbisImeExtOption flags
|
||||
OrbisImeExtOption option;
|
||||
OrbisImeColor color_base;
|
||||
OrbisImeColor color_line;
|
||||
OrbisImeColor color_text_field;
|
||||
@ -401,7 +555,7 @@ struct OrbisImeParamExtended {
|
||||
OrbisImePanelPriority priority;
|
||||
char* additional_dictionary_path;
|
||||
OrbisImeExtKeyboardFilter ext_keyboard_filter;
|
||||
u32 disable_device;
|
||||
OrbisImeDisableDevice disable_device;
|
||||
u32 ext_keyboard_mode;
|
||||
s8 reserved[60];
|
||||
};
|
||||
|
@ -149,20 +149,47 @@ OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() {
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) {
|
||||
LOG_INFO(Lib_ImeDialog, ">> sceImeDialogInit: entering, param={}, extended={}",
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: entering, param={}, extended={}",
|
||||
static_cast<void*>(param), static_cast<void*>(extended));
|
||||
if (g_ime_dlg_status != OrbisImeDialogStatus::None) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: busy (status=%u)", (u32)g_ime_dlg_status);
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: param is null");
|
||||
return Error::INVALID_ADDRESS;
|
||||
} else {
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.user_id = {}",
|
||||
static_cast<u32>(param->user_id));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.type = {}", static_cast<u32>(param->type));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.supported_languages = 0x{:X}",
|
||||
static_cast<u64>(param->supported_languages));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.enter_label = {}",
|
||||
static_cast<u32>(param->enter_label));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_method = {}",
|
||||
static_cast<u32>(param->input_method));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.filter = {}", (void*)param->filter);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.option = 0x{:X}",
|
||||
static_cast<u32>(param->option));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.max_text_length = {}",
|
||||
param->max_text_length);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_text_buffer = {}",
|
||||
(void*)param->input_text_buffer);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posx = {}", param->posx);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posy = {}", param->posy);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.horizontal_alignment = {}",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.vertical_alignment = {}",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.placeholder = {}",
|
||||
param->placeholder ? "<non-null>" : "NULL");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.title = {}",
|
||||
param->title ? "<non-null>" : "NULL");
|
||||
}
|
||||
if (g_ime_dlg_status != OrbisImeDialogStatus::None) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: busy (status={})", (u32)g_ime_dlg_status);
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->type)) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid param->type=%u", (u32)param->type);
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid param->type={}", (u32)param->type);
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
@ -170,14 +197,16 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
// TODO: do correct param->supportedLanguages validation
|
||||
|
||||
if (param->posx < 0.0f ||
|
||||
param->posx >= MAX_X_POSITIONS[False(param->option & OrbisImeOption::USE_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posx=%f", param->posx);
|
||||
param->posx >=
|
||||
MAX_X_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posx={}", param->posx);
|
||||
return Error::INVALID_POSX;
|
||||
}
|
||||
|
||||
if (param->posy < 0.0f ||
|
||||
param->posy >= MAX_Y_POSITIONS[False(param->option & OrbisImeOption::USE_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posy=%f", param->posy);
|
||||
param->posy >=
|
||||
MAX_Y_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posy={}", param->posy);
|
||||
return Error::INVALID_POSY;
|
||||
}
|
||||
|
||||
@ -192,7 +221,7 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
}
|
||||
|
||||
if (!IsValidOption(param->option, param->type)) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid option=0x%X for type=%u",
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid option=0x{:X}for type={}",
|
||||
static_cast<u32>(param->option), (u32)param->type);
|
||||
return Error::INVALID_PARAM;
|
||||
}
|
||||
@ -204,25 +233,27 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
|
||||
if (extended) {
|
||||
if (!magic_enum::enum_contains(extended->priority)) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->priority");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->priority");
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
|
||||
// TODO: do correct extended->option validation
|
||||
|
||||
if ((extended->ext_keyboard_mode & 0xe3fffffc) != 0) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->extKeyboardMode");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->extKeyboardMode");
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
|
||||
if (extended->disable_device > 7) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->disableDevice");
|
||||
if (static_cast<u32>(extended->disable_device) & ~kValidOrbisImeDisableDeviceMask) {
|
||||
LOG_ERROR(Lib_ImeDialog,
|
||||
"sceImeDialogInit: disable_device has invalid bits set (0x{:X})",
|
||||
static_cast<u32>(extended->disable_device));
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
if (param->max_text_length == 0 || param->max_text_length > ORBIS_IME_MAX_TEXT_LENGTH) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid max_text_length=%u",
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid max_text_length={}",
|
||||
param->max_text_length);
|
||||
return Error::INVALID_MAX_TEXT_LENGTH;
|
||||
}
|
||||
@ -238,7 +269,7 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
g_ime_dlg_status = OrbisImeDialogStatus::Running;
|
||||
g_ime_dlg_ui = ImeDialogUi(&g_ime_dlg_state, &g_ime_dlg_status, &g_ime_dlg_result);
|
||||
|
||||
LOG_INFO(Lib_ImeDialog, "<< sceImeDialogInit: successful, status now=Running");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: successful, status now=Running");
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,7 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
|
||||
// the current language?)
|
||||
.user_id = ui->state->user_id,
|
||||
.resource_id = 0,
|
||||
.timestamp = 0,
|
||||
.timestamp = {0},
|
||||
};
|
||||
|
||||
if (!ui->state->ConvertUTF8ToOrbis(event_char, 4, &src_keycode.character, 1)) {
|
||||
|
Loading…
Reference in New Issue
Block a user