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; }
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 cellFsAioFinish(mem8_ptr_t mount_point) { std::string mp = Memory.ReadString(mount_point.GetAddr()); sys_fs.Warning("cellFsAioFinish(mount_point_addr=0x%x (%s))", mount_point.GetAddr(), mp.c_str()); aio_init = false; return CELL_OK; }
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellGifDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellGifDecDataOutInfo> dataOutInfo) { if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood()) return CELL_GIFDEC_ERROR_ARG; dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP; CellGifDecSubHandle* subHandle_data; if(!cellGifDec->CheckId(subHandle, subHandle_data)) return CELL_GIFDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; const CellGifDecOutParam& current_outParam = subHandle_data->outParam; //Copy the GIF file to a buffer MemoryAllocator<unsigned char> gif(fileSize); MemoryAllocator<u64> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, gif.GetAddr(), gif.GetSize(), nread); //Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; std::shared_ptr<unsigned char> image(stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4)); if (!image) return CELL_GIFDEC_ERROR_STREAM_FORMAT; uint image_size = width * height * 4; switch((u32)current_outParam.outputColorSpace) { case CELL_GIFDEC_RGBA: if (!Memory.CopyFromReal(data.GetAddr(), image.get(), image_size)) { cellGifDec->Error("cellGifDecDecodeData() failed (dataa_addr=0x%x)", data.GetAddr()); return CELL_EFAULT; } break; case CELL_GIFDEC_ARGB: for(uint i = 0; i < image_size; i+=4) { data += image.get()[i+3]; data += image.get()[i+0]; data += image.get()[i+1]; data += image.get()[i+2]; } break; default: return CELL_GIFDEC_ERROR_ARG; } dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_FINISH; dataOutInfo->recordType = CELL_GIFDEC_RECORD_TYPE_IMAGE_DESC; return CELL_OK; }
int jstrchk(mem8_ptr_t jstr) { if (!jstr.IsGood()) cellL10n.Error("jstrchk(jstr_addr=0x%x): invalid address", jstr.GetAddr()); else if (jstr[0]) cellL10n.Log("jstrchk(jstr_addr=0x%x): utf-8: [%s]", jstr.GetAddr(), Memory.ReadString(jstr.GetAddr()).c_str()); else cellL10n.Log("jstrchk(jstr_addr=0x%x): empty string", jstr.GetAddr()); return L10N_STR_UTF8; }
//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 }
int cellFontOpenFontFile(mem_ptr_t<CellFontLibrary> library, mem8_ptr_t fontPath, u32 subNum, s32 uniqueId, mem_ptr_t<CellFont> font) { cellFont.Warning("cellFontOpenFontFile(library_addr=0x%x, fontPath=\"%s\", subNum=%d, uniqueId=%d, font_addr=0x%x)", library.GetAddr(), fontPath.GetString(), subNum, uniqueId, font.GetAddr()); vfsFile f(fontPath.GetString()); if (!f.IsOpened()) return CELL_FONT_ERROR_FONT_OPEN_FAILED; u32 fileSize = f.GetSize(); MemoryAllocator<u8> buffer(fileSize); f.Read(Memory.VirtualToRealAddr(buffer.GetAddr()), fileSize); cellFontOpenFontMemory(library.GetAddr(), buffer.GetAddr(), fileSize, subNum, uniqueId, font.GetAddr()); return CELL_FONT_OK; }
int cellFontOpenFontFile(mem_ptr_t<CellFontLibrary> library, mem8_ptr_t fontPath, u32 subNum, s32 uniqueId, mem_ptr_t<CellFont> font) { std::string fp(fontPath.GetString()); cellFont->Warning("cellFontOpenFontFile(library_addr=0x%x, fontPath=\"%s\", subNum=%d, uniqueId=%d, font_addr=0x%x)", library.GetAddr(), fp.c_str(), subNum, uniqueId, font.GetAddr()); vfsFile f(fp); if (!f.IsOpened()) return CELL_FONT_ERROR_FONT_OPEN_FAILED; u32 fileSize = f.GetSize(); u32 bufferAddr = Memory.Alloc(fileSize, 1); // Freed in cellFontCloseFont f.Read(Memory.VirtualToRealAddr(bufferAddr), fileSize); int ret = cellFontOpenFontMemory(library.GetAddr(), bufferAddr, fileSize, subNum, uniqueId, font.GetAddr()); font->origin = CELL_FONT_OPEN_FONT_FILE; return ret; }
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellPngDecDataOutInfo> dataOutInfo) { if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood()) return CELL_PNGDEC_ERROR_ARG; dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; CellPngDecSubHandle* subHandle_data; if(!cellPngDec.CheckId(subHandle, subHandle_data)) return CELL_PNGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; const CellPngDecOutParam& current_outParam = subHandle_data->outParam; //Copy the PNG file to a buffer MemoryAllocator<unsigned char> png(fileSize); MemoryAllocator<u64> pos, nread; switch(subHandle_data->src.srcSelect.ToLE()) { case CELL_PNGDEC_BUFFER: Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize()); break; case CELL_PNGDEC_FILE: cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); cellFsRead(fd, png.GetAddr(), png.GetSize(), nread.GetAddr()); break; } //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; auto image = std::unique_ptr<unsigned char,decltype(&::free)> ( stbi_load_from_memory(png.GetPtr(), fileSize, &width, &height, &actual_components, 4), &::free ); if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; uint image_size = width * height; switch((u32)current_outParam.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: { const char nComponents = (CELL_PNGDEC_RGBA ? 4 : 3); image_size *= nComponents; if (dataCtrlParam->outputBytesPerLine > width * nComponents) //check if we need padding { //TODO: find out if we can't do padding without an extra copy char *output = (char *) malloc(dataCtrlParam->outputBytesPerLine*height); for (int i = 0; i < height; i++) { memcpy(&output[i*dataCtrlParam->outputBytesPerLine], &image.get()[width*nComponents*i], width*nComponents); } Memory.CopyFromReal(data.GetAddr(), output, dataCtrlParam->outputBytesPerLine*height); free(output); } else { Memory.CopyFromReal(data.GetAddr(), image.get(), image_size); } } break; case CELL_PNGDEC_ARGB: { const char nComponents = 4; image_size *= nComponents; if (dataCtrlParam->outputBytesPerLine > width * nComponents) //check if we need padding { //TODO: find out if we can't do padding without an extra copy char *output = (char *) malloc(dataCtrlParam->outputBytesPerLine*height); for (int i = 0; i < height; i++) { for (int j = 0; j < width * nComponents; j += nComponents){ output[i*dataCtrlParam->outputBytesPerLine + j ] = image.get()[i*width * nComponents + j + 3]; output[i*dataCtrlParam->outputBytesPerLine + j + 1] = image.get()[i*width * nComponents + j + 0]; output[i*dataCtrlParam->outputBytesPerLine + j + 2] = image.get()[i*width * nComponents + j + 1]; output[i*dataCtrlParam->outputBytesPerLine + j + 3] = image.get()[i*width * nComponents + j + 2]; } } Memory.CopyFromReal(data.GetAddr(), output, dataCtrlParam->outputBytesPerLine*height); free(output); } else { for (uint i = 0; i < image_size; i += nComponents) { data += image.get()[i + 3]; data += image.get()[i + 0]; data += image.get()[i + 1]; data += image.get()[i + 2]; } } } break; case CELL_PNGDEC_GRAYSCALE: case CELL_PNGDEC_PALETTE: case CELL_PNGDEC_GRAYSCALE_ALPHA: cellPngDec.Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); break; default: return CELL_PNGDEC_ERROR_ARG; } dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH; return CELL_OK; }
int cellWebBrowserEstimate2(mem8_ptr_t _config, mem32_ptr_t memSize) { cellSysutil->Warning("cellWebBrowserEstimate2(config_addr=0x%x, memSize_addr=0x%x)", _config.GetAddr(), memSize.GetAddr()); // TODO: When cellWebBrowser stuff is implemented, change this to some real // needed memory buffer size. *memSize = 1024 * 1024 * 1; // 1 MB return CELL_OK; }
int jstrchk(mem8_ptr_t jstr) { cellL10n->Warning("jstrchk(jstr_addr=0x%x) -> utf8", jstr.GetAddr()); return L10N_STR_UTF8; }
int jstrchk(mem8_ptr_t jstr) { cellL10n.Log("jstrchk(jstr_addr=0x%x [%s])", jstr.GetAddr(), "omitted" /*Memory.ReadString(jstr.GetAddr()).wx_str()*/); return L10N_STR_UTF8; }
int sys_net_inet_addr(mem8_ptr_t cp) { std::string cp_ = Memory.ReadString(cp.GetAddr()); sys_net->Warning("inet_addr(cp=\"%s\")", cp_.c_str()); return htonl(inet_addr(cp_.c_str())); // return a big-endian IP address }
int sys_process_get_paramsfo(mem8_ptr_t buffer) { sc_p.Warning("TODO: sys_process_get_paramsfo(buffer_addr=0x%x) returns CELL_ENOENT", buffer.GetAddr()); return CELL_ENOENT; /*//Before uncommenting this code, we should check if it is actually working. MemoryAllocator<be_t<u32>> fd; char filePath [] = "/app_home/../PARAM.SFO"; if (!cellFsOpen(Memory.RealToVirtualAddr(filePath), 0, fd, NULL, 0)) return CELL_ENOENT; MemoryAllocator<be_t<u64>> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); //TODO: Move to the appropriate offset (probably 0x3F7) cellFsRead(fd, buffer.GetAddr(), 40, nread); //WARNING: If offset==0x3F7: The file will end before the buffer (40 bytes) is filled! cellFsClose(fd); return CELL_OK;*/ }
int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellJpgDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellJpgDecDataOutInfo> dataOutInfo) { if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood()) return CELL_JPGDEC_ERROR_ARG; dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_STOP; CellJpgDecSubHandle* subHandle_data; if(!cellJpgDec.CheckId(subHandle, subHandle_data)) return CELL_JPGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; const CellJpgDecOutParam& current_outParam = subHandle_data->outParam; //Copy the JPG file to a buffer MemoryAllocator<unsigned char> jpg(fileSize); MemoryAllocator<u64> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, jpg.GetAddr(), jpg.GetSize(), nread); //Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; std::shared_ptr<unsigned char> image(stbi_load_from_memory(jpg, fileSize, &width, &height, &actual_components, 4)); if (!image) return CELL_JPGDEC_ERROR_STREAM_FORMAT; uint image_size = width * height; switch((u32)current_outParam.outputColorSpace) { case CELL_JPG_RGBA: case CELL_JPG_RGB: image_size *= current_outParam.outputColorSpace == CELL_JPG_RGBA ? 4 : 3; Memory.CopyFromReal(data.GetAddr(), image.get(), image_size); break; case CELL_JPG_ARGB: image_size *= 4; for(u32 i = 0; i < image_size; i+=4) { data += image.get()[i+3]; data += image.get()[i+0]; data += image.get()[i+1]; data += image.get()[i+2]; } break; case CELL_JPG_GRAYSCALE: case CELL_JPG_YCbCr: case CELL_JPG_UPSAMPLE_ONLY: case CELL_JPG_GRAYSCALE_TO_ALPHA_RGBA: case CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB: cellJpgDec.Error("cellJpgDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); break; default: return CELL_JPGDEC_ERROR_ARG; } dataOutInfo->status = CELL_JPGDEC_DEC_STATUS_FINISH; if(dataCtrlParam->outputBytesPerLine) dataOutInfo->outputLines = image_size / dataCtrlParam->outputBytesPerLine; return CELL_OK; }