From 7881bd352bcbd916f84e320650b7e974e6cdff2d Mon Sep 17 00:00:00 2001 From: w1naenator Date: Tue, 15 Jul 2025 01:40:27 +0300 Subject: [PATCH] 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_*). --- src/core/libraries/ime/ime.cpp | 215 +++++++++++++++++++++-- src/core/libraries/ime/ime.h | 7 +- src/core/libraries/ime/ime_common.h | 194 +++++++++++++++++--- src/core/libraries/ime/ime_dialog.cpp | 65 +++++-- src/core/libraries/ime/ime_dialog_ui.cpp | 2 +- 5 files changed, 432 insertions(+), 51 deletions(-) diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index 54e856e87..e144a622c 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -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(param->option) & ~0x7BFF) { // Basic check for invalid options + LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid option 0x{:X}", + static_cast(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(param->type)); + break; case OrbisImeType::BasicLatin: + *width = 500; // dummy value + *height = 100; // dummy value + LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type BasicLatin ({})", + static_cast(param->type)); + break; case OrbisImeType::Url: + *width = 500; // dummy value + *height = 100; // dummy value + LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Url ({})", static_cast(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(param->type)); break; case OrbisImeType::Number: *width = 370; *height = 402; + LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Number ({})", + static_cast(param->type)); break; + default: + LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid IME type ({})", + static_cast(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(param->type)); + LOG_DEBUG(Lib_Ime, "param: supported_languages={:064b}", + static_cast(param->supported_languages)); + LOG_DEBUG(Lib_Ime, "param: enter_label={}", static_cast(param->enter_label)); + LOG_DEBUG(Lib_Ime, "param: input_method={}", static_cast(param->input_method)); + LOG_DEBUG(Lib_Ime, "param: filter={:p}", reinterpret_cast(param->filter)); + LOG_DEBUG(Lib_Ime, "param: option={:032b}", static_cast(param->option)); + LOG_DEBUG(Lib_Ime, "param: maxTextLength={}", param->maxTextLength); + LOG_DEBUG(Lib_Ime, "param: inputTextBuffer={:p}", + static_cast(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(param->horizontal_alignment)); + LOG_DEBUG(Lib_Ime, "param: vertical_alignment={}", + static_cast(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(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(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(extended->priority)); + LOG_DEBUG(Lib_Ime, "extended: additional_dictionary_path={:p}", + static_cast(extended->additional_dictionary_path)); + LOG_DEBUG(Lib_Ime, "extended: ext_keyboard_filter={:p}", + reinterpret_cast(extended->ext_keyboard_filter)); + LOG_DEBUG(Lib_Ime, "extended: disable_device={:032b}", + static_cast(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(param->user_id)); + return Error::INVALID_USER_ID; + } + + if (!magic_enum::enum_contains(param->type)) { + LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid type ({})", static_cast(param->type)); + return Error::INVALID_TYPE; + } + + if (static_cast(param->supported_languages) & ~kValidOrbisImeLanguageMask) { + LOG_ERROR(Lib_Ime, "sceImeOpen: supported_languages has invalid bits (0x{:016X})", + static_cast(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(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(param->input_method)); + return Error::INVALID_INPUT_METHOD; + } + + if (static_cast(param->option) & ~kValidImeOptionMask) { + LOG_ERROR(Lib_Ime, "sceImeOpen: option has invalid bits set (0x{:X}), mask=(0x{:X})", + static_cast(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(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(param->vertical_alignment)); + return Error::INVALID_VERTICALALIGNMENT; + } + + if (extended) { + u32 ext_option_value = static_cast(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(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; diff --git a/src/core/libraries/ime/ime.h b/src/core/libraries/ime/ime.h index c2b80809c..5fd6943a6 100644 --- a/src/core/libraries/ime/ime.h +++ b/src/core/libraries/ime/ime.h @@ -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(); diff --git a/src/core/libraries/ime/ime_common.h b/src/core/libraries/ime/ime_common.h index 5c0030030..941a8f910 100644 --- a/src/core/libraries/ime/ime_common.h +++ b/src/core/libraries/ime/ime_common.h @@ -3,6 +3,7 @@ #pragma once +#include #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 +constexpr std::underlying_type_t generate_full_mask() { + static_assert(std::is_enum_v, "E must be an enum type."); + static_assert(magic_enum::customize::enum_range::is_flags, + "E must be marked as is_flags = true."); + + using U = std::underlying_type_t; + U mask = 0; + + for (E value : magic_enum::enum_values()) { + mask |= static_cast(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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidImeOptionMask = generate_full_mask(); + +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( + 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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidImeDialogExtOptionMask = generate_full_mask(); 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 { + static constexpr bool is_flags = true; +}; +constexpr u64 kValidOrbisImeLanguageMask = generate_full_mask(); + +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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidOrbisImeDisableDeviceMask = generate_full_mask(); + +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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidOrbisImeInputMethodStateMask = generate_full_mask(); + +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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidOrbisImeInitExtKeyboardModeMask = + generate_full_mask(); + +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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidOrbisImeKeycodeStateMask = generate_full_mask(); + +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 { + static constexpr bool is_flags = true; +}; +constexpr u32 kValidOrbisImeKeyboardOptionMask = generate_full_mask(); + +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]; }; diff --git a/src/core/libraries/ime/ime_dialog.cpp b/src/core/libraries/ime/ime_dialog.cpp index 6f808636b..6d29be046 100644 --- a/src/core/libraries/ime/ime_dialog.cpp +++ b/src/core/libraries/ime/ime_dialog.cpp @@ -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(param), static_cast(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(param->user_id)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.type = {}", static_cast(param->type)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.supported_languages = 0x{:X}", + static_cast(param->supported_languages)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.enter_label = {}", + static_cast(param->enter_label)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_method = {}", + static_cast(param->input_method)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.filter = {}", (void*)param->filter); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.option = 0x{:X}", + static_cast(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(param->horizontal_alignment)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.vertical_alignment = {}", + static_cast(param->vertical_alignment)); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.placeholder = {}", + param->placeholder ? "" : "NULL"); + LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.title = {}", + param->title ? "" : "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(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(extended->disable_device) & ~kValidOrbisImeDisableDeviceMask) { + LOG_ERROR(Lib_ImeDialog, + "sceImeDialogInit: disable_device has invalid bits set (0x{:X})", + static_cast(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; } diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 746a2c8d3..800ba1124 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -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)) {