diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index f3d2c4da8..acfce53d6 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -155,11 +155,13 @@ Error PS4_SYSV_ABI sceImeClose() { LOG_INFO(Lib_Ime, "called"); if (!g_ime_handler) { + LOG_ERROR(Lib_Ime, "No IME handler is open"); return Error::NOT_OPENED; } g_ime_handler.release(); - if (g_keyboard_handler) { + if (g_ime_handler) { + LOG_ERROR(Lib_Ime, "Failed to close IME handler, it is still open"); return Error::INTERNAL; } g_ime_ui = ImeUi(); @@ -252,7 +254,7 @@ Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u3 } if (static_cast(param->option) & ~0x7BFF) { // Basic check for invalid options - LOG_ERROR(Lib_Ime, "Invalid option 0x{:X}", static_cast(param->option)); + LOG_ERROR(Lib_Ime, "Invalid option: {:032b}", static_cast(param->option)); return Error::INVALID_OPTION; } @@ -299,17 +301,16 @@ Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceU LOG_ERROR(Lib_Ime, "No keyboard handler is open"); return Error::NOT_OPENED; } - - if ((userId < 0 || userId > 4) && - false) { // TODO: Check for valid user IDs. Disabled until user manager is ready. + // TODO: Check for valid user IDs. Disabled until user manager is ready. + if ((userId < 0 || userId > 4) && false) { // Maybe g_keyboard_handler should hold a user ID and I must compare it here? LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); return Error::INVALID_USER_ID; } g_keyboard_handler.release(); - if (g_ime_handler) { - LOG_ERROR(Lib_Ime, "failed to close keyboard handler, IME handler is still open"); + if (g_keyboard_handler) { + LOG_ERROR(Lib_Ime, "failed to close keyboard handler, it is still open"); return Error::INTERNAL; } @@ -321,10 +322,45 @@ int PS4_SYSV_ABI sceImeKeyboardGetInfo() { LOG_ERROR(Lib_Ime, "(STUBBED) called"); return ORBIS_OK; } +Error PS4_SYSV_ABI +sceImeKeyboardGetResourceId(Libraries::UserService::OrbisUserServiceUserId userId, + OrbisImeKeyboardResourceIdArray* resourceIdArray) { + LOG_INFO(Lib_Ime, "(partial) called"); -int PS4_SYSV_ABI sceImeKeyboardGetResourceId() { - LOG_ERROR(Lib_Ime, "(STUBBED) called"); - return ORBIS_OK; + if (!resourceIdArray) { + LOG_ERROR(Lib_Ime, "Invalid resourceIdArray: NULL"); + return Error::INVALID_ADDRESS; + } + + // TODO: Check for valid user IDs. Disabled until user manager is ready. + if ((userId < 0 || userId > 4) && false) { + LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); + resourceIdArray->user_id = userId; + for (u32& id : resourceIdArray->resource_id) { + id = 0; + } + return Error::INVALID_USER_ID; + } + + if (!g_keyboard_handler) { + LOG_ERROR(Lib_Ime, "Keyboard handler not opened"); + resourceIdArray->user_id = userId; + for (u32& id : resourceIdArray->resource_id) { + id = 0; + } + return Error::NOT_OPENED; + } + + // Simulate "no USB keyboard connected", needed for some Unity engine games + resourceIdArray->user_id = userId; + for (u32& id : resourceIdArray->resource_id) { + id = 0; + } + LOG_INFO(Lib_Ime, "No USB keyboard connected (simulated)"); + return Error::CONNECTION_FAILED; + + // For future reference, if we had a real keyboard handler + return Error::OK; } Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId, @@ -339,7 +375,8 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs return Error::INVALID_HANDLER; } // seems like arg is optional, need to check if it is used in the handler - if (!param->arg && false) { // Todo: check if arg is used in the handler, temporarily disabled + // Todo: check if arg is used in the handler, temporarily disabled + if (!param->arg && false) { LOG_ERROR(Lib_Ime, "Invalid param->arg: NULL"); return Error::INVALID_ARG; } @@ -351,8 +388,9 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs static_cast(param->option), kValidOrbisImeKeyboardOptionMask); return Error::INVALID_OPTION; } - if ((userId < 0 || userId > 4) && - false) { // TODO: Check for valid user IDs. Disabled until user manager is ready. + + // TODO: Check for valid user IDs. Disabled until user manager is ready. + if ((userId < 0 || userId > 4) && false) { LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); return Error::INVALID_USER_ID; } @@ -368,7 +406,9 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs return Error::INVALID_RESERVED; } } - if (false) { // Todo: figure out what it is, always true for now + + // Todo: figure out what it is, always false for now + if (false) { LOG_ERROR(Lib_Ime, "USB keyboard some special kind of failure"); return Error::CONNECTION_FAILED; } diff --git a/src/core/libraries/ime/ime.h b/src/core/libraries/ime/ime.h index 555ac0f7d..b2b4a51ad 100644 --- a/src/core/libraries/ime/ime.h +++ b/src/core/libraries/ime/ime.h @@ -35,7 +35,9 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm(); Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height); Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceUserId userId); int PS4_SYSV_ABI sceImeKeyboardGetInfo(); -int PS4_SYSV_ABI sceImeKeyboardGetResourceId(); +Error PS4_SYSV_ABI +sceImeKeyboardGetResourceId(Libraries::UserService::OrbisUserServiceUserId userId, + OrbisImeKeyboardResourceIdArray* resourceIdArray); Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId, const OrbisImeKeyboardParam* param); int PS4_SYSV_ABI sceImeKeyboardOpenInternal(); diff --git a/src/core/libraries/ime/ime_dialog.cpp b/src/core/libraries/ime/ime_dialog.cpp index 6578b6249..09d920930 100644 --- a/src/core/libraries/ime/ime_dialog.cpp +++ b/src/core/libraries/ime/ime_dialog.cpp @@ -57,6 +57,7 @@ Error PS4_SYSV_ABI sceImeDialogAbort() { } Error PS4_SYSV_ABI sceImeDialogForceClose() { + LOG_INFO(Lib_ImeDialog, "called"); if (g_ime_dlg_status == OrbisImeDialogStatus::None) { LOG_INFO(Lib_ImeDialog, "IME dialog not in use"); return Error::DIALOG_NOT_IN_USE; @@ -149,47 +150,40 @@ OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() { } Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) { - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: entering, param={}, extended={}", - static_cast(param), static_cast(extended)); + LOG_INFO(Lib_ImeDialog, "called, param={}, extended={}", static_cast(param), + static_cast(extended)); if (param == nullptr) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: param is null"); + LOG_ERROR(Lib_ImeDialog, "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}", + LOG_INFO(Lib_ImeDialog, "param.user_id = {}", static_cast(param->user_id)); + LOG_INFO(Lib_ImeDialog, "param.type: {}", static_cast(param->type)); + LOG_INFO(Lib_ImeDialog, "param.supported_languages: {:064b}", 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 = {}", + LOG_INFO(Lib_ImeDialog, "param.enter_label: {}", static_cast(param->enter_label)); + LOG_INFO(Lib_ImeDialog, "param.input_method: {}", static_cast(param->input_method)); + LOG_INFO(Lib_ImeDialog, "param.filter: {}", (void*)param->filter); + LOG_INFO(Lib_ImeDialog, "param.option: {:032b}", static_cast(param->option)); + LOG_INFO(Lib_ImeDialog, "param.max_text_length: {}", param->max_text_length); + LOG_INFO(Lib_ImeDialog, "param.input_text_buffer: {}", (void*)param->input_text_buffer); + LOG_INFO(Lib_ImeDialog, "param.posx: {}", param->posx); + LOG_INFO(Lib_ImeDialog, "param.posy: {}", param->posy); + LOG_INFO(Lib_ImeDialog, "param.horizontal_alignment: {}", static_cast(param->horizontal_alignment)); - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.vertical_alignment = {}", + LOG_INFO(Lib_ImeDialog, "param.vertical_alignment: {}", static_cast(param->vertical_alignment)); - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.placeholder = {}", + LOG_INFO(Lib_ImeDialog, "param.placeholder: {}", param->placeholder ? "" : "NULL"); - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.title = {}", - param->title ? "" : "NULL"); + LOG_INFO(Lib_ImeDialog, "param.title: {}", param->title ? "" : "NULL"); } if (g_ime_dlg_status != OrbisImeDialogStatus::None) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: busy (status={})", (u32)g_ime_dlg_status); + LOG_ERROR(Lib_ImeDialog, "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={}", (u32)param->type); + LOG_ERROR(Lib_ImeDialog, "invalid param->type={}", (u32)param->type); return Error::INVALID_ADDRESS; } @@ -199,48 +193,50 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt if (param->posx < 0.0f || param->posx >= MAX_X_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posx={}", param->posx); + LOG_ERROR(Lib_ImeDialog, "Invalid posx: {}", param->posx); return Error::INVALID_POSX; } if (param->posy < 0.0f || param->posy >= MAX_Y_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posy={}", param->posy); + LOG_ERROR(Lib_ImeDialog, "invalid posy: {}", param->posy); return Error::INVALID_POSY; } if (!magic_enum::enum_contains(param->horizontal_alignment)) { - LOG_INFO(Lib_ImeDialog, "Invalid param->horizontalAlignment"); + LOG_INFO(Lib_ImeDialog, "Invalid param->horizontalAlignment: {}", + (u32)param->horizontal_alignment); return Error::INVALID_HORIZONTALIGNMENT; } if (!magic_enum::enum_contains(param->vertical_alignment)) { - LOG_INFO(Lib_ImeDialog, "Invalid param->verticalAlignment"); + LOG_INFO(Lib_ImeDialog, "Invalid param->verticalAlignment: {}", + (u32)param->vertical_alignment); return Error::INVALID_VERTICALALIGNMENT; } if (!IsValidOption(param->option, param->type)) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid option=0x{:X}for type={}", + LOG_ERROR(Lib_ImeDialog, "Invalid option: {:032b} for type={}", static_cast(param->option), (u32)param->type); return Error::INVALID_PARAM; } if (param->input_text_buffer == nullptr) { - LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: input_text_buffer is null"); + LOG_ERROR(Lib_ImeDialog, "Invalid input_text_buffer: null"); return Error::INVALID_INPUT_TEXT_BUFFER; } if (extended) { if (!magic_enum::enum_contains(extended->priority)) { - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->priority"); + LOG_INFO(Lib_ImeDialog, "Invalid extended->priority: {}", (u32)extended->priority); return Error::INVALID_EXTENDED; } // TODO: do correct extended->option validation if ((extended->ext_keyboard_mode & 0xe3fffffc) != 0) { - LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->extKeyboardMode"); + LOG_INFO(Lib_ImeDialog, "Invalid extended->extKeyboardMode"); return Error::INVALID_EXTENDED; } @@ -294,6 +290,7 @@ int PS4_SYSV_ABI sceImeDialogSetPanelPosition() { } Error PS4_SYSV_ABI sceImeDialogTerm() { + LOG_INFO(Lib_ImeDialog, "called"); if (g_ime_dlg_status == OrbisImeDialogStatus::None) { LOG_INFO(Lib_ImeDialog, "IME dialog not in use"); return Error::DIALOG_NOT_IN_USE; diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 800ba1124..f0a8de994 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -18,14 +18,18 @@ using namespace ImGui; static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; namespace Libraries::ImeDialog { +ImeDialogState::ImeDialogState() + : input_changed(false), user_id(-1), is_multi_line(false), is_numeric(false), + type(OrbisImeType::Default), enter_label(OrbisImeEnterLabel::Default), text_filter(nullptr), + keyboard_filter(nullptr), max_text_length(ORBIS_IME_DIALOG_MAX_TEXT_LENGTH), + text_buffer(nullptr), title(), placeholder(), current_text() {} ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, const OrbisImeParamExtended* extended) { - LOG_INFO(Lib_ImeDialog, ">> ImeDialogState::Ctor: param={}, text_buffer={}", - static_cast(param), + LOG_INFO(Lib_ImeDialog, "param={}, text_buffer={}", static_cast(param), static_cast(param ? param->input_text_buffer : nullptr)); if (!param) { - LOG_ERROR(Lib_ImeDialog, " param==nullptr, returning without init"); + LOG_ERROR(Lib_ImeDialog, "param==nullptr, returning without init"); return; } @@ -223,8 +227,7 @@ void ImeDialogUi::Free() { } void ImeDialogUi::Draw() { - std::unique_lock lock{draw_mutex}; - LOG_INFO(Lib_ImeDialog, ">> ImeDialogUi::Draw: first_render=%d", first_render); + std::unique_lock lock{draw_mutex}; if (!state) { return; @@ -264,13 +267,9 @@ void ImeDialogUi::Draw() { } if (state->is_multi_line) { - LOG_INFO(Lib_ImeDialog, " Drawing multi-line widget…"); DrawMultiLineInputText(); - LOG_INFO(Lib_ImeDialog, " Done DrawMultiLineInputText"); } else { - LOG_INFO(Lib_ImeDialog, " Drawing input text widget…"); DrawInputText(); - LOG_INFO(Lib_ImeDialog, " Done DrawInputText"); } SetCursorPosY(GetCursorPosY() + 10.0f); @@ -315,7 +314,6 @@ void ImeDialogUi::Draw() { End(); first_render = false; - LOG_INFO(Lib_ImeDialog, "<< ImeDialogUi::Draw complete"); } void ImeDialogUi::DrawInputText() { diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 10dff5eeb..48ddb3291 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -36,8 +36,14 @@ class ImeDialogState final { Common::CString current_text; public: - ImeDialogState(const OrbisImeDialogParam* param = nullptr, - const OrbisImeParamExtended* extended = nullptr); + /* + * Use default constructor ImeDialogState() to initialize default values instead of + * ImeDialogState(const OrbisImeDialogParam* param = nullptr,const OrbisImeParamExtended* + * extended = nullptr) to avoid validation errors in log + */ + ImeDialogState(); + ImeDialogState(const OrbisImeDialogParam* param /*= nullptr*/, + const OrbisImeParamExtended* extended /*= nullptr*/); ImeDialogState(const ImeDialogState& other) = delete; ImeDialogState(ImeDialogState&& other) noexcept; ImeDialogState& operator=(ImeDialogState&& other);