Skip to content

Commit

Permalink
core/libraries: IME implementation (#1436)
Browse files Browse the repository at this point in the history
* core/libraries: IME implementation

* Update ime_common.h

---------

Co-authored-by: georgemoralis <[email protected]>
  • Loading branch information
polybiusproxy and georgemoralis authored Oct 23, 2024
1 parent 406041b commit 6e00121
Show file tree
Hide file tree
Showing 15 changed files with 818 additions and 130 deletions.
22 changes: 12 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,6 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/audio3d/audio3d_error.h
src/core/libraries/audio3d/audio3d_impl.cpp
src/core/libraries/audio3d/audio3d_impl.h
src/core/libraries/ime/ime.cpp
src/core/libraries/ime/ime.h
src/core/libraries/game_live_streaming/gamelivestreaming.cpp
src/core/libraries/game_live_streaming/gamelivestreaming.h
src/core/libraries/remote_play/remoteplay.cpp
Expand All @@ -311,13 +309,17 @@ set(LIBC_SOURCES src/core/libraries/libc_internal/libc_internal.cpp
src/core/libraries/libc_internal/libc_internal.h
)

set(DIALOGS_LIB src/core/libraries/dialogs/error_dialog.cpp
src/core/libraries/dialogs/error_dialog.h
src/core/libraries/dialogs/ime_dialog_ui.cpp
src/core/libraries/dialogs/ime_dialog_ui.h
src/core/libraries/dialogs/ime_dialog.cpp
src/core/libraries/dialogs/ime_dialog.h
src/core/libraries/dialogs/error_codes.h
set(IME_LIB src/core/libraries/ime/error_dialog.cpp
src/core/libraries/ime/error_dialog.h
src/core/libraries/ime/ime_common.h
src/core/libraries/ime/ime_dialog_ui.cpp
src/core/libraries/ime/ime_dialog_ui.h
src/core/libraries/ime/ime_dialog.cpp
src/core/libraries/ime/ime_dialog.h
src/core/libraries/ime/ime_ui.cpp
src/core/libraries/ime/ime_ui.h
src/core/libraries/ime/ime.cpp
src/core/libraries/ime/ime.h
)

set(PAD_LIB src/core/libraries/pad/pad.cpp
Expand Down Expand Up @@ -499,7 +501,7 @@ set(CORE src/core/aerolib/stubs.cpp
${RANDOM_LIB}
${USBD_LIB}
${MISC_LIBS}
${DIALOGS_LIB}
${IME_LIB}
${FIBER_LIB}
${DEV_TOOLS}
src/core/debug_state.cpp
Expand Down
12 changes: 0 additions & 12 deletions src/core/libraries/dialogs/error_codes.h

This file was deleted.

47 changes: 46 additions & 1 deletion src/core/libraries/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,4 +507,49 @@ constexpr int ORBIS_FIBER_ERROR_ALIGNMENT = 0x80590002;
constexpr int ORBIS_FIBER_ERROR_RANGE = 0x80590003;
constexpr int ORBIS_FIBER_ERROR_INVALID = 0x80590004;
constexpr int ORBIS_FIBER_ERROR_PERMISSION = 0x80590005;
constexpr int ORBIS_FIBER_ERROR_STATE = 0x80590006;
constexpr int ORBIS_FIBER_ERROR_STATE = 0x80590006;

// ImeDialog library
constexpr int ORBIS_ERROR_DIALOG_ERROR_NOT_INITIALIZED = 0x80ED0001;
constexpr int ORBIS_ERROR_DIALOG_ERROR_ALREADY_INITIALIZED = 0x80ED0002;
constexpr int ORBIS_ERROR_DIALOG_ERROR_PARAM_INVALID = 0x80ED0003;
constexpr int ORBIS_ERROR_DIALOG_ERROR_UNEXPECTED_FATAL = 0x80ED0004;
constexpr int ORBIS_ERROR_DIALOG_ERROR_INVALID_STATE = 0x80ED0005;
constexpr int ORBIS_ERROR_DIALOG_ERROR_SERVICE_BUSY = 0x80ED0006;
constexpr int ORBIS_ERROR_DIALOG_ERROR_INVALID_USER_ID = 0x80ED0007;

// Ime library
constexpr int ORBIS_IME_ERROR_BUSY = 0x80BC0001;
constexpr int ORBIS_IME_ERROR_NOT_OPENED = 0x80BC0002;
constexpr int ORBIS_IME_ERROR_NO_MEMORY = 0x80BC0003;
constexpr int ORBIS_IME_ERROR_CONNECTION_FAILED = 0x80BC0004;
constexpr int ORBIS_IME_ERROR_TOO_MANY_REQUESTS = 0x80BC0005;
constexpr int ORBIS_IME_ERROR_INVALID_TEXT = 0x80BC0006;
constexpr int ORBIS_IME_ERROR_EVENT_OVERFLOW = 0x80BC0007;
constexpr int ORBIS_IME_ERROR_NOT_ACTIVE = 0x80BC0008;
constexpr int ORBIS_IME_ERROR_IME_SUSPENDING = 0x80BC0009;
constexpr int ORBIS_IME_ERROR_DEVICE_IN_USE = 0x80BC000A;
constexpr int ORBIS_IME_ERROR_INVALID_USER_ID = 0x80BC0010;
constexpr int ORBIS_IME_ERROR_INVALID_TYPE = 0x80BC0011;
constexpr int ORBIS_IME_ERROR_INVALID_SUPPORTED_LANGUAGES = 0x80BC0012;
constexpr int ORBIS_IME_ERROR_INVALID_ENTER_LABEL = 0x80BC0013;
constexpr int ORBIS_IME_ERROR_INVALID_INPUT_METHOD = 0x80BC0014;
constexpr int ORBIS_IME_ERROR_INVALID_OPTION = 0x80BC0015;
constexpr int ORBIS_IME_ERROR_INVALID_MAX_TEXT_LENGTH = 0x80BC0016;
constexpr int ORBIS_IME_ERROR_INVALID_INPUT_TEXT_BUFFER = 0x80BC0017;
constexpr int ORBIS_IME_ERROR_INVALID_POSX = 0x80BC0018;
constexpr int ORBIS_IME_ERROR_INVALID_POSY = 0x80BC0019;
constexpr int ORBIS_IME_ERROR_INVALID_HORIZONTAL_ALIGNMENT = 0x80BC001A;
constexpr int ORBIS_IME_ERROR_INVALID_VERTICAL_ALIGNMENT = 0x80BC001B;
constexpr int ORBIS_IME_ERROR_INVALID_EXTENDED = 0x80BC001C;
constexpr int ORBIS_IME_ERROR_INVALID_KEYBOARD_TYPE = 0x80BC001D;
constexpr int ORBIS_IME_ERROR_INVALID_WORK = 0x80BC0020;
constexpr int ORBIS_IME_ERROR_INVALID_ARG = 0x80BC0021;
constexpr int ORBIS_IME_ERROR_INVALID_HANDLER = 0x80BC0022;
constexpr int ORBIS_IME_ERROR_NO_RESOURCE_ID = 0x80BC0023;
constexpr int ORBIS_IME_ERROR_INVALID_MODE = 0x80BC0024;
constexpr int ORBIS_IME_ERROR_INVALID_PARAM = 0x80BC0030;
constexpr int ORBIS_IME_ERROR_INVALID_ADDRESS = 0x80BC0031;
constexpr int ORBIS_IME_ERROR_INVALID_RESERVED = 0x80BC0032;
constexpr int ORBIS_IME_ERROR_INVALID_TIMING = 0x80BC0033;
constexpr int ORBIS_IME_ERROR_INTERNAL = 0x80BC00FF;
File renamed without changes.
File renamed without changes.
200 changes: 183 additions & 17 deletions src/core/libraries/ime/ime.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,108 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <queue>
#include "ime.h"
#include "ime_ui.h"

#include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/linker.h"

namespace Libraries::Ime {

static std::queue<OrbisImeEvent> g_ime_events;
static ImeState g_ime_state{};
static ImeUi g_ime_ui;

class ImeHandler {
public:
ImeHandler(const OrbisImeKeyboardParam* param) {
Init(param, false);
}
ImeHandler(const OrbisImeParam* param) {
Init(param, true);
}
~ImeHandler() = default;

void Init(const void* param, bool ime_mode) {
if (ime_mode) {
m_param.ime = *(OrbisImeParam*)param;
} else {
m_param.key = *(OrbisImeKeyboardParam*)param;
}
m_ime_mode = ime_mode;

// Open an event to let the game know the IME has started
OrbisImeEvent openEvent{};
openEvent.id = (ime_mode ? OrbisImeEventId::OPEN : OrbisImeEventId::KEYBOARD_OPEN);

if (ime_mode) {
sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
&openEvent.param.rect.height);
openEvent.param.rect.x = m_param.ime.posx;
openEvent.param.rect.y = m_param.ime.posy;
} else {
openEvent.param.resourceIdArray.userId = 1;
openEvent.param.resourceIdArray.resourceId[0] = 1;
}

Execute(nullptr, &openEvent, true);

if (ime_mode) {
g_ime_state = ImeState(&m_param.ime);
g_ime_ui = ImeUi(&g_ime_state, &m_param.ime);
}
}

s32 Update(OrbisImeEventHandler handler) {
std::unique_lock lock{g_ime_state.queue_mutex};

while (!g_ime_state.event_queue.empty()) {
OrbisImeEvent event = g_ime_state.event_queue.front();
g_ime_state.event_queue.pop();
Execute(handler, &event, false);
}

return ORBIS_OK;
}

void Execute(OrbisImeEventHandler handler, OrbisImeEvent* event, bool use_param_handler) {
const auto* linker = Common::Singleton<Core::Linker>::Instance();

if (m_ime_mode) {
OrbisImeParam param = m_param.ime;
if (use_param_handler) {
linker->ExecuteGuest(param.handler, param.arg, event);
} else {
linker->ExecuteGuest(handler, param.arg, event);
}
} else {
OrbisImeKeyboardParam param = m_param.key;
if (use_param_handler) {
linker->ExecuteGuest(param.handler, param.arg, event);
} else {
linker->ExecuteGuest(handler, param.arg, event);
}
}
}

bool IsIme() {
return m_ime_mode;
}

private:
union ImeParam {
OrbisImeKeyboardParam key;
OrbisImeParam ime;
} m_param{};
bool m_ime_mode = false;
};

static std::unique_ptr<ImeHandler> g_ime_handler;

int PS4_SYSV_ABI FinalizeImeModule() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;
Expand All @@ -34,8 +128,19 @@ int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeClose() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
s32 PS4_SYSV_ABI sceImeClose() {
LOG_INFO(Lib_Ime, "(STUBBED) called");

if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
}
if (!g_ime_handler->IsIme()) {
return ORBIS_IME_ERROR_NOT_OPENED;
}

g_ime_handler.release();
g_ime_ui = ImeUi();
g_ime_state = ImeState();
return ORBIS_OK;
}

Expand Down Expand Up @@ -104,13 +209,42 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeGetPanelSize() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
LOG_INFO(Lib_Ime, "called");

if (!width || !height) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
}

switch (param->type) {
case OrbisImeType::DEFAULT:
case OrbisImeType::BASIC_LATIN:
case OrbisImeType::URL:
case OrbisImeType::MAIL:
// We set our custom sizes, commented sizes are the original ones
*width = 500; // 793
*height = 100; // 408
break;
case OrbisImeType::NUMBER:
*width = 370;
*height = 402;
break;
}

return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeKeyboardClose() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) {
LOG_INFO(Lib_Ime, "(STUBBED) called");

if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
}
if (g_ime_handler->IsIme()) {
return ORBIS_IME_ERROR_NOT_OPENED;
}

g_ime_handler.release();
return ORBIS_OK;
}

