//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 }
//TODO: Check the code in emulation. If support for UTF8/UTF16/UTF32/UCS2/UCS4 should use wider chars.. awful. int L10nConvertStr(int src_code, vm::ptr<const void> src, vm::ptr<be_t<u32>> src_len, int dst_code, vm::ptr<void> dst, vm::ptr<be_t<u32>> dst_len) { cellL10n->Todo("L10nConvertStr(src_code=%d,src=0x%x,src_len=%ld,dst_code=%d,dst=0x%x,dst_len=%ld)", src_code, src.addr(), src_len.addr(), dst_code, dst.addr(), dst_len.addr()); cellL10n->Todo("L10nConvertStr: 1st char at dst: %x(Hex)", *((char*)src.get_ptr())); #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*)src.get_ptr(); //std::string wrapped_source((char*)src); if (wrapped_source.length() != *src_len) return SRCIllegal; std::string target = _OemToOem(srcCode, dstCode, wrapped_source); if (target.length() > *dst_len) return DSTExhausted; memcpy(dst.get_ptr(), target.c_str(), target.size()); 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*)src.get_ptr(); char *dstBuf = (char*)dst.get_ptr(); //char *srcBuf = (char*)src, *dstBuf = (char*)dst; //size_t srcLen = *src_len, dstLen = *dst_len; size_t srcLen = *src_len, dstLen = *dst_len; size_t ictd = iconv(ict, &srcBuf, &srcLen, &dstBuf, &dstLen); if (ictd != *src_len)//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 }
s32 _ConvertStr(s32 src_code, const void *src, s32 src_len, s32 dst_code, void *dst, s32 *dst_len, bool allowIncomplete) { HostCode 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; #ifdef _MSC_VER std::string wrapped_source = std::string(static_cast<const char *>(src), src_len); std::string target = _OemToOem(srcCode, dstCode, wrapped_source); if (dst != NULL) { if (target.length() > *dst_len) return DSTExhausted; memcpy(dst, target.c_str(), target.length()); } *dst_len = target.length(); return ConversionOK; #else s32 retValue = ConversionOK; iconv_t ict = iconv_open(dstCode, srcCode); size_t srcLen = src_len; if (dst != NULL) { size_t dstLen = *dst_len; size_t ictd = iconv(ict, (char **)&src, &srcLen, (char **)&dst, &dstLen); *dst_len -= dstLen; if (ictd == -1) { if (errno == EILSEQ) retValue = SRCIllegal; //Invalid multi-byte sequence else if (errno == E2BIG) retValue = DSTExhausted;//Not enough space else if (errno == EINVAL) { if (allowIncomplete) *dst_len = -1; // TODO: correct value? else retValue = SRCIllegal; } } } else { *dst_len = 0; char buf[16]; while (srcLen > 0) { char *bufPtr = buf; size_t bufLeft = sizeof(buf); size_t ictd = iconv(ict, (char **)&src, &srcLen, (char **)&bufPtr, &bufLeft); *dst_len += sizeof(buf) - bufLeft; if (ictd == -1 && errno != E2BIG) { if (errno == EILSEQ) retValue = SRCIllegal; else if (errno == EINVAL) { if (allowIncomplete) *dst_len = -1; // TODO: correct value? else retValue = SRCIllegal; } break; } } } iconv_close(ict); return retValue; #endif }