mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
* Improved image decoding modules:
- Fixed error that appeared after last commit (eebe859f83).
- Changed some functions to use the mem*_t classes.
- Implemented cell*DecSetParameter.
* Created new dummy modules for sys_net (0x0000), sys_http (0x0001),
cellHttpUtil (0x0002) and cellSsl (0x0003).
277 lines
8.7 KiB
C++
277 lines
8.7 KiB
C++
#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,
|
|
};
|
|
|
|
enum CellGifDecColorSpace
|
|
{
|
|
CELL_GIFDEC_RGBA = 10,
|
|
CELL_GIFDEC_ARGB = 20,
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
struct CellGifDecInParam
|
|
{
|
|
u32 *commandPtr;
|
|
u32 colorSpace; // CellGifDecColorSpace
|
|
u8 outputColorAlpha1;
|
|
u8 outputColorAlpha2;
|
|
u8 reserved[2];
|
|
};
|
|
|
|
struct CellGifDecOutParam
|
|
{
|
|
u64 outputWidthByte;
|
|
u32 outputWidth;
|
|
u32 outputHeight;
|
|
u32 outputComponents;
|
|
u32 outputBitDepth;
|
|
u32 outputColorSpace; // CellGifDecColorSpace
|
|
u32 useMemorySpace;
|
|
};
|
|
|
|
struct CellGifDecSubHandle //Custom struct
|
|
{
|
|
u32 fd;
|
|
u64 fileSize;
|
|
CellGifDecInfo info;
|
|
CellGifDecOutParam outParam;
|
|
};
|
|
|
|
|
|
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, mem32_t subHandle, u32 src_addr, u32 openInfo)
|
|
{
|
|
//u32 srcSelect = Memory.Read32(src_addr);
|
|
u32 fileName = Memory.Read32(src_addr+4);
|
|
//u64 fileOffset = Memory.Read32(src_addr+8);
|
|
//u32 fileSize = Memory.Read32(src_addr+12);
|
|
//u32 streamPtr = Memory.Read32(src_addr+16);
|
|
//u32 streamSize = Memory.Read32(src_addr+20);
|
|
//u32 spuThreadEnable = Memory.Read32(src_addr+24);
|
|
|
|
CellGifDecSubHandle *current_subHandle = new CellGifDecSubHandle;
|
|
|
|
// Get file descriptor
|
|
u32 fd_addr = Memory.Alloc(sizeof(u32), 1);
|
|
int ret = cellFsOpen(fileName, 0, fd_addr, NULL, 0);
|
|
current_subHandle->fd = Memory.Read32(fd_addr);
|
|
Memory.Free(fd_addr);
|
|
if(ret != 0) return CELL_GIFDEC_ERROR_OPEN_FILE;
|
|
|
|
// Get size of file
|
|
u32 sb_addr = Memory.Alloc(52,1); // Alloc a CellFsStat struct
|
|
cellFsFstat(current_subHandle->fd, sb_addr);
|
|
current_subHandle->fileSize = Memory.Read64(sb_addr+36); // Get CellFsStat.st_size
|
|
Memory.Free(sb_addr);
|
|
|
|
// From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct.
|
|
subHandle += (u32)current_subHandle;
|
|
|
|
return CELL_OK;
|
|
}
|
|
|
|
int cellGifDecReadHeader(u32 mainHandle, u32 subHandle, mem_class_t info)
|
|
{
|
|
const u32& fd = ((CellGifDecSubHandle*)subHandle)->fd;
|
|
const u64& fileSize = ((CellGifDecSubHandle*)subHandle)->fileSize;
|
|
CellGifDecInfo& current_info = ((CellGifDecSubHandle*)subHandle)->info;
|
|
|
|
//Write the header to buffer
|
|
u32 buffer = Memory.Alloc(13,1); // Alloc buffer for GIF header
|
|
u32 nread = Memory.Alloc(8,1);
|
|
u32 pos_addr = Memory.Alloc(8,1);
|
|
cellFsLseek(fd, 0, 0, pos_addr);
|
|
cellFsRead(fd, buffer, 13, nread);
|
|
Memory.Free(nread);
|
|
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)+1;
|
|
current_info.SSortFlag = (packedField >> 3) & 1;
|
|
current_info.SSizeOfGlobalColorTable = (packedField & 7)+1;
|
|
current_info.SBackGroundColor = Memory.Read8(buffer+11);
|
|
current_info.SPixelAspectRatio = Memory.Read8(buffer+12);
|
|
|
|
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_addr, mem_class_t outParam)
|
|
{
|
|
CellGifDecInfo& current_info = ((CellGifDecSubHandle*)subHandle)->info;
|
|
CellGifDecOutParam& current_outParam = ((CellGifDecSubHandle*)subHandle)->outParam;
|
|
|
|
current_outParam.outputWidthByte = (current_info.SWidth * current_info.SColorResolution * 3)/8;
|
|
current_outParam.outputWidth = current_info.SWidth;
|
|
current_outParam.outputHeight = current_info.SHeight;
|
|
current_outParam.outputColorSpace = Memory.Read32(inParam_addr+4);
|
|
switch (current_outParam.outputColorSpace)
|
|
{
|
|
case CELL_GIFDEC_RGBA: current_outParam.outputComponents = 4; break;
|
|
case CELL_GIFDEC_ARGB: current_outParam.outputComponents = 4; break;
|
|
default: return CELL_GIFDEC_ERROR_ARG; // Not supported color space
|
|
}
|
|
current_outParam.outputBitDepth = 0; // Unimplemented
|
|
current_outParam.useMemorySpace = 0; // Unimplemented
|
|
|
|
outParam += current_outParam.outputWidthByte;
|
|
outParam += current_outParam.outputWidth;
|
|
outParam += current_outParam.outputHeight;
|
|
outParam += current_outParam.outputComponents;
|
|
outParam += current_outParam.outputBitDepth;
|
|
outParam += current_outParam.outputColorSpace;
|
|
outParam += current_outParam.useMemorySpace;
|
|
|
|
return CELL_OK;
|
|
}
|
|
|
|
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, u32 dataCtrlParam_addr, mem_class_t dataOutInfo)
|
|
{
|
|
const u32& fd = ((CellGifDecSubHandle*)subHandle)->fd;
|
|
const u64& fileSize = ((CellGifDecSubHandle*)subHandle)->fileSize;
|
|
const CellGifDecOutParam& current_outParam = ((CellGifDecSubHandle*)subHandle)->outParam; // (TODO: We should use the outParam)
|
|
|
|
//Copy the GIF file to a buffer
|
|
u32 buffer = Memory.Alloc(fileSize,1);
|
|
u32 nread = Memory.Alloc(8,1);
|
|
u32 pos_addr = Memory.Alloc(8,1);
|
|
cellFsLseek(fd, 0, 0, pos_addr);
|
|
cellFsRead(fd, buffer, fileSize, nread);
|
|
Memory.Free(nread);
|
|
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 = (unsigned char*)Memory.VirtualToRealAddr(buffer);
|
|
unsigned char *image = stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4);
|
|
Memory.Free(buffer);
|
|
if (!image) return CELL_GIFDEC_ERROR_STREAM_FORMAT;
|
|
|
|
u32 image_size = width * height * 4;
|
|
if (current_outParam.outputColorSpace == CELL_GIFDEC_RGBA){
|
|
for(u32 i = 0; i < image_size; i+=4){
|
|
data += image[i+0];
|
|
data += image[i+1];
|
|
data += image[i+2];
|
|
data += image[i+3];
|
|
}
|
|
}
|
|
if (current_outParam.outputColorSpace == CELL_GIFDEC_ARGB){
|
|
for(u32 i = 0; i < image_size; i+=4){
|
|
data += image[i+3];
|
|
data += image[i+0];
|
|
data += image[i+1];
|
|
data += image[i+2];
|
|
}
|
|
}
|
|
delete[] image;
|
|
|
|
dataOutInfo += (u32)1; // The output data is an image (dataOutInfo.recordType = 1)
|
|
dataOutInfo += (u32)0; // outExtension.label = 0
|
|
dataOutInfo += Memory.Alloc(20,1); // outExtension.data allocated (TODO: Is this the best way to avoid exceptions when trying to access this data? Will this produce a memory leak?)
|
|
|
|
return CELL_OK;
|
|
}
|
|
|
|
int cellGifDecClose(u32 mainHandle, u32 subHandle)
|
|
{
|
|
cellFsClose( ((CellGifDecSubHandle*)subHandle)->fd );
|
|
delete (CellGifDecSubHandle*)subHandle;
|
|
|
|
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);*/
|
|
} |