int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellJpgDecInfo> info) { cellJpgDec.Log("cellJpgDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr()); if (!info.IsGood()) return CELL_JPGDEC_ERROR_ARG; 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; CellJpgDecInfo& current_info = subHandle_data->info; //Copy the JPG file to a buffer MemoryAllocator<u8> buffer(fileSize); MemoryAllocator<be_t<u64>> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); if (*buffer.To<u32>(0) != 0xE0FFD8FF || // Error: Not a valid SOI header *buffer.To<u32>(6) != 0x4649464A) // Error: Not a valid JFIF string { return CELL_JPGDEC_ERROR_HEADER; } u32 i = 4; if(i >= fileSize) return CELL_JPGDEC_ERROR_HEADER; u16 block_length = buffer[i] * 0xFF + buffer[i+1]; while(true) { i += block_length; // Increase the file index to get to the next block if (i >= fileSize || // Check to protect against segmentation faults buffer[i] != 0xFF) // Check that we are truly at the start of another block { return CELL_JPGDEC_ERROR_HEADER; } if(buffer[i+1] == 0xC0) break; // 0xFFC0 is the "Start of frame" marker which contains the file size i += 2; // Skip the block marker block_length = buffer[i] * 0xFF + buffer[i+1]; // Go to the next block } current_info.imageWidth = buffer[i+7]*0x100 + buffer[i+8]; current_info.imageHeight = buffer[i+5]*0x100 + buffer[i+6]; current_info.numComponents = 3; // Unimplemented current_info.colorSpace = CELL_JPG_RGB; *info = current_info; return CELL_OK; }
ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence) { int ret = 0; if (!stream) return -1; (void)ret; #if defined(VITA) || defined(PSP) ret = sceIoLseek(stream->fd, (SceOff)offset, whence); if (ret == -1) return -1; return 0; #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #elif defined(HAVE_BUFFERED_IO) return fseek(stream->fd, (long)offset, whence); #else ret = lseek(stream->fd, offset, whence); if (ret == -1) return -1; return 0; #endif }
ssize_t filestream_tell(RFILE *stream) { if (!stream) return -1; #if defined(VITA) || defined(PSP) return sceIoLseek(stream->fd, 0, SEEK_CUR); #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return ftell(stream->fp); else #endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function * is called in filestream_open() */ if (stream->mapped && stream->hints & RFILE_HINT_MMAP) return stream->mappos; else #endif return lseek(stream->fd, 0, SEEK_CUR); #endif }
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_struct_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_struct_ptr_t<CellPngDecDataOutInfo> dataOutInfo) { dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; ID sub_handle_id_data; if(!cellPngDec.CheckId(subHandle, sub_handle_id_data)) return CELL_PNGDEC_ERROR_FATAL; auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data; 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; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, png.GetAddr(), png.GetSize(), nread); //Decode PNG 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(png, fileSize, &width, &height, &actual_components, 4)); if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; uint image_size = width * height; switch(current_outParam.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: image_size *= current_outParam.outputColorSpace == CELL_PNGDEC_RGBA ? 4 : 3; memcpy(data, image.get(), image_size); break; case CELL_PNGDEC_ARGB: image_size *= 4; 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; 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 cellPngDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellPngDecInfo> info) { if (!info.IsGood()) return CELL_PNGDEC_ERROR_ARG; cellPngDec.Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%llx)", mainHandle, subHandle, info.GetAddr()); 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; CellPngDecInfo& current_info = subHandle_data->info; //Check size of file if(fileSize < 29) return CELL_PNGDEC_ERROR_HEADER; // Error: The file is smaller than the length of a PNG header //Write the header to buffer MemoryAllocator<be_t<u32>> buffer(34); // Alloc buffer for PNG header MemoryAllocator<be_t<u64>> pos, nread; switch(subHandle_data->src.srcSelect.ToLE()) { case CELL_PNGDEC_BUFFER: Memory.Copy(buffer.GetAddr(), subHandle_data->src.streamPtr.ToLE(), buffer.GetSize()); break; case CELL_PNGDEC_FILE: cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread.GetAddr()); break; } if (buffer[0] != 0x89504E47 || buffer[1] != 0x0D0A1A0A || // Error: The first 8 bytes are not a valid PNG signature buffer[3] != 0x49484452) // Error: The PNG file does not start with an IHDR chunk { return CELL_PNGDEC_ERROR_HEADER; } switch (buffer.To<u8>()[25]) { case 0: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE; current_info.numComponents = 1; break; case 2: current_info.colorSpace = CELL_PNGDEC_RGB; current_info.numComponents = 3; break; case 3: current_info.colorSpace = CELL_PNGDEC_PALETTE; current_info.numComponents = 1; break; case 4: current_info.colorSpace = CELL_PNGDEC_GRAYSCALE_ALPHA; current_info.numComponents = 2; break; case 6: current_info.colorSpace = CELL_PNGDEC_RGBA; current_info.numComponents = 4; break; default: return CELL_PNGDEC_ERROR_HEADER; // Not supported color type } current_info.imageWidth = buffer[4]; current_info.imageHeight = buffer[5]; current_info.bitDepth = buffer.To<u8>()[24]; current_info.interlaceMethod = buffer.To<u8>()[28]; current_info.chunkInformation = 0; // Unimplemented *info = current_info; 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 cellFsReadWithOffset(u32 fd, u64 offset, u32 buf_addr, u64 buffer_size, mem64_t nread) { sys_fs.Warning("cellFsReadWithOffset(fd=%d, offset=0x%llx, buf_addr=0x%x, buffer_size=%lld nread=0x%llx)", fd, offset, buf_addr, buffer_size, nread.GetAddr()); int ret; MemoryAllocator<be_t<u64>> oldPos, newPos; ret = cellFsLseek(fd, 0, CELL_SEEK_CUR, oldPos.GetAddr()); // Save the current position if (ret) return ret; ret = cellFsLseek(fd, offset, CELL_SEEK_SET, newPos.GetAddr()); // Move to the specified offset if (ret) return ret; ret = cellFsRead(fd, buf_addr, buffer_size, nread.GetAddr()); // Read the file if (ret) return ret; ret = cellFsLseek(fd, Memory.Read64(oldPos.GetAddr()), CELL_SEEK_SET, newPos.GetAddr()); // Return to the old position if (ret) return ret; return CELL_OK; }
int sys_psp_read_umd(int unk, void *buf, uint64_t sector, uint64_t ofs, uint64_t size) { uint64_t offset, dummy; int ret; #ifdef DEBUG DPRINTF("umd read %lx %lx %lx\n", sector, ofs, size); #endif if (!mutex) { object_handle_t obj_handle; void *object_table = get_current_process()->object_table; int ret = open_kernel_object(object_table, *(uint32_t *)(emulator_api_base+umd_mutex_offset), (void **)&mutex, &obj_handle, SYS_MUTEX_OBJECT); if (ret != 0) { #ifdef DEBUG DPRINTF("Cannot open user mutex, using an own one\n"); #endif mutex_create(&mutex, SYNC_PRIORITY, SYNC_NOT_RECURSIVE); user_mutex = 0; } else { #ifdef DEBUG DPRINTF("user mutex opened succesfully\n"); #endif user_mutex = 1; close_kernel_object_handle(object_table, obj_handle); } } mutex_lock(mutex, 0); offset = sector*0x800; if (ofs != 0) { offset = offset+0x800-ofs; } ret = cellFsLseek(umd_fd, offset, SEEK_SET, &dummy); if (ret != 0) { mutex_unlock(mutex); return ret; } ret = cellFsRead(umd_fd, get_secure_user_ptr(buf), size, &dummy); mutex_unlock(mutex); if (ret == 0) ret = (int)size; return ret; }
/* * Function: getFileSize() * File: main.c * Project: ArtemisPS3-PRX * Description: Gets the file size of a file * Arguments: * path: path to file * Return: size of file */ int getFileSize(const char * path) { int fd = 0, size = 0; if(cellFsOpen(path, CELL_FS_O_RDONLY, &fd, NULL, 0) == CELL_FS_SUCCEEDED) { u64 pos; cellFsLseek(fd, 0, CELL_FS_SEEK_END, &pos); size = (int)pos; cellFsClose(fd); } return size; }
ssize_t retro_ftell(RFILE *stream) { if (!stream) return -1; #if defined(VITA) || defined(PSP) return sceIoLseek(stream->fd, 0, SEEK_CUR); #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #elif defined(HAVE_BUFFERED_IO) return ftell(stream->fd); #else return lseek(stream->fd, 0, SEEK_CUR); #endif }
/* * Function: readFile() * File: main.c * Project: ArtemisPS3-PRX * Description: Reads a file * Arguments: * path: path to file to read * buffer: buffer to store the file contents toascii * size: number of bytes to read from the file * Return: Returns 0 if failed, 1 if succeeded */ int readFile(const char * path, char * buffer, int size) { int fd, ret = 0; if(cellFsOpen(path, CELL_FS_O_RDONLY, &fd, NULL, 0) == CELL_FS_SUCCEEDED) { u64 read_e = 0, pos; //, write_e cellFsLseek(fd, 0, CELL_FS_SEEK_SET, &pos); if (cellFsRead(fd, (void *)buffer, size, &read_e)==CELL_FS_SUCCEEDED) { ret = 1; } cellFsClose(fd); } buffer[size] = '\0'; return ret; }
/* * Function: art_process() * File: main.c * Project: ArtemisPS3-PRX * Description: Processes an entire codelist once * Arguments: * forceWrite: whether the user activated Artemis (1) or a constant write (0) * Return: void */ static void art_process(int forceWrite) { int fd = 0; if (attachedPID) { doForceWrite = forceWrite; //Force load userCodes on forceWrite if (forceWrite && userCodes) { reset_heap(); userCodes = NULL; } if (!userCodes) { int fileSize = getFileSize("/dev_hdd0/tmp/art.txt"); userCodes = (char *)mem_alloc(fileSize + 2); memset(userCodes, 0, fileSize + 2); if(cellFsOpen("/dev_hdd0/tmp/art.txt", CELL_FS_O_RDONLY, &fd, NULL, 0) == CELL_FS_SUCCEEDED) { u64 read_e = 0, pos; cellFsLseek(fd, 0, CELL_FS_SEEK_SET, &pos); cellFsRead(fd, (void *)userCodes, fileSize, &read_e); cellFsClose(fd); } userCodes[fileSize] = '\n'; } if (attachedPID != NULL && attachedPID != 0) { ConvertCodes(attachedPID, userCodes); sys_timer_sleep(0.1); } } doForceWrite = 0; }
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t<CellGifDecInfo> info) { if (!info.IsGood()) return CELL_GIFDEC_ERROR_ARG; 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; CellGifDecInfo& current_info = subHandle_data->info; //Write the header to buffer MemoryAllocator<u8> buffer(13); // Alloc buffer for GIF header MemoryAllocator<be_t<u64>> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); if (*buffer.To<be_t<u32>>(0) != 0x47494638 || (*buffer.To<u16>(4) != 0x6139 && *buffer.To<u16>(4) != 0x6137)) // Error: The first 6 bytes are not a valid GIF signature { return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss } u8 packedField = buffer[10]; current_info.SWidth = buffer[6] + buffer[7] * 0x100; current_info.SHeight = buffer[8] + buffer[9] * 0x100; current_info.SGlobalColorTableFlag = packedField >> 7; current_info.SColorResolution = ((packedField >> 4) & 7)+1; current_info.SSortFlag = (packedField >> 3) & 1; current_info.SSizeOfGlobalColorTable = (packedField & 7)+1; current_info.SBackGroundColor = buffer[11]; current_info.SPixelAspectRatio = buffer[12]; *info = current_info; return CELL_OK; }
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; }
ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence) { int ret = 0; if (!stream) return -1; (void)ret; #if defined(VITA) || defined(PSP) ret = sceIoLseek(stream->fd, (SceOff)offset, whence); if (ret == -1) return -1; return 0; #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #else #if defined(HAVE_BUFFERED_IO) if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) return fseek(stream->fp, (long)offset, whence); else #endif #ifdef HAVE_MMAP /* Need to check stream->mapped because this function is * called in filestream_open() */ if (stream->mapped && stream->hints & RFILE_HINT_MMAP) { /* fseek() returns error on under/overflow but allows cursor > EOF for read-only file descriptors. */ switch (whence) { case SEEK_SET: if (offset < 0) return -1; stream->mappos = offset; break; case SEEK_CUR: if ((offset < 0 && stream->mappos + offset > stream->mappos) || (offset > 0 && stream->mappos + offset < stream->mappos)) return -1; stream->mappos += offset; break; case SEEK_END: if (stream->mapsize + offset < stream->mapsize) return -1; stream->mappos = stream->mapsize + offset; break; } return stream->mappos; } else #endif { ret = lseek(stream->fd, offset, whence); return ret < 0 ? -1 : ret; } #endif }
int sys_psp_read_header(int fd, char *buf, uint64_t nbytes, uint64_t *nread) { int ret; uint32_t n, unk2; uint64_t umd_size; sys_prx_id_t *list; uint32_t *unk; process_t process; #ifdef DEBUG DPRINTF("umd read header: %p %lx\n", buf, nbytes); #endif buf = get_secure_user_ptr(buf); nread = get_secure_user_ptr(nread); if (!umd_file || nbytes != 0x100) return EABORT; pemucorelib_base = 0; emulator_api_base = 0; list = alloc(SPRX_NUM*sizeof(sys_prx_module_info_t), 0x35); unk = alloc(SPRX_NUM*sizeof(uint32_t), 0x35); process = get_current_process(); ret = prx_get_module_list(process, list, unk, SPRX_NUM, &n, &unk2); if (ret == 0) { char *filename = alloc(256, 0x35); sys_prx_segment_info_t *segments = alloc(sizeof(sys_prx_segment_info_t), 0x35); for (int i = 0; i < SPRX_NUM; i++) { sys_prx_module_info_t modinfo; memset(&modinfo, 0, sizeof(sys_prx_module_info_t)); modinfo.filename_size = 256; modinfo.segments_num = 1; if (prx_get_module_info(process, list[i], &modinfo, filename, segments) == 0) { if (strstr(filename, "/emulator_api.sprx")) { emulator_api_base = segments[0].base; #ifdef DEBUG DPRINTF("emulator_api base = %08lx\n", emulator_api_base); #endif } else if (strstr(filename, "/PEmuCoreLib.sprx")) { pemucorelib_base = segments[0].base; #ifdef DEBUG DPRINTF("PEmuCoreLib base = %08lx\n", pemucorelib_base); #endif } } } if (pemucorelib_base == 0 || emulator_api_base == 0) ret = EABORT; dealloc(filename, 0x35); dealloc(segments, 0x35); } dealloc(list, 0x35); dealloc(unk, 0x35); if (ret != 0) return ret; ret = cellFsOpen(umd_file, CELL_FS_O_RDONLY, &umd_fd, 0, NULL, 0); if (ret != 0) return ret; cellFsLseek(umd_fd, 0, SEEK_END, &umd_size); // Fake header. We will write only values actually used memset(buf, 0, 0x100); *(uint32_t *)(buf+0x0c) = 0x10; *(uint32_t *)(buf+0x64) = (umd_size/0x800)-1; // Last sector of umd strncpy(buf+0x70, psp_id, 10); #ifdef DEBUG DPRINTF("ID: %s\n", psp_id); #endif if (mutex && user_mutex) { mutex = NULL; user_mutex = 0; } *nread = 0x100; return 0; }
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; }