Expand All @@ -124,9 +258,19 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeKeyboardOpen() {
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;

if (!param) {
return ORBIS_IME_ERROR_INVALID_ADDRESS;
}
if (g_ime_handler) {
return ORBIS_IME_ERROR_BUSY;
}

// g_ime_handler = std::make_unique<ImeHandler>(param);
// return ORBIS_OK;
return ORBIS_IME_ERROR_CONNECTION_FAILED; // Fixup
}

int PS4_SYSV_ABI sceImeKeyboardOpenInternal() {
Expand All @@ -144,8 +288,19 @@ int PS4_SYSV_ABI sceImeKeyboardUpdate() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeOpen() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended) {
LOG_INFO(Lib_Ime, "called");

if (!g_ime_handler) {
g_ime_handler = std::make_unique<ImeHandler>(param);
} else {
if (g_ime_handler->IsIme()) {
return ORBIS_IME_ERROR_BUSY;
}

g_ime_handler->Init((void*)param, true);
}

return ORBIS_OK;
}

Expand All @@ -154,17 +309,23 @@ int PS4_SYSV_ABI sceImeOpenInternal() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeParamInit() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param) {
LOG_INFO(Lib_Ime, "called");

if (!param) {
return;
}

memset(param, 0, sizeof(OrbisImeParam));
param->userId = -1;
}

int PS4_SYSV_ABI sceImeSetCandidateIndex() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeSetCaret() {
int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;
}
Expand All @@ -179,9 +340,14 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() {
return ORBIS_OK;
}

int PS4_SYSV_ABI sceImeUpdate() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
return ORBIS_OK;
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
LOG_TRACE(Lib_Ime, "called");

if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
}

return g_ime_handler->Update(handler);
}

int PS4_SYSV_ABI sceImeVshClearPreedit() {
Expand Down
Loading

0 comments on commit 6e00121

Please sign in to comment.