mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-20 22:05:12 +00:00
cellGifDec Module Added
*Implemented 'cellGifDec', using 'sys_fs' to access the files and the 'stb_image' (stblib) library to decode GIF buffers to Raw-pixel buffers that can be used as textures. *Replace 'lodepng' and 'jpeg-compressor' libraries with 'stb_image' in cellPngDec and cellJpgDec, respectively. *Fixed minor issues in cellPngDec and cellJpgDec.
This commit is contained in:
parent
0275b430cf
commit
aea7f4aa77
12 changed files with 4979 additions and 11510 deletions
206
rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp
Normal file
206
rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/SC_FUNC.h"
|
||||
|
||||
#include "stblib/stb_image.h"
|
||||
#include "stblib/stb_image.c" // (TODO: Should we put this elsewhere?)
|
||||
|
||||
void cellGifDec_init();
|
||||
Module cellGifDec(0xf010, cellGifDec_init);
|
||||
|
||||
//Return Codes
|
||||
enum
|
||||
{
|
||||
CELL_GIFDEC_ERROR_OPEN_FILE = 0x80611300,
|
||||
CELL_GIFDEC_ERROR_STREAM_FORMAT = 0x80611301,
|
||||
CELL_GIFDEC_ERROR_SEQ = 0x80611302,
|
||||
CELL_GIFDEC_ERROR_ARG = 0x80611303,
|
||||
CELL_GIFDEC_ERROR_FATAL = 0x80611304,
|
||||
CELL_GIFDEC_ERROR_SPU_UNSUPPORT = 0x80611305,
|
||||
CELL_GIFDEC_ERROR_SPU_ERROR = 0x80611306,
|
||||
CELL_GIFDEC_ERROR_CB_PARAM = 0x80611307,
|
||||
};
|
||||
|
||||
struct CellGifDecInfo
|
||||
{
|
||||
u32 SWidth;
|
||||
u32 SHeight;
|
||||
u32 SGlobalColorTableFlag;
|
||||
u32 SColorResolution;
|
||||
u32 SSortFlag;
|
||||
u32 SSizeOfGlobalColorTable;
|
||||
u32 SBackGroundColor;
|
||||
u32 SPixelAspectRatio;
|
||||
};
|
||||
|
||||
struct CellGifDecSrc
|
||||
{
|
||||
u32 srcSelect; // CellGifDecStreamSrcSel
|
||||
u32 fileName; // const char*
|
||||
u64 fileOffset; // int64_t
|
||||
u32 fileSize;
|
||||
u32 streamPtr;
|
||||
u32 streamSize;
|
||||
u32 spuThreadEnable; // CellGifDecSpuThreadEna
|
||||
};
|
||||
|
||||
CellGifDecInfo current_info;
|
||||
CellGifDecSrc current_src;
|
||||
|
||||
|
||||
int cellGifDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGifDec);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGifDec);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecOpen(u32 mainHandle, u32 subHandle_addr, u32 src_addr, u32 openInfo)
|
||||
{
|
||||
//current_src.srcSelect = Memory.Read32(src_addr);
|
||||
current_src.fileName = Memory.Read32(src_addr+4);
|
||||
//current_src.fileOffset = Memory.Read32(src_addr+8);
|
||||
//current_src.fileSize = Memory.Read32(src_addr+12);
|
||||
//current_src.streamPtr = Memory.Read32(src_addr+16);
|
||||
//current_src.streamSize = Memory.Read32(src_addr+20);
|
||||
//current_src.spuThreadEnable = Memory.Read32(src_addr+24);
|
||||
|
||||
u32& fd_addr = subHandle_addr; // Set file descriptor as sub handler of the decoder
|
||||
int ret = cellFsOpen(current_src.fileName, 0, fd_addr, NULL, 0);
|
||||
if(ret != 0) return CELL_GIFDEC_ERROR_OPEN_FILE;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
||||
{
|
||||
u32& fd = subHandle;
|
||||
|
||||
//Check size of file
|
||||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
|
||||
//Write the header to buffer
|
||||
u32 buffer = Memory.Alloc(13,1); // Alloc buffer for GIF header
|
||||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, 13, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
if (Memory.Read32(buffer) != 0x47494638 ||
|
||||
(Memory.Read16(buffer+4) != 0x3961 &&
|
||||
Memory.Read16(buffer+4) != 0x3761)) // Error: The first 6 bytes are not a valid GIF signature
|
||||
{
|
||||
Memory.Free(buffer);
|
||||
return CELL_GIFDEC_ERROR_STREAM_FORMAT; // Surprisingly there is no error code related with headerss
|
||||
}
|
||||
|
||||
u8 packedField = Memory.Read8(buffer+10);
|
||||
current_info.SWidth = Memory.Read8(buffer+6) + Memory.Read8(buffer+7) * 256;
|
||||
current_info.SHeight = Memory.Read8(buffer+8) + Memory.Read8(buffer+9) * 256;
|
||||
current_info.SGlobalColorTableFlag = packedField >> 7;
|
||||
current_info.SColorResolution = (packedField >> 4) & 7;
|
||||
current_info.SSortFlag = (packedField >> 3) & 1;
|
||||
current_info.SSizeOfGlobalColorTable = packedField & 7;
|
||||
current_info.SBackGroundColor = Memory.Read8(buffer+11);
|
||||
current_info.SPixelAspectRatio = Memory.Read8(buffer+12);
|
||||
|
||||
mem_class_t info(info_addr);
|
||||
info += current_info.SWidth;
|
||||
info += current_info.SHeight;
|
||||
info += current_info.SGlobalColorTableFlag;
|
||||
info += current_info.SColorResolution;
|
||||
info += current_info.SSortFlag;
|
||||
info += current_info.SSizeOfGlobalColorTable;
|
||||
info += current_info.SBackGroundColor;
|
||||
info += current_info.SPixelAspectRatio;
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecSetParameter(u32 mainHandle, u32 subHandle, u32 inParam, u32 outParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGifDec);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataCtrlParam_addr, u32 dataOutInfo_addr)
|
||||
{
|
||||
u32& fd = subHandle;
|
||||
|
||||
//Get size of file
|
||||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
|
||||
//Copy the GIF file to a buffer
|
||||
u32 buffer = Memory.Alloc(fileSize,1);
|
||||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, fileSize, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
//Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
|
||||
int width, height, actual_components;
|
||||
unsigned char *gif = new unsigned char [fileSize];
|
||||
for(u32 i = 0; i < fileSize; i++){
|
||||
gif[i] = Memory.Read8(buffer+i);
|
||||
}
|
||||
|
||||
unsigned char *image = stbi_load_from_memory((const unsigned char*)gif, fileSize, &width, &height, &actual_components, 4);
|
||||
if (!image)
|
||||
{
|
||||
Memory.Free(buffer);
|
||||
return CELL_GIFDEC_ERROR_STREAM_FORMAT;
|
||||
}
|
||||
u32 image_size = width * height * 4;
|
||||
for(u32 i = 0; i < image_size; i+=4){
|
||||
Memory.Write8(data_addr+i+0, image[i+3]);
|
||||
Memory.Write8(data_addr+i+1, image[i+0]);
|
||||
Memory.Write8(data_addr+i+2, image[i+1]);
|
||||
Memory.Write8(data_addr+i+3, image[i+2]);
|
||||
}
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecClose(u32 mainHandle, u32 subHandle)
|
||||
{
|
||||
u32& fd = subHandle;
|
||||
cellFsClose(fd);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellGifDecDestroy(u32 mainHandle)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellGifDec);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void cellGifDec_init()
|
||||
{
|
||||
cellGifDec.AddFunc(0xb60d42a5, cellGifDecCreate);
|
||||
cellGifDec.AddFunc(0x4711cb7f, cellGifDecExtCreate);
|
||||
cellGifDec.AddFunc(0x75745079, cellGifDecOpen);
|
||||
cellGifDec.AddFunc(0xf0da95de, cellGifDecReadHeader);
|
||||
cellGifDec.AddFunc(0x41a90dc4, cellGifDecSetParameter);
|
||||
cellGifDec.AddFunc(0x44b1bc61, cellGifDecDecodeData);
|
||||
cellGifDec.AddFunc(0x116a7da9, cellGifDecClose);
|
||||
cellGifDec.AddFunc(0xe74b2cb1, cellGifDecDestroy);
|
||||
|
||||
/*cellGifDec.AddFunc(0x17fb83c1, cellGifDecExtOpen);
|
||||
cellGifDec.AddFunc(0xe53f91f2, cellGifDecExtReadHeader);
|
||||
cellGifDec.AddFunc(0x95cae771, cellGifDecExtSetParameter);
|
||||
cellGifDec.AddFunc(0x02e7e03e, cellGifDecExtDecodeData);*/
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/SC_FUNC.h"
|
||||
|
||||
#include "jpeg-compressor/jpgd.cpp"
|
||||
#include "stblib/stb_image.h"
|
||||
|
||||
void cellJpgDec_init();
|
||||
Module cellJpgDec(0x000f, cellJpgDec_init);
|
||||
|
|
@ -50,7 +50,7 @@ int cellJpgDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellJpgDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam)
|
||||
int cellJpgDecExtCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam, u32 extThreadInParam, u32 extThreadOutParam)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(cellJpgDec);
|
||||
return CELL_OK;
|
||||
|
|
@ -95,18 +95,18 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
|
||||
//Copy the JPG file to a buffer
|
||||
u32 buffer = Memory.Alloc(fileSize,1);
|
||||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, fileSize, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
if (Memory.Read32(buffer) != 0xFFD8FFE0 || // Error: Not a valid SOI header
|
||||
Memory.Read32(buffer+6) != 0x4A464946) // Error: Not a valid JFIF string
|
||||
{
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
return CELL_JPGDEC_ERROR_HEADER;
|
||||
}
|
||||
|
|
@ -116,9 +116,17 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
while(i < fileSize)
|
||||
{
|
||||
i += block_length; // Increase the file index to get to the next block
|
||||
if (i >= fileSize) return CELL_JPGDEC_ERROR_HEADER; // Check to protect against segmentation faults
|
||||
if(Memory.Read8(buffer+i) != 0xFF) return CELL_JPGDEC_ERROR_HEADER; // Check that we are truly at the start of another block
|
||||
if(Memory.Read8(buffer+i+1) == 0xC0) break; // 0xFFC0 is the "Start of frame" marker which contains the file size
|
||||
if (i >= fileSize){
|
||||
Memory.Free(buffer);
|
||||
return CELL_JPGDEC_ERROR_HEADER; // Check to protect against segmentation faults
|
||||
}
|
||||
if(Memory.Read8(buffer+i) != 0xFF){
|
||||
Memory.Free(buffer);
|
||||
return CELL_JPGDEC_ERROR_HEADER; // Check that we are truly at the start of another block
|
||||
}
|
||||
if(Memory.Read8(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 = Memory.Read8(buffer+i)*0xFF + Memory.Read8(buffer+i+1); // Go to the next block
|
||||
}
|
||||
|
|
@ -133,9 +141,6 @@ int cellJpgDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
info += current_info.imageHeight;
|
||||
info += current_info.numComponents;
|
||||
info += current_info.colorSpace;
|
||||
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
|
|
@ -149,20 +154,28 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC
|
|||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
|
||||
//Copy the JPG file to a buffer
|
||||
u32 buffer = Memory.Alloc(fileSize,1);
|
||||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, fileSize, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
//Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
|
||||
int width, height, actual_components;
|
||||
unsigned char *jpg = new unsigned char [fileSize];
|
||||
for(u32 i = 0; i < fileSize; i++){
|
||||
jpg[i] = Memory.Read8(buffer+i);
|
||||
}
|
||||
|
||||
unsigned char *image = jpgd::decompress_jpeg_image_from_memory((const unsigned char*)jpg, fileSize, &width, &height, &actual_components, 4);
|
||||
unsigned char *image = stbi_load_from_memory((const unsigned char*)jpg, fileSize, &width, &height, &actual_components, 4);
|
||||
if (!image)
|
||||
{
|
||||
Memory.Free(buffer);
|
||||
return CELL_JPGDEC_ERROR_STREAM_FORMAT;
|
||||
}
|
||||
u32 image_size = width * height * 4;
|
||||
for(u32 i = 0; i < image_size; i+=4){
|
||||
Memory.Write8(data_addr+i+0, image[i+3]);
|
||||
|
|
@ -170,9 +183,6 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC
|
|||
Memory.Write8(data_addr+i+2, image[i+1]);
|
||||
Memory.Write8(data_addr+i+3, image[i+2]);
|
||||
}
|
||||
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/SC_FUNC.h"
|
||||
|
||||
#include "lodepng/lodepng.cpp"
|
||||
#include "stblib/stb_image.h"
|
||||
|
||||
void cellPngDec_init();
|
||||
Module cellPngDec(0x0018, cellPngDec_init);
|
||||
|
|
@ -93,6 +93,7 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
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
|
||||
|
|
@ -100,13 +101,12 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, 34, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
if (Memory.Read32(buffer) != 0x89504E47 ||
|
||||
Memory.Read32(buffer+4) != 0x0D0A1A0A || // Error: The first 8 bytes are not a valid PNG signature
|
||||
Memory.Read32(buffer+12) != 0x49484452) // Error: The PNG file does not start with an IHDR chunk
|
||||
{
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
return CELL_PNGDEC_ERROR_HEADER;
|
||||
}
|
||||
|
|
@ -127,9 +127,6 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, u32 info_addr)
|
|||
info += current_info.bitDepth;
|
||||
info += current_info.interlaceMethod;
|
||||
info += current_info.chunkInformation;
|
||||
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
|
|
@ -143,44 +140,35 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC
|
|||
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
||||
cellFsFstat(fd, sb_addr);
|
||||
u64 fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
||||
Memory.Free(sb_addr);
|
||||
|
||||
//Copy the PNG file to a buffer
|
||||
u32 buffer = Memory.Alloc(fileSize,1); // Alloc buffer for PNG header
|
||||
u32 buffer = Memory.Alloc(fileSize,1);
|
||||
u32 pos_addr = Memory.Alloc(8,1);
|
||||
cellFsLseek(fd, 0, 0, pos_addr);
|
||||
cellFsRead(fd, buffer, fileSize, NULL);
|
||||
Memory.Free(pos_addr);
|
||||
|
||||
//Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
|
||||
std::vector<unsigned char> png; // PNG buffer
|
||||
std::vector<unsigned char> image; // Raw buffer
|
||||
|
||||
//Load contents in png buffer
|
||||
png.resize(size_t(fileSize));
|
||||
int width, height, actual_components;
|
||||
unsigned char *png = new unsigned char [fileSize];
|
||||
for(u32 i = 0; i < fileSize; i++){
|
||||
png[i] = Memory.Read8(buffer+i);
|
||||
}
|
||||
|
||||
//Decode
|
||||
unsigned width, height;
|
||||
unsigned error = lodepng::decode(image, width, height, png);
|
||||
if (error)
|
||||
|
||||
unsigned char *image = stbi_load_from_memory((const unsigned char*)png, fileSize, &width, &height, &actual_components, 4);
|
||||
if (!image)
|
||||
{
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
return CELL_PNGDEC_ERROR_STREAM_FORMAT;
|
||||
}
|
||||
|
||||
u32 image_size = image.size();
|
||||
u32 image_size = width * height * 4;
|
||||
for(u32 i = 0; i < image_size; i+=4){
|
||||
Memory.Write8(data_addr+i+0, image[i+3]);
|
||||
Memory.Write8(data_addr+i+1, image[i+0]);
|
||||
Memory.Write8(data_addr+i+2, image[i+1]);
|
||||
Memory.Write8(data_addr+i+3, image[i+2]);
|
||||
}
|
||||
|
||||
Memory.Free(sb_addr);
|
||||
Memory.Free(pos_addr);
|
||||
Memory.Free(buffer);
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue