From f9ab6c48e34163fd1557e28c14fef96f906f7997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valdis=20Bogd=C4=81ns?= Date: Thu, 7 Aug 2025 19:24:14 +0300 Subject: [PATCH] Ime fixes (#3399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Changes -Added support for OrbisImeParamExtended (extended IME parameters) in ImeHandler, ImeState, and ImeUi -Updated all relevant constructors and logic to propagate and store the extended parameter - Now fully supports passing extended options from sceImeOpen to the IME UI and backend * Potential CUSA00434 [Debug] assert.cpp:30 assert_fail_debug_msg: Assertion Failed! buf_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?" at C:/VS/shadPS4-ime-fixes/externals/dear_imgui/imgui_widgets.cpp:4601 fix * Attempting to resolve an assertion failure in Diablo III: - Adjusted buffer sizes - Updated the calculation of text‑length values * ime-lib another hotfix Fixed incorrect param->title validation, which caused the IME dialog to fail to appear in Stardew Valley. Need to be checked. * Clang fix * FF9 ImeDialog Hotfix * Removed the validation that disallowed null text and null placeholder, since using null values is valid in `ImeDialog`. * Added additional debug logs to aid troubleshooting. * IME Fixes - Add missing flags to `OrbisImeExtOption` - Improve debug logging - Resolve nonstop `sceImeKeyboardOpen` calls in Stardew Valley (MonoGame engine) for `userId = 254` --------- Co-authored-by: w1naenator --- src/core/libraries/ime/ime.cpp | 38 ++++++++++++++++++++--------- src/core/libraries/ime/ime_common.h | 3 +++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index 7deef405c..5e3c4729f 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -17,8 +17,10 @@ static ImeUi g_ime_ui; class ImeHandler { public: - ImeHandler(const OrbisImeKeyboardParam* param) { - LOG_INFO(Lib_Ime, "Creating ImeHandler for keyboard"); + ImeHandler(const OrbisImeKeyboardParam* param, + Libraries::UserService::OrbisUserServiceUserId userId) + : m_user_id(userId) { + LOG_INFO(Lib_Ime, "Creating ImeHandler for keyboard (user {})", userId); Init(param, false); } ImeHandler(const OrbisImeParam* param, const OrbisImeParamExtended* extended = nullptr) { @@ -54,8 +56,12 @@ public: openEvent.param.rect.x = m_param.ime.posx; openEvent.param.rect.y = m_param.ime.posy; } else { - openEvent.param.resource_id_array.user_id = 1; - openEvent.param.resource_id_array.resource_id[0] = 1; + + // Report the real PS4 user ID, and mark “no physical keyboard” so games know + openEvent.param.resource_id_array.user_id = m_user_id; + for (auto& rid : openEvent.param.resource_id_array.resource_id) + rid = -1; + Execute(nullptr, &openEvent, /*use_param_handler=*/true); } // Are we supposed to call the event handler on init with @@ -120,6 +126,7 @@ public: } private: + Libraries::UserService::OrbisUserServiceUserId m_user_id{}; union ImeParam { OrbisImeKeyboardParam key; OrbisImeParam ime; @@ -308,8 +315,8 @@ Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceU LOG_ERROR(Lib_Ime, "No keyboard handler is open"); return Error::NOT_OPENED; } - // TODO: Check for valid user IDs. Disabled until user manager is ready. - if ((userId < 0 || userId > 4) && false) { + // TODO: Check for valid user IDs. + if (userId == Libraries::UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) { // 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; @@ -339,8 +346,8 @@ sceImeKeyboardGetResourceId(Libraries::UserService::OrbisUserServiceUserId userI return Error::INVALID_ADDRESS; } - // TODO: Check for valid user IDs. Disabled until user manager is ready. - if ((userId < 0 || userId > 4) && false) { + // TODO: Check for valid user IDs. + if (userId == Libraries::UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) { LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); resourceIdArray->user_id = userId; for (u32& id : resourceIdArray->resource_id) { @@ -377,10 +384,17 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs LOG_ERROR(Lib_Ime, "Invalid param: NULL"); return Error::INVALID_ADDRESS; } + if (!param->handler) { LOG_ERROR(Lib_Ime, "Invalid param->handler: NULL"); return Error::INVALID_HANDLER; } + + LOG_DEBUG(Lib_Ime, " userId: {}", static_cast(userId)); + LOG_DEBUG(Lib_Ime, " param->option: {:032b}", static_cast(param->option)); + LOG_DEBUG(Lib_Ime, " param->arg: {}", param->arg); + LOG_DEBUG(Lib_Ime, " param->handler: {}", reinterpret_cast(param->handler)); + // seems like arg is optional, need to check if it is used in the handler // Todo: check if arg is used in the handler, temporarily disabled if (!param->arg && false) { @@ -396,8 +410,8 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs return Error::INVALID_OPTION; } - // TODO: Check for valid user IDs. Disabled until user manager is ready. - if ((userId < 0 || userId > 4) && false) { + // TODO: Check for valid user IDs. + if (userId == Libraries::UserService::ORBIS_USER_SERVICE_USER_ID_INVALID) { LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); return Error::INVALID_USER_ID; } @@ -423,7 +437,7 @@ Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUs LOG_ERROR(Lib_Ime, "Keyboard handler is already open"); return Error::BUSY; } - g_keyboard_handler = std::make_unique(param); + g_keyboard_handler = std::make_unique(param, userId); if (!g_keyboard_handler) { LOG_ERROR(Lib_Ime, "Failed to create keyboard handler"); return Error::INTERNAL; // or Error::NO_MEMORY; @@ -694,7 +708,7 @@ Error PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) { g_keyboard_handler->Update(handler); } - if (!g_ime_handler || !g_keyboard_handler) { + if (!g_ime_handler && !g_keyboard_handler) { return Error::NOT_OPENED; } diff --git a/src/core/libraries/ime/ime_common.h b/src/core/libraries/ime/ime_common.h index 457748a2d..eafb2ce9d 100644 --- a/src/core/libraries/ime/ime_common.h +++ b/src/core/libraries/ime/ime_common.h @@ -102,7 +102,9 @@ const u32 kValidImeOptionMask = generate_full_mask(); enum class OrbisImeExtOption : u32 { DEFAULT = 0x00000000, + SET_COLOR = 0x00000001, SET_PRIORITY = 0x00000002, + PRIORITY_SHIFT = 0x00000004, PRIORITY_FULL_WIDTH = 0x00000008, PRIORITY_FIXED_PANEL = 0x00000010, DISABLE_POINTER = 0x00000040, @@ -113,6 +115,7 @@ enum class OrbisImeExtOption : u32 { INIT_EXT_KEYBOARD_MODE = 0x00000800, ENABLE_ACCESSIBILITY = 0x00001000, // ImeDialog unly + ACCESSIBILITY_PANEL_FORCED = 0x00002000, // ImeDialog only ADDITIONAL_DICTIONARY_PRIORITY_MODE = 0x00004000, // ImeDialog only }; DECLARE_ENUM_FLAG_OPERATORS(OrbisImeExtOption);