AnyPS5/core/libs/prx/libSceIme/Export.cpp

120 lines
3.8 KiB
C++

#include <cstdint>
#include <cstddef>
#include <cstring>
#include <mutex>
#include <set>
#include <stdexcept>
#include <string>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
namespace {
constexpr int ErrorNotOpened = static_cast<int>(0x80bc0002u);
constexpr int ErrorConnectionFailed = static_cast<int>(0x80bc0004u);
constexpr int ErrorInvalidUserId = static_cast<int>(0x80bc0010u);
constexpr int ErrorInvalidType = static_cast<int>(0x80bc0011u);
constexpr int ErrorInvalidOption = static_cast<int>(0x80bc0015u);
constexpr int ErrorInvalidAddress = static_cast<int>(0x80bc0031u);
constexpr int ErrorNoResourceId = static_cast<int>(0x80bc0023u);
constexpr int ErrorInvalidMode = static_cast<int>(0x80bc0024u);
constexpr uint32_t ValidKeyboardModes = 0x0000007f;
constexpr uint32_t TypeNumber = 4;
constexpr uint32_t ValidOptions = 0x00007bff;
constexpr uint32_t OptionUseOver2K = 0x00004000;
constexpr int32_t UserIdInvalid = -1;
std::mutex g_keyboardMutex;
std::set<int32_t> g_openKeyboards;
}
extern "C" {
int APS5_VABI sceImeClose_nid_postfix(void) {
return ErrorNotOpened;
}
int APS5_VABI sceImeGetPanelSize(const Param* param, uint32_t* width, uint32_t* height) {
if (!param || !width || !height) return ErrorInvalidAddress;
if (param->type > TypeNumber) return ErrorInvalidType;
if ((param->option & ~ValidOptions) != 0) return ErrorInvalidOption;
const uint32_t scale = (param->option & OptionUseOver2K) != 0 ? 2 : 1;
*width = (param->type == TypeNumber ? 370u : 793u) * scale;
*height = (param->type == TypeNumber ? 402u : 408u) * scale;
return 0;
}
int APS5_VABI sceImeKeyboardClose(int32_t user_id) {
std::lock_guard lock(g_keyboardMutex);
if (g_openKeyboards.erase(user_id) == 0) throw std::logic_error("sceImeKeyboardClose: keyboard not open for user " + std::to_string(user_id));
return 0;
}
int APS5_VABI sceImeKeyboardGetInfo(uint32_t resource_id, KeyboardInfo* info) {
(void)resource_id;
if (!info) return ErrorInvalidAddress;
std::lock_guard lock(g_keyboardMutex);
return g_openKeyboards.empty() ? ErrorNotOpened : ErrorNoResourceId;
}
int APS5_VABI sceImeKeyboardGetResourceId(int32_t user_id, KeyboardResourceIdArray* resource_ids) {
if (!resource_ids) return ErrorInvalidAddress;
if (user_id == UserIdInvalid) return ErrorInvalidUserId;
*resource_ids = {};
resource_ids->user_id = user_id;
std::lock_guard lock(g_keyboardMutex);
return g_openKeyboards.contains(user_id) ? ErrorConnectionFailed : ErrorNotOpened;
}
int APS5_VABI sceImeKeyboardOpen(int32_t user_id, const KeyboardParam* param) {
if (!param) APS5_INVALID_ARG_EX;
std::lock_guard lock(g_keyboardMutex);
if (!g_openKeyboards.insert(user_id).second) throw std::logic_error("sceImeKeyboardOpen: keyboard already open for user " + std::to_string(user_id));
return 0;
}
int APS5_VABI sceImeKeyboardSetMode(int32_t user_id, uint32_t mode) {
if (user_id == UserIdInvalid) return ErrorInvalidUserId;
std::lock_guard lock(g_keyboardMutex);
if (!g_openKeyboards.contains(user_id)) return ErrorNotOpened;
return (mode & ~ValidKeyboardModes) == 0 ? 0 : ErrorInvalidMode;
}
int APS5_VABI sceImeOpen_nid_postfix(const Param* param, const ExtendedParam* extended) {
(void)param;
(void)extended;
NotImplemented_nid_no_patch(__func__);
return 0;
}
void APS5_VABI sceImeParamInit(Param* param) {
if (!param) return;
std::memset(param, 0, sizeof(*param));
param->user_id = -1;
}
int APS5_VABI sceImeSetCaret(const Caret* caret) {
(void)caret;
return ErrorNotOpened;
}
int APS5_VABI sceImeSetText(const char16_t* text, uint32_t length) {
(void)text;
(void)length;
return ErrorNotOpened;
}
int APS5_VABI sceImeSetTextGeometry(TextAreaMode mode, const TextGeometry* geometry) {
(void)mode;
(void)geometry;
return ErrorNotOpened;
}
int APS5_VABI sceImeUpdate(EventHandler handler) {
if (!handler) APS5_INVALID_ARG_EX;
return 0;
}
}