From 93a6e9e4e41faf631289ac6df70f61e7b1bce917 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Tue, 31 Dec 2019 16:02:10 +0100 Subject: [PATCH] Improve cellImeJp (#7014) * HLE: add error_code and definitions for cellImeJp * HLE: add function parameters to cellImeJp * HLE: improve cellImeJp * HLE: further improve cellImeJp * HLE: simplify cellImeJp --- rpcs3/Emu/Cell/Modules/cellImeJp.cpp | 1058 +++++++++++++++++++++++--- rpcs3/Emu/Cell/Modules/cellImeJp.h | 145 +++- 2 files changed, 1074 insertions(+), 129 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellImeJp.cpp b/rpcs3/Emu/Cell/Modules/cellImeJp.cpp index 8950b57387..0cfcadd764 100644 --- a/rpcs3/Emu/Cell/Modules/cellImeJp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellImeJp.cpp @@ -1,283 +1,1117 @@ -#include "stdafx.h" +#include "stdafx.h" #include "Emu/Cell/PPUModule.h" +#include "Emu/Cell/lv2/sys_process.h" +#include "Emu/IdManager.h" #include "cellImeJp.h" LOG_CHANNEL(cellImeJp); -// Return Codes -enum +template <> +void fmt_class_string::format(std::string& out, u64 arg) { - CELL_IMEJP_ERROR_ERR = 0x8002bf01, - CELL_IMEJP_ERROR_CONTEXT = 0x8002bf11, - CELL_IMEJP_ERROR_ALREADY_OPEN = 0x8002bf21, - CELL_IMEJP_ERROR_DIC_OPEN = 0x8002bf31, - CELL_IMEJP_ERROR_PARAM = 0x8002bf41, - CELL_IMEJP_ERROR_IME_ALREADY_IN_USE = 0x8002bf51, - CELL_IMEJP_ERROR_OTHER = 0x8002bfff, -}; + format_enum(out, arg, [](auto error) + { + switch (error) + { + STR_CASE(CELL_IMEJP_ERROR_ERR); + STR_CASE(CELL_IMEJP_ERROR_CONTEXT); + STR_CASE(CELL_IMEJP_ERROR_ALREADY_OPEN); + STR_CASE(CELL_IMEJP_ERROR_DIC_OPEN); + STR_CASE(CELL_IMEJP_ERROR_PARAM); + STR_CASE(CELL_IMEJP_ERROR_IME_ALREADY_IN_USE); + STR_CASE(CELL_IMEJP_ERROR_OTHER); + } -static uint16_t s_ime_string[256]; + return unknown; + }); +} -s32 cellImeJpOpen() +using sys_memory_container_t = u32; + +const u32 ime_jp_address = 0xf0000000; + +ime_jp_manager::ime_jp_manager() { - std::memset(s_ime_string, 0, sizeof(s_ime_string)); - cellImeJp.error("cellImeJpOpen()"); + if (static_cast(g_ps3_process_info.sdk_ver) < 0x360000) // firmware < 3.6.0 + allowed_extensions = CELL_IMEJP_EXTENSIONCH_UD85TO94 | CELL_IMEJP_EXTENSIONCH_OUTJIS; + else + allowed_extensions = CELL_IMEJP_EXTENSIONCH_UD09TO15 | CELL_IMEJP_EXTENSIONCH_UD85TO94 | CELL_IMEJP_EXTENSIONCH_OUTJIS; +} + +bool ime_jp_manager::addChar(u16 c) +{ + if (!c || cursor >= (CELL_IMEJP_STRING_MAXLENGTH - 1) || cursor > input_string.length()) + return false; + + std::u16string tmp; + tmp += c; + input_string.insert(cursor++, tmp); + cursor_end = cursor; + input_state = CELL_IMEJP_BEFORE_CONVERT; + return true; +} + +bool ime_jp_manager::addString(vm::cptr str) +{ + if (!str) + return false; + + for (size_t i = 0; i < CELL_IMEJP_STRING_MAXLENGTH; i++) + { + if (!addChar(str[i])) + return false; + } + + return true; +} + +bool ime_jp_manager::backspaceWord() +{ + if (!cursor || cursor > CELL_IMEJP_STRING_MAXLENGTH || cursor > input_string.length()) + return false; + + input_string.erase(--cursor); + cursor_end = cursor; + + if (input_string.empty()) + input_state = CELL_IMEJP_BEFORE_INPUT; + + return true; +} + +bool ime_jp_manager::deleteWord() +{ + if (cursor >= (CELL_IMEJP_STRING_MAXLENGTH - 1) || cursor > (input_string.length() - 1)) + return false; + + input_string.erase(cursor); + cursor_end = cursor; + + if (input_string.empty()) + input_state = CELL_IMEJP_BEFORE_INPUT; + + return true; +} + +void ime_jp_manager::moveCursor(s8 amount) +{ + if (amount > 0) + { + cursor = std::min(cursor + amount, input_string.length() - 1); + cursor_end = std::min(cursor_end + amount, input_string.length() - 1); + } + else if (amount < 0) + { + cursor = std::max(0, static_cast(cursor) + amount); + cursor_end = std::max(static_cast(cursor), static_cast(cursor_end) + amount); + } +} + +void ime_jp_manager::moveCursorEnd(s8 amount) +{ + if (amount > 0) + { + cursor_end = std::max(static_cast(cursor), std::min(cursor_end + amount, input_string.length() - 1)); + } + else if (amount < 0) + { + cursor_end = std::max(static_cast(cursor), static_cast(cursor_end) + amount); + } +} + +error_code cellImeJpOpen(sys_memory_container_t container_id, vm::ptr hImeJpHandle, vm::cptr addDicPath) +{ + cellImeJp.todo("cellImeJpOpen(container_id=*0x%x, hImeJpHandle=*0x%x, addDicPath=*0x%x)", container_id, hImeJpHandle, addDicPath); + + if (!container_id || !hImeJpHandle) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (manager->is_initialized) + { + return CELL_IMEJP_ERROR_ALREADY_OPEN; + } + + if (addDicPath && addDicPath->path[0]) + { + cellImeJp.warning("cellImeJpOpen dictionary path = %s", addDicPath->path); + + manager->dictionary_paths.push_back(std::string(addDicPath->path)); + } + *hImeJpHandle = vm::cast(ime_jp_address); + + manager->is_initialized = true; + return CELL_OK; } -s32 cellImeJpOpen2() +error_code cellImeJpOpen2(sys_memory_container_t container_id, vm::ptr hImeJpHandle, vm::cptr addDicPath) { - std::memset(s_ime_string, 0, sizeof(s_ime_string)); - cellImeJp.error("cellImeJpOpen2()"); + cellImeJp.todo("cellImeJpOpen2(container_id=*0x%x, hImeJpHandle=*0x%x, addDicPath=*0x%x)", container_id, hImeJpHandle, addDicPath); + + if (!container_id || !hImeJpHandle) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (manager->is_initialized) + { + return CELL_IMEJP_ERROR_ALREADY_OPEN; + } + + if (addDicPath && addDicPath->path[0]) + { + cellImeJp.warning("cellImeJpOpen2 dictionary path = %s", addDicPath->path); + + manager->dictionary_paths.push_back(std::string(addDicPath->path)); + } + + *hImeJpHandle = vm::cast(ime_jp_address); + + manager->is_initialized = true; + return CELL_OK; } -s32 cellImeJpOpen3() +error_code cellImeJpOpen3(sys_memory_container_t container_id, vm::ptr hImeJpHandle, vm::cpptr addDicPath) { - std::memset(s_ime_string, 0, sizeof(s_ime_string)); - cellImeJp.error("cellImeJpOpen3()"); + cellImeJp.todo("cellImeJpOpen3(container_id=*0x%x, hImeJpHandle=*0x%x, addDicPath=*0x%x)", container_id, hImeJpHandle, addDicPath); + + if (!container_id || !hImeJpHandle) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (manager->is_initialized) + { + return CELL_IMEJP_ERROR_ALREADY_OPEN; + } + + if (addDicPath) + { + for (size_t i = 0; i < 4; i++) + { + if (addDicPath[i] && addDicPath[i]->path[0]) + { + cellImeJp.warning("cellImeJpOpen3 dictionary %d path = %s", i, addDicPath[i]->path); + + manager->dictionary_paths.push_back(std::string(addDicPath[i]->path)); + } + } + } + + *hImeJpHandle = vm::cast(ime_jp_address); + + manager->is_initialized = true; + return CELL_OK; } -s32 cellImeJpOpenExt() +error_code cellImeJpOpenExt() { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpOpenExt()"); return CELL_OK; } -s32 cellImeJpClose() +error_code cellImeJpClose(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpClose(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + manager->input_state = CELL_IMEJP_BEFORE_INPUT; + manager->input_string.clear(); + manager->converted_string.clear(); + manager->confirmed_string.clear(); + manager->cursor = 0; + manager->cursor_end = 0; + manager->is_initialized = false; + return CELL_OK; } -s32 cellImeJpSetKanaInputMode() +error_code cellImeJpSetKanaInputMode(CellImeJpHandle hImeJpHandle, s16 inputOption) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpSetKanaInputMode(hImeJpHandle=*0x%x, inputOption=%d)", hImeJpHandle, inputOption); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->kana_input_mode = inputOption; + return CELL_OK; } -s32 cellImeJpSetInputCharType() +error_code cellImeJpSetInputCharType(CellImeJpHandle hImeJpHandle, s16 charTypeOption) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpSetInputCharType(hImeJpHandle=*0x%x, charTypeOption=%d)", hImeJpHandle, charTypeOption); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + manager->input_char_type = charTypeOption; + return CELL_OK; } -s32 cellImeJpSetFixInputMode() +error_code cellImeJpSetFixInputMode(CellImeJpHandle hImeJpHandle, s16 fixInputMode) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpSetFixInputMode(hImeJpHandle=*0x%x, fixInputMode=%d)", hImeJpHandle, fixInputMode); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + manager->fix_input_mode = fixInputMode; + return CELL_OK; } -s32 cellImeJpAllowExtensionCharacters() +error_code cellImeJpAllowExtensionCharacters(CellImeJpHandle hImeJpHandle, s16 extensionCharacters) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpSetFixInputMode(hImeJpHandle=*0x%x, extensionCharacters=%d)", hImeJpHandle, extensionCharacters); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->allowed_extensions = extensionCharacters; + return CELL_OK; } -s32 cellImeJpReset() +error_code cellImeJpReset(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpReset(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + manager->input_state = CELL_IMEJP_BEFORE_INPUT; + manager->input_string.clear(); + manager->converted_string.clear(); + manager->confirmed_string.clear(); + manager->cursor = 0; + manager->cursor_end = 0; + return CELL_OK; } -s32 cellImeJpGetStatus(CellImeJpHandle hImeJpHandle, vm::ptr pInputStatus) +error_code cellImeJpGetStatus(CellImeJpHandle hImeJpHandle, vm::ptr pInputStatus) { - cellImeJp.error("cellImeJpGetStatus()"); - *pInputStatus = CELL_IMEJP_CANDIDATE_EMPTY; + cellImeJp.warning("cellImeJpGetStatus(hImeJpHandle=*0x%x, pInputStatus=%d)", hImeJpHandle, pInputStatus); + + if (!pInputStatus) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + *pInputStatus = manager->input_state; + return CELL_OK; } -s32 cellImeJpEnterChar(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) +error_code cellImeJpEnterChar(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) { - LOG_TODO(HLE, "cellImeJpEnterChar hImeJpHandle / inputChar / pOutputStatus (%d / 0x%x / %d)" HERE, hImeJpHandle, inputChar, pOutputStatus); - *s_ime_string = inputChar; + cellImeJp.todo("cellImeJpEnterChar(hImeJpHandle=*0x%x, inputChar=%d, pOutputStatus=%d)", hImeJpHandle, inputChar, pOutputStatus); + + if (!pOutputStatus) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_MOVE_CLAUSE_GAP) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->addChar(inputChar); + *pOutputStatus = CELL_IMEJP_RET_CONFIRMED; + return CELL_OK; } -s32 cellImeJpEnterCharExt(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) +error_code cellImeJpEnterCharExt(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) { - cellImeJp.todo("cellImeJpEnterCharExt()"); + cellImeJp.todo("cellImeJpEnterCharExt(hImeJpHandle=*0x%x, inputChar=%d, pOutputStatus=%d", hImeJpHandle, inputChar, pOutputStatus); return cellImeJpEnterChar(hImeJpHandle, inputChar, pOutputStatus); } -s32 cellImeJpEnterString(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) +error_code cellImeJpEnterString(CellImeJpHandle hImeJpHandle, vm::cptr pInputString, vm::ptr pOutputStatus) { - cellImeJp.todo("cellImeJpEnterString()"); - return cellImeJpEnterChar(hImeJpHandle, inputChar, pOutputStatus); -} + cellImeJp.todo("cellImeJpEnterString(hImeJpHandle=*0x%x, pInputString=*0x%x, pOutputStatus=%d", hImeJpHandle, pInputString, pOutputStatus); -s32 cellImeJpEnterStringExt(CellImeJpHandle hImeJpHandle, u16 inputChar, vm::ptr pOutputStatus) -{ - cellImeJp.todo("cellImeJpEnterStringExt()"); - return cellImeJpEnterChar(hImeJpHandle, inputChar, pOutputStatus); -} + if (!pOutputStatus) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_MOVE_CLAUSE_GAP) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->addString(pInputString); + + *pOutputStatus = CELL_IMEJP_RET_CONFIRMED; -s32 cellImeJpModeCaretRight() -{ - UNIMPLEMENTED_FUNC(cellImeJp); return CELL_OK; } -s32 cellImeJpModeCaretLeft() +error_code cellImeJpEnterStringExt(CellImeJpHandle hImeJpHandle, vm::cptr pInputString, vm::ptr pOutputStatus) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpEnterStringExt(hImeJpHandle=*0x%x, pInputString=*0x%x, pOutputStatus=%d", hImeJpHandle, pInputString, pOutputStatus); + return cellImeJpEnterString(hImeJpHandle, pInputString, pOutputStatus); +} + +error_code cellImeJpModeCaretRight(CellImeJpHandle hImeJpHandle) +{ + cellImeJp.todo("cellImeJpModeCaretRight(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->moveCursor(1); + return CELL_OK; } -s32 cellImeJpBackspaceWord() +error_code cellImeJpModeCaretLeft(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpModeCaretLeft(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->moveCursor(-1); + return CELL_OK; } -s32 cellImeJpDeleteWord() +error_code cellImeJpBackspaceWord(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpBackspaceWord(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->backspaceWord(); + return CELL_OK; } -s32 cellImeJpAllDeleteConvertString() +error_code cellImeJpDeleteWord(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpDeleteWord(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->deleteWord(); + return CELL_OK; } -s32 cellImeJpConvertForward() +error_code cellImeJpAllDeleteConvertString(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpAllDeleteConvertString(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->cursor = 0; + manager->cursor_end = 0; + manager->input_string.clear(); + manager->converted_string.clear(); + manager->input_state = CELL_IMEJP_BEFORE_INPUT; + return CELL_OK; } -s32 cellImeJpConvertBackward() +error_code cellImeJpConvertForward(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpConvertForward(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->input_state = CELL_IMEJP_CANDIDATES; + return CELL_OK; } -s32 cellImeJpCurrentPartConfirm() +error_code cellImeJpConvertBackward(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpConvertBackward(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->input_state = CELL_IMEJP_CANDIDATES; + return CELL_OK; } -s32 cellImeJpAllConfirm() +error_code cellImeJpCurrentPartConfirm(CellImeJpHandle hImeJpHandle, s16 listItem) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpCurrentPartConfirm(hImeJpHandle=*0x%x, listItem=%d)", hImeJpHandle, listItem); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + return CELL_OK; } -s32 cellImeJpConvertCancel() +error_code cellImeJpAllConfirm(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpAllConfirm(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + + // Use input_string for now + manager->confirmed_string = manager->input_string; + manager->cursor = 0; + manager->cursor_end = 0; + manager->input_string.clear(); + manager->converted_string.clear(); + manager->input_state = CELL_IMEJP_BEFORE_INPUT; + return CELL_OK; } -s32 cellImeJpAllConvertCancel() +error_code cellImeJpAllConvertCancel(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpAllConvertCancel(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT || manager->input_state == CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->converted_string.clear(); + manager->input_state = CELL_IMEJP_BEFORE_CONVERT; + return CELL_OK; } -s32 cellImeJpExtendConvertArea() +error_code cellImeJpConvertCancel(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpConvertCancel(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT || manager->input_state == CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + // TODO: only cancel all if cursor is at 0 + return cellImeJpAllConvertCancel(hImeJpHandle); +} + +error_code cellImeJpExtendConvertArea(CellImeJpHandle hImeJpHandle) +{ + cellImeJp.todo("cellImeJpExtendConvertArea(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT || manager->input_state == CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->moveCursorEnd(1); + return CELL_OK; } -s32 cellImeJpShortenConvertArea() +error_code cellImeJpShortenConvertArea(CellImeJpHandle hImeJpHandle) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpShortenConvertArea(hImeJpHandle=*0x%x)", hImeJpHandle); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT || manager->input_state == CELL_IMEJP_BEFORE_CONVERT) + { + return CELL_IMEJP_ERROR_ERR; + } + + manager->moveCursorEnd(-1); + return CELL_OK; } -s32 cellImeJpTemporalConfirm() +error_code cellImeJpTemporalConfirm(CellImeJpHandle hImeJpHandle, s16 selectIndex) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpTemporalConfirm(hImeJpHandle=*0x%x, selectIndex=%d)", hImeJpHandle, selectIndex); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_CANDIDATES) + { + return CELL_IMEJP_ERROR_ERR; + } + return CELL_OK; } -s32 cellImeJpPostConvert() +error_code cellImeJpPostConvert(CellImeJpHandle hImeJpHandle, s16 postType) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpPostConvert(hImeJpHandle=*0x%x, postType=%d)", hImeJpHandle, postType); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT) + { + return CELL_IMEJP_ERROR_ERR; + } + return CELL_OK; } -s32 cellImeJpMoveFocusClause() +error_code cellImeJpMoveFocusClause(CellImeJpHandle hImeJpHandle, s16 moveType) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpMoveFocusClause(hImeJpHandle=*0x%x, moveType=%d)", hImeJpHandle, moveType); + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state == CELL_IMEJP_BEFORE_INPUT || manager->input_state == CELL_IMEJP_BEFORE_CONVERT || manager->input_state == CELL_IMEJP_MOVE_CLAUSE_GAP) + { + return CELL_IMEJP_ERROR_ERR; + } + + switch (moveType) + { + case CELL_IMEJP_FOCUS_NEXT: + manager->moveCursor(1); + break; + case CELL_IMEJP_FOCUS_BEFORE: + manager->moveCursor(-1); + break; + case CELL_IMEJP_FOCUS_TOP: + manager->moveCursor((-1) * manager->input_string.length()); + break; + case CELL_IMEJP_FOCUS_END: + manager->moveCursor(manager->input_string.length()); + manager->moveCursor(-1); + break; + default: + break; + } + + manager->input_state = CELL_IMEJP_CONVERTING; + return CELL_OK; } -s32 cellImeJpGetFocusTop() +error_code cellImeJpGetFocusTop(CellImeJpHandle hImeJpHandle, vm::ptr pFocusTop) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpGetFocusTop(hImeJpHandle=*0x%x, pFocusTop=*0x%x)", hImeJpHandle, pFocusTop); + + if (!pFocusTop) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + *pFocusTop = manager->cursor * 2; // offset in bytes + return CELL_OK; } -s32 cellImeJpGetFocusLength(CellImeJpHandle hImeJpHandle, vm::ptr pFocusLength) +error_code cellImeJpGetFocusLength(CellImeJpHandle hImeJpHandle, vm::ptr pFocusLength) { - cellImeJp.error("cellImeJpGetFocusLength()"); - *pFocusLength = 1; + cellImeJp.todo("cellImeJpGetFocusLength(hImeJpHandle=*0x%x, pFocusLength=*0x%x)", hImeJpHandle, pFocusLength); + + if (!pFocusLength) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->cursor >= (CELL_IMEJP_STRING_MAXLENGTH - 1)) + { + *pFocusLength = 0; + } + else + { + *pFocusLength = (manager->cursor_end - manager->cursor + 1) * 2; // offset in bytes + } + return CELL_OK; } -s32 cellImeJpGetConfirmYomiString(CellImeJpHandle hImeJpHandle, vm::ptr pYomiString) +error_code cellImeJpGetConfirmYomiString(CellImeJpHandle hImeJpHandle, vm::ptr pYomiString) { - cellImeJp.error("cellImeJpGetConfirmYomiString()"); - *pYomiString = *s_ime_string; + cellImeJp.todo("cellImeJpGetConfirmYomiString(hImeJpHandle=*0x%x, pYomiString=*0x%x)", hImeJpHandle, pYomiString); + + if (!pYomiString) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + for (size_t i = 0; i < CELL_IMEJP_STRING_MAXLENGTH; i++) + { + pYomiString[i] = 0; + } + + const size_t max_len = std::min(CELL_IMEJP_STRING_MAXLENGTH - 1, manager->confirmed_string.length()); + + for (size_t i = 0; i < max_len; i++) + { + pYomiString[i] = manager->confirmed_string[i]; + } + return CELL_OK; } -s32 cellImeJpGetConfirmString(CellImeJpHandle hImeJpHandle, vm::ptr pConfirmString) +error_code cellImeJpGetConfirmString(CellImeJpHandle hImeJpHandle, vm::ptr pConfirmString) { - cellImeJp.error("cellImeJpGetConfirmString()"); - *pConfirmString = *s_ime_string; + cellImeJp.todo("cellImeJpGetConfirmString(hImeJpHandle=*0x%x, pConfirmString=*0x%x)", hImeJpHandle, pConfirmString); + + if (!pConfirmString) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + for (size_t i = 0; i < CELL_IMEJP_STRING_MAXLENGTH; i++) + { + pConfirmString[i] = 0; + } + + const size_t max_len = std::min(CELL_IMEJP_STRING_MAXLENGTH - 1, manager->confirmed_string.length()); + + for (size_t i = 0; i < max_len; i++) + { + pConfirmString[i] = manager->confirmed_string[i]; + } + return CELL_OK; } -s32 cellImeJpGetConvertYomiString(CellImeJpHandle hImeJpHandle, vm::ptr pYomiString) +error_code cellImeJpGetConvertYomiString(CellImeJpHandle hImeJpHandle, vm::ptr pYomiString) { - cellImeJp.error("cellImeJpGetConvertYomiString()"); - *pYomiString = *s_ime_string; + cellImeJp.todo("cellImeJpGetConvertYomiString(hImeJpHandle=*0x%x, pYomiString=*0x%x)", hImeJpHandle, pYomiString); + + if (!pYomiString) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + for (size_t i = 0; i < CELL_IMEJP_STRING_MAXLENGTH; i++) + { + pYomiString[i] = 0; + } + + const size_t max_len = std::min(CELL_IMEJP_STRING_MAXLENGTH - 1, manager->input_string.length()); + + for (size_t i = 0; i < max_len; i++) + { + pYomiString[i] = manager->input_string[i]; + } + return CELL_OK; } -s32 cellImeJpGetConvertString(CellImeJpHandle hImeJpHandle, vm::ptr pConvertString) +error_code cellImeJpGetConvertString(CellImeJpHandle hImeJpHandle, vm::ptr pConvertString) { - cellImeJp.error("cellImeJpGetConvertString()"); - *pConvertString = *s_ime_string; + cellImeJp.warning("cellImeJpGetConvertString(hImeJpHandle=*0x%x, pConvertString=*0x%x)", hImeJpHandle, pConvertString); + + if (!pConvertString) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + for (size_t i = 0; i < CELL_IMEJP_STRING_MAXLENGTH; i++) + { + pConvertString[i] = 0; + } + + const size_t max_len = std::min(CELL_IMEJP_STRING_MAXLENGTH - 1, manager->input_string.length()); + + for (size_t i = 0; i < max_len; i++) + { + pConvertString[i] = manager->input_string[i]; + } + return CELL_OK; } -s32 cellImeJpGetCandidateListSize() +error_code cellImeJpGetCandidateListSize(CellImeJpHandle hImeJpHandle, vm::ptr pListSize) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpGetCandidateListSize(hImeJpHandle=*0x%x, pListSize=*0x%x)", hImeJpHandle, pListSize); + + if (!pListSize) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_CANDIDATES) + { + return CELL_IMEJP_ERROR_ERR; + } + + *pListSize = 0; + return CELL_OK; } -s32 cellImeJpGetCandidateList() +error_code cellImeJpGetCandidateList(CellImeJpHandle hImeJpHandle, vm::ptr plistNum, vm::ptr pCandidateString) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpGetCandidateList(hImeJpHandle=*0x%x, plistNum=*0x%x, pCandidateString=*0x%x)", hImeJpHandle, plistNum, pCandidateString); + + if (!plistNum || !pCandidateString) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_CANDIDATES) + { + return CELL_IMEJP_ERROR_ERR; + } + + *plistNum = 0; + return CELL_OK; } -s32 cellImeJpGetCandidateSelect() +error_code cellImeJpGetCandidateSelect(CellImeJpHandle hImeJpHandle, vm::ptr pIndex) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpGetCandidateSelect(hImeJpHandle=*0x%x, pIndex=*0x%x)", hImeJpHandle, pIndex); + + if (!pIndex) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + if (manager->input_state != CELL_IMEJP_CANDIDATES) + { + return CELL_IMEJP_ERROR_ERR; + } + + *pIndex = 0; + return CELL_OK; } -s32 cellImeJpGetPredictList() +error_code cellImeJpGetPredictList(CellImeJpHandle hImeJpHandle, vm::ptr pYomiString, s32 itemNum, vm::ptr plistCount, vm::ptr pPredictItem) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpGetPredictList(hImeJpHandle=*0x%x, pYomiString=*0x%x, itemNum=%d, plistCount=*0x%x, pPredictItem=*0x%x)", hImeJpHandle, pYomiString, itemNum, plistCount, pPredictItem); + + if (!pPredictItem || !plistCount) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + + *plistCount = 0; + return CELL_OK; } -s32 cellImeJpConfirmPrediction() +error_code cellImeJpConfirmPrediction(CellImeJpHandle hImeJpHandle, vm::ptr pPredictItem) { - UNIMPLEMENTED_FUNC(cellImeJp); + cellImeJp.todo("cellImeJpConfirmPrediction(hImeJpHandle=*0x%x, pPredictItem=*0x%x)", hImeJpHandle, pPredictItem); + + if (!pPredictItem) + { + return CELL_IMEJP_ERROR_PARAM; + } + + const auto manager = g_fxo->get(); + std::lock_guard lock(manager->mutex); + + if (!manager->is_initialized) + { + return CELL_IMEJP_ERROR_CONTEXT; + } + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellImeJp.h b/rpcs3/Emu/Cell/Modules/cellImeJp.h index ce027e3383..fcaa9f239d 100644 --- a/rpcs3/Emu/Cell/Modules/cellImeJp.h +++ b/rpcs3/Emu/Cell/Modules/cellImeJp.h @@ -1,25 +1,136 @@ -#pragma once +#pragma once #include "Emu/Memory/vm_ptr.h" typedef vm::ptr CellImeJpHandle; -//Input state of the ImeJp -enum { - CELL_IMEJP_BEFORE_INPUT = 0, - CELL_IMEJP_BEFORE_CONVERT = 1, - CELL_IMEJP_CONVERTING = 2, - CELL_IMEJP_CANDIDATE_EMPTY = 3, - CELL_IMEJP_POSTCONVERT_KANA = 4, - CELL_IMEJP_POSTCONVERT_HALF = 5, - CELL_IMEJP_POSTCONVERT_RAW = 6, - CELL_IMEJP_CANDIDATES = 7, - CELL_IMEJP_MOVE_CLAUSE_GAP = 8, +// Return Codes +enum CellImeJpError : u32 +{ + CELL_IMEJP_ERROR_ERR = 0x8002bf01, + CELL_IMEJP_ERROR_CONTEXT = 0x8002bf11, + CELL_IMEJP_ERROR_ALREADY_OPEN = 0x8002bf21, + CELL_IMEJP_ERROR_DIC_OPEN = 0x8002bf31, + CELL_IMEJP_ERROR_PARAM = 0x8002bf41, + CELL_IMEJP_ERROR_IME_ALREADY_IN_USE = 0x8002bf51, + CELL_IMEJP_ERROR_OTHER = 0x8002bfff, }; -//cellImeJpEnterChar, returning values pointed in pOutputStatus. -enum { - CELL_IMEJP_RET_NONE = 0, - CELL_IMEJP_RET_THROUGH = 1, - CELL_IMEJP_RET_CONFIRMED = 2, +// Input state of the ImeJp +enum +{ + CELL_IMEJP_BEFORE_INPUT = 0, + CELL_IMEJP_BEFORE_CONVERT = 1, + CELL_IMEJP_CONVERTING = 2, + CELL_IMEJP_CANDIDATE_EMPTY = 3, + CELL_IMEJP_POSTCONVERT_KANA = 4, + CELL_IMEJP_POSTCONVERT_HALF = 5, + CELL_IMEJP_POSTCONVERT_RAW = 6, + CELL_IMEJP_CANDIDATES = 7, + CELL_IMEJP_MOVE_CLAUSE_GAP = 8, +}; + +// cellImeJpEnterChar, returning values pointed in pOutputStatus. +enum +{ + CELL_IMEJP_RET_NONE = 0, + CELL_IMEJP_RET_THROUGH = 1, + CELL_IMEJP_RET_CONFIRMED = 2, +}; + +enum +{ + CELL_IMEJP_ROMAN_INPUT = 0, + CELL_IMEJP_KANA_INPUT = 1, +}; + +enum +{ + CELL_IMEJP_DSPCHAR_HIRA = 1, + CELL_IMEJP_DSPCHAR_FKANA = 2, + CELL_IMEJP_DSPCHAR_RAW = 3, + CELL_IMEJP_DSPCHAR_HKANA = 4, + CELL_IMEJP_DSPCHAR_HRAW = 5, +}; + +enum +{ + CELL_IMEJP_FIXINMODE_OFF = 0, + CELL_IMEJP_FIXINMODE_HIRA = 1, + CELL_IMEJP_FIXINMODE_FKAN = 2, + CELL_IMEJP_FIXINMODE_RAW = 3, + CELL_IMEJP_FIXINMODE_HKAN = 4, + CELL_IMEJP_FIXINMODE_HRAW = 5, +}; + +enum +{ + CELL_IMEJP_EXTENSIONCH_NONE = 0x0000, + CELL_IMEJP_EXTENSIONCH_HANKANA = 0x0001, + CELL_IMEJP_EXTENSIONCH_UD09TO15 = 0x0004, + CELL_IMEJP_EXTENSIONCH_UD85TO94 = 0x0008, + CELL_IMEJP_EXTENSIONCH_OUTJIS = 0x0010, +}; + +enum +{ + CELL_IMEJP_POSTCONV_HIRA = 1, + CELL_IMEJP_POSTCONV_KANA = 2, + CELL_IMEJP_POSTCONV_HALF = 3, + CELL_IMEJP_POSTCONV_RAW = 4, +}; + +enum +{ + CELL_IMEJP_FOCUS_NEXT = 0, + CELL_IMEJP_FOCUS_BEFORE = 1, + CELL_IMEJP_FOCUS_TOP = 2, + CELL_IMEJP_FOCUS_END = 3, +}; + +enum +{ + CELL_IMEJP_DIC_PATH_MAXLENGTH = 256, + + // Helper + CELL_IMEJP_STRING_MAXLENGTH = 128, // including terminator +}; + +struct CellImeJpAddDic +{ + char path[CELL_IMEJP_DIC_PATH_MAXLENGTH]; +}; + +struct CellImeJpPredictItem +{ + u16 KanaYomi[31]; + u16 Hyoki[61]; +}; + +struct ime_jp_manager +{ + shared_mutex mutex; + + atomic_t is_initialized{ false }; + + u32 input_state = CELL_IMEJP_BEFORE_INPUT; + std::vector dictionary_paths; + std::u16string confirmed_string; + std::u16string converted_string; + std::u16string input_string; + size_t cursor = 0; + size_t cursor_end = 0; + s16 fix_input_mode = CELL_IMEJP_FIXINMODE_OFF; + s16 input_char_type = CELL_IMEJP_DSPCHAR_HIRA; + s16 kana_input_mode = CELL_IMEJP_ROMAN_INPUT; + s16 allowed_extensions = CELL_IMEJP_EXTENSIONCH_UD09TO15 | CELL_IMEJP_EXTENSIONCH_UD85TO94 | CELL_IMEJP_EXTENSIONCH_OUTJIS; + + ime_jp_manager(); + + bool addChar(u16 c); + bool addString(vm::cptr str); + bool backspaceWord(); + bool deleteWord(); + void moveCursor(s8 amount); + void moveCursorEnd(s8 amount); };