mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-17 00:59:05 +00:00
Ime lib fixes (#3244)
* IME fixes - Moved enums, flags, and structs to ime_common.h to simplify usage with Ime and ImeDialog - Updated Ime to use an enum as the return type, consistent with ImeDialog - Removed duplicate definition of OrbisImeKeycode - Added OrbisImeLanguage as a flags enum - Added missing options to OrbisImeOption - Removed OrbisImeDialogOption; OrbisImeOption should be used instead - Added OrbisImeTextAreaMode - Updated OrbisImeTextAreaMode - Fixed OrbisImeEventParam by adding the missing member OrbisImePanelType panel_type - Updated the sceImeOpen declaration to use extended parameters (not yet implemented) -Fixed Diablo III (CUSA00434) assertion failure on ImeDialog initialization * 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_*). * Data Type Fixes - Replaced the use of the type alias OrbisUserServiceUserId = s32 with Libraries::UserService::OrbisUserServiceUserId directly. * Fixed IDE warnings - generate_full_mask now returns const instead of constexpr. - Added argument list to std::unique_lock<std::mutex> construction for clarity. * Clang fixes * Removed unneccessary comment --------- Co-authored-by: w1naenator <valdis.bogdans@hotmail.com>
This commit is contained in:
@@ -65,7 +65,7 @@ public:
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
std::unique_lock lock{g_ime_state.queue_mutex};
|
||||
std::unique_lock<std::mutex> lock{g_ime_state.queue_mutex};
|
||||
|
||||
while (!g_ime_state.event_queue.empty()) {
|
||||
OrbisImeEvent event = g_ime_state.event_queue.front();
|
||||
@@ -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(Libraries::UserService::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(Libraries::UserService::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;
|
||||
|
||||
Reference in New Issue
Block a user