2013-09-28 04:36:57 +02:00
|
|
|
#include "stdafx.h"
|
2016-03-21 20:43:03 +01:00
|
|
|
#include "Emu/Cell/PPUModule.h"
|
2019-07-15 14:46:46 +02:00
|
|
|
#include "Emu/Memory/vm_ref.h"
|
2014-08-23 22:40:04 +02:00
|
|
|
|
2015-11-16 16:04:49 +01:00
|
|
|
#ifdef _WIN32
|
2025-04-05 21:50:45 +02:00
|
|
|
#include <windows.h>
|
2015-11-16 16:04:49 +01:00
|
|
|
#endif
|
|
|
|
|
|
2023-07-11 20:40:30 +02:00
|
|
|
#ifdef _WIN32
|
2015-12-21 19:17:57 +01:00
|
|
|
typedef int HostCode;
|
|
|
|
|
#else
|
2014-08-18 11:47:54 +02:00
|
|
|
#include <iconv.h>
|
2016-07-27 23:43:22 +02:00
|
|
|
#include <errno.h>
|
2025-04-05 21:50:45 +02:00
|
|
|
typedef const char* HostCode;
|
2014-03-11 17:36:17 +01:00
|
|
|
#endif
|
2014-03-09 04:57:19 +01:00
|
|
|
|
2015-06-13 03:31:45 +02:00
|
|
|
#include "cellL10n.h"
|
|
|
|
|
|
2018-08-25 14:39:00 +02:00
|
|
|
LOG_CHANNEL(cellL10n);
|
2014-05-02 08:30:32 +02:00
|
|
|
|
2015-09-10 16:30:14 +02:00
|
|
|
// Translate code id to code name. some codepage may has another name.
|
|
|
|
|
// If this makes your compilation fail, try replace the string code with one in "iconv -l"
|
2015-12-21 19:17:57 +01:00
|
|
|
bool _L10nCodeParse(s32 code, HostCode& retCode)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2023-07-11 20:40:30 +02:00
|
|
|
#ifdef _WIN32
|
2014-08-18 11:47:54 +02:00
|
|
|
retCode = 0;
|
2025-04-05 21:50:45 +02:00
|
|
|
if ((code >= _L10N_CODE_) || (code < 0))
|
|
|
|
|
return false;
|
2014-08-18 11:47:54 +02:00
|
|
|
switch (code)
|
|
|
|
|
{
|
2025-04-05 21:50:45 +02:00
|
|
|
case L10N_UTF8: retCode = 65001; return false;
|
|
|
|
|
case L10N_UTF16: retCode = 1200; return false; // 1200=LE,1201=BE
|
|
|
|
|
case L10N_UTF32: retCode = 12000; return false; // 12000=LE,12001=BE
|
|
|
|
|
case L10N_UCS2: retCode = 1200; return false; // Not in OEM, but just the same as UTF16
|
|
|
|
|
case L10N_UCS4:
|
|
|
|
|
retCode = 12000;
|
|
|
|
|
return false; // Not in OEM, but just the same as UTF32
|
|
|
|
|
// All OEM Code Pages are Multi-Byte, not wchar_t,u16,u32.
|
|
|
|
|
case L10N_ISO_8859_1: retCode = 28591; return true;
|
|
|
|
|
case L10N_ISO_8859_2: retCode = 28592; return true;
|
|
|
|
|
case L10N_ISO_8859_3: retCode = 28593; return true;
|
|
|
|
|
case L10N_ISO_8859_4: retCode = 28594; return true;
|
|
|
|
|
case L10N_ISO_8859_5: retCode = 28595; return true;
|
|
|
|
|
case L10N_ISO_8859_6: retCode = 28596; return true;
|
|
|
|
|
case L10N_ISO_8859_7: retCode = 28597; return true;
|
|
|
|
|
case L10N_ISO_8859_8: retCode = 28598; return true;
|
|
|
|
|
case L10N_ISO_8859_9: retCode = 28599; return true;
|
|
|
|
|
case L10N_ISO_8859_10: retCode = 28600; return true;
|
|
|
|
|
case L10N_ISO_8859_11: retCode = 28601; return true;
|
|
|
|
|
case L10N_ISO_8859_13: retCode = 28603; return true; // No ISO-8859-12 ha ha.
|
|
|
|
|
case L10N_ISO_8859_14: retCode = 28604; return true;
|
|
|
|
|
case L10N_ISO_8859_15: retCode = 28605; return true;
|
|
|
|
|
case L10N_ISO_8859_16: retCode = 28606; return true;
|
|
|
|
|
case L10N_CODEPAGE_437: retCode = 437; return true;
|
|
|
|
|
case L10N_CODEPAGE_850: retCode = 850; return true;
|
|
|
|
|
case L10N_CODEPAGE_863: retCode = 863; return true;
|
|
|
|
|
case L10N_CODEPAGE_866: retCode = 866; return true;
|
|
|
|
|
case L10N_CODEPAGE_932: retCode = 932; return true;
|
|
|
|
|
case L10N_CODEPAGE_936: retCode = 936; return true; // GBK
|
|
|
|
|
case L10N_CODEPAGE_949: retCode = 949; return true; // UHC
|
|
|
|
|
case L10N_CODEPAGE_950: retCode = 950; return true;
|
|
|
|
|
case L10N_CODEPAGE_1251: retCode = 1251; return true; // CYRL
|
|
|
|
|
case L10N_CODEPAGE_1252: retCode = 1252; return true; // ANSI
|
|
|
|
|
case L10N_EUC_CN: retCode = 51936; return true; // GB2312
|
|
|
|
|
case L10N_EUC_JP: retCode = 51932; return true;
|
|
|
|
|
case L10N_EUC_KR: retCode = 51949; return true;
|
|
|
|
|
case L10N_ISO_2022_JP: retCode = 50222; return true;
|
2015-09-10 16:30:14 +02:00
|
|
|
// Maybe 708/720/864/1256/10004/20420/28596/
|
2025-04-05 21:50:45 +02:00
|
|
|
case L10N_ARIB: retCode = 20420; return true; // TODO: think that should be ARABIC.
|
|
|
|
|
case L10N_HZ: retCode = 52936; return true;
|
|
|
|
|
case L10N_GB18030: retCode = 54936; return true;
|
|
|
|
|
case L10N_RIS_506:
|
|
|
|
|
retCode = 932;
|
|
|
|
|
return true; // MS_KANJI, TODO: Code page
|
2015-09-10 16:30:14 +02:00
|
|
|
// These are only supported with FW 3.10 and above
|
2025-04-05 21:50:45 +02:00
|
|
|
case L10N_CODEPAGE_852: retCode = 852; return true;
|
|
|
|
|
case L10N_CODEPAGE_1250: retCode = 1250; return true; // EE
|
|
|
|
|
case L10N_CODEPAGE_737: retCode = 737; return true;
|
|
|
|
|
case L10N_CODEPAGE_1253: retCode = 1253; return true; // Greek
|
|
|
|
|
case L10N_CODEPAGE_857: retCode = 857; return true;
|
|
|
|
|
case L10N_CODEPAGE_1254: retCode = 1254; return true; // Turk
|
|
|
|
|
case L10N_CODEPAGE_775: retCode = 775; return true;
|
|
|
|
|
case L10N_CODEPAGE_1257: retCode = 1257; return true; // WINBALTRIM
|
|
|
|
|
case L10N_CODEPAGE_855: retCode = 855; return true;
|
|
|
|
|
case L10N_CODEPAGE_858: retCode = 858; return true;
|
|
|
|
|
case L10N_CODEPAGE_860: retCode = 860; return true;
|
|
|
|
|
case L10N_CODEPAGE_861: retCode = 861; return true;
|
|
|
|
|
case L10N_CODEPAGE_865: retCode = 865; return true;
|
|
|
|
|
case L10N_CODEPAGE_869: retCode = 869; return true;
|
|
|
|
|
default: return false;
|
2014-08-18 11:47:54 +02:00
|
|
|
}
|
2015-12-21 19:17:57 +01:00
|
|
|
#else
|
2025-04-05 21:50:45 +02:00
|
|
|
if ((code >= _L10N_CODE_) || (code < 0))
|
|
|
|
|
return false;
|
2015-12-21 19:17:57 +01:00
|
|
|
switch (code)
|
|
|
|
|
{
|
|
|
|
|
// I don't know these Unicode Variants is LB or BE.
|
2025-04-05 21:50:45 +02:00
|
|
|
case L10N_UTF8: retCode = "UTF-8"; return true;
|
|
|
|
|
case L10N_UTF16: retCode = "UTF-16"; return true;
|
|
|
|
|
case L10N_UTF32: retCode = "UTF-32"; return true;
|
|
|
|
|
case L10N_UCS2: retCode = "UCS-2"; return true;
|
|
|
|
|
case L10N_UCS4: retCode = "UCS-4"; return true;
|
|
|
|
|
case L10N_ISO_8859_1: retCode = "ISO-8859-1"; return true;
|
|
|
|
|
case L10N_ISO_8859_2: retCode = "ISO-8859-2"; return true;
|
|
|
|
|
case L10N_ISO_8859_3: retCode = "ISO-8859-3"; return true;
|
|
|
|
|
case L10N_ISO_8859_4: retCode = "ISO-8859-4"; return true;
|
|
|
|
|
case L10N_ISO_8859_5: retCode = "ISO-8859-5"; return true;
|
|
|
|
|
case L10N_ISO_8859_6: retCode = "ISO-8859-6"; return true;
|
|
|
|
|
case L10N_ISO_8859_7: retCode = "ISO-8859-7"; return true;
|
|
|
|
|
case L10N_ISO_8859_8: retCode = "ISO-8859-8"; return true;
|
|
|
|
|
case L10N_ISO_8859_9: retCode = "ISO-8859-9"; return true;
|
|
|
|
|
case L10N_ISO_8859_10: retCode = "ISO-8859-10"; return true;
|
|
|
|
|
case L10N_ISO_8859_11: retCode = "ISO-8859-11"; return true;
|
|
|
|
|
case L10N_ISO_8859_13: retCode = "ISO-8859-13"; return true; // No ISO-8859-12 ha ha.
|
|
|
|
|
case L10N_ISO_8859_14: retCode = "ISO-8859-14"; return true;
|
|
|
|
|
case L10N_ISO_8859_15: retCode = "ISO-8859-15"; return true;
|
|
|
|
|
case L10N_ISO_8859_16: retCode = "ISO-8859-16"; return true;
|
|
|
|
|
case L10N_CODEPAGE_437: retCode = "CP437"; return true;
|
|
|
|
|
case L10N_CODEPAGE_850: retCode = "CP850"; return true;
|
|
|
|
|
case L10N_CODEPAGE_863: retCode = "CP863"; return true;
|
|
|
|
|
case L10N_CODEPAGE_866: retCode = "CP866"; return true;
|
|
|
|
|
case L10N_CODEPAGE_932: retCode = "CP932"; return true;
|
|
|
|
|
case L10N_CODEPAGE_936: retCode = "CP936"; return true;
|
|
|
|
|
case L10N_CODEPAGE_949: retCode = "CP949"; return true;
|
|
|
|
|
case L10N_CODEPAGE_950: retCode = "CP950"; return true;
|
|
|
|
|
case L10N_CODEPAGE_1251: retCode = "CP1251"; return true; // CYRL
|
|
|
|
|
case L10N_CODEPAGE_1252: retCode = "CP1252"; return true; // ANSI
|
|
|
|
|
case L10N_EUC_CN: retCode = "EUC-CN"; return true; // GB2312
|
|
|
|
|
case L10N_EUC_JP: retCode = "EUC-JP"; return true;
|
|
|
|
|
case L10N_EUC_KR: retCode = "EUC-KR"; return true;
|
|
|
|
|
case L10N_ISO_2022_JP: retCode = "ISO-2022-JP"; return true;
|
|
|
|
|
case L10N_ARIB: retCode = "ARABIC"; return true; // TODO: think that should be ARABIC.
|
|
|
|
|
case L10N_HZ: retCode = "HZ"; return true;
|
|
|
|
|
case L10N_GB18030: retCode = "GB18030"; return true;
|
|
|
|
|
case L10N_RIS_506:
|
|
|
|
|
retCode = "Shift_JIS";
|
|
|
|
|
return true; // MS_KANJI
|
2017-02-08 01:25:10 +01:00
|
|
|
// These are only supported with FW 3.10 and below
|
2025-04-05 21:50:45 +02:00
|
|
|
case L10N_CODEPAGE_852: retCode = "CP852"; return true;
|
|
|
|
|
case L10N_CODEPAGE_1250: retCode = "CP1250"; return true; // EE
|
|
|
|
|
case L10N_CODEPAGE_737: retCode = "CP737"; return true;
|
|
|
|
|
case L10N_CODEPAGE_1253: retCode = "CP1253"; return true; // Greek
|
|
|
|
|
case L10N_CODEPAGE_857: retCode = "CP857"; return true;
|
|
|
|
|
case L10N_CODEPAGE_1254: retCode = "CP1254"; return true; // Turk
|
|
|
|
|
case L10N_CODEPAGE_775: retCode = "CP775"; return true;
|
|
|
|
|
case L10N_CODEPAGE_1257: retCode = "CP1257"; return true; // WINBALTRIM
|
|
|
|
|
case L10N_CODEPAGE_855: retCode = "CP855"; return true;
|
|
|
|
|
case L10N_CODEPAGE_858: retCode = "CP858"; return true;
|
|
|
|
|
case L10N_CODEPAGE_860: retCode = "CP860"; return true;
|
|
|
|
|
case L10N_CODEPAGE_861: retCode = "CP861"; return true;
|
|
|
|
|
case L10N_CODEPAGE_865: retCode = "CP865"; return true;
|
|
|
|
|
case L10N_CODEPAGE_869: retCode = "CP869"; return true;
|
|
|
|
|
default: return false;
|
2015-12-21 19:17:57 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
2014-08-18 11:47:54 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-11 20:40:30 +02:00
|
|
|
#ifdef _WIN32
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2015-09-10 16:30:14 +02:00
|
|
|
// Use code page to transform std::string to std::wstring.
|
2025-02-02 19:45:23 +01:00
|
|
|
s32 _OEM2Wide(HostCode oem_code, std::string_view src, std::wstring& dst)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2025-02-02 19:45:23 +01:00
|
|
|
// Such length returned should include the '\0' character.
|
|
|
|
|
const s32 length = MultiByteToWideChar(oem_code, 0, src.data(), -1, nullptr, 0);
|
|
|
|
|
std::vector<wchar_t> store(length);
|
2014-08-19 08:58:26 +02:00
|
|
|
|
2025-02-02 19:45:23 +01:00
|
|
|
MultiByteToWideChar(oem_code, 0, src.data(), -1, static_cast<LPWSTR>(store.data()), length);
|
|
|
|
|
dst = std::wstring(store.data());
|
2014-08-19 08:58:26 +02:00
|
|
|
|
2014-08-18 11:47:54 +02:00
|
|
|
return length - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 16:30:14 +02:00
|
|
|
// Use Code page to transform std::wstring to std::string.
|
2025-02-02 19:45:23 +01:00
|
|
|
s32 _Wide2OEM(HostCode oem_code, std::wstring_view src, std::string& dst)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2025-04-05 21:50:45 +02:00
|
|
|
// Such length returned should include the '\0' character.
|
2025-02-02 19:45:23 +01:00
|
|
|
const s32 length = WideCharToMultiByte(oem_code, 0, src.data(), -1, nullptr, 0, nullptr, nullptr);
|
|
|
|
|
std::vector<char> store(length);
|
2014-08-19 08:58:26 +02:00
|
|
|
|
2025-02-02 19:45:23 +01:00
|
|
|
WideCharToMultiByte(oem_code, 0, src.data(), -1, store.data(), length, nullptr, nullptr);
|
|
|
|
|
dst = std::string(store.data());
|
2014-08-19 08:58:26 +02:00
|
|
|
|
2014-08-18 11:47:54 +02:00
|
|
|
return length - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-10 16:30:14 +02:00
|
|
|
// Convert Codepage to Codepage (all char*)
|
2025-02-02 19:45:23 +01:00
|
|
|
std::string _OemToOem(HostCode src_code, HostCode dst_code, std::string_view str)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2025-02-02 19:45:23 +01:00
|
|
|
std::wstring wide;
|
|
|
|
|
std::string result;
|
2014-08-18 11:47:54 +02:00
|
|
|
_OEM2Wide(src_code, str, wide);
|
|
|
|
|
_Wide2OEM(dst_code, wide, result);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-21 19:17:57 +01:00
|
|
|
#endif
|
|
|
|
|
|
2025-04-05 21:50:45 +02:00
|
|
|
s32 _ConvertStr(s32 src_code, const void* src, s32 src_len, s32 dst_code, void* dst, s32* dst_len, [[maybe_unused]] bool allowIncomplete)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2025-04-05 21:50:45 +02:00
|
|
|
HostCode srcCode = 0, dstCode = 0; // OEM code pages
|
|
|
|
|
const bool src_page_converted = _L10nCodeParse(src_code, srcCode); // Check if code is in list.
|
2025-02-02 19:45:23 +01:00
|
|
|
const bool dst_page_converted = _L10nCodeParse(dst_code, dstCode);
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2025-02-02 19:45:23 +01:00
|
|
|
if (((!src_page_converted) && (srcCode == 0)) ||
|
|
|
|
|
((!dst_page_converted) && (dstCode == 0)))
|
|
|
|
|
{
|
2014-08-18 11:47:54 +02:00
|
|
|
return ConverterUnknown;
|
2025-02-02 19:45:23 +01:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2023-07-11 20:40:30 +02:00
|
|
|
#ifdef _WIN32
|
2025-04-05 21:50:45 +02:00
|
|
|
const std::string_view wrapped_source = std::string_view(static_cast<const char*>(src), src_len);
|
2021-04-09 21:12:47 +02:00
|
|
|
const std::string target = _OemToOem(srcCode, dstCode, wrapped_source);
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
if (dst)
|
2015-12-25 01:01:23 +01:00
|
|
|
{
|
2025-04-05 21:50:45 +02:00
|
|
|
if (target.length() > static_cast<usz>(*dst_len))
|
|
|
|
|
return DSTExhausted;
|
2025-02-02 19:45:23 +01:00
|
|
|
std::memcpy(dst, target.c_str(), target.length());
|
2015-12-25 01:01:23 +01:00
|
|
|
}
|
2019-06-28 14:41:47 +02:00
|
|
|
*dst_len = ::narrow<s32>(target.size());
|
2014-08-18 11:47:54 +02:00
|
|
|
|
|
|
|
|
return ConversionOK;
|
2015-12-21 19:17:57 +01:00
|
|
|
#else
|
2015-06-13 03:31:45 +02:00
|
|
|
s32 retValue = ConversionOK;
|
2015-12-21 19:17:57 +01:00
|
|
|
iconv_t ict = iconv_open(dstCode, srcCode);
|
2020-12-18 08:39:54 +01:00
|
|
|
usz srcLen = src_len;
|
2025-02-02 16:16:33 +01:00
|
|
|
if (dst)
|
2015-12-25 01:01:23 +01:00
|
|
|
{
|
2020-12-18 08:39:54 +01:00
|
|
|
usz dstLen = *dst_len;
|
2021-03-13 16:02:37 +01:00
|
|
|
usz ictd = iconv(ict, utils::bless<char*>(&src), &srcLen, utils::bless<char*>(&dst), &dstLen);
|
2015-12-25 01:01:23 +01:00
|
|
|
*dst_len -= dstLen;
|
2020-02-19 18:03:59 +01:00
|
|
|
if (ictd == umax)
|
2015-12-25 01:01:23 +01:00
|
|
|
{
|
|
|
|
|
if (errno == EILSEQ)
|
2025-04-05 21:50:45 +02:00
|
|
|
retValue = SRCIllegal; // Invalid multi-byte sequence
|
2015-12-25 01:01:23 +01:00
|
|
|
else if (errno == E2BIG)
|
2025-04-05 21:50:45 +02:00
|
|
|
retValue = DSTExhausted; // Not enough space
|
2015-12-25 01:01:23 +01:00
|
|
|
else if (errno == EINVAL)
|
|
|
|
|
{
|
|
|
|
|
if (allowIncomplete)
|
2025-04-05 21:50:45 +02:00
|
|
|
*dst_len = -1; // TODO: correct value?
|
2015-12-25 01:01:23 +01:00
|
|
|
else
|
|
|
|
|
retValue = SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2015-12-25 01:01:23 +01:00
|
|
|
*dst_len = 0;
|
|
|
|
|
char buf[16];
|
|
|
|
|
while (srcLen > 0)
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2025-04-05 21:50:45 +02:00
|
|
|
// char *bufPtr = buf;
|
2020-12-18 08:39:54 +01:00
|
|
|
usz bufLeft = sizeof(buf);
|
2021-03-13 16:02:37 +01:00
|
|
|
usz ictd = iconv(ict, utils::bless<char*>(&src), &srcLen, utils::bless<char*>(&dst), &bufLeft);
|
2015-12-25 01:01:23 +01:00
|
|
|
*dst_len += sizeof(buf) - bufLeft;
|
2020-02-19 18:03:59 +01:00
|
|
|
if (ictd == umax && errno != E2BIG)
|
2015-12-25 01:01:23 +01:00
|
|
|
{
|
|
|
|
|
if (errno == EILSEQ)
|
|
|
|
|
retValue = SRCIllegal;
|
|
|
|
|
else if (errno == EINVAL)
|
|
|
|
|
{
|
|
|
|
|
if (allowIncomplete)
|
2025-04-05 21:50:45 +02:00
|
|
|
*dst_len = -1; // TODO: correct value?
|
2015-12-25 01:01:23 +01:00
|
|
|
else
|
|
|
|
|
retValue = SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-21 19:17:57 +01:00
|
|
|
iconv_close(ict);
|
2014-08-18 11:47:54 +02:00
|
|
|
return retValue;
|
|
|
|
|
#endif
|
2015-12-21 19:17:57 +01:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 _L10nConvertStr(s32 src_code, vm::cptr<void> src, vm::cptr<u32> src_len, s32 dst_code, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-12-21 19:17:57 +01:00
|
|
|
{
|
|
|
|
|
s32 dstLen = *dst_len;
|
2019-12-20 04:51:16 +01:00
|
|
|
s32 result = _ConvertStr(src_code, src.get_ptr(), *src_len, dst_code, dst ? dst.get_ptr() : nullptr, &dstLen, false);
|
2015-12-21 19:17:57 +01:00
|
|
|
*dst_len = dstLen;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 21:50:45 +02:00
|
|
|
s32 _L10nConvertChar(s32 src_code, const void* src, u32 src_len, s32 dst_code, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-12-21 19:17:57 +01:00
|
|
|
{
|
|
|
|
|
s32 dstLen = 0x7FFFFFFF;
|
|
|
|
|
s32 result = _ConvertStr(src_code, src, src_len, dst_code, dst.get_ptr(), &dstLen, true);
|
|
|
|
|
*dst_len = dstLen;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-01 00:48:38 +02:00
|
|
|
s32 UCS2toEUCJP()
|
2014-08-18 11:47:54 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toEUCJP()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 l10n_convert(s32 cd, vm::cptr<void> src, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.todo("l10n_convert(cd=0x%x, src=*0x%x, dst=*0x%x, dst_len=*0x%x)", cd, src, dst, dst_len);
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2toUTF32(u16 ucs2, vm::ptr<u32> utf32)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2toUTF32(ucs2=0x%x, utf32=*0x%x)", ucs2, utf32);
|
|
|
|
|
|
|
|
|
|
const s32 sucs2 = static_cast<s32>(ucs2);
|
|
|
|
|
|
|
|
|
|
if ((sucs2 & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
ensure(!!utf32); // Not actually checked
|
|
|
|
|
|
|
|
|
|
*utf32 = sucs2;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2015-08-01 00:48:38 +02:00
|
|
|
s32 jis2kuten()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("jis2kuten()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2015-08-01 00:48:38 +02:00
|
|
|
s32 UTF8toGB18030()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toGB18030()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
2014-08-18 11:47:54 +02:00
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 JISstoUTF8s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("JISstoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 SjisZen2Han(vm::cptr<u16> src)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2021-03-05 20:05:37 +01:00
|
|
|
cellL10n.todo("SjisZen2Han(src=*0x%x)", src);
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToSjisLower()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToSjisLower()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toGB18030()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toGB18030()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 HZstoUCS2s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u16> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("HZstoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 UCS2stoHZs(vm::cptr<u16> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoHZs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 UCS2stoSJISs(vm::cptr<u16> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoSJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 kuten2eucjp()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("kuten2eucjp()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
u16 sjis2jis(u16 c)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("sjis2jis(c=0x%x)", c);
|
|
|
|
|
|
|
|
|
|
u64 v0 = static_cast<u64>(static_cast<s64>(static_cast<s16>(c))) >> 8 & 0xff;
|
|
|
|
|
u64 v1 = v0 - 0x81;
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((v1 & 0xffff) >= 0x7c) || (0x3f >= ((v0 - 0xa0) & 0xffff)))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 v2 = static_cast<s64>(static_cast<s16>(c)) & 0xff;
|
|
|
|
|
|
|
|
|
|
if (0x3f < v2 && (v2 < 0xfd && (static_cast<s16>(v2) != 0x7f)))
|
|
|
|
|
{
|
|
|
|
|
if (0x9f < v0)
|
|
|
|
|
{
|
|
|
|
|
v1 = v0 - 0xc1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u16 v3 = static_cast<s16>(v2) - 0x7e;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 0x22;
|
|
|
|
|
|
|
|
|
|
if (v2 < 0x9f)
|
|
|
|
|
{
|
|
|
|
|
const s16 v4 = v2 < 0x7f ? 0x1f : 0x20;
|
|
|
|
|
v3 = static_cast<s16>(v2) - v4;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 0x21;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((v0 & 0xffff) < 0x7f)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<u16>((v0 & 0xffff) << 8) | v3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 EUCKRstoUCS2s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u16> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRstoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 UHCstoEUCKRs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCstoEUCKRs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 jis2sjis()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("jis2sjis()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 jstrnchk(vm::cptr<u8> src, s32 src_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
u8 r = 0;
|
2018-08-25 14:39:00 +02:00
|
|
|
|
2019-05-22 05:47:47 +02:00
|
|
|
for (s32 len = 0; len < src_len; len++)
|
2017-02-08 01:25:10 +01:00
|
|
|
{
|
2019-12-20 04:51:16 +01:00
|
|
|
if (src)
|
2017-02-08 01:25:10 +01:00
|
|
|
{
|
|
|
|
|
if (*src >= 0xa1 && *src <= 0xfe)
|
|
|
|
|
{
|
|
|
|
|
cellL10n.warning("jstrnchk: EUCJP (src=*0x%x, src_len=*0x%x)", src, src_len);
|
|
|
|
|
r |= L10N_STR_EUCJP;
|
2018-08-25 14:39:00 +02:00
|
|
|
}
|
2025-04-05 21:50:45 +02:00
|
|
|
else if (((*src >= 0x81 && *src <= 0x9f) || (*src >= 0xe0 && *src <= 0xfc)) || (*src >= 0x40 && *src <= 0xfc && *src != 0x7f))
|
2017-02-08 01:25:10 +01:00
|
|
|
{
|
|
|
|
|
cellL10n.warning("jstrnchk: SJIS (src=*0x%x, src_len=*0x%x)", src, src_len);
|
|
|
|
|
r |= L10N_STR_SJIS;
|
|
|
|
|
}
|
|
|
|
|
// ISO-2022-JP. (JIS X 0202) That's an inaccurate general range which (contains ASCII and UTF-8 characters?).
|
2018-08-25 14:39:00 +02:00
|
|
|
else if (*src >= 0x21 && *src <= 0x7e)
|
2017-02-08 01:25:10 +01:00
|
|
|
{
|
|
|
|
|
cellL10n.warning("jstrnchk: JIS (src=*0x%x, src_len=*0x%x)", src, src_len);
|
|
|
|
|
r |= L10N_STR_JIS;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
cellL10n.todo("jstrnchk: Unimplemented (src=*0x%x, src_len=*0x%x)", src, src_len);
|
|
|
|
|
}
|
|
|
|
|
// TODO:
|
|
|
|
|
// L10N_STR_ASCII
|
|
|
|
|
// L10N_STR_UTF8
|
2018-08-25 14:39:00 +02:00
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
// L10N_STR_UNKNOWN
|
|
|
|
|
// L10N_STR_ILLEGAL
|
|
|
|
|
// L10N_STR_ERROR
|
|
|
|
|
}
|
|
|
|
|
src++;
|
|
|
|
|
}
|
|
|
|
|
return r;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 L10nConvert()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("L10nConvert()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCCNstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCCNstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GBKstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GBKstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 eucjphan2zen(vm::cptr<u16> src)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("eucjphan2zen()");
|
|
|
|
|
return *src; // Returns the character itself if conversion fails
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToSjisHira()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToSjisHira()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GBKtoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GBKtoUCS2()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 eucjp2jis()
|
|
|
|
|
{
|
2019-09-02 13:41:57 +02:00
|
|
|
cellL10n.todo("eucjp2jis()");
|
|
|
|
|
return CELL_OK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32toUTF8(u32 src, vm::ptr<u8> dst);
|
|
|
|
|
|
|
|
|
|
s32 UTF32stoUTF8s(vm::cptr<u32> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32stoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
auto tmp = vm::make_var<be_t<u8>[4]>({0, 0, 0, 0});
|
|
|
|
|
const vm::ptr<u8> utf8_tmp = vm::cast(tmp.addr());
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_len = UTF32toUTF8(src[src_pos], utf8_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf8_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += utf8_len;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len - utf8_len;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (s32 i = 0; i < utf8_len; i++)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = utf8_tmp[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 sjishan2zen()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("sjishan2zen()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 UCS2toSBCS(u16 src, vm::ptr<u8> dst, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("UCS2toSBCS(src=0x%x, dst=*0x%x, code_page=0x%x)", src, dst, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src < 0xfffe)
|
|
|
|
|
{
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (src < 0x80)
|
|
|
|
|
{
|
|
|
|
|
*dst = static_cast<u8>(src);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vm::var<u32> dst_len = vm::make_var<u32>(0);
|
|
|
|
|
const s32 res = _L10nConvertChar(L10N_UCS2, &src, sizeof(src), code_page, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
if (res == ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res == ConverterUnknown)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoGBKs()
|
|
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.todo("UTF8stoGBKs()");
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8toUCS2(vm::cptr<u8> src, vm::ptr<u16> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8toUCS2(src=*0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
ensure(src && dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if ((((src[0] & 0xf0) == 0xe0) && ((src[1] & 0xc0) == 0x80)) && ((src[2] & 0xc0) == 0x80))
|
|
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
const u64 ucs2 = (static_cast<u64>(src[1]) & 0x3f) << 6 | (static_cast<u64>(src[0]) & 0xf) << 0xc | (static_cast<u64>(src[2]) & 0x3f);
|
2025-02-02 16:16:33 +01:00
|
|
|
|
|
|
|
|
if (ucs2 < 0x800)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((static_cast<u32>(ucs2) & UTF16_SURROGATES_MASK1) == UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u16>(ucs2);
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((((src[0] & 0xe0) == 0xc0) && (0xc1 < static_cast<u64>(src[0]))) && ((src[1] & 0xc0) == 0x80))
|
|
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
*dst = (src[0] & 0x1f) << 6 | (src[1] & 0x3f);
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src[0]) < '\0')
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u16>(src[0]);
|
|
|
|
|
return 1;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2toUTF8(u16 ucs2, vm::ptr<u8> utf8);
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoUTF8s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2stoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
auto tmp = vm::make_var<be_t<u8>[4]>({0, 0, 0, 0});
|
|
|
|
|
const vm::ptr<u8> utf8_tmp = vm::cast(tmp.addr());
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_size = UCS2toUTF8(src[src_pos], utf8_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf8_size == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += utf8_size;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len - utf8_size;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (s32 i = 0; i < utf8_size; i++)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = utf8_tmp[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCKRstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16toUTF32(vm::cptr<u16> src, vm::ptr<u32> dst);
|
|
|
|
|
|
|
|
|
|
s32 UTF16stoUTF32s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u32> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16stoUTF32s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
vm::var<u32> utf32_tmp = vm::make_var<u32>(0);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf16_len = UTF16toUTF32(src + src_pos, utf32_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf16_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = *utf32_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_pos += utf16_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toEUCKR()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toEUCKR()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16toUTF8(vm::cptr<u16> src, vm::ptr<u8> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16toUTF8(src=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src && dst && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
const u64 utf16_long = src[0];
|
|
|
|
|
vm::cptr<u8> src_raw = vm::cast(src.addr());
|
|
|
|
|
|
|
|
|
|
if ((src[0] & UTF16_SURROGATES_MASK1) == UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
if (((src[0] & UTF16_SURROGATES_MASK2) == UTF16_HIGH_SURROGATES) && ((src[1] & UTF16_SURROGATES_MASK2) == UTF16_LOW_SURROGATES))
|
|
|
|
|
{
|
|
|
|
|
const s64 lVar2 = (static_cast<u64>(src[0] >> 6) & 0xf) + 1;
|
|
|
|
|
dst[0] = static_cast<u8>(static_cast<u64>(lVar2 << 0x20) >> 0x22) | 0xf0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<s8>(lVar2) * '\x10' & 0x30U) | (static_cast<u8>(src[0] >> 2) & 0xf) | 0x80;
|
|
|
|
|
dst[2] = (static_cast<u8>(src[1] >> 6) & 0xf) | (static_cast<u8>(src[0]) & 3) << 4 | 0x80;
|
|
|
|
|
dst[3] = (static_cast<u8>(src_raw[3]) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = 4;
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0x7ff < utf16_long)
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>((utf16_long << 0x20) >> 0x2c) | 0xe0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u8>(src[0] >> 6) & 0x3f) | 0x80;
|
|
|
|
|
dst[2] = (static_cast<u8>(src_raw[1]) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = 3;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (utf16_long < 0x80)
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>(src[0]);
|
|
|
|
|
*dst_len = 1;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[0] = static_cast<u8>((utf16_long << 0x20) >> 0x26) | 0xc0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u8>(src_raw[1]) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = 2;
|
|
|
|
|
return 1;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ARIBstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ARIBstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2014-08-18 11:47:54 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 SJISstoUTF8s(vm::cptr<void> src, vm::cptr<u32> src_len, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.warning("SJISstoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
2015-12-21 19:17:57 +01:00
|
|
|
return _L10nConvertStr(L10N_CODEPAGE_932, src, src_len, L10N_UTF8, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 sjiszen2han(vm::cptr<u16> src)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("sjiszen2han()");
|
|
|
|
|
return *src; // Returns the character itself if conversion fails
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToEucJpLower()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToEucJpLower()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 MSJIStoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("MSJIStoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoMSJISs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoMSJISs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCJPtoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPtoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 eucjp2sjis()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("eucjp2sjis()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToEucJpHira()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToEucJpHira()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UHCstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToEucJpKata()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToEucJpKata()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 HZstoUTF8s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("HZstoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toMSJIS()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toMSJIS()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 BIG5toUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("BIG5toUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 EUCJPstoSJISs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPstoSJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoBIG5s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoBIG5s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16stoUCS2s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16stoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const u16 utf16 = src[src_pos];
|
|
|
|
|
|
|
|
|
|
if ((utf16 & UTF16_SURROGATES_MASK1) == UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = utf16;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoGB18030s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoGB18030s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCJPtoSJIS()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPtoSJIS()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCJPtoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPtoUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoGBKs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoGBKs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCKRtoUHC()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRtoUHC()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-21 19:17:57 +01:00
|
|
|
s32 UCS2toSJIS(u16 ch, vm::ptr<void> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toSJIS(ch=%d, dst=*0x%x)", ch, dst);
|
2018-08-25 14:39:00 +02:00
|
|
|
// Should be L10N_UCS2 (16bit) not L10N_UTF8 (8bit) and L10N_SHIFT_JIS
|
2017-02-08 01:25:10 +01:00
|
|
|
// return _L10nConvertCharNoResult(L10N_UTF8, &ch, sizeof(ch), L10N_CODEPAGE_932, dst);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 MSJISstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("MSJISstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 EUCJPstoUTF8s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPstoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toBIG5()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toBIG5()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoEUCKRs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoEUCKRs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UHCstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GB18030stoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GB18030stoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 SJIStoUTF8(u8 ch, vm::ptr<void> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SJIStoUTF8(ch=%d, dst=*0x%x, dst_len=*0x%x)", ch, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 JISstoSJISs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("JISstoSJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8toUTF16(vm::cptr<u8> src, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8toUTF16(src=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src && dst && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
u64 longval = src[0];
|
|
|
|
|
|
|
|
|
|
if ((src[0] & 0xf8) == 0xf0)
|
|
|
|
|
{
|
|
|
|
|
if ((src[1] & 0xc0) == 0x80)
|
|
|
|
|
{
|
|
|
|
|
if ((src[2] & 0xc0) == 0x80 && (src[3] & 0xc0) == 0x80)
|
|
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
longval = (longval & 7) << 2 | (static_cast<u64>(src[1] >> 4) & 3);
|
2025-02-02 16:16:33 +01:00
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((longval - 1) & 0xffff) < 0x10)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[0] = (src[1] & 0xf) << 2 | (src[2] >> 4 & 3) | static_cast<u16>(((longval - 1) & 0xffffffff) << 6) | UTF16_HIGH_SURROGATES;
|
|
|
|
|
dst[1] = (src[2] & 0xf) << 6 | (src[3] & 0x3f) | UTF16_LOW_SURROGATES;
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = 2;
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((src[0] & 0xf0) != 0xe0)
|
|
|
|
|
{
|
|
|
|
|
if (((src[0] & 0xe0) == 0xc0) && (0xc1 < longval))
|
|
|
|
|
{
|
|
|
|
|
if ((src[1] & 0xc0) != 0x80)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[0] = (src[0] & 0x1f) << 6 | (src[1] & 0x3f);
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = 1;
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src[0]) < '\0')
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[0] = static_cast<u16>(src[0]);
|
|
|
|
|
*dst_len = 1;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((src[1] & 0xc0) == 0x80 && (src[2] & 0xc0) == 0x80)
|
|
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
longval = (static_cast<u64>(src[1]) & 0x3f) << 6 | (longval & 0xf) << 0xc | (static_cast<u64>(src[2]) & 0x3f);
|
2025-02-02 16:16:33 +01:00
|
|
|
|
|
|
|
|
if ((0x7ff < longval && ((static_cast<u32>(longval) & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)))
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u16>(longval);
|
|
|
|
|
*dst_len = 1;
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoMSJISs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoMSJISs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCKRtoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRtoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 SjisHan2Zen()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SjisHan2Zen()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2toUTF16(u16 ucs2, vm::ptr<u16> utf16)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2toUTF16(ucs2=0x%x, utf16=*0x%x)", ucs2, utf16);
|
|
|
|
|
|
|
|
|
|
const s32 sucs2 = static_cast<s32>(ucs2);
|
|
|
|
|
|
|
|
|
|
if ((sucs2 & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
ensure(!!utf16); // Not actually checked
|
|
|
|
|
|
|
|
|
|
*utf16 = ucs2;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toMSJIS()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toMSJIS()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
u16 sjis2kuten(u16 c)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("sjis2kuten(c=0x%x)", c);
|
|
|
|
|
|
|
|
|
|
u64 v0 = static_cast<u64>(static_cast<s64>(static_cast<s16>(c))) >> 8 & 0xff;
|
|
|
|
|
u64 v1 = v0 - 0x81;
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((v1 & 0xffff) >= 0x7c) || (0x3f >= ((v0 - 0xa0) & 0xffff)))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 v2 = static_cast<s64>(static_cast<s16>(c)) & 0xff;
|
|
|
|
|
|
|
|
|
|
if (0x3f < v2 && (v2 < 0xfd && (static_cast<s32>(v2) != 0x7f)))
|
|
|
|
|
{
|
|
|
|
|
if (0x9f < v0)
|
|
|
|
|
{
|
|
|
|
|
v1 = v0 - 0xc1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u16 v3 = static_cast<s16>(v2) - 0x9e;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 2;
|
|
|
|
|
|
|
|
|
|
if (v2 < 0x9f)
|
|
|
|
|
{
|
|
|
|
|
const s16 v4 = v2 < 0x7f ? 0x1f : 0x20;
|
|
|
|
|
v3 = (static_cast<s16>(v2) - v4) - 0x20;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return static_cast<u16>((v0 & 0xffffffff) << 8) | v3;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toUHC()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toUHC()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32toUCS2(u32 src, vm::ptr<u16> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32toUCS2(src=0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
if ((src < 0x10000) && (0x7ff < src - UTF16_HIGH_SURROGATES))
|
|
|
|
|
{
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u16>(src);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToSjisUpper()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToSjisUpper()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toEUCJP()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toEUCJP()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoEUCJPs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoEUCJPs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16toUCS2(vm::cptr<u16> src, vm::ptr<u16> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16toUCS2(src=*0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
ensure(!!src); // Not really checked
|
|
|
|
|
|
|
|
|
|
if ((*src & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
*dst = *src;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2stoUTF16s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2stoUTF16s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const u16 ucs2 = src[src_pos];
|
|
|
|
|
|
|
|
|
|
if ((ucs2 & UTF16_SURROGATES_MASK1) == UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = ucs2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoEUCCNs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoEUCCNs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 SBCSstoUTF8s(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("SBCSstoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x, code_page=0x%x)", src, src_len, dst, dst_len, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return ConverterUnknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (*src_len == 0u)
|
|
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
u8 src_val = src[src_pos];
|
|
|
|
|
u64 longval = static_cast<u64>(src_val);
|
|
|
|
|
s32 utf8_len = 1;
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src_val) < '\0')
|
|
|
|
|
{
|
|
|
|
|
u8 dst_tmp[4] = {};
|
|
|
|
|
s32 dst_len_tmp = 4;
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(code_page, &src_val, 1, L10N_UTF8, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-24 13:13:34 +02:00
|
|
|
longval = *reinterpret_cast<u32*>(dst_tmp);
|
2025-02-02 22:16:58 +01:00
|
|
|
utf8_len = dst_len_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += utf8_len;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len - utf8_len;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_val = static_cast<u8>(longval);
|
|
|
|
|
|
|
|
|
|
if (utf8_len == 3)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = static_cast<u8>((longval << 0x20) >> 0x2c) | 0xe0;
|
|
|
|
|
dst[dst_pos++] = (static_cast<u8>(longval >> 6) & 0x3f) | 0x80;
|
|
|
|
|
dst[dst_pos++] = (src_val & 0x3f) | 0x80;
|
|
|
|
|
}
|
|
|
|
|
else if (utf8_len == 1)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = src_val;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = static_cast<u8>(longval >> 6) | 0xc0;
|
|
|
|
|
dst[dst_pos++] = (src_val & 0x3f) | 0x80;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 SJISstoJISs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SJISstoJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 SBCStoUTF8(u8 src, vm::ptr<u8> dst, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("SBCStoUTF8(src=0x%x, dst=*0x%x, code_page=0x%x)", src, *dst, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src) >= 0)
|
|
|
|
|
{
|
|
|
|
|
*dst = src;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 dst_tmp = 0;
|
|
|
|
|
s32 dst_len_tmp = 1;
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(L10N_UTF8, &src, 1, code_page, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 longval = static_cast<u64>(dst_tmp);
|
|
|
|
|
const u8 val = static_cast<u8>(dst_tmp) & 0x3f;
|
|
|
|
|
|
|
|
|
|
if (longval < 0x800)
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>((longval << 0x20) >> 0x26) | 0xc0;
|
|
|
|
|
dst[1] = val | 0x80;
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[0] = static_cast<u8>((longval << 0x20) >> 0x2c) | 0xe0;
|
|
|
|
|
dst[1] = (static_cast<u8>(static_cast<u16>(dst_tmp) >> 6) & 0x3f) | 0x80;
|
|
|
|
|
dst[2] = val | 0x80;
|
|
|
|
|
return 3;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8toUTF32(vm::cptr<u8> src, vm::ptr<u32> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8toUTF32(src=*0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
ensure(src && dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
u64 longval = src[0];
|
|
|
|
|
|
|
|
|
|
if ((src[0] & 0xf8) == 0xf0)
|
|
|
|
|
{
|
|
|
|
|
if ((src[1] & 0xc0) != 0x80 ||
|
|
|
|
|
(src[2] & 0xc0) != 0x80 ||
|
|
|
|
|
(src[3] & 0xc0) != 0x80)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
longval = (static_cast<u64>(src[2]) & 0x3f) << 6 | (longval & 7) << 0x12 | (static_cast<u64>(src[1]) & 0x3f) << 0xc | (static_cast<u64>(src[3]) & 0x3f);
|
|
|
|
|
if (0xfffff < ((longval - 0x10000) & 0xffffffff))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u32>(longval);
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((src[0] & 0xf0) == 0xe0)
|
|
|
|
|
{
|
|
|
|
|
if ((src[1] & 0xc0) != 0x80 ||
|
|
|
|
|
(src[2] & 0xc0) != 0x80)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
longval = (static_cast<u64>(src[1]) & 0x3f) << 6 | (longval & 0xf) << 0xc | (static_cast<u64>(src[2]) & 0x3f);
|
|
|
|
|
if (longval < 0x800 || ((longval - UTF16_HIGH_SURROGATES) & 0xffffffff) < 0x800)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u32>(longval);
|
|
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (((src[0] & 0xe0) == 0xc0) && (0xc1 < longval))
|
|
|
|
|
{
|
|
|
|
|
if ((src[1] & 0xc0) != 0x80)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
*dst = (src[0] & 0x1f) << 6 | (src[1] & 0x3f);
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src[0]) < '\0')
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = static_cast<u32>(src[0]);
|
|
|
|
|
return 1;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 jstrchk(vm::cptr<u8> jstr)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-04-02 18:19:06 +02:00
|
|
|
cellL10n.todo("jstrchk(jstr=*0x%x) -> utf8", jstr);
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2016-04-02 18:19:06 +02:00
|
|
|
// TODO: Actually detect the type of the string
|
2015-08-01 00:48:38 +02:00
|
|
|
return L10N_STR_UTF8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UHCtoEUCKR()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCtoEUCKR()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 kuten2jis()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("kuten2jis()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toEUCCN()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toEUCCN()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCCNtoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCCNtoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EucJpZen2Han()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EucJpZen2Han()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32toUTF16(u32 src, vm::ptr<u16> dst);
|
|
|
|
|
|
|
|
|
|
s32 UTF32stoUTF16s(vm::cptr<u32> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32stoUTF16s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
auto tmp = vm::make_var<be_t<u16>[2]>({0, 0});
|
|
|
|
|
const vm::ptr<u16> utf16_tmp = vm::cast(tmp.addr());
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf16_len = UTF32toUTF16(src[src_pos], utf16_tmp);
|
|
|
|
|
if (utf16_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len += utf16_len;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len - utf16_len;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (s32 i = 0; i < utf16_len; i++)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = utf16_tmp[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GBKtoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GBKtoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToEucJpUpper()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToEucJpUpper()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoJISs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoJISs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoGB18030s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoGB18030s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 EUCKRstoUHCs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRstoUHCs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8stoUTF32s(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u32> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8stoUTF32s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
vm::var<u32> utf32_tmp = vm::make_var<u32>(0);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_len = UTF8toUTF32(src + src_pos, utf32_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf8_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = *utf32_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_pos += utf8_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoEUCCNs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoEUCCNs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 EUCJPstoUCS2s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u16> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCJPstoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UHCtoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCtoUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 L10nConvertStr(s32 src_code, vm::cptr<void> src, vm::ptr<u32> src_len, s32 dst_code, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.error("L10nConvertStr(src_code=%d, src=*0x%x, src_len=*0x%x, dst_code=%d, dst=*0x%x, dst_len=*0x%x)", src_code, src, src_len, dst_code, dst, dst_len);
|
2015-12-21 19:17:57 +01:00
|
|
|
return _L10nConvertStr(src_code, src, src_len, dst_code, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GBKstoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GBKstoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toUHC()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toUHC()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32toUTF8(u32 src, vm::ptr<u8> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32toUTF8(src=0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
const u64 utf32 = static_cast<u64>(static_cast<s32>(src));
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((utf32 & 0xffffffff) >= 0x110000) || (0x7ff >= ((utf32 - UTF16_HIGH_SURROGATES) & 0xffffffff)))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (0xffff < (utf32 & 0xffffffff))
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>((utf32 << 0x20) >> 0x32) | 0xf0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u8>(utf32 >> 0xc) & 0x3f) | 0x80;
|
|
|
|
|
dst[2] = (static_cast<u8>(utf32 >> 6) & 0x3f) | 0x80;
|
|
|
|
|
dst[3] = (static_cast<u8>(src) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((utf32 & 0xffffffff) < 0x80)
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>(src);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((utf32 & 0xffffffff) < 0x800)
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u8>((utf32 << 0x20) >> 0x26) | 0xc0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u8>(src) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[0] = static_cast<u8>((utf32 << 0x20) >> 0x2c) | 0xe0;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u8>(utf32 >> 6) & 0x3f) | 0x80;
|
|
|
|
|
dst[2] = (static_cast<u8>(src) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 3;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
u16 sjis2eucjp(u16 c)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("sjis2eucjp(c=0x%x)", c);
|
|
|
|
|
|
|
|
|
|
u64 v0 = static_cast<u64>(static_cast<s64>(static_cast<s16>(c))) >> 8 & 0xff;
|
|
|
|
|
u64 v1 = v0 - 0x81;
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((v1 & 0xffff) >= 0x7c) || (0x3f >= ((v0 - 0xa0) & 0xffff)))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u64 v2 = static_cast<s64>(static_cast<s16>(c)) & 0xff;
|
|
|
|
|
|
|
|
|
|
if (0x3f < v2 && (v2 < 0xfd && (static_cast<s32>(v2) != 0x7f)))
|
|
|
|
|
{
|
|
|
|
|
if (0x9f < v0)
|
|
|
|
|
{
|
|
|
|
|
v1 = v0 - 0xc1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u16 v3 = static_cast<s16>(v2) - 0x7e;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 0x22;
|
|
|
|
|
|
|
|
|
|
if (v2 < 0x9f)
|
|
|
|
|
{
|
|
|
|
|
const s16 v4 = v2 < 0x7f ? 0x1f : 0x20;
|
|
|
|
|
v3 = static_cast<s16>(v2) - v4;
|
|
|
|
|
v0 = (v1 & 0x7fffffff) * 2 + 0x21;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((v0 & 0xffff) < 0x7f)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<u16>((v0 & 0xffff) << 8) | v3 | 0x8080;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toEUCCN()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toEUCCN()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoUHCs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoUHCs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCKRtoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCKRtoUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32toUTF16(u32 src, vm::ptr<u16> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32toUTF16(src=0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
const u64 utf32 = static_cast<s64>(static_cast<s32>(src));
|
2025-02-02 20:01:36 +01:00
|
|
|
if (((utf32 & 0xffffffff) >= 0x110000) || (0x7ff >= ((utf32 - UTF16_HIGH_SURROGATES) & 0xffffffff)))
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (0xffff < (utf32 & 0xffffffff))
|
|
|
|
|
{
|
|
|
|
|
dst[0] = static_cast<u16>(((utf32 - 0x10000) << 0x20) >> 0x2a) | UTF16_HIGH_SURROGATES;
|
2025-02-02 20:01:36 +01:00
|
|
|
dst[1] = (static_cast<u16>(src) & 0x3ff) | UTF16_LOW_SURROGATES;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[0] = static_cast<u16>(src);
|
|
|
|
|
return 1;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCCNstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EUCCNstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 SBCSstoUCS2s(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("SBCSstoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x, code_page=0x%x)", src, src_len, dst, dst_len, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return ConverterUnknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (*src_len == 0u)
|
|
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const u8 src_val = src[src_pos];
|
|
|
|
|
u16 val = static_cast<u16>(src_val);
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src_val) < '\0')
|
|
|
|
|
{
|
|
|
|
|
u16 dst_tmp = 0;
|
|
|
|
|
s32 dst_len_tmp = 2;
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(code_page, &src_val, 1, L10N_UCS2, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = dst_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 UTF8stoJISs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ToSjisKata()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ToSjisKata()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 jis2eucjp()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("jis2eucjp()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 BIG5toUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("BIG5toUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toGBK()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toGBK()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16toUTF32(vm::cptr<u16> src, vm::ptr<u32> dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16toUTF32(src=*0x%x, dst=*0x%x)", src, dst);
|
|
|
|
|
|
|
|
|
|
ensure(src && dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if ((src[0] & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
*dst = static_cast<u32>(src[0]);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (((src[0] & UTF16_SURROGATES_MASK2) == (src[0] & UTF16_SURROGATES_MASK1)) && ((src[1] & UTF16_SURROGATES_MASK2) == UTF16_LOW_SURROGATES))
|
|
|
|
|
{
|
2025-02-02 20:01:36 +01:00
|
|
|
*dst = ((src[0] & 0x3ff) * 0x400 + 0x10000) | (src[1] & 0x3ff);
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 l10n_convert_str(s32 cd, vm::cptr<void> src, vm::cptr<u32> src_len, vm::ptr<void> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.warning("l10n_convert_str(cd=%d, src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", cd, src, src_len, dst, dst_len);
|
2015-09-10 16:13:31 +02:00
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
const s32 src_code = cd >> 16;
|
|
|
|
|
const s32 dst_code = cd & 0xffff;
|
2015-09-10 16:13:31 +02:00
|
|
|
|
2015-12-21 19:17:57 +01:00
|
|
|
return _L10nConvertStr(src_code, src, src_len, dst_code, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 EUCJPstoJISs(vm::cptr<u8> src, vm::cptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.warning("EUCJPstoJISs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return _L10nConvertStr(L10N_EUC_JP, src, src_len, L10N_ISO_2022_JP, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoARIBs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoARIBs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 JISstoEUCJPs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("JISstoEUCJPs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EucJpHan2Zen()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("EucJpHan2Zen()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 isEucJpKigou()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("isEucJpKigou()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2toUTF8(u16 ucs2, vm::ptr<u8> utf8)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2toUTF8(ucs2=0x%x, utf8=*0x%x)", ucs2, utf8);
|
|
|
|
|
|
|
|
|
|
const u64 val = static_cast<s64>(ucs2) & 0xffff;
|
|
|
|
|
|
|
|
|
|
if ((static_cast<u32>(val) & UTF16_SURROGATES_MASK1) != UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
ensure(!!utf8); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (val < 0x80)
|
|
|
|
|
{
|
|
|
|
|
utf8[0] = static_cast<u8>(ucs2);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (val < 0x800)
|
|
|
|
|
{
|
|
|
|
|
utf8[0] = static_cast<u8>((val << 0x20) >> 0x26) | 0xc0;
|
2025-02-02 20:01:36 +01:00
|
|
|
utf8[1] = (static_cast<u8>(ucs2) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utf8[0] = static_cast<u8>((val << 0x20) >> 0x2c) | 0xe0;
|
2025-02-02 20:01:36 +01:00
|
|
|
utf8[1] = (static_cast<u8>(val >> 6) & 0x3f) | 0x80;
|
|
|
|
|
utf8[2] = (static_cast<u8>(ucs2) & 0x3f) | 0x80;
|
2025-02-02 16:16:33 +01:00
|
|
|
return 3;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GB18030toUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GB18030toUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UHCtoUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UHCtoUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 MSJIStoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("MSJIStoUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toGBK()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toGBK()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 kuten2sjis()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("kuten2sjis()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 UTF8toSBCS(vm::cptr<u8> src, vm::ptr<u8> dst, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("UTF8toSBCS(src=*0x%x, dst=*0x%x, code_page=0x%x)", src, dst, code_page);
|
|
|
|
|
|
|
|
|
|
vm::var<u16> ucs2_tmp = vm::make_var<u16>(0);
|
|
|
|
|
|
|
|
|
|
const s32 utf8_len = UTF8toUCS2(src, ucs2_tmp);
|
|
|
|
|
if (utf8_len != 0)
|
|
|
|
|
{
|
|
|
|
|
const s32 len = UCS2toSBCS(*ucs2_tmp, dst, code_page);
|
|
|
|
|
if (1 < len + 1U)
|
|
|
|
|
{
|
|
|
|
|
return utf8_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 SJIStoUCS2()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SJIStoUCS2()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 eucjpzen2han(vm::cptr<u16> src)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("eucjpzen2han()");
|
|
|
|
|
return *src; // Returns the character itself if conversion fails
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoARIBs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoARIBs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 isSjisKigou()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("isSjisKigou()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoEUCJPs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoEUCJPs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2toEUCKR()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2toEUCKR()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 SBCStoUCS2(u8 src, vm::ptr<u16> dst, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("SBCStoUCS2(src=0x%x, dst=*0x%x, code_page=0x%x)", src, dst, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(!!dst); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (static_cast<s8>(src) >= 0)
|
|
|
|
|
{
|
|
|
|
|
*dst = static_cast<s16>(static_cast<s8>(src)) & 0xff;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u16 dst_tmp = 0;
|
|
|
|
|
s32 dst_len_tmp = sizeof(u16);
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(code_page, &src, 1, L10N_UCS2, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst = dst_tmp;
|
|
|
|
|
return 1;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 MSJISstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("MSJISstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-10 16:13:31 +02:00
|
|
|
s32 l10n_get_converter(u32 src_code, u32 dst_code)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.warning("l10n_get_converter(src_code=%d, dst_code=%d)", src_code, dst_code);
|
2015-09-13 09:26:01 +02:00
|
|
|
return (src_code << 16) | dst_code;
|
2025-02-02 22:16:58 +01:00
|
|
|
|
|
|
|
|
if (_L10N_CODE_ <= src_code || _L10N_CODE_ <= dst_code)
|
|
|
|
|
{
|
|
|
|
|
return 0xffffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (src_code << 16) | dst_code;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GB18030stoUTF8s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GB18030stoUTF8s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 SJISstoEUCJPs(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SJISstoEUCJPs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF32stoUCS2s(vm::cptr<u32> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF32stoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const u32 utf32 = src[src_pos];
|
|
|
|
|
|
|
|
|
|
if (utf32 >= 0x10000 || (0x7ff >= utf32 - UTF16_HIGH_SURROGATES))
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = static_cast<u16>(utf32);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 BIG5stoUTF8s(vm::cptr<u8> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("BIG5stoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 EUCCNtoUCS2()
|
|
|
|
|
{
|
2019-09-02 13:41:57 +02:00
|
|
|
cellL10n.todo("EUCCNtoUCS2()");
|
|
|
|
|
return CELL_OK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 UTF8stoSBCSs(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("UTF8stoSBCSs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x, code_page=0x%x)", src, src_len, dst, dst_len, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return ConverterUnknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (*src_len == 0u)
|
|
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
vm::var<u16> ucs2_tmp = vm::make_var<u16>(0);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_len = UTF8toUCS2(src + src_pos, ucs2_tmp);
|
|
|
|
|
if (utf8_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u16 ucs2 = *ucs2_tmp;
|
|
|
|
|
|
|
|
|
|
if ((*src_len < (utf8_len + src_pos)) || (0xfffd < ucs2))
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0x7f < ucs2)
|
|
|
|
|
{
|
|
|
|
|
const u8 src_tmp = src[src_pos];
|
|
|
|
|
u8 dst_tmp = 0;
|
|
|
|
|
s32 dst_len_tmp = 1;
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(L10N_UTF8, &src_tmp, 1, code_page, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ucs2 = dst_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = static_cast<u8>(ucs2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_pos += utf8_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
s32 UCS2stoEUCKRs(vm::cptr<u16> src, vm::cptr<s32> src_len, vm::ptr<u8> dst, vm::ptr<s32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoEUCKRs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoSJISs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoSJISs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8stoHZs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8stoHZs()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 eucjp2kuten()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("eucjp2kuten()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UTF8toBIG5()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UTF8toBIG5()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF16stoUTF8s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF16stoUTF8s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
auto tmp = vm::make_var<be_t<u8>[4]>({0, 0, 0, 0});
|
|
|
|
|
const vm::ptr<u8> utf8_tmp = vm::cast(tmp.addr());
|
|
|
|
|
vm::var<u32> utf8_len_tmp = vm::make_var<u32>(0);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
*utf8_len_tmp = 4;
|
|
|
|
|
const s32 utf16_len = UTF16toUTF8(src + src_pos, utf8_tmp, utf8_len_tmp);
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
if (utf16_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
const u32 utf8_len = *utf8_len_tmp;
|
|
|
|
|
len += utf8_len;
|
2015-08-01 00:48:38 +02:00
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
if (dst)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
if (*dst_len < len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len - utf8_len;
|
2015-08-01 00:48:38 +02:00
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
for (u32 i = 0; i < utf8_len; i++)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
dst[dst_pos++] = utf8_tmp[i];
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-02-02 16:16:33 +01:00
|
|
|
|
|
|
|
|
src_pos += utf16_len;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
*dst_len = len;
|
2015-08-01 00:48:38 +02:00
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 JISstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("JISstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 GB18030toUTF8()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("GB18030toUTF8()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8toSJIS(u8 ch, vm::ptr<u8> dst, vm::ptr<u32> dst_len) // Doesn't work backwards
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.warning("UTF8toSJIS(ch=%d, dst=*0x%x, dst_len=*0x%x)", ch, dst, dst_len);
|
2015-12-21 19:17:57 +01:00
|
|
|
return _L10nConvertChar(L10N_UTF8, &ch, sizeof(ch), L10N_CODEPAGE_932, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 ARIBstoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("ARIBstoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UCS2stoUTF32s(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u32> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UCS2stoUTF32s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const u16 ucs2 = src[src_pos];
|
|
|
|
|
|
|
|
|
|
if ((ucs2 & UTF16_SURROGATES_MASK1) == UTF16_HIGH_SURROGATES)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = static_cast<u32>(ucs2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 22:16:58 +01:00
|
|
|
s32 UCS2stoSBCSs(vm::cptr<u16> src, vm::ptr<u32> src_len, vm::ptr<u8> dst, vm::ptr<u32> dst_len, u32 code_page)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 22:16:58 +01:00
|
|
|
cellL10n.notice("UCS2stoSBCSs(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x, code_page=*0x%x)", src, src_len, dst, dst_len, code_page);
|
|
|
|
|
|
|
|
|
|
HostCode code = 0;
|
|
|
|
|
if ((code_page >= _L10N_CODE_) || !_L10nCodeParse(code_page, code))
|
|
|
|
|
{
|
|
|
|
|
return ConverterUnknown;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
|
|
|
|
if (*src_len == 0u)
|
|
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len; src_pos++)
|
|
|
|
|
{
|
|
|
|
|
const s16 ucs2 = src[src_pos];
|
|
|
|
|
|
|
|
|
|
if (ucs2 >= 0xfffe)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 val = static_cast<u8>(ucs2);
|
|
|
|
|
|
|
|
|
|
if (0x7f < ucs2)
|
|
|
|
|
{
|
|
|
|
|
const u16 src_tmp = src[src_pos];
|
|
|
|
|
u8 dst_tmp = 0;
|
|
|
|
|
s32 dst_len_tmp = 1;
|
|
|
|
|
|
|
|
|
|
const s32 res = _ConvertStr(L10N_UCS2, &src_tmp, sizeof(u16), code_page, &dst_tmp, &dst_len_tmp, false);
|
|
|
|
|
|
|
|
|
|
if (res != ConversionOK)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = dst_tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = src_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoBIG5s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoBIG5s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 UCS2stoUHCs()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("UCS2stoUHCs()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 SJIStoEUCJP()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("SJIStoEUCJP()");
|
|
|
|
|
return 0;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8stoUTF16s(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8stoUTF16s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
auto tmp = vm::make_var<be_t<u16>[2]>({0, 0});
|
|
|
|
|
const vm::ptr<u16> utf16_tmp = vm::cast(tmp.addr());
|
|
|
|
|
vm::var<u32> utf16_len_tmp = vm::make_var<u32>(0);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_len = UTF8toUTF16(src + src_pos, utf16_tmp, utf16_len_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf8_len == 0)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const u32 utf16_len = *utf16_len_tmp;
|
|
|
|
|
len += utf16_len;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (u32 i = 0; i < utf16_len; i++)
|
|
|
|
|
{
|
|
|
|
|
dst[dst_pos++] = utf16_tmp[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_pos += utf8_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 SJISstoUCS2s(vm::cptr<u8> src, vm::cptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2016-01-12 22:57:16 +01:00
|
|
|
cellL10n.warning("SJISstoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
2015-12-21 19:17:57 +01:00
|
|
|
return _L10nConvertStr(L10N_CODEPAGE_932, src, src_len, L10N_UCS2, dst, dst_len);
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 BIG5stoUCS2s()
|
|
|
|
|
{
|
2017-02-08 01:25:10 +01:00
|
|
|
cellL10n.todo("BIG5stoUCS2s()");
|
|
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2025-02-02 16:16:33 +01:00
|
|
|
s32 UTF8stoUCS2s(vm::cptr<u8> src, vm::ptr<u32> src_len, vm::ptr<u16> dst, vm::ptr<u32> dst_len)
|
2015-08-01 00:48:38 +02:00
|
|
|
{
|
2025-02-02 16:16:33 +01:00
|
|
|
cellL10n.notice("UTF8stoUCS2s(src=*0x%x, src_len=*0x%x, dst=*0x%x, dst_len=*0x%x)", src, src_len, dst, dst_len);
|
|
|
|
|
|
|
|
|
|
ensure(src_len && dst_len); // Not really checked
|
|
|
|
|
|
2025-02-02 20:01:36 +01:00
|
|
|
if (*src_len == 0u)
|
2025-02-02 16:16:33 +01:00
|
|
|
{
|
|
|
|
|
*dst_len = 0;
|
|
|
|
|
return ConversionOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure(src); // Not really checked
|
|
|
|
|
|
|
|
|
|
u32 len = 0;
|
|
|
|
|
u32 dst_pos = 0;
|
|
|
|
|
|
|
|
|
|
vm::var<u16> ucs2_tmp = vm::make_var<u16>(5);
|
|
|
|
|
|
|
|
|
|
for (u32 src_pos = 0; src_pos < *src_len;)
|
|
|
|
|
{
|
|
|
|
|
const s32 utf8_len = UTF8toUCS2(src + src_pos, ucs2_tmp);
|
|
|
|
|
|
|
|
|
|
if (utf8_len == 0 || *src_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = len;
|
|
|
|
|
return SRCIllegal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len++;
|
|
|
|
|
|
|
|
|
|
if (dst)
|
|
|
|
|
{
|
|
|
|
|
if (*dst_len < len)
|
|
|
|
|
{
|
|
|
|
|
*src_len -= src_pos;
|
|
|
|
|
*dst_len = dst_pos;
|
|
|
|
|
return DSTExhausted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dst[dst_pos++] = ucs2_tmp[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
src_pos += utf8_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*dst_len = len;
|
2017-02-08 01:25:10 +01:00
|
|
|
return ConversionOK;
|
2015-08-01 00:48:38 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-21 20:43:03 +01:00
|
|
|
DECLARE(ppu_module_manager::cellL10n)("cellL10n", []()
|
2025-04-05 21:50:45 +02:00
|
|
|
{
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toEUCJP);
|
|
|
|
|
REG_FUNC(cellL10n, l10n_convert);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toUTF32);
|
|
|
|
|
REG_FUNC(cellL10n, jis2kuten);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toGB18030);
|
|
|
|
|
REG_FUNC(cellL10n, JISstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, SjisZen2Han);
|
|
|
|
|
REG_FUNC(cellL10n, ToSjisLower);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toGB18030);
|
|
|
|
|
REG_FUNC(cellL10n, HZstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoHZs);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, kuten2eucjp);
|
|
|
|
|
REG_FUNC(cellL10n, sjis2jis);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UHCstoEUCKRs);
|
|
|
|
|
REG_FUNC(cellL10n, jis2sjis);
|
|
|
|
|
REG_FUNC(cellL10n, jstrnchk);
|
|
|
|
|
REG_FUNC(cellL10n, L10nConvert);
|
|
|
|
|
REG_FUNC(cellL10n, EUCCNstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, GBKstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, eucjphan2zen);
|
|
|
|
|
REG_FUNC(cellL10n, ToSjisHira);
|
|
|
|
|
REG_FUNC(cellL10n, GBKtoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, eucjp2jis);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32stoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, sjishan2zen);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toSBCS);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoGBKs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16stoUTF32s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toEUCKR);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16toUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, ARIBstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, SJISstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, sjiszen2han);
|
|
|
|
|
REG_FUNC(cellL10n, ToEucJpLower);
|
|
|
|
|
REG_FUNC(cellL10n, MSJIStoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoMSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPtoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, eucjp2sjis);
|
|
|
|
|
REG_FUNC(cellL10n, ToEucJpHira);
|
|
|
|
|
REG_FUNC(cellL10n, UHCstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, ToEucJpKata);
|
|
|
|
|
REG_FUNC(cellL10n, HZstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toMSJIS);
|
|
|
|
|
REG_FUNC(cellL10n, BIG5toUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPstoSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoBIG5s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16stoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoGB18030s);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPtoSJIS);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPtoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoGBKs);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRtoUHC);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toSJIS);
|
|
|
|
|
REG_FUNC(cellL10n, MSJISstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toBIG5);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoEUCKRs);
|
|
|
|
|
REG_FUNC(cellL10n, UHCstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, GB18030stoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, SJIStoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, JISstoSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toUTF16);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoMSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRtoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, SjisHan2Zen);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toUTF16);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toMSJIS);
|
|
|
|
|
REG_FUNC(cellL10n, sjis2kuten);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toUHC);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32toUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, ToSjisUpper);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toEUCJP);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoEUCJPs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16toUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoUTF16s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoEUCCNs);
|
|
|
|
|
REG_FUNC(cellL10n, SBCSstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, SJISstoJISs);
|
|
|
|
|
REG_FUNC(cellL10n, SBCStoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toUTF32);
|
|
|
|
|
REG_FUNC(cellL10n, jstrchk);
|
|
|
|
|
REG_FUNC(cellL10n, UHCtoEUCKR);
|
|
|
|
|
REG_FUNC(cellL10n, kuten2jis);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toEUCCN);
|
|
|
|
|
REG_FUNC(cellL10n, EUCCNtoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, EucJpZen2Han);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32stoUTF16s);
|
|
|
|
|
REG_FUNC(cellL10n, GBKtoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, ToEucJpUpper);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoJISs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoGB18030s);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRstoUHCs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoUTF32s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoEUCCNs);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UHCtoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, L10nConvertStr);
|
|
|
|
|
REG_FUNC(cellL10n, GBKstoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toUHC);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32toUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, sjis2eucjp);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toEUCCN);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoUHCs);
|
|
|
|
|
REG_FUNC(cellL10n, EUCKRtoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32toUTF16);
|
|
|
|
|
REG_FUNC(cellL10n, EUCCNstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, SBCSstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoJISs);
|
|
|
|
|
REG_FUNC(cellL10n, ToSjisKata);
|
|
|
|
|
REG_FUNC(cellL10n, jis2eucjp);
|
|
|
|
|
REG_FUNC(cellL10n, BIG5toUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toGBK);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16toUTF32);
|
|
|
|
|
REG_FUNC(cellL10n, l10n_convert_str);
|
|
|
|
|
REG_FUNC(cellL10n, EUCJPstoJISs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoARIBs);
|
|
|
|
|
REG_FUNC(cellL10n, JISstoEUCJPs);
|
|
|
|
|
REG_FUNC(cellL10n, EucJpHan2Zen);
|
|
|
|
|
REG_FUNC(cellL10n, isEucJpKigou);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, GB18030toUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UHCtoUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, MSJIStoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toGBK);
|
|
|
|
|
REG_FUNC(cellL10n, kuten2sjis);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toSBCS);
|
|
|
|
|
REG_FUNC(cellL10n, SJIStoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, eucjpzen2han);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoARIBs);
|
|
|
|
|
REG_FUNC(cellL10n, isSjisKigou);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoEUCJPs);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2toEUCKR);
|
|
|
|
|
REG_FUNC(cellL10n, SBCStoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, MSJISstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, l10n_get_converter);
|
|
|
|
|
REG_FUNC(cellL10n, GB18030stoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, SJISstoEUCJPs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF32stoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, BIG5stoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, EUCCNtoUCS2);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoSBCSs);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoEUCKRs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoSJISs);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoHZs);
|
|
|
|
|
REG_FUNC(cellL10n, eucjp2kuten);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toBIG5);
|
|
|
|
|
REG_FUNC(cellL10n, UTF16stoUTF8s);
|
|
|
|
|
REG_FUNC(cellL10n, JISstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, GB18030toUTF8);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8toSJIS);
|
|
|
|
|
REG_FUNC(cellL10n, ARIBstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoUTF32s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoSBCSs);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoBIG5s);
|
|
|
|
|
REG_FUNC(cellL10n, UCS2stoUHCs);
|
|
|
|
|
REG_FUNC(cellL10n, SJIStoEUCJP);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoUTF16s);
|
|
|
|
|
REG_FUNC(cellL10n, SJISstoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, BIG5stoUCS2s);
|
|
|
|
|
REG_FUNC(cellL10n, UTF8stoUCS2s);
|
|
|
|
|
});
|