From 350daeee41bccb4d07436eee9130e2ae2342f3df Mon Sep 17 00:00:00 2001 From: Rookie <175737347+rooklz@users.noreply.github.com> Date: Fri, 23 Oct 2026 23:13:07 +0100 Subject: [PATCH] feat(libSceCesCs): add the ISO 646 national variants and JIS X 0201 profiles --- core/libs/prx/libSceCesCs/CMakeLists.txt | 6 +- core/libs/prx/libSceCesCs/Export.cpp | 129 +++++++++- core/libs/prx/libSceCesCs/PendingExports.cpp | 60 ----- core/libs/prx/libSceCesCs/SingleByte.hpp | 231 ++++++++++++++++++ core/libs/prx/libSceCesCs/include/Api.hpp | 24 +- core/libs/tests/GuestCesIso646.cpp | 240 +++++++++++++++++++ docs/dev/debt/libSceCesCs.md | 3 +- 7 files changed, 609 insertions(+), 84 deletions(-) create mode 100644 core/libs/tests/GuestCesIso646.cpp diff --git a/core/libs/prx/libSceCesCs/CMakeLists.txt b/core/libs/prx/libSceCesCs/CMakeLists.txt index b87f620d08..36a84feff4 100644 --- a/core/libs/prx/libSceCesCs/CMakeLists.txt +++ b/core/libs/prx/libSceCesCs/CMakeLists.txt @@ -25,9 +25,11 @@ if(BUILD_TESTING) endif() if(BUILD_TESTING) - foreach(variant IN ITEMS unicode unicode_module japanese japanese_module wide wide_module chinese chinese_module mbc mbc_module jis2004 jis2004_module) + foreach(variant IN ITEMS unicode unicode_module japanese japanese_module wide wide_module chinese chinese_module mbc mbc_module jis2004 jis2004_module iso646 iso646_module) if(variant MATCHES "^jis2004") add_test_executable(guest_ces_${variant}_tests ${LIBS_INCLUDE_DIR}/tests/GuestCesJis2004.cpp) + elseif(variant MATCHES "^iso646") + add_test_executable(guest_ces_${variant}_tests ${LIBS_INCLUDE_DIR}/tests/GuestCesIso646.cpp) elseif(variant MATCHES "^mbc") add_test_executable(guest_ces_${variant}_tests ${LIBS_INCLUDE_DIR}/tests/GuestCesMbc.cpp) elseif(variant MATCHES "^chinese") @@ -49,7 +51,7 @@ if(BUILD_TESTING) add_test(NAME guest_ces_${variant} COMMAND guest_ces_${variant}_tests) endforeach() if(WIN32) - set_tests_properties(guest_ces_unicode guest_ces_unicode_module guest_ces_japanese guest_ces_japanese_module guest_ces_wide guest_ces_wide_module guest_ces_chinese guest_ces_chinese_module guest_ces_mbc guest_ces_mbc_module guest_ces_jis2004 guest_ces_jis2004_module PROPERTIES ENVIRONMENT_MODIFICATION + set_tests_properties(guest_ces_unicode guest_ces_unicode_module guest_ces_japanese guest_ces_japanese_module guest_ces_wide guest_ces_wide_module guest_ces_chinese guest_ces_chinese_module guest_ces_mbc guest_ces_mbc_module guest_ces_jis2004 guest_ces_jis2004_module guest_ces_iso646 guest_ces_iso646_module PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() endif() diff --git a/core/libs/prx/libSceCesCs/Export.cpp b/core/libs/prx/libSceCesCs/Export.cpp index d36d477c1f..c8b608f204 100644 --- a/core/libs/prx/libSceCesCs/Export.cpp +++ b/core/libs/prx/libSceCesCs/Export.cpp @@ -75,29 +75,92 @@ const uint8_t* singleByteProfile(SingleByte::Table table) { return PROFILES[3 + table]; } +bool singleByteTable(const void* profile, SingleByte::Table& table) { + for (std::size_t index = 0; index < SingleByte::Count; ++index) { + if (profile != singleByteProfile(static_cast(index))) continue; + table = static_cast(index); + return true; + } + return false; +} + const uint16_t* sbcHighTable(const void* profile) { if (profile == CP1251_PROFILE) return CP1251_HIGH; if (profile == CP1250_PROFILE) return CP1250_HIGH; - for (std::size_t table = 0; table < SingleByte::Count; ++table) { - if (profile == singleByteProfile(static_cast(table))) return SingleByte::HIGH[table]; - } - return nullptr; + SingleByte::Table table; + return singleByteTable(profile, table) ? SingleByte::HIGH[table] : nullptr; +} + +bool lowGraphicsUnassigned(const void* profile, uint8_t sbc) { + SingleByte::Table table; + return sbc >= 0x21 && sbc <= 0x7E && singleByteTable(profile, table) && SingleByte::LOW_GRAPHICS_UNASSIGNED[table]; +} + +const SingleByte::LowCode* lowCodes(const void* profile) { + SingleByte::Table table; + return singleByteTable(profile, table) ? SingleByte::LOW[table] : nullptr; +} + +bool isSingleByte(const void* profile, SingleByte::Table expected) { + SingleByte::Table table; + return singleByteTable(profile, table) && table == expected; +} + +bool isSevenBit(const void* profile) { + SingleByte::Table table; + return singleByteTable(profile, table) && SingleByte::SEVEN_BIT[table]; } bool sbcToUnicode(const uint8_t* profile, uint8_t sbc, uint32_t& code) { code = sbc; - if (sbc < 0x80) return true; + if (isSingleByte(profile, SingleByte::JisX0201Katakana) && sbc >= 0x21 && sbc <= 0x7E) { + code = 0xFF61 + (sbc - 0x21); + return sbc <= 0x5F; + } + if (sbc < 0x80) { + if (lowGraphicsUnassigned(profile, sbc)) return false; + if (const SingleByte::LowCode* low = lowCodes(profile)) { + for (std::size_t i = 0; i < std::size(SingleByte::LOW[0]) && low[i].byte != 0; ++i) { + if (low[i].byte == sbc) code = low[i].code; + } + } + return true; + } if (const uint16_t* high = sbcHighTable(profile)) code = high[sbc - 0x80]; else if (sbc < 0xA0) code = CP1252_HIGH[sbc - 0x80]; - return code != 0; + return code != 0 && code != SingleByte::Unassigned; +} + +int sbcError(const uint8_t* profile, uint8_t sbc, uint32_t& code) { + if (sbc >= 0x80 && isSevenBit(profile)) return CES_ERROR_INVALID_ENCODE; + return sbcToUnicode(profile, sbc, code) ? 0 : CES_ERROR_UNASSIGNED_CODE; } bool unicodeToSbc(const uint8_t* profile, uint32_t code, uint8_t& sbc) { + if (isSingleByte(profile, SingleByte::JisX0201Katakana)) { + if (code >= 0xFF61 && code <= 0xFF9F) { + sbc = static_cast(0x21 + (code - 0xFF61)); + return true; + } + if (code >= 0x21 && code <= 0x7E) return false; + } + if (const SingleByte::LowCode* low = lowCodes(profile)) { + for (std::size_t i = 0; i < std::size(SingleByte::LOW[0]) && low[i].byte != 0; ++i) { + if (low[i].code == code) { + sbc = low[i].byte; + return true; + } + if (low[i].byte == code) return false; + } + } + if (code >= 0x80 && isSevenBit(profile)) return false; if (const uint16_t* high = sbcHighTable(profile)) { if (code < 0x80) { + if (lowGraphicsUnassigned(profile, static_cast(code))) return false; sbc = static_cast(code); return true; } + if (code == SingleByte::Unassigned) return false; for (uint32_t i = 0; i < 128; ++i) { if (high[i] == code) { sbc = static_cast(0x80 + i); @@ -838,7 +901,7 @@ int decodeMbcs(const void* profile, const uint8_t* mbcs, uint32_t mbcsMax, uint3 const uint8_t lead = mbcs[0]; if (isSbc(profile)) { length = 1; - return sbcToUnicode(static_cast(profile), lead, code) ? 0 : CES_ERROR_UNASSIGNED_CODE; + return sbcError(static_cast(profile), lead, code); } if (isSjis(profile)) { const bool strict = isSjisX0208(profile); @@ -1266,7 +1329,7 @@ int unitTarget(const void*, uint32_t code, Unit* target, uint32_t& length) { int sbcToUnit(const uint8_t* profile, uint8_t sbc, const void* target, uint32_t& code) { if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; if (!target) return CES_ERROR_INVALID_DST_BUFFER; - return sbcToUnicode(profile, sbc, code) ? 0 : CES_ERROR_UNASSIGNED_CODE; + return sbcError(profile, sbc, code); } template @@ -1443,6 +1506,54 @@ const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1258(void) { return singleByteProfile(SingleByte::Cp1258); } +const uint8_t* APS5_VABI sceCesRefersUcsProfileAscii(void) { + return singleByteProfile(SingleByte::Ascii); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void) { + return singleByteProfile(SingleByte::AsciiWithKatakana); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileBs4730(void) { + return singleByteProfile(SingleByte::Bs4730); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988(void) { + return singleByteProfile(SingleByte::GbT1988); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void) { + return singleByteProfile(SingleByte::GbT1988Tilde0x7e); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201(void) { + return singleByteProfile(SingleByte::JisX0201); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void) { + return singleByteProfile(SingleByte::JisX0201Katakana); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void) { + return singleByteProfile(SingleByte::JisX0201Roman); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void) { + return singleByteProfile(SingleByte::JisX0201RomanTilde0x7e); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void) { + return singleByteProfile(SingleByte::JisX0201Tilde0x7e); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003(void) { + return singleByteProfile(SingleByte::KsX1003); +} + +const uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void) { + return singleByteProfile(SingleByte::KsX1003Tilde0x7e); +} + void* APS5_VABI sceCesUcsProfileInitSJis1997Cp932(void* sheet) { if (!sheet) return nullptr; std::memcpy(sheet, SJIS_TAG, sizeof(SJIS_TAG)); @@ -1563,7 +1674,7 @@ int APS5_VABI sceCesSbcToUtf8(const uint8_t* profile, uint8_t sbc, uint8_t* utf8 if (!profile) return CES_ERROR_INVALID_PROFILE; if (!isSbc(profile)) return CES_ERROR_INVALID_PARAMETER; uint32_t code = 0; - if (!sbcToUnicode(profile, sbc, code)) return CES_ERROR_UNASSIGNED_CODE; + if (const int result = sbcError(profile, sbc, code); result != 0) return result; uint8_t encoded[4]; const uint32_t length = encodeUtf8(code, encoded); if (utf8_len) *utf8_len = length; diff --git a/core/libs/prx/libSceCesCs/PendingExports.cpp b/core/libs/prx/libSceCesCs/PendingExports.cpp index 9b52506fec..9089f429b9 100644 --- a/core/libs/prx/libSceCesCs/PendingExports.cpp +++ b/core/libs/prx/libSceCesCs/PendingExports.cpp @@ -108,21 +108,6 @@ int APS5_VABI sceCesMbcsUcsSetMbcsReplacementCharUCode(void) { return 0; } -int APS5_VABI sceCesRefersUcsProfileAscii(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileBs4730(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesRefersUcsProfileCp1253(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -158,16 +143,6 @@ int APS5_VABI sceCesRefersUcsProfileCp874(void) { return 0; } -int APS5_VABI sceCesRefersUcsProfileGbT1988(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesRefersUcsProfileIso8859_11(void) { NotImplemented_nid_no_patch(__func__); return 0; @@ -193,41 +168,6 @@ int APS5_VABI sceCesRefersUcsProfileIso8859_8(void) { return 0; } -int APS5_VABI sceCesRefersUcsProfileJisX0201(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileKsX1003(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - -int APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void) { - NotImplemented_nid_no_patch(__func__); - return 0; -} - int APS5_VABI sceCesSJisUcsProfileSetSbcs(void) { NotImplemented_nid_no_patch(__func__); return 0; diff --git a/core/libs/prx/libSceCesCs/SingleByte.hpp b/core/libs/prx/libSceCesCs/SingleByte.hpp index 6f24ada575..be73a4adaa 100644 --- a/core/libs/prx/libSceCesCs/SingleByte.hpp +++ b/core/libs/prx/libSceCesCs/SingleByte.hpp @@ -34,9 +34,23 @@ enum Table : std::size_t { Cp1256, Cp1258, Cp858, + Ascii, + AsciiWithKatakana, + Bs4730, + GbT1988, + GbT1988Tilde0x7e, + JisX0201, + JisX0201Katakana, + JisX0201Roman, + JisX0201RomanTilde0x7e, + JisX0201Tilde0x7e, + KsX1003, + KsX1003Tilde0x7e, Count, }; +inline constexpr uint16_t Unassigned = 0xFFFF; + inline constexpr uint16_t HIGH[Count][128] = { { 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, 0x008F, @@ -318,6 +332,223 @@ inline constexpr uint16_t HIGH[Count][128] = { 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0, }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, + 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, + 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, + 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, + { + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + }, +}; + +struct LowCode { + uint8_t byte; + uint16_t code; +}; + +inline constexpr LowCode LOW[Count][2] = { + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {{0x23, 0x00A3}}, + {{0x24, 0x00A5}, {0x7E, 0x203E}}, + {{0x24, 0x00A5}}, + {{0x5C, 0x00A5}, {0x7E, 0x203E}}, + {}, + {{0x5C, 0x00A5}, {0x7E, 0x203E}}, + {{0x5C, 0x00A5}}, + {{0x5C, 0x00A5}}, + {{0x5C, 0x20A9}, {0x7E, 0x203E}}, + {{0x5C, 0x20A9}}, +}; + +inline constexpr bool SEVEN_BIT[Count] = { + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, true, + true, false, true, true, true, false, true, true, +}; + +inline constexpr bool LOW_GRAPHICS_UNASSIGNED[Count] = { + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + false, + false, + false, + false, + false, }; } diff --git a/core/libs/prx/libSceCesCs/include/Api.hpp b/core/libs/prx/libSceCesCs/include/Api.hpp index 25baf6ac58..868da5a976 100644 --- a/core/libs/prx/libSceCesCs/include/Api.hpp +++ b/core/libs/prx/libSceCesCs/include/Api.hpp @@ -229,9 +229,9 @@ int APS5_VABI sceCesJisGetLevel(void); int APS5_VABI sceCesJiscsToUcs(void); int APS5_VABI sceCesMbcsUcsSetMbcsReplacementCharCode(void); int APS5_VABI sceCesMbcsUcsSetMbcsReplacementCharUCode(void); -int APS5_VABI sceCesRefersUcsProfileAscii(void); -int APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void); -int APS5_VABI sceCesRefersUcsProfileBs4730(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileAscii(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileBs4730(void); int APS5_VABI sceCesRefersUcsProfileCp1253(void); int APS5_VABI sceCesRefersUcsProfileCp1255(void); int APS5_VABI sceCesRefersUcsProfileCp1257(void); @@ -239,20 +239,20 @@ int APS5_VABI sceCesRefersUcsProfileCp857(void); int APS5_VABI sceCesRefersUcsProfileCp864(void); int APS5_VABI sceCesRefersUcsProfileCp869(void); int APS5_VABI sceCesRefersUcsProfileCp874(void); -int APS5_VABI sceCesRefersUcsProfileGbT1988(void); -int APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void); int APS5_VABI sceCesRefersUcsProfileIso8859_11(void); int APS5_VABI sceCesRefersUcsProfileIso8859_3(void); int APS5_VABI sceCesRefersUcsProfileIso8859_6(void); int APS5_VABI sceCesRefersUcsProfileIso8859_7(void); int APS5_VABI sceCesRefersUcsProfileIso8859_8(void); -int APS5_VABI sceCesRefersUcsProfileJisX0201(void); -int APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void); -int APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void); -int APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void); -int APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void); -int APS5_VABI sceCesRefersUcsProfileKsX1003(void); -int APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003(void); +const uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void); int APS5_VABI sceCesSJisUcsProfileSetSbcs(void); int APS5_VABI sceCesUcs2StrGetIso2022Len(void); int APS5_VABI sceCesUcs2StrToIso2022Str(void); diff --git a/core/libs/tests/GuestCesIso646.cpp b/core/libs/tests/GuestCesIso646.cpp new file mode 100644 index 0000000000..14c12edf2f --- /dev/null +++ b/core/libs/tests/GuestCesIso646.cpp @@ -0,0 +1,240 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include +#include + +extern "C" { +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileAscii(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileAsciiWithKatakana(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileBs4730(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileGbT1988Tilde0x7e(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Katakana(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Roman(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201RomanTilde0x7e(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileJisX0201Tilde0x7e(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileKsX1003Tilde0x7e(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileIso8859_1(void); +const std::uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void); +int APS5_VABI sceCesSbcToUtf8(const std::uint8_t*, std::uint8_t, std::uint8_t*, std::uint32_t, std::uint32_t*); +int APS5_VABI sceCesUtf8ToSbc(const std::uint8_t*, std::uint32_t, std::uint32_t*, const std::uint8_t*, std::uint8_t*); +int APS5_VABI sceCesSbcToUcs2(const std::uint8_t*, std::uint8_t, std::uint16_t*); +int APS5_VABI sceCesUcs2ToSbc(std::uint16_t, const std::uint8_t*, std::uint8_t*); +int APS5_VABI sceCesSbcToUtf32(const std::uint8_t*, std::uint8_t, std::uint32_t*); +int APS5_VABI sceCesUtf32ToSbc(std::uint32_t, const std::uint8_t*, std::uint8_t*); +int APS5_VABI sceCesMbcsUcsContextInit(void*, const void*); +int APS5_VABI sceCesMbcsStrToUtf8Str(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); +int APS5_VABI sceCesUtf8StrToMbcsStr(void*, const std::uint8_t*, std::uint32_t, std::uint32_t*, std::uint8_t*, std::uint32_t, std::uint32_t*); +} + +namespace { + +constexpr int invalidEncode = static_cast(0x805C0014); +constexpr int unassignedCode = static_cast(0x805C0020); + +void Require(bool value) { if (!value) std::abort(); } + +void RequireByte(const std::uint8_t* profile, std::uint8_t sbc, std::uint32_t code) { + std::uint8_t utf8[4]; + std::uint32_t length = 0; + Require(sceCesSbcToUtf8(profile, sbc, utf8, sizeof(utf8), &length) == 0); + std::uint32_t decoded = 0; + if (length == 1) decoded = utf8[0]; + else if (length == 2) decoded = (utf8[0] & 0x1Fu) << 6 | (utf8[1] & 0x3Fu); + else if (length == 3) decoded = (utf8[0] & 0x0Fu) << 12 | (utf8[1] & 0x3Fu) << 6 | (utf8[2] & 0x3Fu); + else Require(false); + Require(decoded == code); + std::uint16_t ucs2 = 0; + Require(sceCesSbcToUcs2(profile, sbc, &ucs2) == 0 && ucs2 == code); + std::uint32_t utf32 = 0; + Require(sceCesSbcToUtf32(profile, sbc, &utf32) == 0 && utf32 == code); + std::uint8_t back = 0; + Require(sceCesUtf8ToSbc(utf8, length, &length, profile, &back) == 0 && back == sbc); + Require(sceCesUcs2ToSbc(static_cast(code), profile, &back) == 0 && back == sbc); + Require(sceCesUtf32ToSbc(code, profile, &back) == 0 && back == sbc); +} + +void RequireByteUnassigned(const std::uint8_t* profile, std::uint8_t sbc) { + std::uint8_t utf8[4]; + std::uint32_t length = 0; + Require(sceCesSbcToUtf8(profile, sbc, utf8, sizeof(utf8), &length) == unassignedCode); + std::uint16_t ucs2 = 0; + Require(sceCesSbcToUcs2(profile, sbc, &ucs2) == unassignedCode); + std::uint32_t utf32 = 0; + Require(sceCesSbcToUtf32(profile, sbc, &utf32) == unassignedCode); +} + +void RequireByteInvalid(const std::uint8_t* profile, std::uint8_t sbc) { + std::uint8_t utf8[4]; + std::uint32_t length = 0; + Require(sceCesSbcToUtf8(profile, sbc, utf8, sizeof(utf8), &length) == invalidEncode); + std::uint16_t ucs2 = 0; + Require(sceCesSbcToUcs2(profile, sbc, &ucs2) == invalidEncode); + std::uint32_t utf32 = 0; + Require(sceCesSbcToUtf32(profile, sbc, &utf32) == invalidEncode); +} + +void RequireCodeUnassigned(const std::uint8_t* profile, std::uint32_t code) { + std::uint8_t back = 0; + Require(sceCesUtf32ToSbc(code, profile, &back) == unassignedCode); + if (code < 0x10000) Require(sceCesUcs2ToSbc(static_cast(code), profile, &back) == unassignedCode); +} + +void CheckAsciiHalf(const std::uint8_t* profile) { + for (std::uint32_t sbc = 0; sbc < 0x80; ++sbc) RequireByte(profile, static_cast(sbc), sbc); +} + +void CheckUpperHalfInvalid(const std::uint8_t* profile) { + for (std::uint32_t sbc = 0x80; sbc < 0x100; ++sbc) RequireByteInvalid(profile, static_cast(sbc)); + for (const std::uint32_t code : {0x00A0u, 0x00E9u, 0x00FFu, 0xFF61u, 0x30A2u}) RequireCodeUnassigned(profile, code); +} + +void CheckKatakanaHalf(const std::uint8_t* profile) { + for (std::uint32_t sbc = 0x80; sbc <= 0xA0; ++sbc) RequireByteUnassigned(profile, static_cast(sbc)); + for (std::uint32_t sbc = 0xA1; sbc <= 0xDF; ++sbc) RequireByte(profile, static_cast(sbc), 0xFF61 + (sbc - 0xA1)); + for (std::uint32_t sbc = 0xE0; sbc < 0x100; ++sbc) RequireByteUnassigned(profile, static_cast(sbc)); + for (const std::uint32_t code : {0x00A0u, 0x00E9u, 0x30A2u, 0xFF60u, 0xFFA0u}) RequireCodeUnassigned(profile, code); +} + +void CheckSevenBitVariant(const std::uint8_t* profile, std::uint8_t changedByte, std::uint32_t changedCode, bool overline) { + for (std::uint32_t sbc = 0; sbc < 0x80; ++sbc) { + if (sbc == changedByte) continue; + if (sbc == 0x7E) continue; + RequireByte(profile, static_cast(sbc), sbc); + } + RequireByte(profile, changedByte, changedCode); + RequireCodeUnassigned(profile, changedByte); + RequireByte(profile, 0x7E, overline ? 0x203E : 0x007E); + RequireCodeUnassigned(profile, overline ? 0x007E : 0x203E); +} + +void CheckKatakanaOnly(const std::uint8_t* profile) { + for (std::uint32_t sbc = 0; sbc < 0x21; ++sbc) RequireByte(profile, static_cast(sbc), sbc); + RequireByte(profile, 0x7F, 0x7F); + for (std::uint32_t sbc = 0x21; sbc <= 0x5F; ++sbc) { + RequireByte(profile, static_cast(sbc), 0xFF61 + (sbc - 0x21)); + RequireCodeUnassigned(profile, sbc); + } + for (std::uint32_t sbc = 0x60; sbc < 0x7F; ++sbc) { + RequireByteUnassigned(profile, static_cast(sbc)); + RequireCodeUnassigned(profile, sbc); + } + for (std::uint32_t sbc = 0x80; sbc < 0x100; ++sbc) RequireByteInvalid(profile, static_cast(sbc)); +} + +struct ConsoleSweep { + const std::uint8_t* profile; + std::uint32_t hash; +}; + +void Fnv(std::uint32_t& hash, std::uint32_t value) { + for (int i = 0; i < 4; ++i) hash = (hash ^ ((value >> (8 * i)) & 0xFF)) * 0x01000193u; +} + +void CheckConsoleSweeps() { + const ConsoleSweep sweeps[] = { + {sceCesRefersUcsProfileAscii(), 0xA4AF75C5u}, + {sceCesRefersUcsProfileAsciiWithKatakana(), 0xC583F150u}, + {sceCesRefersUcsProfileBs4730(), 0x64BDCEC5u}, + {sceCesRefersUcsProfileGbT1988(), 0x053CAAE4u}, + {sceCesRefersUcsProfileGbT1988Tilde0x7e(), 0x8263EFD4u}, + {sceCesRefersUcsProfileJisX0201(), 0x278F62F9u}, + {sceCesRefersUcsProfileJisX0201Katakana(), 0xC38B3C90u}, + {sceCesRefersUcsProfileJisX0201Roman(), 0xF41F4A5Cu}, + {sceCesRefersUcsProfileJisX0201RomanTilde0x7e(), 0x9E7AC56Cu}, + {sceCesRefersUcsProfileJisX0201Tilde0x7e(), 0xFBAEB089u}, + {sceCesRefersUcsProfileKsX1003(), 0xF7F42B10u}, + {sceCesRefersUcsProfileKsX1003Tilde0x7e(), 0xBD6CF7C0u}, + }; + for (const ConsoleSweep& sweep : sweeps) { + std::uint32_t hash = 0x811C9DC5u; + for (std::uint32_t sbc = 0; sbc < 0x100; ++sbc) { + std::uint32_t code = 0; + const int result = sceCesSbcToUtf32(sweep.profile, static_cast(sbc), &code); + Fnv(hash, static_cast(result)); + Fnv(hash, result == 0 ? code : 0); + } + for (std::uint32_t code = 0; code < 0x10000; ++code) { + if (code >= 0xD800 && code <= 0xDFFF) continue; + std::uint8_t sbc = 0; + const int result = sceCesUtf32ToSbc(code, sweep.profile, &sbc); + Fnv(hash, static_cast(result)); + Fnv(hash, result == 0 ? sbc : 0); + } + Require(hash == sweep.hash); + } +} + +void CheckDistinct() { + const std::uint8_t* profiles[] = { + sceCesRefersUcsProfileAscii(), sceCesRefersUcsProfileAsciiWithKatakana(), sceCesRefersUcsProfileBs4730(), + sceCesRefersUcsProfileGbT1988(), sceCesRefersUcsProfileGbT1988Tilde0x7e(), sceCesRefersUcsProfileJisX0201(), + sceCesRefersUcsProfileJisX0201Katakana(), sceCesRefersUcsProfileJisX0201Roman(), sceCesRefersUcsProfileJisX0201RomanTilde0x7e(), + sceCesRefersUcsProfileJisX0201Tilde0x7e(), sceCesRefersUcsProfileKsX1003(), sceCesRefersUcsProfileKsX1003Tilde0x7e(), + sceCesRefersUcsProfileIso8859_1(), sceCesRefersUcsProfileCp1252(), + }; + for (std::size_t i = 0; i < std::size(profiles); ++i) { + Require(profiles[i] != nullptr); + for (std::size_t j = 0; j < i; ++j) Require(profiles[i] != profiles[j]); + } + Require(sceCesRefersUcsProfileJisX0201() == sceCesRefersUcsProfileJisX0201()); +} + +void CheckStrings() { + alignas(8) std::uint8_t context[64] = {}; + Require(sceCesMbcsUcsContextInit(context, sceCesRefersUcsProfileJisX0201()) == 0); + const std::uint8_t jis[] = {0x5C, 0xB6, 0x41, 0x7E}; + std::uint8_t utf8[16] = {}; + std::uint32_t used = 0; + std::uint32_t produced = 0; + Require(sceCesMbcsStrToUtf8Str(context, jis, sizeof(jis), &used, utf8, sizeof(utf8), &produced) == 0); + Require(used == sizeof(jis) && produced == 9 && std::memcmp(utf8, "\xC2\xA5\xEF\xBD\xB6\x41\xE2\x80\xBE", 9) == 0); + std::uint8_t back[8] = {}; + Require(sceCesUtf8StrToMbcsStr(context, utf8, produced, &used, back, sizeof(back), &produced) == 0); + Require(used == 9 && produced == sizeof(jis) && std::memcmp(back, jis, sizeof(jis)) == 0); + const std::uint8_t hole[] = {0x41, 0xE0}; + Require(sceCesMbcsStrToUtf8Str(context, hole, sizeof(hole), &used, utf8, sizeof(utf8), &produced) == unassignedCode); + Require(sceCesUtf8StrToMbcsStr(context, reinterpret_cast("\x5C"), 1, &used, back, sizeof(back), &produced) == unassignedCode); + Require(sceCesMbcsUcsContextInit(context, sceCesRefersUcsProfileAscii()) == 0); + Require(sceCesUtf8StrToMbcsStr(context, reinterpret_cast("\x5C"), 1, &used, back, sizeof(back), &produced) == 0); + Require(used == 1 && produced == 1 && back[0] == 0x5C); +} + +} + +int main() { + CheckDistinct(); + CheckAsciiHalf(sceCesRefersUcsProfileAscii()); + CheckUpperHalfInvalid(sceCesRefersUcsProfileAscii()); + for (const std::uint32_t code : {0x00A5u, 0x203Eu, 0x20A9u, 0x00A3u}) RequireCodeUnassigned(sceCesRefersUcsProfileAscii(), code); + CheckAsciiHalf(sceCesRefersUcsProfileAsciiWithKatakana()); + CheckKatakanaHalf(sceCesRefersUcsProfileAsciiWithKatakana()); + CheckSevenBitVariant(sceCesRefersUcsProfileBs4730(), 0x23, 0x00A3, false); + CheckUpperHalfInvalid(sceCesRefersUcsProfileBs4730()); + CheckSevenBitVariant(sceCesRefersUcsProfileGbT1988(), 0x24, 0x00A5, true); + CheckUpperHalfInvalid(sceCesRefersUcsProfileGbT1988()); + CheckSevenBitVariant(sceCesRefersUcsProfileGbT1988Tilde0x7e(), 0x24, 0x00A5, false); + CheckUpperHalfInvalid(sceCesRefersUcsProfileGbT1988Tilde0x7e()); + CheckSevenBitVariant(sceCesRefersUcsProfileJisX0201(), 0x5C, 0x00A5, true); + CheckKatakanaHalf(sceCesRefersUcsProfileJisX0201()); + CheckKatakanaOnly(sceCesRefersUcsProfileJisX0201Katakana()); + CheckSevenBitVariant(sceCesRefersUcsProfileJisX0201Roman(), 0x5C, 0x00A5, true); + CheckUpperHalfInvalid(sceCesRefersUcsProfileJisX0201Roman()); + CheckSevenBitVariant(sceCesRefersUcsProfileJisX0201RomanTilde0x7e(), 0x5C, 0x00A5, false); + CheckUpperHalfInvalid(sceCesRefersUcsProfileJisX0201RomanTilde0x7e()); + CheckSevenBitVariant(sceCesRefersUcsProfileJisX0201Tilde0x7e(), 0x5C, 0x00A5, false); + CheckKatakanaHalf(sceCesRefersUcsProfileJisX0201Tilde0x7e()); + CheckSevenBitVariant(sceCesRefersUcsProfileKsX1003(), 0x5C, 0x20A9, true); + CheckUpperHalfInvalid(sceCesRefersUcsProfileKsX1003()); + CheckSevenBitVariant(sceCesRefersUcsProfileKsX1003Tilde0x7e(), 0x5C, 0x20A9, false); + CheckUpperHalfInvalid(sceCesRefersUcsProfileKsX1003Tilde0x7e()); + CheckStrings(); + CheckConsoleSweeps(); + RequireByte(sceCesRefersUcsProfileIso8859_1(), 0xE9, 0x00E9); + return 0; +} diff --git a/docs/dev/debt/libSceCesCs.md b/docs/dev/debt/libSceCesCs.md index a28ecaf3cc..23a1c6fd72 100644 --- a/docs/dev/debt/libSceCesCs.md +++ b/docs/dev/debt/libSceCesCs.md @@ -23,5 +23,6 @@ - [EUC-JIS-2004 and Shift_JIS-2004 profiles](../../../core/libs/prx/libSceCesCs/JisX0213.hpp) (libSceCesCs) - the errors follow the other JIS profiles, unmeasured; the tables were measured on a PS5 (`sceCesMbcToUtf32` over every one-, two- and `0x8F`-led three-byte sequence, `sceCesUtf32ToMbc` over U+0000-U+110001). Both planes follow Project X0213's JIS X 0213:2004 table with the 90 cells it notes as having a fullwidth form mapped to that form, and also cells 1-17, 1-79 and 2-15 to 2-18 (U+FFE3, U+FFE5, U+FF07, U+FF02, U+FF0D, U+FF5E); U+203E and U+00A5 still encode into 1-17 and 1-79. EUC-JIS-2004's SS3 reads JIS X 0212 in the rows plane 2 leaves empty, both ways, with plane 2 preferred for a code point in both. The 25 cells the standard maps to two code points are unassigned both ways on the console (`A4F7` gives `0x805C0020`; U+304B U+309A encodes U+304B, then fails). Bytes below `0x80` are ASCII. The `sceCesEucJp*` and `sceCesSJis*` scalar helpers keep refusing these two profiles. - [Single-byte profiles](../../../core/libs/prx/libSceCesCs/SingleByte.hpp) (libSceCesCs) - the console's tables for these 27 profiles are not verified. Each returns a profile accepted by `sceCesSbcToUtf8`, `sceCesUtf8ToSbc` and the MBCS context conversions, with bytes 0x00-0x7F unchanged and the high half of a public table: ISO 8859-1, -2, -4, -5, -9, -10, -13, -14, -15 and -16 from [unicode.org](https://unicode.org/Public/MAPPINGS/ISO8859/), code pages 437, 737, 775, 850, 852, 855, 860-863, 865 and 866 from [Microsoft's PC tables](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/), KOI8-R and KOI8-U from [unicode.org](https://unicode.org/Public/MAPPINGS/VENDORS/MISC/), and 1254, 1256 and 1258 from Microsoft's [best-fit tables](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/), whose unassigned bytes map to C1 controls as in Cp1250. Profiles whose public table leaves bytes undefined or maps them to private use still throw - [sceCesRefersUcsProfileCp858](../../../core/libs/prx/libSceCesCs/SingleByte.hpp) (libSceCesCs) - the console's table is not verified. The profile is the Cp850 one with byte 0xD5 mapped to U+20AC instead of U+0131, which is the whole high half of ICU's [ibm-858_P100-1997.ucm](https://github.com/unicode-org/icu-data/blob/main/charset/data/ucm/ibm-858_P100-1997.ucm); bytes 0x00-0x7F stay unchanged as in the other single-byte profiles, not swapped as in IBM's control mapping -- [libSceCesCs firmware 3.20 pending exports](../../../core/libs/prx/libSceCesCs/PendingExports.cpp) - 59 symbol names are present in [the PS5 3.20 libSceCesCs export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCesCs.c). Their signatures and console behaviour are unverified. The declarations use the existing no-parameter unknown-signature convention solely to resolve imports, and every call throws through `NotImplemented_nid_no_patch`. +- [libSceCesCs firmware 3.20 pending exports](../../../core/libs/prx/libSceCesCs/PendingExports.cpp) - 47 symbol names are present in [the PS5 3.20 libSceCesCs export list](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceCesCs.c). Their signatures and console behaviour are unverified. The declarations use the existing no-parameter unknown-signature convention solely to resolve imports, and every call throws through `NotImplemented_nid_no_patch`. - [EUC-KR, UHC and Big5 conversions](../../../core/libs/prx/libSceCesCs/Export.cpp) (libSceCesCs) - the errors are assumed; the decode tables and the Big5 duplicate choices were measured on a PS5 (`sceCesMbcToUtf32` and each `ToUtf8` over every one- and two-byte sequence): UHC and Big5 match, EUC-KR apart from its single bytes. The tables are Microsoft's [CP949.TXT](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT), plus `0xA2E8` U+327E from KS X 1001:2002, and [CP950.TXT](https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT); EUC-KR is CP949 limited to bytes `0xA1`-`0xFE`, below `0x80` ASCII; the KS X 1003 profile is not implemented. User-defined areas answer `UNASSIGNED_CODE`. Big5 encoding takes the lower of two cells except for U+5341 and U+5345, as a PS5's `sceCesUtf32ToMbc` does for every scalar (CP950 takes the higher cell of U+2550, U+255E, U+2561 and U+256A; the console does not). The profiles tag the caller's sheet like the EUC-JP profile +- [ISO 646 variants and JIS X 0201 profiles](../../../core/libs/prx/libSceCesCs/SingleByte.hpp) (libSceCesCs) - the tables and errors were measured on a PS5 with `sceCesSbcToUtf32` over every byte and `sceCesUtf32ToSbc` over every BMP scalar; the other single-byte forms share them and were not measured separately. The 7-bit sets (ASCII, BS 4730, GB 1988-80, JIS X 0201 Roman and Katakana, KS X 1003 and their `Tilde0x7e` variants) answer `INVALID_ENCODE` for bytes `0x80`-`0xFF`. BS 4730 changes only `0x23` (£), GB 1988-80 `0x24` (¥), JIS X 0201 Roman `0x5C` (¥) and KS X 1003 `0x5C` (₩); the base GB, JIS and KS profiles also map `0x7E` to overline and the `Tilde0x7e` variants keep a tilde. The katakana-only profile maps `0x21`-`0x5F` to U+FF61-U+FF9F and leaves `0x60`-`0x7E` unassigned; the 8-bit katakana profiles use `0xA1`-`0xDF`.