diff --git a/rpcs3/Emu/Cell/Modules/cellGifDec.cpp b/rpcs3/Emu/Cell/Modules/cellGifDec.cpp index 5d00f1074..2a32c9bf6 100644 --- a/rpcs3/Emu/Cell/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGifDec.cpp @@ -39,61 +39,134 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } -// cellGifDec aliases (only for cellGifDec.cpp) -using PPMainHandle = vm::pptr; -using PMainHandle = vm::ptr; -using PThreadInParam = vm::cptr; -using PThreadOutParam = vm::ptr; -using PExtThreadInParam = vm::cptr; -using PExtThreadOutParam = vm::ptr; -using PPSubHandle = vm::pptr; -using PSubHandle = vm::ptr; -using PSrc = vm::cptr; -using POpenInfo = vm::ptr; -using PInfo = vm::ptr; -using PInParam = vm::cptr; -using POutParam = vm::ptr; -using PDataCtrlParam = vm::cptr; -using PDataOutInfo = vm::ptr; - -error_code cellGifDecCreate(PPMainHandle mainHandle, PThreadInParam threadInParam, PThreadOutParam threadOutParam) +error_code cellGifDecCreate(vm::ptr mainHandle, vm::cptr threadInParam, vm::ptr threadOutParam) { - UNIMPLEMENTED_FUNC(cellGifDec); + cellGifDec.todo("cellGifDecCreate(mainHandle=*0x%x, threadInParam=*0x%x, threadOutParam=*0x%x)", mainHandle, threadInParam, threadOutParam); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + *mainHandle = {}; + + if (!threadOutParam || !threadInParam || !threadInParam->cbCtrlMallocFunc || !threadInParam->cbCtrlFreeFunc || + (threadInParam->spuThreadEnable != CELL_GIFDEC_SPU_THREAD_DISABLE && + (threadInParam->spuThreadEnable != CELL_GIFDEC_SPU_THREAD_ENABLE || + threadInParam->ppuThreadPriority > 3071 || + threadInParam->spuThreadPriority > 255))) + { + return CELL_GIFDEC_ERROR_ARG; + } + + threadOutParam->gifCodecVersion = 0x240000; + return CELL_OK; } -error_code cellGifDecExtCreate(PPMainHandle mainHandle, PThreadInParam threadInParam, PThreadOutParam threadOutParam, PExtThreadInParam extThreadInParam, PExtThreadOutParam extThreadOutParam) +error_code cellGifDecExtCreate(vm::ptr mainHandle, vm::cptr threadInParam, vm::ptr threadOutParam, vm::cptr extThreadInParam, vm::ptr extThreadOutParam) { - UNIMPLEMENTED_FUNC(cellGifDec); + cellGifDec.todo("cellGifDecExtCreate(mainHandle=*0x%x, threadInParam=*0x%x, threadOutParam=*0x%x, extThreadInParam=*0x%x, extThreadOutParam=*0x%x)", mainHandle, threadInParam, threadOutParam, extThreadInParam, extThreadOutParam); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + *mainHandle = {}; + + if (!threadOutParam || !extThreadOutParam || !extThreadInParam || !threadInParam || !threadInParam->cbCtrlMallocFunc || !threadInParam->cbCtrlFreeFunc || + (threadInParam->spuThreadEnable != CELL_GIFDEC_SPU_THREAD_DISABLE && threadInParam->spuThreadEnable != CELL_GIFDEC_SPU_THREAD_ENABLE)) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (threadInParam->spuThreadEnable == CELL_GIFDEC_SPU_THREAD_ENABLE && !extThreadInParam->spurs) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (extThreadInParam->maxContention == 0 || extThreadInParam->maxContention >= 8) + { + return CELL_GIFDEC_ERROR_ARG; + } + + for (u32 i = 0; i < 8; i++) + { + if (extThreadInParam->priority[i] > 15) + { + return CELL_GIFDEC_ERROR_ARG; + } + } + + threadOutParam->gifCodecVersion = 0x240000; + return CELL_OK; } -error_code cellGifDecOpen(PMainHandle mainHandle, PPSubHandle subHandle, PSrc src, POpenInfo openInfo) +error_code cellGifDecOpen(vm::ptr mainHandle, vm::pptr subHandle, vm::cptr src, vm::ptr openInfo) { cellGifDec.warning("cellGifDecOpen(mainHandle=*0x%x, subHandle=**0x%x, src=*0x%x, openInfo=*0x%x)", mainHandle, subHandle, src, openInfo); - GifStream current_subHandle; + if (!mainHandle || !subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!openInfo || !src) + { + return CELL_GIFDEC_ERROR_ARG; + } + + GifStream current_subHandle{}; current_subHandle.fd = 0; current_subHandle.src = *src; switch (src->srcSelect) { case CELL_GIFDEC_BUFFER: + { + if (!src->streamPtr || !src->streamSize) + { + return CELL_GIFDEC_ERROR_ARG; + } + current_subHandle.fileSize = src->streamSize; break; - + } case CELL_GIFDEC_FILE: { + if (!src->fileName) + { + return CELL_GIFDEC_ERROR_OPEN_FILE; + } + // Get file descriptor and size - const auto real_path = vfs::get(src->fileName.get_ptr()); + const std::string real_path = vfs::get(src->fileName.get_ptr()); fs::file file_s(real_path); - if (!file_s) return CELL_GIFDEC_ERROR_OPEN_FILE; + if (!file_s) + { + return CELL_GIFDEC_ERROR_OPEN_FILE; + } + + if (src->fileOffset < 0) + { + return CELL_GIFDEC_ERROR_ARG; + } current_subHandle.fileSize = file_s.size(); current_subHandle.fd = idm::make(src->fileName.get_ptr(), std::move(file_s), 0, 0, real_path); break; } - default: break; // TODO + default: + { + return CELL_GIFDEC_ERROR_ARG; + } } subHandle->set(vm::alloc(sizeof(GifStream), vm::main)); @@ -103,16 +176,103 @@ error_code cellGifDecOpen(PMainHandle mainHandle, PPSubHandle subHandle, PSrc sr return CELL_OK; } -error_code cellGifDecExtOpen() +error_code cellGifDecExtOpen(vm::ptr mainHandle, vm::pptr subHandle, vm::cptr src, vm::ptr openInfo, vm::cptr cbCtrlStrm) { - cellGifDec.todo("cellGifDecExtOpen()"); + cellGifDec.todo("cellGifDecExtOpen(mainHandle=*0x%x, subHandle=*0x%x, src=*0x%x, openInfo=*0x%x, cbCtrlStrm=*0x%x)", mainHandle, subHandle, src, openInfo, cbCtrlStrm); + + if (!mainHandle || !subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!openInfo || !src) + { + return CELL_GIFDEC_ERROR_ARG; + } + + GifStream current_subHandle{}; + current_subHandle.fd = 0; + current_subHandle.src = *src; + + switch (src->srcSelect) + { + case CELL_GIFDEC_BUFFER: + { + if (!src->streamPtr || !src->streamSize) + { + return CELL_GIFDEC_ERROR_ARG; + } + + current_subHandle.fileSize = src->streamSize; + break; + } + case CELL_GIFDEC_FILE: + { + if (!src->fileName) + { + return CELL_GIFDEC_ERROR_OPEN_FILE; + } + + // Get file descriptor and size + const std::string real_path = vfs::get(src->fileName.get_ptr()); + fs::file file_s(real_path); + if (!file_s) + { + return CELL_GIFDEC_ERROR_OPEN_FILE; + } + + if (src->fileOffset < 0) + { + return CELL_GIFDEC_ERROR_ARG; + } + + current_subHandle.fileSize = file_s.size(); + current_subHandle.fd = idm::make(src->fileName.get_ptr(), std::move(file_s), 0, 0, real_path); + break; + } + default: + { + return CELL_GIFDEC_ERROR_ARG; + } + } + return CELL_OK; } -error_code cellGifDecReadHeader(PMainHandle mainHandle, PSubHandle subHandle, PInfo info) +error_code cellGifDecReadHeader(vm::ptr mainHandle, vm::ptr subHandle, vm::ptr info) { cellGifDec.warning("cellGifDecReadHeader(mainHandle=*0x%x, subHandle=*0x%x, info=*0x%x)", mainHandle, subHandle, info); + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!info) + { + return CELL_GIFDEC_ERROR_ARG; + } + const u32& fd = subHandle->fd; CellGifDecInfo& current_info = subHandle->info; @@ -122,9 +282,10 @@ error_code cellGifDecReadHeader(PMainHandle mainHandle, PSubHandle subHandle, PI switch (subHandle->src.srcSelect) { case CELL_GIFDEC_BUFFER: + { std::memcpy(buffer, subHandle->src.streamPtr.get_ptr(), sizeof(buffer)); break; - + } case CELL_GIFDEC_FILE: { auto file = idm::get(fd); @@ -156,20 +317,71 @@ error_code cellGifDecReadHeader(PMainHandle mainHandle, PSubHandle subHandle, PI return CELL_OK; } -error_code cellGifDecExtReadHeader() +error_code cellGifDecExtReadHeader(vm::ptr mainHandle, vm::cptr subHandle, vm::ptr info, vm::ptr extInfo) { - cellGifDec.todo("cellGifDecExtReadHeader()"); + cellGifDec.todo("cellGifDecExtReadHeader(mainHandle=*0x%x, subHandle=*0x%x, info=*0x%x, extInfo=*0x%x)", mainHandle, subHandle, info, extInfo); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!info || !extInfo) + { + return CELL_GIFDEC_ERROR_ARG; + } + return CELL_OK; } -error_code cellGifDecSetParameter(PMainHandle mainHandle, PSubHandle subHandle, PInParam inParam, POutParam outParam) +error_code cellGifDecSetParameter(vm::ptr mainHandle, vm::ptr subHandle, vm::cptr inParam, vm::ptr outParam) { cellGifDec.warning("cellGifDecSetParameter(mainHandle=*0x%x, subHandle=*0x%x, inParam=*0x%x, outParam=*0x%x)", mainHandle, subHandle, inParam, outParam); + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!inParam || !outParam) + { + return CELL_GIFDEC_ERROR_ARG; + } + CellGifDecInfo& current_info = subHandle->info; CellGifDecOutParam& current_outParam = subHandle->outParam; - current_outParam.outputWidthByte = (current_info.SWidth * current_info.SColorResolution * 3)/8; + 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 = inParam->colorSpace; @@ -179,24 +391,98 @@ error_code cellGifDecSetParameter(PMainHandle mainHandle, PSubHandle subHandle, 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 + current_outParam.outputBitDepth = 0; // Unimplemented + current_outParam.useMemorySpace = 0; // Unimplemented *outParam = current_outParam; return CELL_OK; } -error_code cellGifDecExtSetParameter() +error_code cellGifDecExtSetParameter(vm::ptr mainHandle, vm::ptr subHandle, vm::cptr inParam, vm::ptr outParam, vm::cptr extInParam, vm::ptr extOutParam) { - cellGifDec.todo("cellGifDecExtSetParameter()"); + cellGifDec.todo("cellGifDecExtSetParameter(mainHandle=*0x%x, subHandle=*0x%x, inParam=*0x%x, outParam=*0x%x, extInParam=*0x%x, extOutParam=*0x%x)", mainHandle, subHandle, inParam, outParam, extInParam, extOutParam); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!inParam || !outParam) + { + return CELL_GIFDEC_ERROR_ARG; + } + + CellGifDecInfo& current_info = subHandle->info; + CellGifDecOutParam& current_outParam = 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 = inParam->colorSpace; + switch (current_outParam.outputColorSpace) + { + case CELL_GIFDEC_RGBA: + 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; + + if (!extInParam || extInParam->bufferMode != CELL_GIFDEC_LINE_MODE || !extOutParam) + { + return CELL_GIFDEC_ERROR_ARG; + } + return CELL_OK; } -error_code cellGifDecDecodeData(PMainHandle mainHandle, PSubHandle subHandle, vm::ptr data, PDataCtrlParam dataCtrlParam, PDataOutInfo dataOutInfo) +error_code cellGifDecDecodeData(vm::ptr mainHandle, vm::cptr subHandle, vm::ptr data, vm::cptr dataCtrlParam, vm::ptr dataOutInfo) { cellGifDec.warning("cellGifDecDecodeData(mainHandle=*0x%x, subHandle=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x)", mainHandle, subHandle, data, dataCtrlParam, dataOutInfo); + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!dataOutInfo || !dataCtrlParam) + { + return CELL_GIFDEC_ERROR_ARG; + } + dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP; const u32 fd = subHandle->fd; @@ -306,16 +592,57 @@ error_code cellGifDecDecodeData(PMainHandle mainHandle, PSubHandle subHandle, vm return CELL_OK; } -error_code cellGifDecExtDecodeData() +error_code cellGifDecExtDecodeData(vm::ptr mainHandle, vm::cptr subHandle, vm::ptr data, vm::cptr dataCtrlParam, vm::ptr dataOutInfo, vm::cptr cbCtrlDisp, vm::ptr dispParam) { - cellGifDec.todo("cellGifDecExtDecodeData()"); + cellGifDec.todo("cellGifDecExtDecodeData(mainHandle=*0x%x, subHandle=*0x%x, data=*0x%x, dataCtrlParam=*0x%x, dataOutInfo=*0x%x, cbCtrlDisp=*0x%x, dispParam=*0x%x)", mainHandle, subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check sub handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!dataOutInfo || !dataCtrlParam) + { + return CELL_GIFDEC_ERROR_ARG; + } + return CELL_OK; } -error_code cellGifDecClose(PMainHandle mainHandle, PSubHandle subHandle) +error_code cellGifDecClose(vm::ptr mainHandle, vm::cptr subHandle) { cellGifDec.warning("cellGifDecClose(mainHandle=*0x%x, subHandle=*0x%x)", mainHandle, subHandle); + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + + if (!subHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + idm::remove(subHandle->fd); vm::dealloc(subHandle.addr()); @@ -323,9 +650,20 @@ error_code cellGifDecClose(PMainHandle mainHandle, PSubHandle subHandle) return CELL_OK; } -error_code cellGifDecDestroy(PMainHandle mainHandle) +error_code cellGifDecDestroy(vm::ptr mainHandle) { - UNIMPLEMENTED_FUNC(cellGifDec); + cellGifDec.todo("cellGifDecDestroy(mainHandle=*0x%x)", mainHandle); + + if (!mainHandle) + { + return CELL_GIFDEC_ERROR_ARG; + } + + if (false) // TODO: check main handle + { + return CELL_GIFDEC_ERROR_SEQ; + } + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellGifDec.h b/rpcs3/Emu/Cell/Modules/cellGifDec.h index b760254a7..113ebcee9 100644 --- a/rpcs3/Emu/Cell/Modules/cellGifDec.h +++ b/rpcs3/Emu/Cell/Modules/cellGifDec.h @@ -52,6 +52,23 @@ enum CellGifDecDecodeStatus : s32 CELL_GIFDEC_DEC_STATUS_STOP = 1, // Decoding was stopped }; +enum CellGifDecBufferMode : s32 +{ + CELL_GIFDEC_LINE_MODE = 1 +}; + +enum CellGifDecSpuMode : s32 +{ + CELL_GIFDEC_RECEIVE_EVENT = 0, + CELL_GIFDEC_TRYRECEIVE_EVENT = 1 +}; + +enum CellGifDecInterlaceMode : s32 +{ + CELL_GIFDEC_NO_INTERLACE = 0, + CELL_GIFDEC_INTERLACE = 1 +}; + // Callbacks for memory management using CellGifDecCbControlMalloc = vm::ptr(u32 size, vm::ptr cbCtrlMallocArg); using CellGifDecCbControlFree = s32(vm::ptr ptr, vm::ptr cbCtrlFreeArg); @@ -151,6 +168,71 @@ struct CellGifDecDataCtrlParam be_t outputBytesPerLine; }; +struct CellGifDecExtInfo +{ + vm::bptr reserved; +}; + +struct CellGifDecStrmInfo +{ + be_t decodedStrmSize; +}; + +struct CellGifDecStrmParam +{ + vm::bptr strmPtr; + be_t strmSize; +}; + +using CellGifDecCbControlStream = s32(vm::ptr strmInfo, vm::ptr strmParam, vm::ptr cbCtrlStrmArg); + +struct CellGifDecCbCtrlStrm +{ + vm::bptr cbCtrlStrmFunc; + vm::bptr cbCtrlStrmArg; +}; + +struct CellGifDecExtInParam +{ + be_t bufferMode; // CellGifDecBufferMode + be_t outputCounts; + be_t spuMode; // CellGifDecSpuMode +}; + +struct CellGifDecExtOutParam +{ + be_t outputWidthByte; + be_t outputHeight; +}; + +struct CellGifDecDispParam +{ + vm::bptr nextOutputImage; +}; + +struct CellGifDecDispInfo +{ + be_t outputFrameWidthByte; + be_t outputFrameHeight; + be_t outputStartXByte; + be_t outputStartY; + be_t outputWidthByte; + be_t outputHeight; + be_t outputBitDepth; + be_t outputComponents; + be_t scanPassCount; + vm::bptr outputImage; + be_t interlaceFlag; // CellGifDecInterlaceMode +}; + +using CellGifDecCbControlDisp = s32(vm::ptr dispInfo, vm::ptr dispParam, vm::ptr cbCtrlDispArg); + +struct CellGifDecCbCtrlDisp +{ + vm::bptr cbCtrlDispFunc; + vm::bptr cbCtrlDispArg; +}; + // Custom structs struct GifDecoder { @@ -158,9 +240,9 @@ struct GifDecoder struct GifStream { - u32 fd; - u64 fileSize; - CellGifDecInfo info; - CellGifDecOutParam outParam; - CellGifDecSrc src; + u32 fd{}; + u64 fileSize{}; + CellGifDecInfo info{}; + CellGifDecOutParam outParam{}; + CellGifDecSrc src{}; };