From fe46a4591564b2317a6f7b2f3b68ec28dccb6fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Tue, 22 Jul 2014 17:16:15 +0200 Subject: [PATCH] Fixed memory exception on cellJpgDec & cellGifDec * Added support for CELL_JPGDEC_BUFFER and CELL_GIFDEC_BUFFER. --- rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp | 95 +++++++++++++---------- rpcs3/Emu/SysCalls/Modules/cellGifDec.h | 8 +- rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp | 71 +++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellJpgDec.h | 12 ++- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 11 ++- rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 38 ++++----- 6 files changed, 146 insertions(+), 89 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index b21151bbdd..3e39e91d54 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -29,49 +29,33 @@ int cellGifDecOpen(u32 mainHandle, mem32_t subHandle, const mem_ptr_tsrcSelect) - { - case CELL_GIFDEC_FILE: - stream = Emu.GetVFS().Open(src->fileName.GetString(), vfsRead); - stream->Seek(src->fileOffset); - src->fileSize; - break; - - case CELL_GIFDEC_BUFFER: - if(src->streamSize < 5) - return CELL_GIFDEC_ERROR_ARG; - - stream = new vfsStreamMemory(src->streamPtr.GetAddr(), src->streamSize); - break; - - default: - return CELL_GIFDEC_ERROR_ARG; - } - - if(!stream->IsOpened()) - { - return CELL_GIFDEC_ERROR_OPEN_FILE; - } - */ - + CellGifDecSubHandle *current_subHandle = new CellGifDecSubHandle; + current_subHandle->fd = 0; + current_subHandle->src = *src; - // Get file descriptor - MemoryAllocator> fd; - int ret = cellFsOpen(src->fileName, 0, fd, 0, 0); - current_subHandle->fd = fd->ToLE(); - if(ret != CELL_OK) return CELL_GIFDEC_ERROR_OPEN_FILE; + switch(src->srcSelect.ToBE()) + { + case se32(CELL_GIFDEC_BUFFER): + current_subHandle->fileSize = src->streamSize.ToLE(); + break; - // Get size of file - MemoryAllocator sb; // Alloc a CellFsStat struct - ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); - if(ret != CELL_OK) return ret; - current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size + case se32(CELL_GIFDEC_FILE): + // Get file descriptor + MemoryAllocator> fd; + int ret = cellFsOpen(src->fileName, 0, fd.GetAddr(), 0, 0); + current_subHandle->fd = fd->ToLE(); + if (ret != CELL_OK) return CELL_GIFDEC_ERROR_OPEN_FILE; - // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. + // Get size of file + MemoryAllocator sb; // Alloc a CellFsStat struct + ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); + if (ret != CELL_OK) return ret; + current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size + break; + } + + // From now, every u32 subHandle argument is a pointer to a CellGifDecSubHandle struct. subHandle = cellGifDec->GetNewId(current_subHandle); return CELL_OK; @@ -94,8 +78,20 @@ int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_t buffer(13); // Alloc buffer for GIF header MemoryAllocator> pos, nread; - cellFsLseek(fd, 0, CELL_SEEK_SET, pos); - cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); + switch(subHandle_data->src.srcSelect.ToBE()) + { + case se32(CELL_GIFDEC_BUFFER): + if (!Memory.Copy(buffer.GetAddr(), subHandle_data->src.streamPtr.ToLE(), buffer.GetSize())) { + cellGifDec->Error("cellGifDecReadHeader() failed ()"); + return CELL_EFAULT; + } + break; + + case se32(CELL_GIFDEC_FILE): + cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); + cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); + break; + } if (*buffer.To>(0) != 0x47494638 || (*buffer.To(4) != 0x6139 && *buffer.To(4) != 0x6137)) // Error: The first 6 bytes are not a valid GIF signature @@ -166,8 +162,21 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m //Copy the GIF file to a buffer MemoryAllocator gif(fileSize); MemoryAllocator pos, nread; - cellFsLseek(fd, 0, CELL_SEEK_SET, pos); - cellFsRead(fd, gif.GetAddr(), gif.GetSize(), nread); + + switch(subHandle_data->src.srcSelect.ToBE()) + { + case se32(CELL_GIFDEC_BUFFER): + if (!Memory.Copy(gif.GetAddr(), subHandle_data->src.streamPtr.ToLE(), gif.GetSize())) { + cellGifDec->Error("cellGifDecDecodeData() failed (I)"); + return CELL_EFAULT; + } + break; + + case se32(CELL_GIFDEC_FILE): + cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); + cellFsRead(fd, gif.GetAddr(), gif.GetSize(), nread); + break; + } //Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.h b/rpcs3/Emu/SysCalls/Modules/cellGifDec.h index e6b13ac7c2..7ed3160b27 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.h @@ -16,8 +16,8 @@ enum enum CellGifDecStreamSrcSel { - CELL_GIFDEC_FILE = 0, //Input from a file - CELL_GIFDEC_BUFFER = 1, //Input from a buffer + CELL_GIFDEC_FILE = 0, // Input from a file + CELL_GIFDEC_BUFFER = 1, // Input from a buffer }; enum CellGifDecColorSpace @@ -105,10 +105,12 @@ struct CellGifDecDataCtrlParam be_t outputBytesPerLine; }; -struct CellGifDecSubHandle //Custom struct +//Custom structs +struct CellGifDecSubHandle { u32 fd; u64 fileSize; CellGifDecInfo info; CellGifDecOutParam outParam; + CellGifDecSrc src; }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index 8a7aa659c7..b3e5dd50af 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -33,24 +33,36 @@ int cellJpgDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t s cellJpgDec->Warning("cellJpgDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)", mainHandle, subHandle.GetAddr(), src.GetAddr(), openInfo); - if (!subHandle.IsGood() || !src.IsGood() || !openInfo.IsGood()) + if (!subHandle.IsGood() || !src.IsGood()) return CELL_JPGDEC_ERROR_ARG; CellJpgDecSubHandle *current_subHandle = new CellJpgDecSubHandle; - // Get file descriptor - MemoryAllocator> fd; - int ret = cellFsOpen(src->fileName, 0, fd, 0, 0); - current_subHandle->fd = fd->ToLE(); - if(ret != CELL_OK) return CELL_JPGDEC_ERROR_OPEN_FILE; + current_subHandle->fd = 0; + current_subHandle->src = *src; - // Get size of file - MemoryAllocator sb; // Alloc a CellFsStat struct - ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); - if(ret != CELL_OK) return ret; - current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size + switch(src->srcSelect.ToBE()) + { + case se32(CELL_JPGDEC_BUFFER): + current_subHandle->fileSize = src->streamSize.ToLE(); + break; - // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. + case se32(CELL_JPGDEC_FILE): + // Get file descriptor + MemoryAllocator> fd; + int ret = cellFsOpen(src->fileName, 0, fd.GetAddr(), 0, 0); + current_subHandle->fd = fd->ToLE(); + if (ret != CELL_OK) return CELL_JPGDEC_ERROR_OPEN_FILE; + + // Get size of file + MemoryAllocator sb; // Alloc a CellFsStat struct + ret = cellFsFstat(current_subHandle->fd, sb.GetAddr()); + if (ret != CELL_OK) return ret; + current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size + break; + } + + // From now, every u32 subHandle argument is a pointer to a CellJpgDecSubHandle struct. subHandle = cellJpgDec->GetNewId(current_subHandle); return CELL_OK; @@ -83,12 +95,24 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, mem_ptr_tfileSize; CellJpgDecInfo& current_info = subHandle_data->info; - //Copy the JPG file to a buffer + //Write the header to buffer MemoryAllocator buffer(fileSize); MemoryAllocator> pos, nread; - cellFsLseek(fd, 0, CELL_SEEK_SET, pos); - cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); + switch(subHandle_data->src.srcSelect.ToBE()) + { + case se32(CELL_JPGDEC_BUFFER): + if (!Memory.Copy(buffer.GetAddr(), subHandle_data->src.streamPtr.ToLE(), buffer.GetSize())) { + cellJpgDec->Error("cellJpgDecReadHeader() failed ()"); + return CELL_EFAULT; + } + break; + + case se32(CELL_JPGDEC_FILE): + cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); + cellFsRead(fd, buffer.GetAddr(), buffer.GetSize(), nread); + break; + } if (*buffer.To(0) != 0xE0FFD8FF || // Error: Not a valid SOI header *buffer.To(6) != 0x4649464A) // Error: Not a valid JFIF string @@ -146,8 +170,21 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m //Copy the JPG file to a buffer MemoryAllocator jpg(fileSize); MemoryAllocator pos, nread; - cellFsLseek(fd, 0, CELL_SEEK_SET, pos); - cellFsRead(fd, jpg.GetAddr(), jpg.GetSize(), nread); + + switch(subHandle_data->src.srcSelect.ToBE()) + { + case se32(CELL_JPGDEC_BUFFER): + if (!Memory.Copy(jpg.GetAddr(), subHandle_data->src.streamPtr.ToLE(), jpg.GetSize())) { + cellJpgDec->Error("cellJpgDecDecodeData() failed (I)"); + return CELL_EFAULT; + } + break; + + case se32(CELL_JPGDEC_FILE): + cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); + cellFsRead(fd, jpg.GetAddr(), jpg.GetSize(), nread); + break; + } //Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.h b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.h index 207dc0a7c2..4fa1438385 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.h @@ -27,6 +27,12 @@ enum CellJpgDecColorSpace CELL_JPG_GRAYSCALE_TO_ALPHA_ARGB = 41, }; +enum CellJpgDecStreamSrcSel +{ + CELL_JPGDEC_FILE = 0, + CELL_JPGDEC_BUFFER = 1, +}; + enum CellJpgDecDecodeStatus { CELL_JPGDEC_DEC_STATUS_FINISH = 0, //Decoding finished @@ -92,10 +98,12 @@ struct CellJpgDecDataOutInfo be_t status; }; -struct CellJpgDecSubHandle //Custom struct +// Custom structs +struct CellJpgDecSubHandle { u32 fd; u64 fileSize; CellJpgDecInfo info; CellJpgDecOutParam outParam; -}; \ No newline at end of file + CellJpgDecSrc src; +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1b7e153a4c..adb503a8d3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -60,7 +60,6 @@ int cellPngDecOpen(u32 mainHandle, mem32_t subHandle, mem_ptr_t s return CELL_PNGDEC_ERROR_ARG; CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle; - current_subHandle->fd = 0; current_subHandle->src = *src; @@ -212,16 +211,16 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const m MemoryAllocator png(fileSize); MemoryAllocator pos, nread; - switch(subHandle_data->src.srcSelect.ToLE()) + switch(subHandle_data->src.srcSelect.ToBE()) { - case CELL_PNGDEC_BUFFER: - if (!Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize())) - { + case se32(CELL_PNGDEC_BUFFER): + if (!Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize())) { cellPngDec->Error("cellPngDecDecodeData() failed (I)"); return CELL_EFAULT; } break; - case CELL_PNGDEC_FILE: + + case se32(CELL_PNGDEC_FILE): cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); cellFsRead(fd, png.GetAddr(), png.GetSize(), nread.GetAddr()); break; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index b93f82ba8e..271e1e837f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -49,6 +49,7 @@ enum CellPngDecOutputMode CELL_PNGDEC_BOTTOM_TO_TOP = 1, }; + // Structs struct CellPngDecDataOutInfo { @@ -108,23 +109,6 @@ struct CellPngDecOutParam be_t useMemorySpace; }; -//Custom structs -struct CellPngDecSubHandle -{ - be_t fd; - be_t fileSize; - CellPngDecInfo info; - CellPngDecOutParam outParam; - CellPngDecSrc src; -}; - -struct CellPngDecMainHandle -{ - be_t mainHandle; - be_t threadInParam; - be_t threadOutParam; -}; - struct CellPngDecStrmInfo { be_t decodedStrmSize; @@ -174,4 +158,22 @@ struct CellPngDecExtOutParam struct CellPngDecOpnParam { be_t selectChunk; -}; \ No newline at end of file +}; + + +// Custom structs +struct CellPngDecSubHandle +{ + be_t fd; + be_t fileSize; + CellPngDecInfo info; + CellPngDecOutParam outParam; + CellPngDecSrc src; +}; + +struct CellPngDecMainHandle +{ + be_t mainHandle; + be_t threadInParam; + be_t threadOutParam; +};