int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) { cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", utf16.GetAddr(), utf16_len.GetAddr(), utf8.GetAddr(), utf8_len.GetAddr()); if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) return SRCIllegal; std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16); wstr.resize(utf16_len.GetValue()); // TODO: Is this really the role of utf16_len in this function? #ifdef _MSC_VER std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert; std::string str = convert.to_bytes(wstr); if (!utf8.IsGood() || utf8_len.GetValue() < str.size()) { utf8_len = str.size(); return DSTExhausted; } utf8_len = str.size(); Memory.WriteString(utf8, str.c_str()); #endif return ConversionOK; }
int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) { cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", utf16.GetAddr(), utf16_len.GetAddr(), utf8.GetAddr(), utf8_len.GetAddr()); if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) return SRCIllegal; std::wstring wstr = (wchar_t*)Memory.VirtualToRealAddr(utf16); std::string str; int len = min((int)utf16_len.GetValue(), (int)wstr.size()); int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); if (!utf8.IsGood()) utf8_len = size; if (utf8_len.GetValue() < size) return DSTExhausted; #ifdef WIN32 WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &str[0], size, NULL, NULL); #else // TODO #endif Memory.WriteString(utf8, str); return ConversionOK; }
//TODO: Check the code in emulation. If support for UTF8/UTF16/UTF32/UCS2/UCS4 should use wider chars.. awful. int L10nConvertStr(int src_code, mem8_ptr_t src, mem64_t src_len, int dst_code, mem8_ptr_t dst, mem64_t dst_len) { LOG_ERROR(HLE, "L10nConvertStr(src_code=%d,src=0x%x,src_len=%ld,dst_code=%d,dst=0x%x,dst_len=%ld)", src_code, src.GetAddr(), src_len.GetValue(), dst_code, dst.GetAddr(), dst_len.GetValue()); LOG_ERROR(HLE, "L10nConvertStr: 1st char at dst: %x(Hex)", *((char*)Memory.VirtualToRealAddr(src.GetAddr()))); #ifdef _MSC_VER unsigned int srcCode = 0, dstCode = 0; //OEM code pages bool src_page_converted = _L10nCodeParse(src_code, srcCode); //Check if code is in list. bool dst_page_converted = _L10nCodeParse(dst_code, dstCode); if (((!src_page_converted) && (srcCode == 0)) || ((!dst_page_converted) && (dstCode == 0))) return ConverterUnknown; //if (strnlen_s((char*)src, *src_len) != *src_len) return SRCIllegal; std::string wrapped_source = (char*)Memory.VirtualToRealAddr(src.GetAddr()); //std::string wrapped_source((char*)src); if (wrapped_source.length() != src_len.GetValue()) return SRCIllegal; std::string target = _OemToOem(srcCode, dstCode, wrapped_source); if (target.length() > dst_len.GetValue()) return DSTExhausted; Memory.WriteString(dst, target.c_str()); return ConversionOK; #else std::string srcCode, dstCode; int retValue = ConversionOK; if ((_L10nCodeParse(src_code, srcCode)) && (_L10nCodeParse(dst_code, dstCode))) { iconv_t ict = iconv_open(srcCode.c_str(), dstCode.c_str()); char *srcBuf = (char*)Memory.VirtualToRealAddr(src.GetAddr()); char *dstBuf = (char*)Memory.VirtualToRealAddr(dst.GetAddr()); //char *srcBuf = (char*)src, *dstBuf = (char*)dst; //size_t srcLen = *src_len, dstLen = *dst_len; size_t srcLen = src_len.GetValue(), dstLen = dst_len.GetValue(); size_t ictd = iconv(ict, &srcBuf, &srcLen, &dstBuf, &dstLen); if (ictd != src_len.GetValue())//if (ictd != *src_len) { if (errno == EILSEQ) retValue = SRCIllegal; //Invalid multi-byte sequence else if (errno == E2BIG) retValue = DSTExhausted;//Not enough space else if (errno == EINVAL) retValue = SRCIllegal; } iconv_close(ict); //retValue = ConversionOK; } else retValue = ConverterUnknown; return retValue; #endif }