From 470afd78d5e2ac52c87047456e95329e7279a6d4 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 8 Sep 2014 04:54:17 +0400 Subject: [PATCH 01/15] WIP (cellPngDec refactoring) --- Utilities/BEType.h | 6 +- rpcs3/Emu/Memory/vm_ptr.h | 12 + rpcs3/Emu/SysCalls/Modules/cellPng.h | 174 +++++ rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 694 +++++++++++++++---- rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 358 ++++++++-- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 19 +- rpcs3/Emu/SysCalls/SC_FUNC.h | 29 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 9 files changed, 1081 insertions(+), 215 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/Modules/cellPng.h diff --git a/Utilities/BEType.h b/Utilities/BEType.h index a261146e8c..50058489d4 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -438,9 +438,9 @@ public: } } - template be_t operator & (const be_t& right) const { const T res; res = ToBE() & right.ToBE(); return (be_t&)res; } - template be_t operator | (const be_t& right) const { const T res; res = ToBE() | right.ToBE(); return (be_t&)res; } - template be_t operator ^ (const be_t& right) const { const T res; res = ToBE() ^ right.ToBE(); return (be_t&)res; } + template be_t operator & (const be_t& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; } + template be_t operator | (const be_t& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; } + template be_t operator ^ (const be_t& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; } template bool operator == (T1 right) const { return (T1)ToLE() == right; } template bool operator != (T1 right) const { return !(*this == right); } diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 385d34f1aa..24824b382f 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -238,6 +238,13 @@ namespace vm return (_ptr_base&)addr; } + template + operator const _ptr_base() const + { + typename std::remove_const::type addr; addr = m_addr; + return (_ptr_base&)addr; + } + static _ptr_base make(AT addr) { return (_ptr_base&)addr; @@ -352,15 +359,20 @@ namespace vm AT m_addr; static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); + static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); template struct _func_arg { static_assert(!std::is_floating_point::value, "TODO: Unsupported callback argument type (floating point)"); + static_assert(!std::is_same::value, "TODO: Unsupported callback argument type (vector)"); + static_assert(sizeof(TT) <= 8, "Invalid callback argument type"); static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); __forceinline static u64 get_value(const TT& arg) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellPng.h b/rpcs3/Emu/SysCalls/Modules/cellPng.h new file mode 100644 index 0000000000..79c88a83fe --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellPng.h @@ -0,0 +1,174 @@ +#pragma once + +enum CellPngTxtType +{ + CELL_PNG_TEXT = 0, + CELL_PNG_ZTXT = 1, + CELL_PNG_ITXT = 2, +}; + +struct CellPngPLTEentry +{ + u8 red; + u8 green; + u8 blue; +}; + +struct CellPngPaletteEntries +{ + be_t red; + be_t green; + be_t blue; + be_t alpha; + be_t frequency; +}; + +struct CellPngSPLTentry +{ + vm::bptr paletteName; + u8 sampleDepth; + vm::bptr paletteEntries; + be_t paletteEntriesNumber; +}; + +enum CellPngUnknownLocation +{ + CELL_PNG_BEFORE_PLTE = 1, + CELL_PNG_BEFORE_IDAT = 2, + CELL_PNG_AFTER_IDAT = 8, +}; + +struct CellPngTextInfo +{ + be_t txtType; + vm::bptr keyword; + vm::bptr text; + be_t textLength; + vm::bptr languageTag; + vm::bptr translatedKeyword; +}; + +struct CellPngPLTE +{ + be_t paletteEntriesNumber; + vm::bptr paletteEntries; +}; + +struct CellPngGAMA +{ + be_t gamma; +}; + +struct CellPngSRGB +{ + be_t renderingIntent; +}; + +struct CellPngICCP +{ + vm::bptr profileName; + vm::bptr profile; + be_t profileLength; +}; + +struct CellPngSBIT +{ + be_t red; + be_t green; + be_t blue; + be_t gray; + be_t alpha; +}; + +struct CellPngTRNS +{ + vm::bptr alphaForPaletteIndex; + be_t alphaForPaletteIndexNumber; + be_t red; + be_t green; + be_t blue; + be_t gray; +}; + +struct CellPngHIST +{ + vm::bptr histgramEntries; + be_t histgramEntriesNumber; +}; + +struct CellPngTIME +{ + be_t year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; +}; + +struct CellPngBKGD +{ + u8 paletteIndex; + be_t red; + be_t green; + be_t blue; + be_t gray; +}; + +struct CellPngSPLT +{ + vm::bptr sPLTentries; + be_t sPLTentriesNumber; +}; + +struct CellPngOFFS +{ + be_t xPosition; + be_t yPosition; + be_t unitSpecifier; +}; + +struct CellPngPHYS +{ + be_t xAxis; + be_t yAxis; + be_t unitSpecifier; +}; + +struct CellPngSCAL +{ + be_t unitSpecifier; + be_t pixelWidth; + be_t pixelHeight; +}; + +struct CellPngCHRM +{ + be_t whitePointX; + be_t whitePointY; + be_t redX; + be_t redY; + be_t greenX; + be_t greenY; + be_t blueX; + be_t blueY; +}; + +struct CellPngPCAL +{ + vm::bptr calibrationName; + be_t x0; + be_t x1; + be_t equationType; + be_t numberOfParameters; + vm::bptr unitName; + vm::bptr parameter; +}; + +struct CellPngUnknownChunk +{ + char chunkType[5]; + vm::bptr chunkData; + be_t length; + be_t location; +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index af26cb2a59..1b2557945c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "stblib/stb_image.h" @@ -11,149 +12,111 @@ //Module cellPngDec(0x0018, cellPngDec_init); Module *cellPngDec = nullptr; -static std::map cellPngDecMap; +#ifdef PRX_DEBUG +#include "prx_libpngdec.h" +u32 libpngdec; +u32 libpngdec_rtoc; +#endif -CellPngDecMainHandle *getCellPngDecCtx(u32 mainHandle) { - if (cellPngDecMap.find(mainHandle) == cellPngDecMap.end()) - return nullptr; - - return cellPngDecMap[mainHandle]; -} - -int cellPngDecCreate(u32 mainHandle, u32 threadInParam, u32 threadOutParam) +u32 pngDecCreate(vm::ptr param, vm::ptr ext = {}) { - cellPngDec->Warning("cellPngDecCreate(mainHandle=0x%x, threadInParam=0x%x, threadOutParam=0x%x)", mainHandle, threadInParam, threadOutParam); - CellPngDecMainHandle *ctx = new CellPngDecMainHandle; - if (cellPngDecMap.find(mainHandle) != cellPngDecMap.end()) { - delete cellPngDecMap[mainHandle]; - cellPngDecMap.erase(mainHandle); + // alloc memory (should probably use param->cbCtrlMallocFunc) + auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128)); + + // initialize decoder + dec->malloc = param->cbCtrlMallocFunc; + dec->malloc_arg = param->cbCtrlMallocArg; + dec->free = param->cbCtrlFreeFunc; + dec->free_arg = param->cbCtrlFreeArg; + + if (ext) + { } - cellPngDecMap[mainHandle] = ctx; - - ctx->threadInParam = threadInParam; - ctx->threadOutParam = threadOutParam; - - return CELL_OK; + + // use virtual memory address as a handle + return dec.addr(); } -int cellPngDecDestroy(u32 mainHandle) +void pngDecDestroy(CellPngDecMainHandle dec) { - cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle); - CellPngDecMainHandle *ctx = getCellPngDecCtx(mainHandle); - if (!ctx) { - cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x): bad handle", mainHandle); - return -1; - } - - delete ctx; - cellPngDecMap.erase(mainHandle); - - return CELL_OK; + Memory.Free(dec.addr()); } -int cellPngDecOpen(u32 mainHandle, vm::ptr> subHandle, vm::ptr src, u32 openInfo) +u32 pngDecOpen(CellPngDecMainHandle dec, vm::ptr src, vm::ptr cb = {}, vm::ptr param = {}) { - cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x)", - mainHandle, subHandle.addr(), src.addr(), openInfo); + // alloc memory (should probably use dec->malloc) + auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128)); + + // initialize stream + stream->fd = 0; + stream->src = *src; - CellPngDecSubHandle *current_subHandle = new CellPngDecSubHandle; - current_subHandle->fd = 0; - current_subHandle->src = *src; - - switch(src->srcSelect.ToBE()) + switch (src->srcSelect.ToBE()) { case se32(CELL_PNGDEC_BUFFER): - current_subHandle->fileSize = src->streamSize.ToLE(); + stream->fileSize = src->streamSize.ToLE(); break; case se32(CELL_PNGDEC_FILE): // Get file descriptor vm::var> fd; int ret = cellFsOpen(vm::ptr::make(src->fileName.addr()), 0, fd, vm::ptr>::make(0), 0); - current_subHandle->fd = fd->ToLE(); - if(ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE; + stream->fd = fd->ToLE(); + if (ret != CELL_OK) return CELL_PNGDEC_ERROR_OPEN_FILE; // Get size of file vm::var sb; // Alloc a CellFsStat struct - ret = cellFsFstat(current_subHandle->fd, sb); - if(ret != CELL_OK) return ret; - current_subHandle->fileSize = sb->st_size; // Get CellFsStat.st_size + ret = cellFsFstat(stream->fd, sb); + if (ret != CELL_OK) return ret; + stream->fileSize = sb->st_size; // Get CellFsStat.st_size break; } - // From now, every u32 subHandle argument is a pointer to a CellPngDecSubHandle struct. - *subHandle = cellPngDec->GetNewId(current_subHandle); + if (cb) + { + // TODO: callback + } - return CELL_OK; + if (param) + { + // TODO: param->selectChunk + } + + // use virtual memory address as a handle + return stream.addr(); } -int cellPngDecExtOpen(u32 mainHandle, vm::ptr> subHandle, vm::ptr src, u32 openInfo, vm::ptr cbCtrlStrm, vm::ptr opnParam) +void pngDecClose(CellPngDecSubHandle stream) { - cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle=0x%x, src_addr=0x%x, openInfo=0x%x, cbCtrlStrm_addr=0x%x, opnParam=0x%x)", - mainHandle, subHandle.addr(), src.addr(), openInfo, cbCtrlStrm.addr(), opnParam.addr()); - - cellPngDec->Warning("*** cbCtrlStrm->cbCtrlStrmFunc_addr=0x%x", cbCtrlStrm->cbCtrlStrmFunc.addr()); - - vm::var streamInfo; - vm::var streamParam; - - int res = cellPngDecOpen(mainHandle, subHandle, src, openInfo); - - if (!res) cbCtrlStrm->cbCtrlStrmFunc(streamInfo, streamParam, cbCtrlStrm->cbCtrlStrmArg); - - return res; + cellFsClose(stream->fd); + Memory.Free(stream.addr()); } -int cellPngDecClose(u32 mainHandle, u32 subHandle) +void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm::ptr extInfo = {}) { - cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x,subHandle=0x%x)", mainHandle, subHandle); + CellPngDecInfo& current_info = stream->info; - CellPngDecSubHandle* subHandle_data; - if(!cellPngDec->CheckId(subHandle, subHandle_data)) - return CELL_PNGDEC_ERROR_FATAL; + assert(stream->fileSize >= 29); // Error: The file is smaller than the length of a PNG header - cellFsClose(subHandle_data->fd); - cellPngDec->RemoveId(subHandle); - - return CELL_OK; -} - -int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr info) -{ - cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle, subHandle, info.addr()); - 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 vm::var buffer; // Alloc buffer for PNG header auto buffer_32 = buffer.To>(); vm::var> pos, nread; - switch(subHandle_data->src.srcSelect.ToBE()) + switch (stream->src.srcSelect.ToBE()) { case se32(CELL_PNGDEC_BUFFER): - memmove(buffer.begin(), vm::get_ptr(subHandle_data->src.streamPtr), buffer.size()); + memmove(buffer.begin(), vm::get_ptr(stream->src.streamPtr), buffer.size()); break; case se32(CELL_PNGDEC_FILE): - cellFsLseek(fd, 0, CELL_SEEK_SET, pos); - cellFsRead(fd, vm::ptr::make(buffer.addr()), buffer.size(), nread); + cellFsLseek(stream->fd, 0, CELL_SEEK_SET, pos); + cellFsRead(stream->fd, vm::ptr::make(buffer.addr()), buffer.size(), nread); break; } - if (buffer_32[0].ToBE() != se32(0x89504E47) || - buffer_32[1].ToBE() != se32(0x0D0A1A0A) || // Error: The first 8 bytes are not a valid PNG signature - buffer_32[3].ToBE() != se32(0x49484452)) // Error: The PNG file does not start with an IHDR chunk - { - return CELL_PNGDEC_ERROR_HEADER; - } + assert(buffer_32[0].ToBE() == se32(0x89504E47) && + buffer_32[1].ToBE() == se32(0x0D0A1A0A) && // Error: The first 8 bytes are not a valid PNG signature + buffer_32[3].ToBE() == se32(0x49484452)); // Error: The PNG file does not start with an IHDR chunk switch (buffer[25]) { @@ -162,27 +125,19 @@ int cellPngDecReadHeader(u32 mainHandle, u32 subHandle, vm::ptr 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 + default: assert(!"Unknown color type"); return; // Not supported color type } - current_info.imageWidth = buffer_32[4]; - current_info.imageHeight = buffer_32[5]; - current_info.bitDepth = buffer[24]; - current_info.interlaceMethod = buffer[28]; + current_info.imageWidth = buffer_32[4]; + current_info.imageHeight = buffer_32[5]; + current_info.bitDepth = buffer[24]; + current_info.interlaceMethod = (CellPngDecInterlaceMode)buffer[28]; current_info.chunkInformation = 0; // Unimplemented *info = current_info; - - return CELL_OK; } -int cellPngDecExtReadHeader(u32 mainHandle, u32 subHandle, vm::ptr info, vm::ptr extInfo) -{ - cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", - mainHandle, subHandle, info.addr(), extInfo.addr()); - - return cellPngDecReadHeader(mainHandle, subHandle, info); -} +/* int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::ptr dataCtrlParam, vm::ptr dataOutInfo) { @@ -367,39 +322,496 @@ int cellPngDecExtSetParameter(u32 mainHandle, u32 subHandle, vm::ptr mainHandle, vm::ptr threadInParam, vm::ptr threadOutParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x295C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", + mainHandle.addr(), threadInParam.addr(), threadOutParam.addr()); + + *mainHandle = pngDecCreate(threadInParam); + + // set codec version + threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; + + return CELL_OK; +#endif +} + +s32 cellPngDecExtCreate( + vm::ptr mainHandle, + vm::ptr threadInParam, + vm::ptr threadOutParam, + vm::ptr extThreadInParam, + vm::ptr extThreadOutParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x296C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x, extThreadInParam_addr=0x%x, extThreadOutParam_addr=0x%x)", + mainHandle.addr(), threadInParam.addr(), threadOutParam.addr(), extThreadInParam.addr(), extThreadOutParam.addr()); + + // create decoder + *mainHandle = pngDecCreate(threadInParam, extThreadInParam); + + // set codec version + threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; + + extThreadOutParam->reserved = 0; + + return CELL_OK; +#endif +} + +s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x1E6C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle.addr()); + + pngDecDestroy(mainHandle); + return CELL_OK; +#endif +} + +s32 cellPngDecOpen( + CellPngDecMainHandle mainHandle, + vm::ptr subHandle, + vm::ptr src, + vm::ptr openInfo) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x3F3C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr()); + + // create stream handle + *subHandle = pngDecOpen(mainHandle, src); + + // set memory info + openInfo->initSpaceAllocated = 4096; + + return CELL_OK; +#endif +} + +s32 cellPngDecExtOpen( + CellPngDecMainHandle mainHandle, + vm::ptr subHandle, + vm::ptr src, + vm::ptr openInfo, + vm::ptr cbCtrlStrm, + vm::ptr opnParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x3F34, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x, cbCtrlStrm_addr=0x%x, opnParam_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr(), cbCtrlStrm.addr(), opnParam.addr()); + + // create stream handle + *subHandle = pngDecOpen(mainHandle, src, cbCtrlStrm, opnParam); + + // set memory info + openInfo->initSpaceAllocated = 4096; + + return CELL_OK; +#endif +} + +s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x066C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle.addr(), subHandle.addr()); + + pngDecClose(subHandle); + + return CELL_OK; +#endif +} + +s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr info) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x3A3C, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), info.addr()); + + pngReadHeader(subHandle, info); + + return CELL_OK; +#endif +} + +s32 cellPngDecExtReadHeader( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr info, + vm::ptr extInfo) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x3A34, libpngdec_rtoc); +#else + cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), info.addr(), extInfo.addr()); + + pngReadHeader(subHandle, info, extInfo); + + return CELL_OK; +#endif +} + +s32 cellPngDecSetParameter( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr inParam, + vm::ptr outParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x33F4, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecExtSetParameter( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr inParam, + vm::ptr outParam, + vm::ptr extInParam, + vm::ptr extOutParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x33EC, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecDecodeData( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr data, + vm::ptr dataCtrlParam, + vm::ptr dataOutInfo) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D40, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecExtDecodeData( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr data, + vm::ptr dataCtrlParam, + vm::ptr dataOutInfo, + vm::ptr cbCtrlDisp, + vm::ptr dispParam) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D38, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetUnknownChunks( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr unknownChunk, + vm::ptr unknownChunkNumber) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x03EC, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetpCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr pcal) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0730, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetcHRM(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr chrm) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0894, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetsCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr scal) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x09EC, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetpHYs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr phys) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0B14, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetoFFs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr offs) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0C58, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetsPLT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr splt) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0D9C, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetbKGD(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr bkgd) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x0ED0, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGettIME(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr time) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x1024, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGethIST(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr hist) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x116C, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGettRNS(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr trns) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x12A4, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetsBIT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr sbit) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x1420, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetiCCP(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr iccp) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x1574, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetsRGB(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr srgb) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x16B4, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetgAMA(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr gama) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x17CC, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetPLTE(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr plte) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x18E4, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif +} + +s32 cellPngDecGetTextChunk( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr textInfoNum, + vm::ptr textInfo) +{ +#ifdef PRX_DEBUG + cellPngDec->Warning("%s()", __FUNCTION__); + return GetCurrentPPUThread().FastCall2(libpngdec + 0x19FC, libpngdec_rtoc); +#else + UNIMPLEMENTED_FUNC(cellPngDec); + return CELL_OK; +#endif } void cellPngDec_init() { - cellPngDec->AddFunc(0x157d30c5, cellPngDecCreate); - cellPngDec->AddFunc(0x820dae1a, cellPngDecDestroy); - cellPngDec->AddFunc(0xd2bc5bfd, cellPngDecOpen); - cellPngDec->AddFunc(0x5b3d1ff1, cellPngDecClose); - cellPngDec->AddFunc(0x9ccdcc95, cellPngDecReadHeader); - cellPngDec->AddFunc(0x2310f155, cellPngDecDecodeData); - cellPngDec->AddFunc(0xe97c9bd4, cellPngDecSetParameter); + REG_FUNC(cellPngDec, cellPngDecGetUnknownChunks); + REG_FUNC(cellPngDec, cellPngDecClose); + REG_FUNC(cellPngDec, cellPngDecGetpCAL); + REG_FUNC(cellPngDec, cellPngDecGetcHRM); + REG_FUNC(cellPngDec, cellPngDecGetsCAL); + REG_FUNC(cellPngDec, cellPngDecGetpHYs); + REG_FUNC(cellPngDec, cellPngDecGetoFFs); + REG_FUNC(cellPngDec, cellPngDecGetsPLT); + REG_FUNC(cellPngDec, cellPngDecGetbKGD); + REG_FUNC(cellPngDec, cellPngDecGettIME); + REG_FUNC(cellPngDec, cellPngDecGethIST); + REG_FUNC(cellPngDec, cellPngDecGettRNS); + REG_FUNC(cellPngDec, cellPngDecGetsBIT); + REG_FUNC(cellPngDec, cellPngDecGetiCCP); + REG_FUNC(cellPngDec, cellPngDecGetsRGB); + REG_FUNC(cellPngDec, cellPngDecGetgAMA); + REG_FUNC(cellPngDec, cellPngDecGetPLTE); + REG_FUNC(cellPngDec, cellPngDecGetTextChunk); + REG_FUNC(cellPngDec, cellPngDecDestroy); + REG_FUNC(cellPngDec, cellPngDecCreate); + REG_FUNC(cellPngDec, cellPngDecExtCreate); + REG_FUNC(cellPngDec, cellPngDecExtSetParameter); + REG_FUNC(cellPngDec, cellPngDecSetParameter); + REG_FUNC(cellPngDec, cellPngDecExtReadHeader); + REG_FUNC(cellPngDec, cellPngDecReadHeader); + REG_FUNC(cellPngDec, cellPngDecExtOpen); + REG_FUNC(cellPngDec, cellPngDecOpen); + REG_FUNC(cellPngDec, cellPngDecExtDecodeData); + REG_FUNC(cellPngDec, cellPngDecDecodeData); - cellPngDec->AddFunc(0x0c515302, cellPngDecExtOpen); - cellPngDec->AddFunc(0x8b33f863, cellPngDecExtReadHeader); - cellPngDec->AddFunc(0x726fc1d0, cellPngDecExtDecodeData); - cellPngDec->AddFunc(0x9e9d7d42, cellPngDecExtSetParameter); +#ifdef PRX_DEBUG + CallAfter([]() + { + libpngdec = (u32)Memory.PRXMem.AllocAlign(sizeof(libpngdec_data), 4096); + memcpy(vm::get_ptr(libpngdec), libpngdec_data, sizeof(libpngdec_data)); + libpngdec_rtoc = libpngdec + 0x49710; - /*cellPngDec->AddFunc(0x48436b2d, cellPngDecExtCreate); - cellPngDec->AddFunc(0x7585a275, cellPngDecGetbKGD); - cellPngDec->AddFunc(0x7a062d26, cellPngDecGetcHRM); - cellPngDec->AddFunc(0xb153629c, cellPngDecGetgAMA); - cellPngDec->AddFunc(0xb905ebb7, cellPngDecGethIST); - cellPngDec->AddFunc(0xf44b6c30, cellPngDecGetiCCP); - cellPngDec->AddFunc(0x27c921b5, cellPngDecGetoFFs); - cellPngDec->AddFunc(0xb4fe75e1, cellPngDecGetpCAL); - cellPngDec->AddFunc(0x3d50016a, cellPngDecGetpHYs); - cellPngDec->AddFunc(0x30cb334a, cellPngDecGetsBIT); - cellPngDec->AddFunc(0xc41e1198, cellPngDecGetsCAL); - cellPngDec->AddFunc(0xa5cdf57e, cellPngDecGetsPLT); - cellPngDec->AddFunc(0xe4416e82, cellPngDecGetsRGB); - cellPngDec->AddFunc(0x35a6846c, cellPngDecGettIME); - cellPngDec->AddFunc(0xb96fb26e, cellPngDecGettRNS); - cellPngDec->AddFunc(0xe163977f, cellPngDecGetPLTE); - cellPngDec->AddFunc(0x609ec7d5, cellPngDecUnknownChunks); - cellPngDec->AddFunc(0xb40ca175, cellPngDecGetTextChunk);*/ + extern Module* sysPrxForUser; + extern Module* cellSpurs; + extern Module* sys_fs; + + FIX_IMPORT(sysPrxForUser, _sys_snprintf , libpngdec + 0x1E6D0); + FIX_IMPORT(sysPrxForUser, _sys_strlen , libpngdec + 0x1E6F0); + fix_import(sysPrxForUser, 0x3EF17F8C , libpngdec + 0x1E710); + FIX_IMPORT(sysPrxForUser, _sys_memset , libpngdec + 0x1E730); + FIX_IMPORT(sysPrxForUser, _sys_memcpy , libpngdec + 0x1E750); + FIX_IMPORT(sysPrxForUser, _sys_strcpy , libpngdec + 0x1E770); + FIX_IMPORT(sysPrxForUser, _sys_strncpy , libpngdec + 0x1E790); + FIX_IMPORT(sysPrxForUser, _sys_memcmp , libpngdec + 0x1E7B0); + FIX_IMPORT(cellSpurs, cellSpursQueueDetachLv2EventQueue , libpngdec + 0x1E7D0); + FIX_IMPORT(cellSpurs, cellSpursAttributeSetNamePrefix , libpngdec + 0x1E7F0); + FIX_IMPORT(cellSpurs, _cellSpursQueueInitialize , libpngdec + 0x1E810); + FIX_IMPORT(cellSpurs, _cellSpursTasksetAttributeInitialize, libpngdec + 0x1E830); + FIX_IMPORT(cellSpurs, cellSpursTasksetAttributeSetName , libpngdec + 0x1E850); + FIX_IMPORT(cellSpurs, cellSpursTaskGetReadOnlyAreaPattern , libpngdec + 0x1E870); + FIX_IMPORT(cellSpurs, cellSpursTaskGetContextSaveAreaSize , libpngdec + 0x1E890); + FIX_IMPORT(cellSpurs, cellSpursQueuePopBody , libpngdec + 0x1E8B0); + FIX_IMPORT(cellSpurs, cellSpursQueuePushBody , libpngdec + 0x1E8D0); + FIX_IMPORT(cellSpurs, _cellSpursAttributeInitialize , libpngdec + 0x1E8F0); + FIX_IMPORT(cellSpurs, cellSpursJoinTaskset , libpngdec + 0x1E910); + FIX_IMPORT(cellSpurs, cellSpursShutdownTaskset , libpngdec + 0x1E930); + FIX_IMPORT(cellSpurs, cellSpursInitializeWithAttribute , libpngdec + 0x1E950); + FIX_IMPORT(cellSpurs, cellSpursCreateTask , libpngdec + 0x1E970); + FIX_IMPORT(cellSpurs, cellSpursCreateTasksetWithAttribute , libpngdec + 0x1E990); + FIX_IMPORT(cellSpurs, cellSpursFinalize , libpngdec + 0x1E9B0); + FIX_IMPORT(cellSpurs, cellSpursQueueAttachLv2EventQueue , libpngdec + 0x1E9D0); + FIX_IMPORT(sys_fs, cellFsClose , libpngdec + 0x1E9F0); + FIX_IMPORT(sys_fs, cellFsRead , libpngdec + 0x1EA10); + FIX_IMPORT(sys_fs, cellFsOpen , libpngdec + 0x1EA30); + FIX_IMPORT(sys_fs, cellFsLseek , libpngdec + 0x1EA50); + + fix_relocs(cellPngDec, libpngdec, 0x41C30, 0x47AB0, 0x40A00); + }); +#endif } diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index c436ad5fc3..a411d704d6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -1,6 +1,18 @@ #pragma once +#include "cellPng.h" -//Return Codes +enum : u32 +{ + PNGDEC_CODEC_VERSION = 0x00420000, +}; + +struct PngDecoder; +struct PngStream; + +typedef vm::ptr CellPngDecMainHandle; +typedef vm::ptr CellPngDecSubHandle; + +// Return Codes enum { CELL_PNGDEC_ERROR_HEADER = 0x80611201, @@ -15,6 +27,7 @@ enum CELL_PNGDEC_ERROR_CB_PARAM = 0x8061120a, }; +// Consts enum CellPngDecColorSpace { CELL_PNGDEC_GRAYSCALE = 1, @@ -25,10 +38,10 @@ enum CellPngDecColorSpace CELL_PNGDEC_ARGB = 20, }; -enum CellPngDecDecodeStatus +enum CellPngDecSpuThreadEna : u32 { - CELL_PNGDEC_DEC_STATUS_FINISH = 0, //Decoding finished - CELL_PNGDEC_DEC_STATUS_STOP = 1, //Decoding halted + CELL_PNGDEC_SPU_THREAD_DISABLE = 0, + CELL_PNGDEC_SPU_THREAD_ENABLE = 1, }; enum CellPngDecStreamSrcSel @@ -49,19 +62,77 @@ enum CellPngDecOutputMode CELL_PNGDEC_BOTTOM_TO_TOP = 1, }; - -// Structs -struct CellPngDecDataOutInfo +enum CellPngDecPackFlag { - be_t chunkInformation; - be_t numText; - be_t numUnknownChunk; - be_t status; + CELL_PNGDEC_1BYTE_PER_NPIXEL = 0, + CELL_PNGDEC_1BYTE_PER_1PIXEL = 1, }; -struct CellPngDecDataCtrlParam +enum CellPngDecAlphaSelect { - be_t outputBytesPerLine; + CELL_PNGDEC_STREAM_ALPHA = 0, + CELL_PNGDEC_FIX_ALPHA = 1, +}; + +enum CellPngDecCommand +{ + CELL_PNGDEC_CONTINUE = 0, + CELL_PNGDEC_STOP = 1, +}; + +enum CellPngDecDecodeStatus +{ + CELL_PNGDEC_DEC_STATUS_FINISH = 0, + CELL_PNGDEC_DEC_STATUS_STOP = 1, +}; + +// Callbacks +typedef vm::ptr(*CellPngDecCbControlMalloc)(u32 size, vm::ptr cbCtrlMallocArg); +typedef s32(*CellPngDecCbControlFree)(vm::ptr ptr, vm::ptr cbCtrlFreeArg); + +// Structs +struct CellPngDecThreadInParam +{ + be_t spuThreadEnable; + be_t ppuThreadPriority; + be_t spuThreadPriority; + vm::bptr cbCtrlMallocFunc; + be_t> cbCtrlMallocArg; // rough attempt (it's hard to pass vm::bptr as vm::ptr in function argument) + vm::bptr cbCtrlFreeFunc; + be_t> cbCtrlFreeArg; +}; + +struct CellPngDecExtThreadInParam +{ + be_t spurs_addr; // it could be vm::bptr, but nobody will use SPURS in HLE implementation + u8 priority[8]; + be_t maxContention; +}; + +struct CellPngDecThreadOutParam +{ + be_t pngCodecVersion; +}; + +struct CellPngDecExtThreadOutParam +{ + be_t reserved; +}; + +struct CellPngDecSrc +{ + be_t srcSelect; + vm::bptr fileName; + be_t fileOffset; + be_t fileSize; + vm::bptr streamPtr; + be_t streamSize; + be_t spuThreadEnable; +}; + +struct CellPngDecOpnInfo +{ + be_t initSpaceAllocated; }; struct CellPngDecInfo @@ -69,31 +140,20 @@ struct CellPngDecInfo be_t imageWidth; be_t imageHeight; be_t numComponents; - be_t colorSpace; // CellPngDecColorSpace + be_t colorSpace; be_t bitDepth; - be_t interlaceMethod; // CellPngDecInterlaceMode + be_t interlaceMethod; be_t chunkInformation; }; -struct CellPngDecSrc -{ - be_t srcSelect; // CellPngDecStreamSrcSel - vm::bptr fileName; - be_t fileOffset; - be_t fileSize; - be_t streamPtr; - be_t streamSize; - be_t spuThreadEnable; // CellPngDecSpuThreadEna -}; - struct CellPngDecInParam { - be_t commandPtr; - be_t outputMode; // CellPngDecOutputMode - be_t outputColorSpace; // CellPngDecColorSpace + vm::bptr commandPtr; + be_t outputMode; + be_t outputColorSpace; be_t outputBitDepth; - be_t outputPackFlag; // CellPngDecPackFlag - be_t outputAlphaSelect; // CellPngDecAlphaSelect + be_t outputPackFlag; + be_t outputAlphaSelect; be_t outputColorAlpha; }; @@ -104,11 +164,114 @@ struct CellPngDecOutParam be_t outputHeight; be_t outputComponents; be_t outputBitDepth; - be_t outputMode; // CellPngDecOutputMode - be_t outputColorSpace; // CellPngDecColorSpace + be_t outputMode; + be_t outputColorSpace; be_t useMemorySpace; }; +struct CellPngDecDataCtrlParam +{ + be_t outputBytesPerLine; +}; + +struct CellPngDecDataOutInfo +{ + be_t chunkInformation; + be_t numText; + be_t numUnknownChunk; + be_t status; +}; + +// Functions +s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptr threadInParam, vm::ptr threadOutParam); + +s32 cellPngDecExtCreate( + vm::ptr mainHandle, + vm::ptr threadInParam, + vm::ptr threadOutParam, + vm::ptr extThreadInParam, + vm::ptr extThreadOutParam); + +s32 cellPngDecOpen( + CellPngDecMainHandle mainHandle, + vm::ptr subHandle, + vm::ptr src, + vm::ptr openInfo); + +s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr info); + +s32 cellPngDecSetParameter( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr inParam, + vm::ptr outParam); + +s32 cellPngDecDecodeData( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr data, + vm::ptr dataCtrlParam, + vm::ptr dataOutInfo); + +s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle); + +s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle); + +s32 cellPngDecGetTextChunk( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr textInfoNum, + vm::ptr textInfo); + +s32 cellPngDecGetPLTE(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr plte); + +s32 cellPngDecGetgAMA(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr gama); + +s32 cellPngDecGetsRGB(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr srgb); + +s32 cellPngDecGetiCCP(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr iccp); + +s32 cellPngDecGetsBIT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr sbit); + +s32 cellPngDecGettRNS(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr trns); + +s32 cellPngDecGethIST(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr hist); + +s32 cellPngDecGettIME(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr time); + +s32 cellPngDecGetbKGD(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr bkgd); + +s32 cellPngDecGetsPLT(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr splt); + +s32 cellPngDecGetoFFs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr offs); + +s32 cellPngDecGetpHYs(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr phys); + +s32 cellPngDecGetsCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr scal); + +s32 cellPngDecGetcHRM(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr chrm); + +s32 cellPngDecGetpCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr pcal); + +s32 cellPngDecGetUnknownChunks( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr unknownChunk, + vm::ptr unknownChunkNumber); + + +enum CellPngDecBufferMode +{ + CELL_PNGDEC_LINE_MODE = 1, +}; + +enum CellPngDecSpuMode +{ + CELL_PNGDEC_RECEIVE_EVENT = 0, + CELL_PNGDEC_TRYRECEIVE_EVENT = 1, +}; + +// Structs struct CellPngDecStrmInfo { be_t decodedStrmSize; @@ -116,25 +279,49 @@ struct CellPngDecStrmInfo struct CellPngDecStrmParam { - be_t strmPtr; + vm::bptr strmPtr; be_t strmSize; }; -struct CellPngDecCbCtrlStrm -{ - vm::bptr strmInfo, vm::ptr strmParam, u32 cbCtrlStrmArg)> cbCtrlStrmFunc; - be_t cbCtrlStrmArg; -}; +typedef s32(*CellPngDecCbControlStream)( + vm::ptr strmInfo, + vm::ptr strmParam, + vm::ptr cbCtrlStrmArg + ); -struct CellPngDecCbCtrlDisp +struct CellPngDecDispInfo { - be_t cbCtrlDispFunc_addr; - be_t cbCtrlDispArg; + 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 nextOutputStartY; + be_t scanPassCount; + vm::bptr outputImage; }; struct CellPngDecDispParam { - be_t nextOutputImage_addr; + vm::bptr nextOutputImage; +}; + +// Callback +typedef s32(*CellPngDecCbControlDisp)(vm::ptr dispInfo, vm::ptr dispParam, vm::ptr cbCtrlDispArg); + +// Structs +struct CellPngDecOpnParam +{ + be_t selectChunk; +}; + +struct CellPngDecCbCtrlStrm +{ + vm::bptr cbCtrlStrmFunc; + be_t> cbCtrlStrmArg; }; struct CellPngDecExtInfo @@ -144,9 +331,9 @@ struct CellPngDecExtInfo struct CellPngDecExtInParam { - be_t bufferMode; // CellPngDecBufferMode + be_t bufferMode; be_t outputCounts; - be_t spuMode; // CellPngDecSpuMode + be_t spuMode; }; struct CellPngDecExtOutParam @@ -155,25 +342,80 @@ struct CellPngDecExtOutParam be_t outputHeight; }; -struct CellPngDecOpnParam +struct CellPngDecCbCtrlDisp { - be_t selectChunk; + vm::bptr cbCtrlDispFunc; + be_t> cbCtrlDispArg; }; +// Functions +s32 cellPngDecExtOpen( + CellPngDecMainHandle mainHandle, + vm::ptr subHandle, + vm::ptr src, + vm::ptr openInfo, + vm::ptr cbCtrlStrm, + vm::ptr opnParam); -// Custom structs -struct CellPngDecSubHandle +s32 cellPngDecExtReadHeader( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr info, + vm::ptr extInfo); + +s32 cellPngDecExtSetParameter( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr inParam, + vm::ptr outParam, + vm::ptr extInParam, + vm::ptr extOutParam); + +s32 cellPngDecExtDecodeData( + CellPngDecMainHandle mainHandle, + CellPngDecSubHandle subHandle, + vm::ptr data, + vm::ptr dataCtrlParam, + vm::ptr dataOutInfo, + vm::ptr cbCtrlDisp, + vm::ptr dispParam); + +//// 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 PngDecoder { - be_t fd; - be_t fileSize; + vm::ptr malloc; + vm::ptr malloc_arg; + vm::ptr free; + vm::ptr free_arg; +}; + +struct PngStream +{ + CellPngDecMainHandle dec; + + // old data: + u32 fd; + u64 fileSize; CellPngDecInfo info; CellPngDecOutParam outParam; CellPngDecSrc src; -}; -struct CellPngDecMainHandle -{ - be_t mainHandle; - be_t threadInParam; - be_t threadOutParam; -}; + CellPngDecStrmInfo streamInfo; + CellPngDecStrmParam streamParam; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 2a9835a27c..b01d5e6c68 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Emu/Memory/Memory.h" +#include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/FS/vfsFile.h" @@ -299,12 +300,26 @@ s64 _sys_spu_printf_detach_thread(u32 arg) return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_dtcb), vm::read32(spu_printf_dtcb + 4), arg); } +s32 _sys_snprintf(vm::ptr dst, u32 count, vm::ptr fmt, u32 a1, u32 a2) // va_args... +{ + sysPrxForUser->Todo("_sys_snprintf(dst_addr=0x%x, count=%d, fmt_addr=0x%x['%s'], ...)", dst.addr(), count, fmt.addr(), fmt.get_ptr()); + + if (std::string(fmt.get_ptr()) == "%s_%08x") + { + return snprintf(dst.get_ptr(), count, fmt.get_ptr(), vm::get_ptr(a1), a2); + } + + Emu.Pause(); + return 0; +} + s32 _sys_printf(vm::ptr fmt) { sysPrxForUser->Todo("_sys_printf(fmt_addr=0x%x, ...)", fmt.addr()); // probably, assertion failed sysPrxForUser->Warning("_sys_printf: \n%s", fmt.get_ptr()); + Emu.Pause(); return CELL_OK; } @@ -395,7 +410,6 @@ void sysPrxForUser_init() REG_FUNC(sysPrxForUser, _sys_strncat); REG_FUNC(sysPrxForUser, _sys_strcpy); REG_FUNC(sysPrxForUser, _sys_strncpy); - sysPrxForUser->AddFunc(0xe75c40f2, _unnamed_E75C40F2); // real name is unknown REG_FUNC(sysPrxForUser, _sys_spu_printf_initialize); REG_FUNC(sysPrxForUser, _sys_spu_printf_finalize); @@ -404,7 +418,10 @@ void sysPrxForUser_init() REG_FUNC(sysPrxForUser, _sys_spu_printf_attach_thread); REG_FUNC(sysPrxForUser, _sys_spu_printf_detach_thread); + REG_FUNC(sysPrxForUser, _sys_snprintf); + REG_FUNC(sysPrxForUser, _sys_printf); + sysPrxForUser->AddFunc(0xe75c40f2, _unnamed_E75C40F2); // real name is unknown } void sysPrxForUser_load() diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index 68039bf993..f01cc741d4 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -24,7 +24,7 @@ namespace detail template struct bind_arg { - static_assert(sizeof(T) <= 8, "Wrong argument type for ARG_GENERAL"); + static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_GENERAL"); static __forceinline T func(PPUThread& CPU) { @@ -35,7 +35,7 @@ namespace detail template struct bind_arg { - static_assert(sizeof(T) <= 8, "Wrong argument type for ARG_FLOAT"); + static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT"); static __forceinline T func(PPUThread& CPU) { @@ -46,7 +46,7 @@ namespace detail template struct bind_arg { - static_assert(std::is_same::value, "Wrong argument type for ARG_VECTOR"); + static_assert(std::is_same::value, "Invalid function argument type for ARG_VECTOR"); static __forceinline T func(PPUThread& CPU) { @@ -57,11 +57,14 @@ namespace detail template struct bind_arg { - static_assert(sizeof(T) <= 8 && v_count <= 12, "Wrong argument type for ARG_STACK"); + static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); + static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); + static_assert(sizeof(T) <= 8, "Invalid function argument type (ARG_STACK)"); static __forceinline T func(PPUThread& CPU) { - const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 12, 0)); + // TODO: check stack argument displacement + const u64 res = CPU.GetStackArg(8 + std::max(g_count - 8, 0) + std::max(f_count - 12, 0) + std::max(v_count - 12, 0)); return (T&)res; } }; @@ -69,18 +72,19 @@ namespace detail template struct bind_result { - static_assert(!std::is_pointer::value, "Invalid function result type: pointer"); static_assert(sizeof(T) <= 8, "Invalid function result type"); + static_assert(!std::is_pointer::value, "Invalid function result type (pointer)"); + static_assert(!std::is_reference::value, "Invalid function result type (reference)"); - static __forceinline void func(PPUThread& CPU, T value) + static __forceinline void func(PPUThread& CPU, T result) { if (std::is_floating_point::value) { - CPU.FPR[1] = (double)value; + CPU.FPR[1] = (double)result; } else { - (T&)CPU.GPR[3] = value; + (T&)CPU.GPR[3] = result; } } }; @@ -88,9 +92,9 @@ namespace detail template<> struct bind_result { - static __forceinline void func(PPUThread& CPU, u128 value) + static __forceinline void func(PPUThread& CPU, u128 result) { - CPU.VPR[2] = value; + CPU.VPR[2] = result; } }; @@ -128,7 +132,8 @@ namespace detail template static __forceinline std::tuple iterate(PPUThread& CPU) { - static_assert(!std::is_pointer::value, "Invalid function argument type: pointer"); + static_assert(!std::is_pointer::value, "Invalid function argument type (pointer)"); + static_assert(!std::is_reference::value, "Invalid function argument type (reference)"); // TODO: check calculations const bool is_float = std::is_floating_point::value; const bool is_vector = std::is_same::value; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index f2e3905be6..b8b7237a8a 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -377,6 +377,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index e0d50650bc..b129a2094e 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1210,5 +1210,8 @@ Header Files + + Emu\SysCalls\Modules + \ No newline at end of file From 311a3b3e4781440fcff3e8c75651937e9e1c627e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 8 Sep 2014 14:20:25 +0400 Subject: [PATCH 02/15] Compilation fix --- rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index a411d704d6..54444e1c81 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -97,9 +97,9 @@ struct CellPngDecThreadInParam be_t ppuThreadPriority; be_t spuThreadPriority; vm::bptr cbCtrlMallocFunc; - be_t> cbCtrlMallocArg; // rough attempt (it's hard to pass vm::bptr as vm::ptr in function argument) + vm::bptr cbCtrlMallocArg; vm::bptr cbCtrlFreeFunc; - be_t> cbCtrlFreeArg; + vm::bptr cbCtrlFreeArg; }; struct CellPngDecExtThreadInParam From 5d951451c5ae82f88a7a7703b235326b5d5dec8c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 8 Sep 2014 18:56:47 +0400 Subject: [PATCH 03/15] cellPngDec (nothing changed) --- rpcs3/Emu/SysCalls/LogBase.cpp | 56 +++- rpcs3/Emu/SysCalls/LogBase.h | 46 ++- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 351 ++++++++++++++-------- rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 22 +- 4 files changed, 321 insertions(+), 154 deletions(-) diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index 6a8f4a6bed..47bb4458be 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -9,7 +9,7 @@ bool LogBase::CheckLogging() const return Ini.HLELogging.GetValue(); } -void LogBase::LogOutput(LogType type, const char* info, const std::string& text) +void LogBase::LogOutput(LogType type, const char* info, const std::string& text) const { switch (type) { @@ -20,7 +20,7 @@ void LogBase::LogOutput(LogType type, const char* info, const std::string& text) } } -void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std::string& text) +void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std::string& text) const { switch (type) { @@ -29,4 +29,54 @@ void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std: case LogWarning: LOG_WARNING(HLE, "%s[%d]%s%s", GetName().c_str(), id, info, text.c_str()); break; case LogError: LOG_ERROR(HLE, "%s[%d]%s%s", GetName().c_str(), id, info, text.c_str()); break; } -} \ No newline at end of file +} + +hle::error::error(s32 errorCode, const char* errorText) + : code(errorCode) + , base(nullptr) + , text(errorText) +{ +} + +hle::error::error(s32 errorCode, const LogBase& errorBase, const char* errorText) + : code(errorCode) + , base(&errorBase) + , text(errorText) +{ +} + +hle::error::error(s32 errorCode, const LogBase* errorBase, const char* errorText) + : code(errorCode) + , base(errorBase) + , text(errorText) +{ +} + +void hle::error::print(const char* func) +{ + if (!text.empty()) + { + if (base) + { + if (func) + { + base->Error("%s(): %s (0x%X)", func, text.c_str(), code); + } + else + { + base->Error("%s (0x%X)", text.c_str(), code); + } + } + else + { + if (func) + { + LOG_ERROR(HLE, "%s(): %s (0x%X)", func, text.c_str(), code); + } + else + { + LOG_ERROR(HLE, "%s (0x%X)", text.c_str(), code); + } + } + } +} diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index dc3d280d43..d50257378c 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -13,8 +13,8 @@ class LogBase LogError, }; - void LogOutput(LogType type, const char* info, const std::string& text); - void LogOutput(LogType type, const u32 id, const char* info, const std::string& text); + void LogOutput(LogType type, const char* info, const std::string& text) const; + void LogOutput(LogType type, const u32 id, const char* info, const std::string& text) const; public: void SetLogging(bool value) @@ -29,17 +29,17 @@ public: virtual const std::string& GetName() const = 0; - template void Notice(const u32 id, const char* fmt, Targs... args) + template void Notice(const u32 id, const char* fmt, Targs... args) const { LogOutput(LogNotice, id, ": ", fmt::Format(fmt, args...)); } - template void Notice(const char* fmt, Targs... args) + template void Notice(const char* fmt, Targs... args) const { LogOutput(LogNotice, ": ", fmt::Format(fmt, args...)); } - template __forceinline void Log(const char* fmt, Targs... args) + template __forceinline void Log(const char* fmt, Targs... args) const { if (CheckLogging()) { @@ -47,7 +47,7 @@ public: } } - template __forceinline void Log(const u32 id, const char* fmt, Targs... args) + template __forceinline void Log(const u32 id, const char* fmt, Targs... args) const { if (CheckLogging()) { @@ -55,43 +55,59 @@ public: } } - template void Success(const u32 id, const char* fmt, Targs... args) + template void Success(const u32 id, const char* fmt, Targs... args) const { LogOutput(LogSuccess, id, ": ", fmt::Format(fmt, args...)); } - template void Success(const char* fmt, Targs... args) + template void Success(const char* fmt, Targs... args) const { LogOutput(LogSuccess, ": ", fmt::Format(fmt, args...)); } - template void Warning(const u32 id, const char* fmt, Targs... args) + template void Warning(const u32 id, const char* fmt, Targs... args) const { LogOutput(LogWarning, id, " warning: ", fmt::Format(fmt, args...)); } - template void Warning(const char* fmt, Targs... args) + template void Warning(const char* fmt, Targs... args) const { LogOutput(LogWarning, " warning: ", fmt::Format(fmt, args...)); } - template void Error(const u32 id, const char* fmt, Targs... args) + template void Error(const u32 id, const char* fmt, Targs... args) const { LogOutput(LogError, id, " error: ", fmt::Format(fmt, args...)); } - template void Error(const char* fmt, Targs... args) + template void Error(const char* fmt, Targs... args) const { LogOutput(LogError, " error: ", fmt::Format(fmt, args...)); } - template void Todo(const u32 id, const char* fmt, Targs... args) + template void Todo(const u32 id, const char* fmt, Targs... args) const { LogOutput(LogError, id, " TODO: ", fmt::Format(fmt, args...)); } - template void Todo(const char* fmt, Targs... args) + template void Todo(const char* fmt, Targs... args) const { LogOutput(LogError, " TODO: ", fmt::Format(fmt, args...)); } -}; \ No newline at end of file +}; + +namespace hle +{ + struct error + { + const s32 code; + const LogBase* const base; + const std::string text; + + error(s32 errorCode, const char* errorText = nullptr); + error(s32 errorCode, const LogBase& base, const char* errorText = nullptr); + error(s32 errorCode, const LogBase* base, const char* errorText = nullptr); + + void print(const char* func = nullptr); + }; +} diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1b2557945c..e22ce0b368 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -18,11 +18,18 @@ u32 libpngdec; u32 libpngdec_rtoc; #endif -u32 pngDecCreate(vm::ptr param, vm::ptr ext = {}) +u32 pngDecCreate( + vm::ptr param, + vm::ptr ext = {}) { // alloc memory (should probably use param->cbCtrlMallocFunc) auto dec = CellPngDecMainHandle::make(Memory.Alloc(sizeof(PngDecoder), 128)); + if (!dec) + { + throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory allocation failed"); + } + // initialize decoder dec->malloc = param->cbCtrlMallocFunc; dec->malloc_arg = param->cbCtrlMallocArg; @@ -39,13 +46,25 @@ u32 pngDecCreate(vm::ptr param, vm::ptr src, vm::ptr cb = {}, vm::ptr param = {}) +u32 pngDecOpen( + CellPngDecMainHandle dec, + vm::ptr src, + vm::ptr cb = {}, + vm::ptr param = {}) { // alloc memory (should probably use dec->malloc) auto stream = CellPngDecSubHandle::make(Memory.Alloc(sizeof(PngStream), 128)); + + if (!stream) + { + throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory allocation failed"); + } // initialize stream stream->fd = 0; @@ -89,14 +108,23 @@ u32 pngDecOpen(CellPngDecMainHandle dec, vm::ptr src, vm::p void pngDecClose(CellPngDecSubHandle stream) { cellFsClose(stream->fd); - Memory.Free(stream.addr()); + if (!Memory.Free(stream.addr())) + { + throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory deallocation failed"); + } } -void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm::ptr extInfo = {}) +void pngReadHeader( + CellPngDecSubHandle stream, + vm::ptr info, + vm::ptr extInfo = {}) { CellPngDecInfo& current_info = stream->info; - assert(stream->fileSize >= 29); // Error: The file is smaller than the length of a PNG header + if (stream->fileSize < 29) + { + throw hle::error(CELL_PNGDEC_ERROR_HEADER, "The file is smaller than the length of a PNG header"); + } //Write the header to buffer vm::var buffer; // Alloc buffer for PNG header @@ -106,7 +134,7 @@ void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm: switch (stream->src.srcSelect.ToBE()) { case se32(CELL_PNGDEC_BUFFER): - memmove(buffer.begin(), vm::get_ptr(stream->src.streamPtr), buffer.size()); + memmove(buffer.begin(), stream->src.streamPtr.get_ptr(), buffer.size()); break; case se32(CELL_PNGDEC_FILE): cellFsLseek(stream->fd, 0, CELL_SEEK_SET, pos); @@ -114,9 +142,12 @@ void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm: break; } - assert(buffer_32[0].ToBE() == se32(0x89504E47) && - buffer_32[1].ToBE() == se32(0x0D0A1A0A) && // Error: The first 8 bytes are not a valid PNG signature - buffer_32[3].ToBE() == se32(0x49484452)); // Error: The PNG file does not start with an IHDR chunk + if (buffer_32[0].ToBE() != se32(0x89504E47) || + buffer_32[1].ToBE() != se32(0x0D0A1A0A) || // Error: The first 8 bytes are not a valid PNG signature + buffer_32[3].ToBE() != se32(0x49484452)) // Error: The PNG file does not start with an IHDR chunk + { + throw hle::error(CELL_PNGDEC_ERROR_HEADER, "Invalid PNG header"); + } switch (buffer[25]) { @@ -125,7 +156,7 @@ void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm: 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: assert(!"Unknown color type"); return; // Not supported color type + default: throw hle::error(CELL_PNGDEC_ERROR_HEADER, "Unknown color space (%d)"); return; } current_info.imageWidth = buffer_32[4]; @@ -137,30 +168,65 @@ void pngReadHeader(CellPngDecSubHandle stream, vm::ptr info, vm: *info = current_info; } -/* - -int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::ptr dataCtrlParam, vm::ptr dataOutInfo) +void pngDecSetParameter( + CellPngDecSubHandle stream, + vm::ptr inParam, + vm::ptr outParam, + vm::ptr extInParam = {}, + vm::ptr extOutParam = {}) { - cellPngDec->Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", - mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr()); + CellPngDecInfo& current_info = stream->info; + CellPngDecOutParam& current_outParam = stream->outParam; + current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth) / 8; + current_outParam.outputWidth = current_info.imageWidth; + current_outParam.outputHeight = current_info.imageHeight; + current_outParam.outputColorSpace = inParam->outputColorSpace; + + switch ((u32)current_outParam.outputColorSpace) + { + case CELL_PNGDEC_PALETTE: + case CELL_PNGDEC_GRAYSCALE: current_outParam.outputComponents = 1; break; + + case CELL_PNGDEC_GRAYSCALE_ALPHA: current_outParam.outputComponents = 2; break; + + case CELL_PNGDEC_RGB: current_outParam.outputComponents = 3; break; + + case CELL_PNGDEC_RGBA: + case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break; + + default: throw hle::error(CELL_PNGDEC_ERROR_ARG, fmt::Format("Unknown color space (%d)", (u32)current_outParam.outputColorSpace).c_str()); + } + + current_outParam.outputBitDepth = inParam->outputBitDepth; + current_outParam.outputMode = inParam->outputMode; + current_outParam.useMemorySpace = 0; // Unimplemented + + *outParam = current_outParam; +} + +void pngDecodeData( + CellPngDecSubHandle stream, + vm::ptr data, + vm::ptr dataCtrlParam, + vm::ptr dataOutInfo, + vm::ptr cbCtrlDisp = {}, + vm::ptr dispParam = {}) +{ 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; + const u32& fd = stream->fd; + const u64& fileSize = stream->fileSize; + const CellPngDecOutParam& current_outParam = stream->outParam; //Copy the PNG file to a buffer vm::var png((u32)fileSize); vm::var> pos, nread; - switch(subHandle_data->src.srcSelect.ToBE()) + switch (stream->src.srcSelect.ToBE()) { case se32(CELL_PNGDEC_BUFFER): - memmove(png.begin(), vm::get_ptr(subHandle_data->src.streamPtr), png.size()); + memmove(png.begin(), stream->src.streamPtr.get_ptr(), png.size()); break; case se32(CELL_PNGDEC_FILE): @@ -171,18 +237,18 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt //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 - ( - stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), - &::free - ); - if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; + auto image = std::unique_ptr + ( + stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), + &::free + ); + if (!image) throw hle::error(CELL_PNGDEC_ERROR_STREAM_FORMAT); const bool flip = current_outParam.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP; const int bytesPerLine = (u32)dataCtrlParam->outputBytesPerLine; uint image_size = width * height; - switch((u32)current_outParam.outputColorSpace) + switch ((u32)current_outParam.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: @@ -204,7 +270,7 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt memcpy(data.get_ptr(), image.get(), image_size); } } - break; + break; case CELL_PNGDEC_ARGB: { @@ -214,7 +280,7 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt { //TODO: find out if we can't do padding without an extra copy const int linesize = std::min(bytesPerLine, width * nComponents); - char *output = (char *) malloc(linesize); + char *output = (char *)malloc(linesize); for (int i = 0; i < height; i++) { const int dstOffset = i * bytesPerLine; @@ -235,7 +301,7 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt uint* img = (uint*)new char[image_size]; uint* source_current = (uint*)&(image.get()[0]); uint* dest_current = img; - for (uint i = 0; i < image_size / nComponents; i++) + for (uint i = 0; i < image_size / nComponents; i++) { uint val = *source_current; *dest_current = (val >> 24) | (val << 8); // set alpha (A8) as leftmost byte @@ -246,84 +312,21 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::pt delete[] img; } } - break; + 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; + break; default: - return CELL_PNGDEC_ERROR_ARG; + throw hle::error(CELL_PNGDEC_ERROR_ARG); } dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH; - - return CELL_OK; } -int cellPngDecExtDecodeData(u32 mainHandle, u32 subHandle, vm::ptr data, vm::ptr dataCtrlParam, - vm::ptr dataOutInfo, vm::ptr cbCtrlDisp, vm::ptr dispParam) -{ - cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam=0x%x)", - mainHandle, subHandle, data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr()); - - if (cbCtrlDisp) cellPngDec->Warning("*** cbCtrlDisp->cbCtrlDispFunc_addr=0x%x", (u32)cbCtrlDisp->cbCtrlDispFunc_addr); - - return cellPngDecDecodeData(mainHandle, subHandle, data, dataCtrlParam, dataOutInfo); -} - -int cellPngDecSetParameter(u32 mainHandle, u32 subHandle, vm::ptr inParam, vm::ptr outParam) -{ - cellPngDec->Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", - mainHandle, subHandle, inParam.addr(), outParam.addr()); - - CellPngDecSubHandle* subHandle_data; - if(!cellPngDec->CheckId(subHandle, subHandle_data)) - return CELL_PNGDEC_ERROR_FATAL; - - CellPngDecInfo& current_info = subHandle_data->info; - CellPngDecOutParam& current_outParam = subHandle_data->outParam; - - current_outParam.outputWidthByte = (current_info.imageWidth * current_info.numComponents * current_info.bitDepth) / 8; - current_outParam.outputWidth = current_info.imageWidth; - current_outParam.outputHeight = current_info.imageHeight; - current_outParam.outputColorSpace = inParam->outputColorSpace; - - switch ((u32)current_outParam.outputColorSpace) - { - case CELL_PNGDEC_PALETTE: - case CELL_PNGDEC_GRAYSCALE: current_outParam.outputComponents = 1; break; - - case CELL_PNGDEC_GRAYSCALE_ALPHA: current_outParam.outputComponents = 2; break; - - case CELL_PNGDEC_RGB: current_outParam.outputComponents = 3; break; - - case CELL_PNGDEC_RGBA: - case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break; - - default: return CELL_PNGDEC_ERROR_ARG; // Not supported color space - } - - current_outParam.outputBitDepth = inParam->outputBitDepth; - current_outParam.outputMode = inParam->outputMode; - current_outParam.useMemorySpace = 0; // Unimplemented - - *outParam = current_outParam; - - return CELL_OK; -} - -int cellPngDecExtSetParameter(u32 mainHandle, u32 subHandle, vm::ptr inParam, vm::ptr outParam, - vm::ptr extInParam, vm::ptr extOutParam) -{ - cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x", - mainHandle, subHandle, inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr()); - - return cellPngDecSetParameter(mainHandle, subHandle, inParam, outParam); -}*/ - s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptr threadInParam, vm::ptr threadOutParam) { #ifdef PRX_DEBUG @@ -333,7 +336,16 @@ s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptrWarning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", mainHandle.addr(), threadInParam.addr(), threadOutParam.addr()); - *mainHandle = pngDecCreate(threadInParam); + try + { + // create decoder + *mainHandle = pngDecCreate(threadInParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } // set codec version threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; @@ -356,8 +368,16 @@ s32 cellPngDecExtCreate( cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x, extThreadInParam_addr=0x%x, extThreadOutParam_addr=0x%x)", mainHandle.addr(), threadInParam.addr(), threadOutParam.addr(), extThreadInParam.addr(), extThreadOutParam.addr()); - // create decoder - *mainHandle = pngDecCreate(threadInParam, extThreadInParam); + try + { + // create decoder + *mainHandle = pngDecCreate(threadInParam, extThreadInParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } // set codec version threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; @@ -376,7 +396,16 @@ s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle) #else cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle.addr()); - pngDecDestroy(mainHandle); + try + { + pngDecDestroy(mainHandle); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } + return CELL_OK; #endif } @@ -394,8 +423,16 @@ s32 cellPngDecOpen( cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr()); - // create stream handle - *subHandle = pngDecOpen(mainHandle, src); + try + { + // create stream handle + *subHandle = pngDecOpen(mainHandle, src); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } // set memory info openInfo->initSpaceAllocated = 4096; @@ -419,8 +456,16 @@ s32 cellPngDecExtOpen( cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x, cbCtrlStrm_addr=0x%x, opnParam_addr=0x%x)", mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr(), cbCtrlStrm.addr(), opnParam.addr()); - // create stream handle - *subHandle = pngDecOpen(mainHandle, src, cbCtrlStrm, opnParam); + try + { + // create stream handle + *subHandle = pngDecOpen(mainHandle, src, cbCtrlStrm, opnParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } // set memory info openInfo->initSpaceAllocated = 4096; @@ -437,7 +482,15 @@ s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHand #else cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle.addr(), subHandle.addr()); - pngDecClose(subHandle); + try + { + pngDecClose(subHandle); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } return CELL_OK; #endif @@ -452,7 +505,15 @@ s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle su cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle.addr(), subHandle.addr(), info.addr()); - pngReadHeader(subHandle, info); + try + { + pngReadHeader(subHandle, info); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } return CELL_OK; #endif @@ -471,7 +532,15 @@ s32 cellPngDecExtReadHeader( cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", mainHandle.addr(), subHandle.addr(), info.addr(), extInfo.addr()); - pngReadHeader(subHandle, info, extInfo); + try + { + pngReadHeader(subHandle, info, extInfo); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } return CELL_OK; #endif @@ -487,7 +556,19 @@ s32 cellPngDecSetParameter( cellPngDec->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libpngdec + 0x33F4, libpngdec_rtoc); #else - UNIMPLEMENTED_FUNC(cellPngDec); + cellPngDec->Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr()); + + try + { + pngDecSetParameter(subHandle, inParam, outParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } + return CELL_OK; #endif } @@ -504,7 +585,19 @@ s32 cellPngDecExtSetParameter( cellPngDec->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libpngdec + 0x33EC, libpngdec_rtoc); #else - UNIMPLEMENTED_FUNC(cellPngDec); + cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x", + mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr()); + + try + { + pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } + return CELL_OK; #endif } @@ -520,7 +613,19 @@ s32 cellPngDecDecodeData( cellPngDec->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D40, libpngdec_rtoc); #else - UNIMPLEMENTED_FUNC(cellPngDec); + cellPngDec->Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr()); + + try + { + pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } + return CELL_OK; #endif } @@ -538,7 +643,19 @@ s32 cellPngDecExtDecodeData( cellPngDec->Warning("%s()", __FUNCTION__); return GetCurrentPPUThread().FastCall2(libpngdec + 0x5D38, libpngdec_rtoc); #else - UNIMPLEMENTED_FUNC(cellPngDec); + cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam_addr=0x%x)", + mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr()); + + try + { + pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam); + } + catch (hle::error& e) + { + e.print(__FUNCTION__); + return e.code; + } + return CELL_OK; #endif } @@ -546,7 +663,7 @@ s32 cellPngDecExtDecodeData( s32 cellPngDecGetUnknownChunks( CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, - vm::ptr unknownChunk, + vm::ptr> unknownChunk, vm::ptr unknownChunkNumber) { #ifdef PRX_DEBUG @@ -727,7 +844,7 @@ s32 cellPngDecGetTextChunk( CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr textInfoNum, - vm::ptr textInfo) + vm::ptr> textInfo) { #ifdef PRX_DEBUG cellPngDec->Warning("%s()", __FUNCTION__); diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index 54444e1c81..3f0edf4d3a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -221,7 +221,7 @@ s32 cellPngDecGetTextChunk( CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr textInfoNum, - vm::ptr textInfo); + vm::ptr> textInfo); s32 cellPngDecGetPLTE(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, vm::ptr plte); @@ -256,7 +256,7 @@ s32 cellPngDecGetpCAL(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHa s32 cellPngDecGetUnknownChunks( CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHandle, - vm::ptr unknownChunk, + vm::ptr> unknownChunk, vm::ptr unknownChunkNumber); @@ -380,23 +380,7 @@ s32 cellPngDecExtDecodeData( vm::ptr cbCtrlDisp, vm::ptr dispParam); -//// 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; -//}; - +// Custom structs struct PngDecoder { vm::ptr malloc; From c79b52b3348ec369319c8eb9d752cb11e19357f2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 8 Sep 2014 21:06:08 +0400 Subject: [PATCH 04/15] bugfix --- rpcs3/Emu/SysCalls/LogBase.cpp | 6 +++--- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 11 ++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index 47bb4458be..2afeb52bae 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -34,21 +34,21 @@ void LogBase::LogOutput(LogType type, const u32 id, const char* info, const std: hle::error::error(s32 errorCode, const char* errorText) : code(errorCode) , base(nullptr) - , text(errorText) + , text(errorText ? errorText : "") { } hle::error::error(s32 errorCode, const LogBase& errorBase, const char* errorText) : code(errorCode) , base(&errorBase) - , text(errorText) + , text(errorText ? errorText : "") { } hle::error::error(s32 errorCode, const LogBase* errorBase, const char* errorText) : code(errorCode) , base(errorBase) - , text(errorText) + , text(errorText ? errorText : "") { } diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index bccbb5fd8d..009d91d35a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -127,19 +127,12 @@ int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr Date: Tue, 9 Sep 2014 16:13:38 +0400 Subject: [PATCH 05/15] It was overcomplicated --- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 229 +++++++--------------- 1 file changed, 71 insertions(+), 158 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index e22ce0b368..1da9f18ddc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -18,7 +18,8 @@ u32 libpngdec; u32 libpngdec_rtoc; #endif -u32 pngDecCreate( +s32 pngDecCreate( + vm::ptr mainHandle, vm::ptr param, vm::ptr ext = {}) { @@ -27,7 +28,7 @@ u32 pngDecCreate( if (!dec) { - throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory allocation failed"); + return CELL_PNGDEC_ERROR_FATAL; } // initialize decoder @@ -41,20 +42,26 @@ u32 pngDecCreate( } // use virtual memory address as a handle - return dec.addr(); + *mainHandle = dec.addr(); + + return CELL_OK; } -void pngDecDestroy(CellPngDecMainHandle dec) +s32 pngDecDestroy(CellPngDecMainHandle dec) { if (!Memory.Free(dec.addr())) { - throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory deallocation failed"); + return CELL_PNGDEC_ERROR_FATAL; } + + return CELL_OK; } -u32 pngDecOpen( +s32 pngDecOpen( CellPngDecMainHandle dec, + vm::ptr subHandle, vm::ptr src, + vm::ptr openInfo, vm::ptr cb = {}, vm::ptr param = {}) { @@ -63,7 +70,7 @@ u32 pngDecOpen( if (!stream) { - throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory allocation failed"); + return CELL_PNGDEC_ERROR_FATAL; } // initialize stream @@ -102,19 +109,26 @@ u32 pngDecOpen( } // use virtual memory address as a handle - return stream.addr(); + *subHandle = stream.addr(); + + // set memory info + openInfo->initSpaceAllocated = 4096; + + return CELL_OK; } -void pngDecClose(CellPngDecSubHandle stream) +s32 pngDecClose(CellPngDecSubHandle stream) { cellFsClose(stream->fd); if (!Memory.Free(stream.addr())) { - throw hle::error(CELL_PNGDEC_ERROR_FATAL, "Memory deallocation failed"); + return CELL_PNGDEC_ERROR_FATAL; } + + return CELL_OK; } -void pngReadHeader( +s32 pngReadHeader( CellPngDecSubHandle stream, vm::ptr info, vm::ptr extInfo = {}) @@ -123,7 +137,7 @@ void pngReadHeader( if (stream->fileSize < 29) { - throw hle::error(CELL_PNGDEC_ERROR_HEADER, "The file is smaller than the length of a PNG header"); + return CELL_PNGDEC_ERROR_HEADER; // The file is smaller than the length of a PNG header } //Write the header to buffer @@ -146,7 +160,7 @@ void pngReadHeader( buffer_32[1].ToBE() != se32(0x0D0A1A0A) || // Error: The first 8 bytes are not a valid PNG signature buffer_32[3].ToBE() != se32(0x49484452)) // Error: The PNG file does not start with an IHDR chunk { - throw hle::error(CELL_PNGDEC_ERROR_HEADER, "Invalid PNG header"); + return CELL_PNGDEC_ERROR_HEADER; } switch (buffer[25]) @@ -156,7 +170,9 @@ void pngReadHeader( 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: throw hle::error(CELL_PNGDEC_ERROR_HEADER, "Unknown color space (%d)"); return; + default: + cellPngDec->Error("cellPngDecDecodeData: Unsupported color space (%d)", (u32)buffer[25]); + return CELL_PNGDEC_ERROR_HEADER; } current_info.imageWidth = buffer_32[4]; @@ -166,9 +182,16 @@ void pngReadHeader( current_info.chunkInformation = 0; // Unimplemented *info = current_info; + + if (extInfo) + { + extInfo->reserved = 0; + } + + return CELL_OK; } -void pngDecSetParameter( +s32 pngDecSetParameter( CellPngDecSubHandle stream, vm::ptr inParam, vm::ptr outParam, @@ -195,7 +218,9 @@ void pngDecSetParameter( case CELL_PNGDEC_RGBA: case CELL_PNGDEC_ARGB: current_outParam.outputComponents = 4; break; - default: throw hle::error(CELL_PNGDEC_ERROR_ARG, fmt::Format("Unknown color space (%d)", (u32)current_outParam.outputColorSpace).c_str()); + default: + cellPngDec->Error("pngDecSetParameter: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); + return CELL_PNGDEC_ERROR_ARG; } current_outParam.outputBitDepth = inParam->outputBitDepth; @@ -203,9 +228,11 @@ void pngDecSetParameter( current_outParam.useMemorySpace = 0; // Unimplemented *outParam = current_outParam; + + return CELL_OK; } -void pngDecodeData( +s32 pngDecodeData( CellPngDecSubHandle stream, vm::ptr data, vm::ptr dataCtrlParam, @@ -242,7 +269,11 @@ void pngDecodeData( stbi_load_from_memory(png.ptr(), (s32)fileSize, &width, &height, &actual_components, 4), &::free ); - if (!image) throw hle::error(CELL_PNGDEC_ERROR_STREAM_FORMAT); + if (!image) + { + cellPngDec->Error("pngDecodeData: stbi_load_from_memory failed"); + return CELL_PNGDEC_ERROR_STREAM_FORMAT; + } const bool flip = current_outParam.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP; const int bytesPerLine = (u32)dataCtrlParam->outputBytesPerLine; @@ -317,14 +348,17 @@ void pngDecodeData( case CELL_PNGDEC_GRAYSCALE: case CELL_PNGDEC_PALETTE: case CELL_PNGDEC_GRAYSCALE_ALPHA: - cellPngDec->Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); + cellPngDec->Error("pngDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); break; default: - throw hle::error(CELL_PNGDEC_ERROR_ARG); + cellPngDec->Error("pngDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); + return CELL_PNGDEC_ERROR_ARG; } dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH; + + return CELL_OK; } s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptr threadInParam, vm::ptr threadOutParam) @@ -336,16 +370,8 @@ s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptrWarning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", mainHandle.addr(), threadInParam.addr(), threadOutParam.addr()); - try - { - // create decoder - *mainHandle = pngDecCreate(threadInParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } + // create decoder + if (s32 res = pngDecCreate(mainHandle, threadInParam)) return res; // set codec version threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; @@ -368,16 +394,8 @@ s32 cellPngDecExtCreate( cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x, extThreadInParam_addr=0x%x, extThreadOutParam_addr=0x%x)", mainHandle.addr(), threadInParam.addr(), threadOutParam.addr(), extThreadInParam.addr(), extThreadOutParam.addr()); - try - { - // create decoder - *mainHandle = pngDecCreate(threadInParam, extThreadInParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } + // create decoder + if (s32 res = pngDecCreate(mainHandle, threadInParam, extThreadInParam)) return res; // set codec version threadOutParam->pngCodecVersion = PNGDEC_CODEC_VERSION; @@ -396,17 +414,8 @@ s32 cellPngDecDestroy(CellPngDecMainHandle mainHandle) #else cellPngDec->Warning("cellPngDecDestroy(mainHandle=0x%x)", mainHandle.addr()); - try - { - pngDecDestroy(mainHandle); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + // destroy decoder + return pngDecDestroy(mainHandle); #endif } @@ -423,21 +432,8 @@ s32 cellPngDecOpen( cellPngDec->Warning("cellPngDecOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x)", mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr()); - try - { - // create stream handle - *subHandle = pngDecOpen(mainHandle, src); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - // set memory info - openInfo->initSpaceAllocated = 4096; - - return CELL_OK; + // create stream handle + return pngDecOpen(mainHandle, subHandle, src, openInfo); #endif } @@ -456,21 +452,8 @@ s32 cellPngDecExtOpen( cellPngDec->Warning("cellPngDecExtOpen(mainHandle=0x%x, subHandle_addr=0x%x, src_addr=0x%x, openInfo_addr=0x%x, cbCtrlStrm_addr=0x%x, opnParam_addr=0x%x)", mainHandle.addr(), subHandle.addr(), src.addr(), openInfo.addr(), cbCtrlStrm.addr(), opnParam.addr()); - try - { - // create stream handle - *subHandle = pngDecOpen(mainHandle, src, cbCtrlStrm, opnParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - // set memory info - openInfo->initSpaceAllocated = 4096; - - return CELL_OK; + // create stream handle + return pngDecOpen(mainHandle, subHandle, src, openInfo, cbCtrlStrm, opnParam); #endif } @@ -482,17 +465,7 @@ s32 cellPngDecClose(CellPngDecMainHandle mainHandle, CellPngDecSubHandle subHand #else cellPngDec->Warning("cellPngDecClose(mainHandle=0x%x, subHandle=0x%x)", mainHandle.addr(), subHandle.addr()); - try - { - pngDecClose(subHandle); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngDecClose(subHandle); #endif } @@ -505,17 +478,7 @@ s32 cellPngDecReadHeader(CellPngDecMainHandle mainHandle, CellPngDecSubHandle su cellPngDec->Warning("cellPngDecReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x)", mainHandle.addr(), subHandle.addr(), info.addr()); - try - { - pngReadHeader(subHandle, info); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngReadHeader(subHandle, info); #endif } @@ -532,17 +495,7 @@ s32 cellPngDecExtReadHeader( cellPngDec->Warning("cellPngDecExtReadHeader(mainHandle=0x%x, subHandle=0x%x, info_addr=0x%x, extInfo_addr=0x%x)", mainHandle.addr(), subHandle.addr(), info.addr(), extInfo.addr()); - try - { - pngReadHeader(subHandle, info, extInfo); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngReadHeader(subHandle, info, extInfo); #endif } @@ -559,17 +512,7 @@ s32 cellPngDecSetParameter( cellPngDec->Warning("cellPngDecSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x)", mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr()); - try - { - pngDecSetParameter(subHandle, inParam, outParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngDecSetParameter(subHandle, inParam, outParam); #endif } @@ -588,17 +531,7 @@ s32 cellPngDecExtSetParameter( cellPngDec->Warning("cellPngDecExtSetParameter(mainHandle=0x%x, subHandle=0x%x, inParam_addr=0x%x, outParam_addr=0x%x, extInParam=0x%x, extOutParam=0x%x", mainHandle.addr(), subHandle.addr(), inParam.addr(), outParam.addr(), extInParam.addr(), extOutParam.addr()); - try - { - pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngDecSetParameter(subHandle, inParam, outParam, extInParam, extOutParam); #endif } @@ -616,17 +549,7 @@ s32 cellPngDecDecodeData( cellPngDec->Warning("cellPngDecDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x)", mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr()); - try - { - pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo); #endif } @@ -646,17 +569,7 @@ s32 cellPngDecExtDecodeData( cellPngDec->Warning("cellPngDecExtDecodeData(mainHandle=0x%x, subHandle=0x%x, data_addr=0x%x, dataCtrlParam_addr=0x%x, dataOutInfo_addr=0x%x, cbCtrlDisp_addr=0x%x, dispParam_addr=0x%x)", mainHandle.addr(), subHandle.addr(), data.addr(), dataCtrlParam.addr(), dataOutInfo.addr(), cbCtrlDisp.addr(), dispParam.addr()); - try - { - pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam); - } - catch (hle::error& e) - { - e.print(__FUNCTION__); - return e.code; - } - - return CELL_OK; + return pngDecodeData(subHandle, data, dataCtrlParam, dataOutInfo, cbCtrlDisp, dispParam); #endif } From cd392563616140859bc6374640644905d03c06b7 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 11 Sep 2014 23:18:19 +0400 Subject: [PATCH 06/15] CallbackManager rewritten --- Utilities/Thread.cpp | 27 ++- rpcs3/Emu/Memory/Memory.h | 1 - rpcs3/Emu/Memory/vm_ptr.h | 129 +++----------- rpcs3/Emu/RSX/GL/GLProgram.cpp | 1 + rpcs3/Emu/RSX/GSManager.cpp | 2 +- rpcs3/Emu/RSX/GSRender.cpp | 1 + rpcs3/Emu/RSX/RSXTexture.cpp | 1 + rpcs3/Emu/RSX/RSXThread.cpp | 36 ++-- rpcs3/Emu/RSX/RSXThread.h | 9 +- rpcs3/Emu/SysCalls/CB_FUNC.h | 34 ++++ rpcs3/Emu/SysCalls/Callback.cpp | 176 +++++++------------ rpcs3/Emu/SysCalls/Callback.h | 168 ++---------------- rpcs3/Emu/SysCalls/ModuleManager.cpp | 3 +- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 18 +- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 16 +- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp | 5 +- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellPngDec.h | 16 +- rpcs3/Emu/SysCalls/Modules/cellResc.cpp | 71 ++++++-- rpcs3/Emu/SysCalls/Modules/cellResc.h | 42 +---- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 84 +++++++-- rpcs3/Emu/SysCalls/Modules/cellSysutil.h | 23 +++ rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp | 1 + rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 6 +- rpcs3/Emu/System.cpp | 6 +- rpcs3/Emu/System.h | 4 +- rpcs3/Gui/GLGSFrame.cpp | 1 + rpcs3/Gui/MainFrame.cpp | 7 +- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 34 files changed, 395 insertions(+), 503 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/CB_FUNC.h diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index aa59aa2384..727005e651 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Log.h" #include "Thread.h" thread_local NamedThreadBase* g_tls_this_thread = nullptr; @@ -66,7 +67,18 @@ void ThreadBase::Start() SetCurrentNamedThread(this); g_thread_count++; - Task(); + try + { + Task(); + } + catch (const char* e) + { + LOG_ERROR(HLE, "%s: %s", GetThreadName().c_str(), e); + } + catch (const std::string& e) + { + LOG_ERROR(HLE, "%s: %s", GetThreadName().c_str(), e.c_str()); + } m_alive = false; g_thread_count--; @@ -142,7 +154,18 @@ void thread::start(std::function func) SetCurrentNamedThread(&info); g_thread_count++; - func(); + try + { + func(); + } + catch (const char* e) + { + LOG_ERROR(HLE, "%s: %s", name.c_str(), e); + } + catch (const std::string& e) + { + LOG_ERROR(HLE, "%s: %s", name.c_str(), e.c_str()); + } g_thread_count--; }); diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 4d83e2ec67..6866bd22fa 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -1,7 +1,6 @@ #pragma once #include "MemoryBlock.h" -#include "Emu/SysCalls/Callback.h" using std::nullptr_t; diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 24824b382f..a687eab5d4 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -87,6 +87,11 @@ namespace vm return m_addr; } + void set(const AT value) + { + m_addr = value; + } + static _ptr_base make(AT addr) { return (_ptr_base&)addr; @@ -181,6 +186,11 @@ namespace vm return m_addr; } + void set(const AT value) + { + m_addr = value; + } + operator bool() const { return m_addr != 0; @@ -219,6 +229,11 @@ namespace vm return m_addr; } + void set(const AT value) + { + m_addr = value; + } + void* const get_ptr() const { return vm::get_ptr(m_addr); @@ -264,6 +279,11 @@ namespace vm return m_addr; } + void set(const AT value) + { + m_addr = value; + } + const void* const get_ptr() const { return vm::get_ptr(m_addr); @@ -290,124 +310,27 @@ namespace vm _ptr_base& operator = (const _ptr_base& right) = default; }; - - template - class _ptr_base - { - AT m_addr; - - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); - - static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); - - __forceinline RT call_func(bool is_async) const - { - Callback cb; - cb.SetAddr(m_addr); - return (RT)cb.Branch(!is_async); - } - - public: - typedef RT(*type)(); - - __forceinline RT operator()() const - { - return call_func(false); - } - - __forceinline void async() const - { - call_func(true); - } - - AT addr() const - { - return m_addr; - } - - operator bool() const - { - return m_addr != 0; - } - - //typedef typename invert_be_t::type AT2; - - template - operator const _ptr_base() const - { - typename std::remove_const::type addr; addr = m_addr; - return (_ptr_base&)addr; - } - - static _ptr_base make(AT addr) - { - return (_ptr_base&)addr; - } - - operator std::function() const - { - const AT addr = m_addr; - return [addr]() -> RT { return make(addr)(); }; - } - - _ptr_base& operator = (const _ptr_base& right) = default; - }; template class _ptr_base { AT m_addr; - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); - - static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); - static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); - - template - struct _func_arg - { - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback argument type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback argument type (vector)"); - - static_assert(sizeof(TT) <= 8, "Invalid callback argument type"); - static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); - static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); - - __forceinline static u64 get_value(const TT& arg) - { - u64 res = 0; - (TT&)res = arg; - return res; - } - }; - - __forceinline RT call_func(bool is_async, T... args) const - { - Callback cb; - cb.SetAddr(m_addr); - cb.Handle(_func_arg::get_value(args)...); - return (RT)cb.Branch(!is_async); - } - public: typedef RT(*type)(T...); - __forceinline RT operator()(T... args) const - { - return call_func(false, args...); - } - - __forceinline void async(T... args) const - { - call_func(true, args...); - } + RT operator()(T... args) const; // defined in Callback.h (CB_FUNC.h) AT addr() const { return m_addr; } + void set(const AT value) + { + m_addr = value; + } + operator bool() const { return m_addr != 0; diff --git a/rpcs3/Emu/RSX/GL/GLProgram.cpp b/rpcs3/Emu/RSX/GL/GLProgram.cpp index 96e32f6be4..e7e7fdaa0a 100644 --- a/rpcs3/Emu/RSX/GL/GLProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLProgram.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" #include "GLProgram.h" #include "GLGSRender.h" diff --git a/rpcs3/Emu/RSX/GSManager.cpp b/rpcs3/Emu/RSX/GSManager.cpp index 17155bbbb3..e4870d13ad 100644 --- a/rpcs3/Emu/RSX/GSManager.cpp +++ b/rpcs3/Emu/RSX/GSManager.cpp @@ -1,6 +1,6 @@ #include "stdafx.h" #include "rpcs3/Ini.h" - +#include "Emu/Memory/Memory.h" #include "sysutil_video.h" #include "GSManager.h" diff --git a/rpcs3/Emu/RSX/GSRender.cpp b/rpcs3/Emu/RSX/GSRender.cpp index acad3443c5..371db32257 100644 --- a/rpcs3/Emu/RSX/GSRender.cpp +++ b/rpcs3/Emu/RSX/GSRender.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "GSManager.h" diff --git a/rpcs3/Emu/RSX/RSXTexture.cpp b/rpcs3/Emu/RSX/RSXTexture.cpp index c7d4d0bb8d..6904da2420 100644 --- a/rpcs3/Emu/RSX/RSXTexture.cpp +++ b/rpcs3/Emu/RSX/RSXTexture.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "Emu/Memory/Memory.h" #include "RSXThread.h" #include "RSXTexture.h" diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 9958db93a6..861a7f02d1 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -4,6 +4,9 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "RSXThread.h" + +#include "Emu/Cell/PPUThread.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/lv2/sys_time.h" #define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.addr()) : args[x].ToLE()) @@ -293,8 +296,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const if(m_flip_handler) { - m_flip_handler.Handle(1, 0, 0); - m_flip_handler.Branch(false); + auto cb = m_flip_handler; + Emu.GetCallbackManager().Async([cb]() + { + cb(1); + }); } //Emu.Pause(); @@ -1969,8 +1975,11 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const case GCM_SET_USER_COMMAND: { const u32 cause = ARGS(0); - m_user_handler.Handle(cause); - m_user_handler.Branch(false); + auto cb = m_user_handler; + Emu.GetCallbackManager().Async([cb, cause]() + { + cb(cause); + }); } break; @@ -2084,22 +2093,12 @@ void RSXThread::Begin(u32 draw_mode) m_draw_mode = draw_mode; m_draw_array_count = 0; m_draw_array_first = ~0; - - if(Emu.GetCallbackManager().m_exit_callback.m_callbacks.size()) - { - //Emu.GetCallbackManager().m_exit_callback.Handle(0x0121, 0); - } } void RSXThread::End() { ExecCMD(); - if(Emu.GetCallbackManager().m_exit_callback.m_callbacks.size()) - { - //Emu.GetCallbackManager().m_exit_callback.Handle(0x0122, 0); - } - m_indexed_array.Reset(); m_fragment_constants.clear(); m_transform_constants.clear(); @@ -2120,7 +2119,7 @@ void RSXThread::Task() OnInitThread(); - m_last_flip_time = get_system_time(); + m_last_flip_time = get_system_time() - 1000000; volatile bool is_vblank_stopped = false; thread vblank("VBlank thread", [&]() @@ -2142,8 +2141,11 @@ void RSXThread::Task() m_vblank_count++; if (m_vblank_handler) { - m_vblank_handler.Handle(1); - m_vblank_handler.Branch(false); + auto cb = m_vblank_handler; + Emu.GetCallbackManager().Async([cb]() + { + cb(1); + }); } continue; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index d7bad7561b..c928d9c288 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -150,10 +150,10 @@ public: SSemaphore m_sem_flush; SSemaphore m_sem_flip; u64 m_last_flip_time; - Callback m_flip_handler; - Callback m_user_handler; + vm::ptr m_flip_handler; + vm::ptr m_user_handler; u64 m_vblank_count; - Callback m_vblank_handler; + vm::ptr m_vblank_handler; public: // Dither @@ -444,6 +444,9 @@ protected: , m_gcm_current_buffer(0) , m_read_buffer(true) { + m_flip_handler.set(0); + m_vblank_handler.set(0); + m_user_handler.set(0); m_set_depth_test = false; m_set_alpha_test = false; m_set_depth_bounds_test = false; diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h new file mode 100644 index 0000000000..afbc35912b --- /dev/null +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -0,0 +1,34 @@ +#pragma once + +namespace vm +{ + template + struct _func_arg + { + static_assert(!std::is_floating_point::value, "TODO: Unsupported callback argument type (floating point)"); + static_assert(!std::is_same::value, "TODO: Unsupported callback argument type (vector)"); + + static_assert(sizeof(TT) <= 8, "Invalid callback argument type"); + static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); + + __forceinline static u64 get_value(const TT& arg) + { + u64 res = 0; + (TT&)res = arg; + return res; + } + }; + + template + RT _ptr_base::operator ()(T... args) const + { + static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); + static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); + + static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); + + return (RT)GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg::get_value(args)...); + } +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index f3af71d9b8..3f8968736d 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -1,152 +1,100 @@ #include "stdafx.h" #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" +#include "ErrorCodes.h" #include "Emu/System.h" +#include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" - #include "Callback.h" -Callback::Callback(u32 slot, u64 addr) - : m_addr(addr) - , m_slot(slot) - , a1(0) - , a2(0) - , a3(0) - , a4(0) - , a5(0) - , m_has_data(false) - , m_name("Callback") +void CallbackManager::Register(const std::function& func) { + std::lock_guard lock(m_mutex); + + m_cb_list.push_back(func); } -u32 Callback::GetSlot() const +void CallbackManager::Async(const std::function& func) { - return m_slot; + std::lock_guard lock(m_mutex); + + m_async_list.push_back(func); + m_cb_thread->Notify(); } -u64 Callback::GetAddr() const +bool CallbackManager::Check(s32& result) { - return m_addr; -} + std::function func = nullptr; -void Callback::SetSlot(u32 slot) -{ - m_slot = slot; -} - -void Callback::SetAddr(u64 addr) -{ - m_addr = addr; -} - -bool Callback::HasData() const -{ - return m_has_data; -} - -void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4, u64 _a5) -{ - a1 = _a1; - a2 = _a2; - a3 = _a3; - a4 = _a4; - a5 = _a5; - m_has_data = true; -} - -u64 Callback::Branch(bool wait) -{ - m_has_data = false; - - static std::mutex cb_mutex; - - CPUThread& thr = Emu.GetCallbackThread(); - -again: - - while (thr.IsAlive()) { - if (Emu.IsStopped()) + std::lock_guard lock(m_mutex); + + if (m_cb_list.size()) { - LOG_WARNING(HLE, "Callback::Branch() aborted"); - return 0; + func = m_cb_list[0]; + m_cb_list.erase(m_cb_list.begin()); } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - - std::lock_guard lock(cb_mutex); - - if (thr.IsAlive()) + + if (func) { - goto again; + result = func(); + return true; } - if (Emu.IsStopped()) + else { - LOG_WARNING(HLE, "Callback::Branch() aborted"); - return 0; + return false; } +} - thr.Stop(); - thr.Reset(); +void CallbackManager::Init() +{ + std::lock_guard lock(m_mutex); - thr.SetEntry(m_addr); - thr.SetPrio(1001); - thr.SetStackSize(0x10000); - thr.SetName(m_name); + m_cb_thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - thr.SetArg(0, a1); - thr.SetArg(1, a2); - thr.SetArg(2, a3); - thr.SetArg(3, a4); - thr.Run(); - ((PPUThread&)thr).GPR[7] = a5; + u32 cb_shit = Memory.MainMem.AllocAlign(8); + vm::write32(cb_shit, Emu.m_ppu_thr_stop); + vm::write32(cb_shit + 4, 0); - thr.Exec(); + m_cb_thread->SetEntry(cb_shit); + m_cb_thread->SetPrio(1001); // ??? + m_cb_thread->SetStackSize(0x10000); + m_cb_thread->Run(); - if (!wait) + thread cb_async_thread("CallbackManager::Async() thread", [this]() { - return 0; - } + SetCurrentNamedThread(m_cb_thread); - while (thr.IsAlive()) - { - if (Emu.IsStopped()) + while (!Emu.IsStopped()) { - LOG_WARNING(HLE, "Callback::Branch(true) aborted (end)"); - return 0; + std::function func = nullptr; + { + std::lock_guard lock(m_mutex); + + if (m_async_list.size()) + { + func = m_async_list[0]; + m_async_list.erase(m_async_list.begin()); + } + } + + if (func) + { + func(); + continue; + } + m_cb_thread->WaitForAnySignal(); } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + }); - return thr.GetExitStatus(); + cb_async_thread.detach(); } -void Callback::SetName(const std::string& name) +void CallbackManager::Clear() { - m_name = name; -} + std::lock_guard lock(m_mutex); -Callback::operator bool() const -{ - return GetAddr() != 0; -} - -Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr) -{ - a2 = userdata; -} - -void Callback2::Handle(u64 status) -{ - Callback::Handle(status, a2, 0); -} - -Callback3::Callback3(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr) -{ - a3 = userdata; -} - -void Callback3::Handle(u64 status, u64 param) -{ - Callback::Handle(status, param, a3); + m_cb_list.clear(); + m_async_list.clear(); } diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index faf3b79e99..6402ca84b6 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -1,163 +1,23 @@ #pragma once +#include "CB_FUNC.h" -class Callback +class CPUThread; + +class CallbackManager { -protected: - u64 m_addr; - u32 m_slot; - - bool m_has_data; - - std::string m_name; + std::vector> m_cb_list; + std::vector> m_async_list; + CPUThread* m_cb_thread; + std::mutex m_mutex; public: - u64 a1; - u64 a2; - u64 a3; - u64 a4; - u64 a5; + void Register(const std::function& func); // register callback (called in Check() method) - u32 GetSlot() const; - u64 GetAddr() const; - void SetSlot(u32 slot); - void SetAddr(u64 addr); - bool HasData() const; + void Async(const std::function& func); // register callback for callback thread (called immediately) - Callback(u32 slot = 0, u64 addr = 0); - void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0, u64 a5 = 0); - u64 Branch(bool wait); - void SetName(const std::string& name); + bool Check(s32& result); // call one callback registered by Register() method - operator bool() const; -}; - -struct Callback2 : public Callback -{ - Callback2(u32 slot, u64 addr, u64 userdata); - void Handle(u64 status); -}; - -struct Callback3 : public Callback -{ - Callback3(u32 slot, u64 addr, u64 userdata); - void Handle(u64 status, u64 param); -}; - -struct Callbacks -{ - std::vector m_callbacks; - bool m_in_manager; - - Callbacks() : m_in_manager(false) - { - } - - virtual void Register(u32 slot, u64 addr, u64 userdata) - { - Unregister(slot); - } - - void Unregister(u32 slot) - { - for(u32 i=0; i m_callbacks; - Callbacks3 m_exit_callback; - - void Add(Callbacks& c) - { - if(c.m_in_manager) return; - - c.m_in_manager = true; - m_callbacks.push_back(&c); - } - - void Init() - { - Add(m_exit_callback); - } - - void Clear() - { - for(u32 i=0; im_callbacks.clear(); - m_callbacks[i]->m_in_manager = false; - } - - m_callbacks.clear(); - } + void Init(); + + void Clear(); }; diff --git a/rpcs3/Emu/SysCalls/ModuleManager.cpp b/rpcs3/Emu/SysCalls/ModuleManager.cpp index 1bcb6e7466..3e894fdd29 100644 --- a/rpcs3/Emu/SysCalls/ModuleManager.cpp +++ b/rpcs3/Emu/SysCalls/ModuleManager.cpp @@ -58,6 +58,7 @@ extern Module *cellSync2; extern void cellSysmodule_init(); extern Module *cellSysmodule; extern void cellSysutil_init(); +extern void cellSysutil_load(); extern Module *cellSysutil; extern void cellSysutilAp_init(); extern Module *cellSysutilAp; @@ -266,7 +267,7 @@ void ModuleManager::init() cellSync2 = static_cast (&(m_mod_init.back())) + 1; m_mod_init.emplace_back(0x0055, cellSync2_init); cellSysutil = static_cast (&(m_mod_init.back())) + 1; - m_mod_init.emplace_back(0x0015, cellSysutil_init); + m_mod_init.emplace_back(0x0015, cellSysutil_init, cellSysutil_load, nullptr); cellSysutilAp = static_cast (&(m_mod_init.back())) + 1; m_mod_init.emplace_back(0x0039, cellSysutilAp_init); cellSysmodule = static_cast (&(m_mod_init.back())) + 1; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 097106036e..b55bbcec80 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Utilities/rMsgBox.h" #include "Emu/FS/VFS.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 0ae9f803d7..edcc13f0e6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -456,11 +456,11 @@ int cellGcmSetFlip(vm::ptr ctxt, u32 id) return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; } -void cellGcmSetFlipHandler(u32 handler_addr) +void cellGcmSetFlipHandler(vm::ptr handler) { - cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler_addr); + cellGcmSys->Warning("cellGcmSetFlipHandler(handler_addr=%d)", handler.addr()); - Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); + Emu.GetGSManager().GetRender().m_flip_handler = handler; } int cellGcmSetFlipMode(u32 mode) @@ -596,18 +596,18 @@ int cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u return CELL_OK; } -void cellGcmSetUserHandler(u32 handler_addr) +void cellGcmSetUserHandler(vm::ptr handler) { - cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler_addr); + cellGcmSys->Warning("cellGcmSetUserHandler(handler_addr=0x%x)", handler.addr()); - Emu.GetGSManager().GetRender().m_user_handler.SetAddr(handler_addr); + Emu.GetGSManager().GetRender().m_user_handler = handler; } -void cellGcmSetVBlankHandler(u32 handler_addr) +void cellGcmSetVBlankHandler(vm::ptr handler) { - cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler_addr); + cellGcmSys->Warning("cellGcmSetVBlankHandler(handler_addr=0x%x)", handler.addr()); - Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr); + Emu.GetGSManager().GetRender().m_vblank_handler = handler; } int cellGcmSetWaitFlip(vm::ptr ctxt) diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index 009d91d35a..8df2d3f476 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Utilities/Log.h" #include "Utilities/rMsgBox.h" @@ -104,6 +105,8 @@ int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr msgString, vm::ptrWarning("MsgDialog thread aborted"); + return; + } std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -125,7 +133,13 @@ int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr s32 + { + callback((s32)status, userData); + return CELL_OK; + }); + } CallAfter([]() { diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h index 820d2a7792..9c0b2eeb55 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.h @@ -79,7 +79,7 @@ enum CELL_MSGDIALOG_BUTTON_ESCAPE = 3, }; -typedef void(*CellMsgDialogCallback)(int buttonType, u32 userData); +typedef void(*CellMsgDialogCallback)(s32 buttonType, u32 userData); int cellMsgDialogOpen2(u32 type, vm::ptr msgString, vm::ptr callback, u32 userData, u32 extParam); int cellMsgDialogOpenErrorCode(u32 errorCode, vm::ptr callback, u32 userData, u32 extParam); diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp index 0402966732..35b3d378a3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp @@ -3,6 +3,7 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "cellSysutil.h" #include "cellNetCtl.h" //void cellNetCtl_init(); @@ -56,7 +57,7 @@ int cellNetCtlNetStartDialogLoadAsync(vm::ptr par cellNetCtl->Warning("cellNetCtlNetStartDialogLoadAsync(param_addr=0x%x)", param.addr()); // TODO: Actually sign into PSN - Emu.GetCallbackManager().m_exit_callback.Handle(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0); + sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_FINISHED, 0); return CELL_OK; } @@ -71,7 +72,7 @@ int cellNetCtlNetStartDialogUnloadAsync(vm::ptr { cellNetCtl->Warning("cellNetCtlNetStartDialogUnloadAsync(result_addr=0x%x)", result.addr()); - Emu.GetCallbackManager().m_exit_callback.Handle(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0); + sysutilSendSystemCommand(CELL_SYSUTIL_NET_CTL_NETSTART_UNLOADED, 0); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1da9f18ddc..c036052c2a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -365,6 +365,7 @@ s32 cellPngDecCreate(vm::ptr mainHandle, vm::ptrWarning("%s()", __FUNCTION__); + const_cast(*threadInParam).spuThreadEnable = CELL_PNGDEC_SPU_THREAD_DISABLE; // hack return GetCurrentPPUThread().FastCall2(libpngdec + 0x295C, libpngdec_rtoc); #else cellPngDec->Warning("cellPngDecCreate(mainHandle_addr=0x%x, threadInParam_addr=0x%x, threadOutParam_addr=0x%x)", diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h index 3f0edf4d3a..6bb2d021a4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.h @@ -28,7 +28,7 @@ enum }; // Consts -enum CellPngDecColorSpace +enum CellPngDecColorSpace : u32 { CELL_PNGDEC_GRAYSCALE = 1, CELL_PNGDEC_RGB = 2, @@ -44,43 +44,43 @@ enum CellPngDecSpuThreadEna : u32 CELL_PNGDEC_SPU_THREAD_ENABLE = 1, }; -enum CellPngDecStreamSrcSel +enum CellPngDecStreamSrcSel : u32 { CELL_PNGDEC_FILE = 0, CELL_PNGDEC_BUFFER = 1, }; -enum CellPngDecInterlaceMode +enum CellPngDecInterlaceMode : u32 { CELL_PNGDEC_NO_INTERLACE = 0, CELL_PNGDEC_ADAM7_INTERLACE = 1, }; -enum CellPngDecOutputMode +enum CellPngDecOutputMode : u32 { CELL_PNGDEC_TOP_TO_BOTTOM = 0, CELL_PNGDEC_BOTTOM_TO_TOP = 1, }; -enum CellPngDecPackFlag +enum CellPngDecPackFlag : u32 { CELL_PNGDEC_1BYTE_PER_NPIXEL = 0, CELL_PNGDEC_1BYTE_PER_1PIXEL = 1, }; -enum CellPngDecAlphaSelect +enum CellPngDecAlphaSelect : u32 { CELL_PNGDEC_STREAM_ALPHA = 0, CELL_PNGDEC_FIX_ALPHA = 1, }; -enum CellPngDecCommand +enum CellPngDecCommand : u32 { CELL_PNGDEC_CONTINUE = 0, CELL_PNGDEC_STOP = 1, }; -enum CellPngDecDecodeStatus +enum CellPngDecDecodeStatus : u32 { CELL_PNGDEC_DEC_STATUS_FINISH = 0, CELL_PNGDEC_DEC_STATUS_STOP = 1, diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index da87d67abe..079e9d82c6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -11,6 +11,41 @@ Module *cellResc = nullptr; extern s32 cellVideoOutConfigure(u32 videoOut, vm::ptr config, vm::ptr option, u32 waitForEvent); +extern int cellGcmSetFlipMode(u32 mode); +extern void cellGcmSetFlipHandler(vm::ptr handler); +extern void cellGcmSetVBlankHandler(vm::ptr handler); +extern int cellGcmAddressToOffset(u64 address, vm::ptr> offset); +extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); +extern int cellGcmSetPrepareFlip(vm::ptr ctx, u32 id); +extern int cellGcmSetSecondVFrequency(u32 freq); +extern u32 cellGcmGetLabelAddress(u8 index); +extern u32 cellGcmGetTiledPitchSize(u32 size); + +CCellRescInternal* s_rescInternalInstance = nullptr; + +// Local Functions +int cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved); + +// Help Functions +inline bool IsPal() { return s_rescInternalInstance->m_dstMode == CELL_RESC_720x576; } +inline bool IsPal60Hsync() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC); } +inline bool IsPalDrop() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_DROP); } +inline bool IsPalInterpolate() { + return (IsPal() && ((s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE) + || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_30_DROP) + || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE))); +} +inline bool IsNotPalInterpolate() { return !IsPalInterpolate(); } +inline bool IsPalTemporal() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode != CELL_RESC_PAL_50); } +inline bool IsNotPalTemporal() { return !IsPalTemporal(); } +inline bool IsNotPal() { return !IsPal(); } +inline bool IsGcmFlip() { + return (IsNotPal() || (IsPal() && (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_50 + || s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC))); +} +inline int GetNumColorBuffers(){ return IsPalInterpolate() ? 6 : (IsPalDrop() ? 3 : 2); } +inline bool IsInterlace() { return s_rescInternalInstance->m_initConfig.interlaceMode == CELL_RESC_INTERLACE_FILTER; } +inline bool IsTextureNR() { return !IsInterlace(); } static const float PICTURE_SIZE = (1.0f), @@ -373,8 +408,8 @@ void InitMembers() s_rescInternalInstance->m_bInitialized = false; s_rescInternalInstance->m_bNewlyAdjustRatio = false; - s_rescInternalInstance->s_applicationVBlankHandler = 0; - s_rescInternalInstance->s_applicationFlipHandler = 0; + s_rescInternalInstance->s_applicationVBlankHandler.set(0); + s_rescInternalInstance->s_applicationFlipHandler.set(0); //E PAL related variables //s_rescInternalInstance->m_intrThread50 = 0; @@ -567,7 +602,7 @@ void cellRescExit() if (IsPalTemporal()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_DISABLE); - cellGcmSetVBlankHandler(0); + cellGcmSetVBlankHandler({}); //GcmSysTypePrefix::cellGcmSetSecondVHandler(NULL); if (IsPalInterpolate()) @@ -631,7 +666,7 @@ int cellRescSetDsts(u32 dstsMode, vm::ptr dsts) return CELL_OK; } -void SetVBlankHandler(u32 handler) +void SetVBlankHandler(vm::ptr handler) { if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) { @@ -643,12 +678,12 @@ void SetVBlankHandler(u32 handler) if (IsNotPalTemporal()) { cellGcmSetVBlankHandler(handler); - s_rescInternalInstance->s_applicationVBlankHandler = 0; + s_rescInternalInstance->s_applicationVBlankHandler.set(0); } else if (IsPal60Hsync()) { //cellGcmSetSecondVHandler(handler); - s_rescInternalInstance->s_applicationVBlankHandler = 0; + s_rescInternalInstance->s_applicationVBlankHandler.set(0); } else { @@ -657,7 +692,7 @@ void SetVBlankHandler(u32 handler) } -void SetFlipHandler(u32 handler) +void SetFlipHandler(vm::ptr handler) { if (!s_rescInternalInstance->m_bInitialized || s_rescInternalInstance->m_dstMode == 0) { @@ -669,7 +704,7 @@ void SetFlipHandler(u32 handler) if (IsGcmFlip()) { cellGcmSetFlipHandler(handler); - s_rescInternalInstance->s_applicationFlipHandler = 0; + s_rescInternalInstance->s_applicationFlipHandler.set(0); } else { @@ -744,20 +779,20 @@ int cellRescSetDisplayMode(u32 displayMode) cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); //cellGcmSetVBlankHandler(IntrHandler50); //cellGcmSetSecondVHandler(IntrHandler60); - cellGcmSetFlipHandler(0); + cellGcmSetFlipHandler({}); } else if (IsPalDrop()) { //InitLabels(); cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(0); + cellGcmSetVBlankHandler({}); //cellGcmSetSecondVHandler(IntrHandler60Drop); - cellGcmSetFlipHandler(0); + cellGcmSetFlipHandler({}); } else if (IsPal60Hsync()) { cellGcmSetSecondVFrequency(CELL_GCM_DISPLAY_FREQUENCY_59_94HZ); - cellGcmSetVBlankHandler(0); + cellGcmSetVBlankHandler({}); } if (s_rescInternalInstance->s_applicationVBlankHandler) SetVBlankHandler(s_rescInternalInstance->s_applicationVBlankHandler); @@ -1037,11 +1072,11 @@ int cellRescSetBufferAddress(vm::ptr> colorBuffers, vm::ptr> return CELL_OK; } -void cellRescSetFlipHandler(u32 handler_addr) +void cellRescSetFlipHandler(vm::ptr handler) { - cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler_addr); + cellResc->Warning("cellRescSetFlipHandler(handler_addr=0x%x)", handler.addr()); - Emu.GetGSManager().GetRender().m_flip_handler.SetAddr(handler_addr); + Emu.GetGSManager().GetRender().m_flip_handler = handler; } void cellRescResetFlipStatus() @@ -1077,11 +1112,11 @@ int cellRescSetRegisterCount() return CELL_OK; } -void cellRescSetVBlankHandler(u32 handler_addr) +void cellRescSetVBlankHandler(vm::ptr handler) { - cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler_addr); + cellResc->Warning("cellRescSetVBlankHandler(handler_addr=0x%x)", handler.addr()); - Emu.GetGSManager().GetRender().m_vblank_handler.SetAddr(handler_addr); + Emu.GetGSManager().GetRender().m_vblank_handler = handler; } u16 FloatToHalf(float val) diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.h b/rpcs3/Emu/SysCalls/Modules/cellResc.h index 9e3d2fa16e..74a7652397 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.h +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.h @@ -137,49 +137,11 @@ struct CCellRescInternal bool m_isDummyFlipped; u8 m_cgParamIndex[RESC_PARAM_NUM]; u64 m_commandIdxCaF, m_rcvdCmdIdx; - u32 s_applicationFlipHandler; - u32 s_applicationVBlankHandler; + vm::ptr s_applicationFlipHandler; + vm::ptr s_applicationVBlankHandler; CCellRescInternal() : m_bInitialized(false) { } }; - - -CCellRescInternal* s_rescInternalInstance = nullptr; - -// Extern Functions -extern int cellGcmSetFlipMode(u32 mode); -extern void cellGcmSetFlipHandler(u32 handler_addr); -extern void cellGcmSetVBlankHandler(u32 handler_addr); -extern int cellGcmAddressToOffset(u64 address, vm::ptr> offset); -extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); -extern int cellGcmSetPrepareFlip(vm::ptr ctx, u32 id); -extern int cellGcmSetSecondVFrequency(u32 freq); -extern u32 cellGcmGetLabelAddress(u8 index); -extern u32 cellGcmGetTiledPitchSize(u32 size); - -// Local Functions -int cellRescGetNumColorBuffers(u32 dstMode, u32 palTemporalMode, u32 reserved); - -// Help Functions -inline bool IsPal() { return s_rescInternalInstance->m_dstMode == CELL_RESC_720x576; } -inline bool IsPal60Hsync() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC); } -inline bool IsPalDrop() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_DROP); } -inline bool IsPalInterpolate() { - return (IsPal() && ((s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE) - || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_30_DROP) - || (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE))); -} -inline bool IsNotPalInterpolate() { return !IsPalInterpolate(); } -inline bool IsPalTemporal() { return (IsPal() && s_rescInternalInstance->m_initConfig.palTemporalMode != CELL_RESC_PAL_50); } -inline bool IsNotPalTemporal() { return !IsPalTemporal(); } -inline bool IsNotPal() { return !IsPal(); } -inline bool IsGcmFlip() { - return (IsNotPal() || (IsPal() && (s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_50 - || s_rescInternalInstance->m_initConfig.palTemporalMode == CELL_RESC_PAL_60_FOR_HSYNC))); -} -inline int GetNumColorBuffers(){ return IsPalInterpolate() ? 6 : (IsPalDrop() ? 3 : 2); } -inline bool IsInterlace() { return s_rescInternalInstance->m_initConfig.interlaceMode == CELL_RESC_INTERLACE_FILTER; } -inline bool IsTextureNR() { return !IsInterlace(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index a06a9f6975..61dad6c763 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/FS/VFS.h" #include "Emu/FS/vfsFile.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index 9c521e9e65..eda13622ec 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/Event.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index e4a7f96cff..e2babf4c71 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -1,9 +1,11 @@ #include "stdafx.h" +#include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/DbgCommand.h" +#include "Emu/SysCalls/Callback.h" +#include "Emu/DbgCommand.h" #include "rpcs3/Ini.h" #include "Emu/FS/vfsFile.h" #include "Loader/PSF.h" @@ -303,46 +305,85 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; } -int cellSysutilCheckCallback() +struct sys_callback +{ + vm::ptr func; + vm::ptr arg; + +} g_sys_callback[4]; + +void sysutilSendSystemCommand(u64 status, u64 param) +{ + // TODO: check it and find the source of the return value (not sure that void becomes CELL_OK) + for (auto& cb : g_sys_callback) + { + if (cb.func) + { + Emu.GetCallbackManager().Register([=]() -> s32 + { + cb.func(status, param, cb.arg); + return CELL_OK; + }); + } + } +} + +s32 cellSysutilCheckCallback() { cellSysutil->Log("cellSysutilCheckCallback()"); - Emu.GetCallbackManager().m_exit_callback.Check(); + s32 res; + u32 count = 0; - CPUThread& thr = Emu.GetCallbackThread(); - - while (thr.IsAlive()) + while (Emu.GetCallbackManager().Check(res)) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + count++; + if (Emu.IsStopped()) { cellSysutil->Warning("cellSysutilCheckCallback() aborted"); - break; + return CELL_OK; } + + if (res) + { + return res; + } + } + + if (!count && !g_sys_callback[0].func && !g_sys_callback[1].func && !g_sys_callback[2].func && !g_sys_callback[3].func) + { + LOG_WARNING(TTY, "System warning: no callback registered\n"); } return CELL_OK; } -int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata) +s32 cellSysutilRegisterCallback(s32 slot, vm::ptr func, vm::ptr userdata) { - cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata); + cellSysutil->Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%x, userdata=0x%x)", slot, func.addr(), userdata.addr()); - Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata); - - SendDbgCommand(DID_REGISTRED_CALLBACK); + if ((u32)slot > 3) + { + return CELL_SYSUTIL_ERROR_VALUE; + } + g_sys_callback[slot].func = func; + g_sys_callback[slot].arg = userdata; return CELL_OK; } -int cellSysutilUnregisterCallback(int slot) +s32 cellSysutilUnregisterCallback(s32 slot) { cellSysutil->Warning("cellSysutilUnregisterCallback(slot=%d)", slot); - Emu.GetCallbackManager().m_exit_callback.Unregister(slot); - - SendDbgCommand(DID_UNREGISTRED_CALLBACK); + if ((u32)slot > 3) + { + return CELL_SYSUTIL_ERROR_VALUE; + } + g_sys_callback[slot].func.set(0); + g_sys_callback[slot].arg.set(0); return CELL_OK; } @@ -887,3 +928,12 @@ void cellSysutil_init() cellSysutil->AddFunc(0xe7951dee, cellGameDataCheckCreate); cellSysutil->AddFunc(0xc9645c41, cellGameDataCheckCreate2); } + +void cellSysutil_load() +{ + for (auto& v : g_sys_callback) + { + v.func.set(0); + v.arg.set(0); + } +} diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h index 48918d51c7..7b8c4fb8d6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.h @@ -59,6 +59,29 @@ enum CELL_SYSUTIL_LANG_ENGLISH_GB = 18, }; +enum +{ + CELL_SYSUTIL_REQUEST_EXITGAME = 0x0101, + CELL_SYSUTIL_DRAWING_BEGIN = 0x0121, + CELL_SYSUTIL_DRAWING_END = 0x0122, + CELL_SYSUTIL_SYSTEM_MENU_OPEN = 0x0131, + CELL_SYSUTIL_SYSTEM_MENU_CLOSE = 0x0132, + CELL_SYSUTIL_BGMPLAYBACK_PLAY = 0x0141, + CELL_SYSUTIL_BGMPLAYBACK_STOP = 0x0142, + + CELL_SYSUTIL_NP_INVITATION_SELECTED = 0x0151, + CELL_SYSUTIL_NP_DATA_MESSAGE_SELECTED = 0x0152, + + CELL_SYSUTIL_SYSCHAT_START = 0x0161, + CELL_SYSUTIL_SYSCHAT_STOP = 0x0162, + CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_RESUMED = 0x0163, + CELL_SYSUTIL_SYSCHAT_VOICE_STREAMING_PAUSED = 0x0164, +}; + +typedef void(*CellSysutilCallback)(u64 status, u64 param, vm::ptr userdata); + +void sysutilSendSystemCommand(u64 status, u64 param); + enum { CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE = 0, diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp index 76676966d0..8f56d50067 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "rpcs3/Ini.h" #include "Utilities/rXml.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 28d4407706..d98a276f25 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/FS/VFS.h" #include "Emu/FS/vfsFileBase.h" @@ -198,7 +199,10 @@ void fsAioRead(u32 fd, vm::ptr aio, int xid, vm::ptr& GetBreakPoints() { return m_break_points; } std::vector& GetMarkedPoints() { return m_marked_points; } - CPUThread& GetCallbackThread() { return *m_ppu_callback_thr; } EventManager& GetEventManager() { return *m_event_manager; } StaticFuncManager& GetSFuncManager() { return *m_sfunc_manager; } ModuleManager& GetModuleManager() { return *m_module_manager; } diff --git a/rpcs3/Gui/GLGSFrame.cpp b/rpcs3/Gui/GLGSFrame.cpp index 98883da472..f4f1a5f4b7 100644 --- a/rpcs3/Gui/GLGSFrame.cpp +++ b/rpcs3/Gui/GLGSFrame.cpp @@ -1,4 +1,5 @@ #include "stdafx_gui.h" +#include "Emu/Memory/Memory.h" #include "GLGSFrame.h" #include "Utilities/Timer.h" diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index dca2b82f88..73eb40caef 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -7,6 +7,7 @@ #include "git-version.h" #include "Ini.h" +#include "Emu/Syscalls/Modules/cellSysutil.h" #include "Emu/RSX/sysutil_video.h" #include "Gui/PADManager.h" #include "Gui/VHDDManager.h" @@ -309,12 +310,12 @@ void MainFrame::Stop(wxCommandEvent& WXUNUSED(event)) void MainFrame::SendExit(wxCommandEvent& event) { - Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0); + sysutilSendSystemCommand(CELL_SYSUTIL_REQUEST_EXITGAME, 0); } void MainFrame::SendOpenCloseSysMenu(wxCommandEvent& event) { - Emu.GetCallbackManager().m_exit_callback.Handle(m_sys_menu_opened ? 0x0132 : 0x0131, 0); + sysutilSendSystemCommand(m_sys_menu_opened ? CELL_SYSUTIL_SYSTEM_MENU_CLOSE : CELL_SYSUTIL_SYSTEM_MENU_OPEN, 0); m_sys_menu_opened = !m_sys_menu_opened; wxCommandEvent ce; UpdateUI(ce); @@ -744,7 +745,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event) // PS3 Commands wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu ); - bool enable_commands = !is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.size(); + bool enable_commands = !is_stopped; send_open_menu.SetItemLabel(wxString::Format("Send %s system menu cmd", (m_sys_menu_opened ? "close" : "open"))); send_open_menu.Enable(enable_commands); send_exit.Enable(enable_commands); diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index b8b7237a8a..493972abc2 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -334,6 +334,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index b129a2094e..4b1f50caa3 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -1213,5 +1213,8 @@ Emu\SysCalls\Modules + + Emu\SysCalls + \ No newline at end of file From fe53f6f2d7844dfda27cafe9f14dd4c489987c99 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 11 Sep 2014 23:33:20 +0400 Subject: [PATCH 07/15] Compilation fix --- rpcs3/Emu/Memory/Memory.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 1 - rpcs3/Emu/SysCalls/CB_FUNC.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 6866bd22fa..c043614dab 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -115,7 +115,7 @@ public: { for (u32 i = addr / 4096; i <= (addr + size - 1) / 4096; i++) { - if (m_pages[i] != 0) return false; // TODO: define page parameters + if (!m_pages[i]) return false; // TODO: define page parameters } return true; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 861a7f02d1..e2d38dc287 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -5,7 +5,6 @@ #include "Emu/System.h" #include "RSXThread.h" -#include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/lv2/sys_time.h" diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index afbc35912b..0e0c79f7c4 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/Cell/PPUThread.h" namespace vm { From ed55011edeb19af616d7896d5a0c36da992284cd Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 11 Sep 2014 23:40:50 +0400 Subject: [PATCH 08/15] Compilation fix 2 --- rpcs3/Gui/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 73eb40caef..d53c4aec7d 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -7,7 +7,7 @@ #include "git-version.h" #include "Ini.h" -#include "Emu/Syscalls/Modules/cellSysutil.h" +#include "Emu/SysCalls/Modules/cellSysutil.h" #include "Emu/RSX/sysutil_video.h" #include "Gui/PADManager.h" #include "Gui/VHDDManager.h" From 8cde1c18c484a35556264c09d129f151581f9f32 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Sep 2014 00:46:11 +0400 Subject: [PATCH 09/15] Cb fix --- rpcs3/Emu/Cell/SPURecompiler.h | 10 +++++----- rpcs3/Emu/SysCalls/CB_FUNC.h | 24 +++++++++++++++++++++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 03602fc564..4601054474 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -288,7 +288,7 @@ public: const XmmLink& XmmGet(s8 reg, s8 target = -1) // get xmm register with specific SPU reg { assert(reg >= 0); - XmmLink* res = nullptr; + const XmmLink* res = nullptr; if (reg == target) { for (u32 i = 0; i < 16; i++) @@ -311,7 +311,7 @@ public: } if (!res) { - res = &(XmmLink&)XmmAlloc(target); + res = &XmmAlloc(target); /*if (target != res->reg) { c.movdqa(*res->data, cpu_xmm(GPR[reg])); @@ -327,7 +327,7 @@ public: c.movdqa(*res->data, cpu_xmm(GPR[reg])); } } - res->reg = -1; // ??? + const_cast(res)->reg = -1; // ??? LOG4_OPCODE("* cached GPR[%d] not found", reg); } return *res; @@ -335,9 +335,9 @@ public: const XmmLink& XmmCopy(const XmmLink& from, s8 pref = -1) // XmmAlloc + mov { - XmmLink* res = &(XmmLink&)XmmAlloc(pref); + const XmmLink* res = &XmmAlloc(pref); c.movdqa(*res->data, *from.data); - res->reg = -1; // ??? + const_cast(res)->reg = -1; // ??? LOG4_OPCODE("*"); return *res; } diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 0e0c79f7c4..83d1de2c0b 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -21,15 +21,33 @@ namespace vm } }; - template - RT _ptr_base::operator ()(T... args) const + template + struct _func_res { static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); + static_assert(sizeof(RT) <= 8, "Invalid callback result type"); static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); - return (RT)GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg::get_value(args)...); + __forceinline static RT get_value(const u64 res) + { + return (RT&)res; + } + }; + + template<> + struct _func_res + { + __forceinline static void get_value(const u64 res) + { + } + }; + + template + RT _ptr_base::operator ()(T... args) const + { + return _func_res::get_value(GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg::get_value(args)...)); } } \ No newline at end of file From 3e1c04b3560249d0f2efb955691c5ce38ba2abb9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Sep 2014 01:10:44 +0400 Subject: [PATCH 10/15] Small fix --- rpcs3/Emu/Cell/PPUInterpreter.h | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index f72a38cf64..267905f4a9 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2298,10 +2298,9 @@ private: } void LVEBX(u32 vd, u32 ra, u32 rb) { - //const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - //CPU.VPR[vd].Clear(); - //CPU.VPR[vd]._u8[addr & 0xf] = vm::read8(addr); - CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + CPU.VPR[vd]._u8[15 - (addr & 0xf)] = vm::read8(addr); + // check LVEWX comments } void SUBFC(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { @@ -2447,10 +2446,9 @@ private: } void LVEHX(u32 vd, u32 ra, u32 rb) { - //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; - //CPU.VPR[vd].Clear(); - //(u16&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read16(addr); - CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; + CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::read16(addr); + // check LVEWX comments } void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { @@ -2497,10 +2495,11 @@ private: } void LVEWX(u32 vd, u32 ra, u32 rb) { - //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; - //CPU.VPR[vd].Clear(); - //(u32&)CPU.VPR[vd]._u8[addr & 0xf] = vm::read32(addr); - CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; + CPU.VPR[vd]._u32[3 - ((addr >> 2) & 0x3)] = vm::read32(addr); + // It's not very good idea to implement it using read128(), + // because it can theoretically read RawSPU 32-bit MMIO register (read128() will fail) + //CPU.VPR[vd] = vm::read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } void MULHD(u32 rd, u32 ra, u32 rb, bool rc) { @@ -2964,8 +2963,7 @@ private: } void LFSX(u32 frd, u32 ra, u32 rb) { - (u32&)CPU.FPR[frd] = vm::read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); - CPU.FPR[frd] = (float&)CPU.FPR[frd]; + CPU.FPR[frd] = vm::get_ref>(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]).ToLE(); } void SRW(u32 ra, u32 rs, u32 rb, bool rc) { From 5a4aa9096b7a1b44a2dc38994e18b95e385d2863 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Sep 2014 17:08:24 +0400 Subject: [PATCH 11/15] Float/vector arg support for callbacks --- rpcs3/Emu/Memory/vm_ptr.h | 6 +- rpcs3/Emu/SysCalls/CB_FUNC.h | 137 +++++++++++++++++++++++++++++----- rpcs3/Emu/SysCalls/Callback.h | 2 - rpcs3/Emu/SysCalls/SC_FUNC.h | 4 +- 4 files changed, 125 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index a687eab5d4..9a7e150170 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -1,5 +1,7 @@ #pragma once +class PPUThread; + namespace vm { template @@ -319,7 +321,9 @@ namespace vm public: typedef RT(*type)(T...); - RT operator()(T... args) const; // defined in Callback.h (CB_FUNC.h) + RT call(PPUThread& CPU, T... args) const; // call using specified PPU thread context, defined in Callback.h (CB_FUNC.h) + + RT operator()(T... args) const; // call using current PPU thread context, defined in Callback.h (CB_FUNC.h) AT addr() const { diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 83d1de2c0b..9d35e3d885 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -3,51 +3,148 @@ namespace vm { - template - struct _func_arg + enum _func_arg_type { - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback argument type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback argument type (vector)"); + ARG_GENERAL, + ARG_FLOAT, + ARG_VECTOR, + ARG_STACK, + }; - static_assert(sizeof(TT) <= 8, "Invalid callback argument type"); - static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); - static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); + template + struct _func_arg; - __forceinline static u64 get_value(const TT& arg) + template + struct _func_arg + { + static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_GENERAL"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) { - u64 res = 0; - (TT&)res = arg; - return res; + (T&)CPU.GPR[g_count + 2] = arg; } }; + template + struct _func_arg + { + static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_FLOAT"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) + { + CPU.FPR[f_count] = arg; + } + }; + + template + struct _func_arg + { + static_assert(std::is_same::value, "Invalid callback argument type for ARG_VECTOR"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) + { + (T&)CPU.VPR[v_count + 1] = arg; + } + }; + + template + struct _func_arg + { + static_assert(g_count <= 8, "TODO: Unsupported stack argument type (general)"); + static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); + static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); + static_assert(sizeof(T) <= 8, "Invalid callback argument type for ARG_STACK"); + + __forceinline static void set_value(PPUThread& CPU, const T arg) + { + // TODO + } + }; + + template + __forceinline static void _bind_func_args(PPUThread& CPU) + { + // terminator + } + + template + __forceinline static void _bind_func_args(PPUThread& CPU, T1 arg1, T... args) + { + static_assert(!std::is_pointer::value, "Invalid callback argument type (pointer)"); + static_assert(!std::is_reference::value, "Invalid callback argument type (reference)"); + const bool is_float = std::is_floating_point::value; + const bool is_vector = std::is_same::value; + const _func_arg_type t = is_float + ? ((f_count >= 12) ? ARG_STACK : ARG_FLOAT) + : (is_vector ? ((v_count >= 12) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 8) ? ARG_STACK : ARG_GENERAL)); + const int g = g_count + (is_float || is_vector ? 0 : 1); + const int f = f_count + (is_float ? 1 : 0); + const int v = v_count + (is_vector ? 1 : 0); + + _func_arg::set_value(CPU, arg1); + _bind_func_args(CPU, args...); + } + template struct _func_res { - static_assert(!std::is_floating_point::value, "TODO: Unsupported callback result type (floating point)"); - static_assert(!std::is_same::value, "TODO: Unsupported callback result type (vector)"); - static_assert(sizeof(RT) <= 8, "Invalid callback result type"); static_assert(!std::is_pointer::value, "Invalid callback result type (pointer)"); static_assert(!std::is_reference::value, "Invalid callback result type (reference)"); - __forceinline static RT get_value(const u64 res) + __forceinline static RT get_value(const PPUThread& CPU) { - return (RT&)res; + if (std::is_floating_point::value) + { + return (RT)CPU.FPR[1]; + } + else + { + return (RT&)CPU.GPR[3]; + } + } + }; + + template<> + struct _func_res + { + __forceinline static u128 get_value(const PPUThread& CPU) + { + return CPU.VPR[2]; } }; template<> struct _func_res { - __forceinline static void get_value(const u64 res) + __forceinline static void get_value(const PPUThread& CPU) { } }; - template - RT _ptr_base::operator ()(T... args) const + template + struct _func_caller { - return _func_res::get_value(GetCurrentPPUThread().FastCall(vm::read32(m_addr), vm::read32(m_addr + 4), _func_arg::get_value(args)...)); + __forceinline static RT call(PPUThread& CPU, u32 pc, u32 rtoc, T... args) + { + _bind_func_args<0, 0, 0>(CPU, args...); + CPU.FastCall2(pc, rtoc); + return _func_res::get_value(CPU); + } + }; + + template + __forceinline RT _ptr_base::call(PPUThread& CPU, T... args) const + { + const u32 pc = vm::get_ref>(m_addr); + const u32 rtoc = vm::get_ref>(m_addr + 4); + + return _func_caller::call(CPU, pc, rtoc, args...); + } + + template + __forceinline RT _ptr_base::operator ()(T... args) const + { + return call(GetCurrentPPUThread(), args...); } } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 6402ca84b6..f5747e6ac5 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -1,8 +1,6 @@ #pragma once #include "CB_FUNC.h" -class CPUThread; - class CallbackManager { std::vector> m_cb_list; diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h index f01cc741d4..16e16cd2ab 100644 --- a/rpcs3/Emu/SysCalls/SC_FUNC.h +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -59,7 +59,7 @@ namespace detail { static_assert(f_count <= 12, "TODO: Unsupported stack argument type (float)"); static_assert(v_count <= 12, "TODO: Unsupported stack argument type (vector)"); - static_assert(sizeof(T) <= 8, "Invalid function argument type (ARG_STACK)"); + static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_STACK"); static __forceinline T func(PPUThread& CPU) { @@ -126,6 +126,7 @@ namespace detail template static __forceinline std::tuple<> iterate(PPUThread& CPU) { + // terminator return std::tuple<>(); } @@ -143,6 +144,7 @@ namespace detail const int g = g_count + (is_float || is_vector ? 0 : 1); const int f = f_count + (is_float ? 1 : 0); const int v = v_count + (is_vector ? 1 : 0); + return std::tuple_cat(std::tuple(bind_arg::func(CPU)), iterate(CPU)); } From c1da446653e417b80dc03e2623e5a61bbdfc3381 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 12 Sep 2014 23:27:33 +0400 Subject: [PATCH 12/15] FastCall() removed --- Utilities/Thread.cpp | 4 +- Utilities/Thread.h | 2 +- rpcs3/Emu/Cell/PPUThread.cpp | 14 ------- rpcs3/Emu/Cell/PPUThread.h | 1 - rpcs3/Emu/Cell/SPUThread.cpp | 3 +- rpcs3/Emu/SysCalls/CB_FUNC.h | 14 +++++-- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 29 ++++++++----- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 44 ++++++++++++-------- 8 files changed, 61 insertions(+), 50 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 727005e651..ab804bd2e4 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -25,10 +25,10 @@ void NamedThreadBase::SetThreadName(const std::string& name) m_name = name; } -void NamedThreadBase::WaitForAnySignal() // wait 1 ms for something +void NamedThreadBase::WaitForAnySignal(u64 time) // wait for Notify() signal or sleep { std::unique_lock lock(m_signal_mtx); - m_signal_cv.wait_for(lock, std::chrono::milliseconds(1)); + m_signal_cv.wait_for(lock, std::chrono::milliseconds(time)); } void NamedThreadBase::Notify() // wake up waiting thread or nothing diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 1daeeb5f59..72daae43ab 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -21,7 +21,7 @@ public: virtual std::string GetThreadName() const; virtual void SetThreadName(const std::string& name); - void WaitForAnySignal(); + void WaitForAnySignal(u64 time = 1); void Notify(); }; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index dfa0654251..94752d653b 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -222,20 +222,6 @@ u64 PPUThread::GetStackArg(s32 i) return vm::read64(GPR[1] + 0x70 + 0x8 * (i - 9)); } -u64 PPUThread::FastCall(u64 addr, u64 rtoc, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7, u64 arg8) -{ - GPR[3] = arg1; - GPR[4] = arg2; - GPR[5] = arg3; - GPR[6] = arg4; - GPR[7] = arg5; - GPR[8] = arg6; - GPR[9] = arg7; - GPR[10] = arg8; - - return FastCall2(addr, rtoc); -} - u64 PPUThread::FastCall2(u64 addr, u64 rtoc) { auto old_status = m_status; diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 4583172ff5..fd30fdca16 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -789,7 +789,6 @@ public: virtual void InitRegs(); virtual u64 GetFreeStackSize() const; u64 GetStackArg(s32 i); - u64 FastCall(u64 addr, u64 rtoc, u64 arg1 = 0, u64 arg2 = 0, u64 arg3 = 0, u64 arg4 = 0, u64 arg5 = 0, u64 arg6 = 0, u64 arg7 = 0, u64 arg8 = 0); u64 FastCall2(u64 addr, u64 rtoc); void FastStop(); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 137b5c2326..b82f9047d6 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -561,7 +561,8 @@ void SPUThread::WriteChannel(u32 ch, const u128& r) PPUThread& ppu = *(PPUThread*)t; ppu.FastStop(); ppu.Run(); - ppu.FastCall(ppu.PC, ppu.GPR[2], ppu.m_interrupt_arg); + ppu.GPR[3] = ppu.m_interrupt_arg; + ppu.FastCall2(ppu.PC, ppu.GPR[2]); } } } diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 9d35e3d885..7b00d0ac70 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -1,7 +1,7 @@ #pragma once #include "Emu/Cell/PPUThread.h" -namespace vm +namespace cb_detail { enum _func_arg_type { @@ -132,14 +132,17 @@ namespace vm return _func_res::get_value(CPU); } }; +} +namespace vm +{ template __forceinline RT _ptr_base::call(PPUThread& CPU, T... args) const { const u32 pc = vm::get_ref>(m_addr); const u32 rtoc = vm::get_ref>(m_addr + 4); - return _func_caller::call(CPU, pc, rtoc, args...); + return cb_detail::_func_caller::call(CPU, pc, rtoc, args...); } template @@ -147,4 +150,9 @@ namespace vm { return call(GetCurrentPPUThread(), args...); } -} \ No newline at end of file +} + +template +struct cb_caller : public cb_detail::_func_caller +{ +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index eda13622ec..15e293c746 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -15,7 +15,7 @@ Module *cellSync = nullptr; #ifdef PRX_DEBUG #include "prx_libsre.h" u32 libsre; -u32 libsre_rtoc; +u32 libsre_rtoc; #endif s32 syncMutexInitialize(vm::ptr mutex) @@ -1081,7 +1081,8 @@ void syncLFQueueInit(vm::ptr queue, vm::ptr buffer, u32 siz s32 syncLFQueueInitialize(vm::ptr queue, vm::ptr buffer, u32 size, u32 depth, CellSyncQueueDirection direction, vm::ptr eaSignal) { #ifdef PRX_DEBUG_XXX - return GetCurrentPPUThread().FastCall(libsre + 0x205C, libsre_rtoc, queue.addr(), buffer_addr, size, depth, direction, eaSignal_addr); + return cb_caller, vm::ptr, u32, u32, CellSyncQueueDirection, vm::ptr>::call(GetCurrentPPUThread(), libsre + 0x205C, libsre_rtoc, + queue, buffer, size, depth, direction, eaSignal); #else if (!queue) @@ -1526,7 +1527,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) { #ifdef PRX_DEBUG_XXX - res = GetCurrentPPUThread().FastCall(libsre + 0x24B0, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); + res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x24B0, libsre_rtoc, + queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else res = syncLFQueueGetPushPointer(queue, position, isBlocking, 0); @@ -1535,7 +1537,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x3050, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); + res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x3050, libsre_rtoc, + queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else res = syncLFQueueGetPushPointer2(queue, position, isBlocking, 0); @@ -1570,7 +1573,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) { #ifdef PRX_DEBUG_XXX - res = GetCurrentPPUThread().FastCall(libsre + 0x26C0, libsre_rtoc, queue.addr(), position, 0); + res = cb_caller, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x26C0, libsre_rtoc, + queue, position, 0); #else res = syncLFQueueCompletePushPointer(queue, position, nullptr); #endif @@ -1578,7 +1582,8 @@ s32 _cellSyncLFQueuePushBody(vm::ptr queue, vm::ptr else { #ifdef PRX_DEBUG - res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x355C, libsre_rtoc, queue.addr(), position, 0); + res = cb_caller, s32, u64>::call(GetCurrentPPUThread(), libsre + 0x355C, libsre_rtoc, + queue, position, 0); #else res = syncLFQueueCompletePushPointer2(queue, position, nullptr); #endif @@ -1917,7 +1922,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) { #ifdef PRX_DEBUG_XXX - res = GetCurrentPPUThread().FastCall(libsre + 0x2A90, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0, 0); + res = cb_caller, u32, u32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2A90, libsre_rtoc, + queue, position_v.addr(), isBlocking, 0, 0); position = position_v->ToLE(); #else res = syncLFQueueGetPopPointer(queue, position, isBlocking, 0, 0); @@ -1926,7 +1932,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x39AC, libsre_rtoc, queue.addr(), position_v.addr(), isBlocking, 0); + res = cb_caller, u32, u32, u64>::call(GetCurrentPPUThread(), libsre + 0x39AC, libsre_rtoc, + queue, position_v.addr(), isBlocking, 0); position = position_v->ToLE(); #else res = syncLFQueueGetPopPointer2(queue, position, isBlocking, 0); @@ -1958,7 +1965,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer if (queue->m_direction.ToBE() != se32(CELL_SYNC_QUEUE_ANY2ANY)) { #ifdef PRX_DEBUG_XXX - res = GetCurrentPPUThread().FastCall(libsre + 0x2CA8, libsre_rtoc, queue.addr(), position, 0, 0); + res = cb_caller, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x2CA8, libsre_rtoc, + queue, position, 0, 0); #else res = syncLFQueueCompletePopPointer(queue, position, nullptr, 0); #endif @@ -1966,7 +1974,8 @@ s32 _cellSyncLFQueuePopBody(vm::ptr queue, vm::ptr buffer else { #ifdef PRX_DEBUG - res = (s32)GetCurrentPPUThread().FastCall(libsre + 0x3EB8, libsre_rtoc, queue.addr(), position, 0, 0); + res = cb_caller, s32, u64, u64>::call(GetCurrentPPUThread(), libsre + 0x3EB8, libsre_rtoc, + queue, position, 0, 0); #else res = syncLFQueueCompletePopPointer2(queue, position, nullptr, 0); #endif diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index b01d5e6c68..0c297d4715 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/FS/vfsFile.h" #include "Emu/FS/vfsStreamMemory.h" @@ -224,14 +225,21 @@ vm::ptr _sys_strncpy(vm::ptr dest, vm::ptr source, u32 l return dest; } -u32 spu_printf_agcb; -u32 spu_printf_dgcb; -u32 spu_printf_atcb; -u32 spu_printf_dtcb; +typedef s32(*spu_printf_cb_t)(u32 arg); -s32 _sys_spu_printf_initialize(u32 agcb, u32 dgcb, u32 atcb, u32 dtcb) +vm::ptr spu_printf_agcb; +vm::ptr spu_printf_dgcb; +vm::ptr spu_printf_atcb; +vm::ptr spu_printf_dtcb; + +s32 _sys_spu_printf_initialize( + vm::ptr agcb, + vm::ptr dgcb, + vm::ptr atcb, + vm::ptr dtcb) { - sysPrxForUser->Warning("_sys_spu_printf_initialize(agcb=0x%x, dgcb=0x%x, atcb=0x%x, dtcb=0x%x)", agcb, dgcb, atcb, dtcb); + sysPrxForUser->Warning("_sys_spu_printf_initialize(agcb_addr=0x%x, dgcb_addr=0x%x, atcb_addr=0x%x, dtcb_addr=0x%x)", + agcb.addr(), dgcb.addr(), atcb.addr(), dtcb.addr()); // prx: register some callbacks spu_printf_agcb = agcb; @@ -245,10 +253,10 @@ s32 _sys_spu_printf_finalize() { sysPrxForUser->Warning("_sys_spu_printf_finalize()"); - spu_printf_agcb = 0; - spu_printf_dgcb = 0; - spu_printf_atcb = 0; - spu_printf_dtcb = 0; + spu_printf_agcb.set(0); + spu_printf_dgcb.set(0); + spu_printf_atcb.set(0); + spu_printf_dtcb.set(0); return CELL_OK; } @@ -261,7 +269,7 @@ s64 _sys_spu_printf_attach_group(u32 arg) return CELL_ESTAT; } - return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_agcb), vm::read32(spu_printf_agcb + 4), arg); + return spu_printf_agcb(arg); } s64 _sys_spu_printf_detach_group(u32 arg) @@ -273,7 +281,7 @@ s64 _sys_spu_printf_detach_group(u32 arg) return CELL_ESTAT; } - return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_dgcb), vm::read32(spu_printf_dgcb + 4), arg); + return spu_printf_dgcb(arg); } s64 _sys_spu_printf_attach_thread(u32 arg) @@ -285,7 +293,7 @@ s64 _sys_spu_printf_attach_thread(u32 arg) return CELL_ESTAT; } - return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_atcb), vm::read32(spu_printf_atcb + 4), arg); + return spu_printf_atcb(arg); } s64 _sys_spu_printf_detach_thread(u32 arg) @@ -297,7 +305,7 @@ s64 _sys_spu_printf_detach_thread(u32 arg) return CELL_ESTAT; } - return GetCurrentPPUThread().FastCall(vm::read32(spu_printf_dtcb), vm::read32(spu_printf_dtcb + 4), arg); + return spu_printf_dtcb(arg); } s32 _sys_snprintf(vm::ptr dst, u32 count, vm::ptr fmt, u32 a1, u32 a2) // va_args... @@ -426,8 +434,8 @@ void sysPrxForUser_init() void sysPrxForUser_load() { - spu_printf_agcb = 0; - spu_printf_dgcb = 0; - spu_printf_atcb = 0; - spu_printf_dtcb = 0; + spu_printf_agcb.set(0); + spu_printf_dgcb.set(0); + spu_printf_atcb.set(0); + spu_printf_dtcb.set(0); } \ No newline at end of file From 10e9d383d4adb81d329ea6c665caff7fa911adc7 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 13 Sep 2014 01:14:48 +0400 Subject: [PATCH 13/15] ExecAsCallback() removed --- rpcs3/Emu/CPU/CPUThread.cpp | 41 ------------------- rpcs3/Emu/CPU/CPUThread.h | 2 - rpcs3/Emu/SysCalls/Callback.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 39 +++++++----------- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 10 ++--- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 54 ++++++++----------------- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 24 +++++------ rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 38 ++++++----------- rpcs3/Emu/SysCalls/Modules/cellVdec.h | 10 ++--- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 48 +++++++++++++++------- rpcs3/Emu/SysCalls/Modules/libmixer.h | 4 +- 11 files changed, 103 insertions(+), 168 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index ec5278fe67..6f03ab000b 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -374,44 +374,3 @@ void CPUThread::Task() if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str()); } - -s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe -{ - while (m_alive) - { - if (Emu.IsStopped()) - { - LOG_WARNING(PPU, "ExecAsCallback() aborted"); - return CELL_ECANCELED; // doesn't mean anything - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - Stop(); - Reset(); - - SetEntry(pc); - SetPrio(1001); - SetStackSize(0x10000); - SetExitStatus(CELL_OK); - - SetArg(0, a1); - SetArg(1, a2); - SetArg(2, a3); - SetArg(3, a4); - Run(); - - Exec(); - - while (wait && m_alive) - { - if (Emu.IsStopped()) - { - LOG_WARNING(PPU, "ExecAsCallback(wait=%s) aborted", wait ? "true" : "false"); - return CELL_EABORT; // doesn't mean anything - } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - return wait * m_exit_status; -} diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 0610219e8e..c03bcd934f 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -242,8 +242,6 @@ public: return pc + 4; } - s64 ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); - protected: virtual void DoReset()=0; virtual void DoRun()=0; diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 3f8968736d..8a5bb9c941 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -57,6 +57,7 @@ void CallbackManager::Init() vm::write32(cb_shit, Emu.m_ppu_thr_stop); vm::write32(cb_shit + 4, 0); + m_cb_thread->SetName("Callback Thread"); m_cb_thread->SetEntry(cb_shit); m_cb_thread->SetPrio(1001); // ??? m_cb_thread->SetStackSize(0x10000); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 11b9158bc6..9a6ced9dae 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" extern std::mutex g_mutex_avcodec_open2; @@ -20,7 +21,7 @@ extern "C" //Module cellAdec(0x0006, cellAdec_init); Module *cellAdec = nullptr; -AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) +AudioDecoder::AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) , memAddr(addr) , memSize(size) @@ -122,7 +123,7 @@ next: buf_size -= adec.reader.size; res += adec.reader.size; - adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg); + adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg); adec.job.Pop(adec.task); @@ -244,13 +245,16 @@ u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; - adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - u32 adec_id = cellAdec->GetNewId(data); adec.id = adec_id; + adec.adecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback"); + adec.adecCb->SetEntry(0x10000); + adec.adecCb->SetPrio(1001); + adec.adecCb->SetStackSize(0x10000); + adec.adecCb->Run(); thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]() { @@ -304,12 +308,7 @@ u32 adecOpen(AudioDecoder* data) { // TODO: finalize cellAdec->Warning("adecEndSeq:"); - - /*Callback cb; - cb.SetAddr(adec.cbFunc); - cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); - cb.Branch(true); // ???*/ - adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); + adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); adec.is_running = false; adec.just_finished = true; @@ -446,7 +445,7 @@ u32 adecOpen(AudioDecoder* data) frame.data = nullptr; adec.frames.Push(frame); - adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); + adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; }*/ @@ -538,19 +537,11 @@ u32 adecOpen(AudioDecoder* data) adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction - /*Callback cb; - cb.SetAddr(adec.cbFunc); - cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false);*/ - adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); + adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); } } - - /*Callback cb; - cb.SetAddr(adec.cbFunc); - cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); - cb.Branch(false);*/ - adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); + + adec.cbFunc.call(*adec.adecCb, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); } break; @@ -621,7 +612,7 @@ int cellAdecOpen(vm::ptr type, vm::ptr res, vm:: if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; - *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, vm::ptr::make(cb->cbFunc.addr()), cb->cbArg)); return CELL_OK; } @@ -633,7 +624,7 @@ int cellAdecOpenEx(vm::ptr type, vm::ptr res, if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; - *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + *handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, vm::ptr::make(cb->cbFunc.addr()), cb->cbArg)); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index a77840187e..210e4695d3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -360,11 +360,11 @@ enum CellAdecMsgType CELL_ADEC_MSG_TYPE_SEQDONE, }; -typedef s32(*CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, int msgData, u32 cbArg); +typedef s32(*CellAdecCbMsg)(u32 handle, CellAdecMsgType msgType, s32 msgData, u32 cbArg); struct CellAdecCb { - be_t cbFunc; + vm::bptr cbFunc; be_t cbArg; }; @@ -1108,16 +1108,16 @@ public: const AudioCodecType type; const u32 memAddr; const u32 memSize; - const u32 cbFunc; + const vm::ptr cbFunc; const u32 cbArg; u32 memBias; AdecTask task; u64 last_pts, first_pts; - CPUThread* adecCb; + PPUThread* adecCb; - AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg); + AudioDecoder(AudioCodecType type, u32 addr, u32 size, vm::ptr func, u32 arg); ~AudioDecoder(); }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 2640aa7360..a3422b0e11 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/CPU/CPUThreadManager.h" #include "cellPamf.h" @@ -292,13 +293,16 @@ u32 dmuxOpen(Demuxer* data) { Demuxer& dmux = *data; - dmux.dmuxCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - u32 dmux_id = cellDmux->GetNewId(data); dmux.id = dmux_id; + dmux.dmuxCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback"); + dmux.dmuxCb->SetEntry(0x10000); + dmux.dmuxCb->SetPrio(1001); + dmux.dmuxCb->SetStackSize(0x10000); + dmux.dmuxCb->Run(); thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]() { @@ -340,11 +344,8 @@ u32 dmuxOpen(Demuxer* data) auto dmuxMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(dmux.cbFunc); - cb.Handle(dmux.id, dmuxMsg.addr(), dmux.cbArg); - cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ - dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.addr(), dmux.cbArg); + dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg); + updates_signaled++; } else switch (code.ToLE()) @@ -424,11 +425,7 @@ u32 dmuxOpen(Demuxer* data) auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(es.cbFunc); - cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg); - cb.Branch(false);*/ - dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg); + es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg); } else { @@ -477,11 +474,7 @@ u32 dmuxOpen(Demuxer* data) auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(es.cbFunc); - cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg); - cb.Branch(false);*/ - dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg); + es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg); } if (pes.new_au) @@ -589,12 +582,7 @@ u32 dmuxOpen(Demuxer* data) auto dmuxMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(dmux.cbFunc); - cb.Handle(dmux.id, dmuxMsg.addr(), dmux.cbArg); - cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ - dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, task.type == dmuxResetStreamAndWaitDone, - dmux.id, dmuxMsg.addr(), dmux.cbArg); + dmux.cbFunc.call(*dmux.dmuxCb, dmux.id, dmuxMsg, dmux.cbArg); updates_signaled++; dmux.is_running = false; @@ -675,22 +663,14 @@ u32 dmuxOpen(Demuxer* data) auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(es.cbFunc); - cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg); - cb.Branch(false);*/ - dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg); + es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg); } // callback auto esMsg = vm::ptr::make(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE; esMsg->supplementalInfo = stream.userdata; - /*Callback cb; - cb.SetAddr(es.cbFunc); - cb.Handle(dmux.id, es.id, esMsg.addr(), es.cbArg); - cb.Branch(false);*/ - dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.addr(), es.cbArg); + es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg); } break; @@ -752,7 +732,7 @@ int cellDmuxOpen(vm::ptr demuxerType, vm::ptrmemAddr, demuxerResource->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); + *demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, vm::ptr::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg)); return CELL_OK; } @@ -770,7 +750,7 @@ int cellDmuxOpenEx(vm::ptr demuxerType, vm::ptrmemAddr, demuxerResourceEx->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); + *demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, vm::ptr::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg)); return CELL_OK; } @@ -788,7 +768,7 @@ int cellDmuxOpen2(vm::ptr demuxerType2, vm::ptrmemAddr, demuxerResource2->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr)); + *demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, vm::ptr::make(demuxerCb->cbMsgFunc.addr()), demuxerCb->cbArg)); return CELL_OK; } @@ -959,7 +939,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr esFil ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize, esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2, - esCb->cbEsMsgFunc, esCb->cbArg_addr, esSpecificInfo_addr); + vm::ptr::make(esCb->cbEsMsgFunc.addr()), esCb->cbArg, esSpecificInfo_addr); u32 id = cellDmux->GetNewId(es); es->id = id; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 1b3fc33a1d..5c41043952 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -222,22 +222,20 @@ struct CellDmuxResource2 be_t shit[4]; }; -typedef u32(*CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr demuxerMsg, u32 cbArg_addr); +typedef u32(*CellDmuxCbMsg)(u32 demuxerHandle, vm::ptr demuxerMsg, u32 cbArg); struct CellDmuxCb { - // CellDmuxCbMsg callback - be_t cbMsgFunc; - be_t cbArg_addr; + vm::bptr cbMsgFunc; + be_t cbArg; }; -typedef u32(*CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr esMsg, u32 cbArg_addr); +typedef u32(*CellDmuxCbEsMsg)(u32 demuxerHandle, u32 esHandle, vm::ptr esMsg, u32 cbArg); struct CellDmuxEsCb { - // CellDmuxCbEsMsg callback - be_t cbEsMsgFunc; - be_t cbArg_addr; + vm::bptr cbEsMsgFunc; + be_t cbArg; }; struct CellDmuxAttr @@ -413,15 +411,15 @@ public: SQueue fbSetStream; const u32 memAddr; const u32 memSize; - const u32 cbFunc; + const vm::ptr cbFunc; const u32 cbArg; u32 id; volatile bool is_finished; volatile bool is_running; - CPUThread* dmuxCb; + PPUThread* dmuxCb; - Demuxer(u32 addr, u32 size, u32 func, u32 arg) + Demuxer(u32 addr, u32 size, vm::ptr func, u32 arg) : is_finished(false) , is_running(false) , memAddr(addr) @@ -458,11 +456,11 @@ public: const u32 fidMinor; const u32 sup1; const u32 sup2; - const u32 cbFunc; + const vm::ptr cbFunc; const u32 cbArg; const u32 spec; //addr - ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, u32 cbFunc, u32 cbArg, u32 spec) + ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr cbFunc, u32 cbArg, u32 spec) : dmux(dmux) , memAddr(a128(addr)) , memSize(size - (addr - memAddr)) diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 0f7fc6b45c..9d89d2c984 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" std::mutex g_mutex_avcodec_open2; @@ -20,7 +21,7 @@ extern "C" //Module cellVdec(0x0005, cellVdec_init); Module *cellVdec = nullptr; -VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) +VideoDecoder::VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, vm::ptr func, u32 arg) : type(type) , profile(profile) , memAddr(addr) @@ -122,11 +123,7 @@ next: buf_size -= vdec.reader.size; res += vdec.reader.size; - /*Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false);*/ - vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); + vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); vdec.job.Pop(vdec.task); @@ -183,13 +180,16 @@ u32 vdecOpen(VideoDecoder* data) { VideoDecoder& vdec = *data; - vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - u32 vdec_id = cellVdec->GetNewId(data); vdec.id = vdec_id; + vdec.vdecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback"); + vdec.vdecCb->SetEntry(0x10000); + vdec.vdecCb->SetPrio(1001); + vdec.vdecCb->SetStackSize(0x10000); + vdec.vdecCb->Run(); thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]() { @@ -240,11 +240,7 @@ u32 vdecOpen(VideoDecoder* data) // TODO: finalize cellVdec->Warning("vdecEndSeq:"); - vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); - /*Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); - cb.Branch(true); // ???*/ + vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); vdec.is_running = false; vdec.just_finished = true; @@ -439,19 +435,11 @@ u32 vdecOpen(VideoDecoder* data) vdec.frames.Push(frame); // !!!!!!!! frame.data = nullptr; // to prevent destruction - vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); - /*Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); - cb.Branch(false);*/ + vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); } } - vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - /*Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false);*/ + vdec.cbFunc.call(*vdec.vdecCb, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); } break; @@ -501,7 +489,7 @@ int cellVdecOpen(vm::ptr type, vm::ptrWarning("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.addr(), res.addr(), cb.addr(), handle.addr()); - *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, vm::ptr::make(cb->cbFunc.addr()), cb->cbArg)); return CELL_OK; } @@ -511,7 +499,7 @@ int cellVdecOpenEx(vm::ptr type, vm::ptrWarning("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.addr(), res.addr(), cb.addr(), handle.addr()); - *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + *handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, vm::ptr::make(cb->cbFunc.addr()), cb->cbArg)); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index e36b792526..ca4795e145 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -167,12 +167,12 @@ struct CellVdecPicFormat u8 alpha; }; -typedef void(*CellVdecCbMsg)(u32 handle_addr, CellVdecMsgType msgType, int msgData, u32 cbArg_addr); +typedef u32(*CellVdecCbMsg)(u32 handle, CellVdecMsgType msgType, s32 msgData, u32 cbArg); // Callback Function Information struct CellVdecCb { - be_t cbFunc; + vm::bptr cbFunc; be_t cbArg; }; @@ -717,7 +717,7 @@ public: const u32 profile; const u32 memAddr; const u32 memSize; - const u32 cbFunc; + const vm::ptr cbFunc; const u32 cbArg; u32 memBias; @@ -725,9 +725,9 @@ public: u64 last_pts, first_pts, first_dts; AVRational rfr, afr; - CPUThread* vdecCb; + PPUThread* vdecCb; - VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg); + VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, vm::ptr func, u32 arg); ~VideoDecoder(); }; diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index 3f0a49e95a..d3b540cd60 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Audio/cellAudio.h" @@ -14,8 +15,8 @@ Module *libmixer = nullptr; CellSurMixerConfig surMixer; #define SUR_PORT (7) -u32 surMixerCb; -u32 surMixerCbArg; +vm::ptr surMixerCb; +vm::ptr surMixerCbArg; std::mutex mixer_mutex; float mixdata[8*256]; u64 mixcount; @@ -323,15 +324,18 @@ int cellSurMixerCreate(vm::ptr config) (u32)surMixer.chStrips1, (u32)surMixer.chStrips2, (u32)surMixer.chStrips6, (u32)surMixer.chStrips8); mixcount = 0; - surMixerCb = 0; + surMixerCb.set(0); thread t("Surmixer Thread", []() { AudioPortConfig& port = m_config.m_ports[SUR_PORT]; - CPUThread* mixerCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - - mixerCb->SetName("Surmixer Callback"); + PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); + cb_thread.SetName("Surmixer Callback Thread"); + cb_thread.SetEntry(0x10000); + cb_thread.SetPrio(1001); + cb_thread.SetStackSize(0x10000); + cb_thread.Run(); while (port.m_is_audio_port_opened) { @@ -352,7 +356,10 @@ int cellSurMixerCreate(vm::ptr config) //u64 stamp0 = get_system_time(); memset(mixdata, 0, sizeof(mixdata)); - if (surMixerCb) mixerCb->ExecAsCallback(surMixerCb, true, surMixerCbArg, mixcount, 256); + if (surMixerCb) + { + surMixerCb.call(cb_thread, surMixerCbArg, mixcount, 256); + } //u64 stamp1 = get_system_time(); @@ -456,7 +463,8 @@ int cellSurMixerCreate(vm::ptr config) ssp.clear(); } - Emu.GetCPU().RemoveThread(mixerCb->GetId()); + Emu.GetCPU().RemoveThread(cb_thread.GetId()); + surMixerCb.set(0); }); t.detach(); @@ -477,19 +485,31 @@ int cellSurMixerChStripGetAANPortNo(vm::ptr> port, u32 type, u32 index return CELL_OK; } -int cellSurMixerSetNotifyCallback(u32 func, u32 arg) +int cellSurMixerSetNotifyCallback(vm::ptr func, vm::ptr arg) { - libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x) (surMixerCb=0x%x)", func, arg, surMixerCb); + libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x)", func.addr(), arg.addr()); + + if (surMixerCb) + { + libmixer->Error("cellSurMixerSetNotifyCallback: surMixerCb already set (addr=0x%x)", surMixerCb.addr()); + } surMixerCb = func; surMixerCbArg = arg; return CELL_OK; } -int cellSurMixerRemoveNotifyCallback(u32 func) +int cellSurMixerRemoveNotifyCallback(vm::ptr func) { - libmixer->Warning("cellSurMixerSetNotifyCallback(func_addr=0x%x) (surMixerCb=0x%x)", func, surMixerCb); - surMixerCb = 0; - surMixerCbArg = 0; + libmixer->Warning("cellSurMixerRemoveNotifyCallback(func_addr=0x%x)", func.addr()); + + if (surMixerCb.addr() != func.addr()) + { + libmixer->Error("cellSurMixerRemoveNotifyCallback: surMixerCb had different value (addr=0x%x)", surMixerCb.addr()); + } + else + { + surMixerCb.set(0); + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.h b/rpcs3/Emu/SysCalls/Modules/libmixer.h index c5cac3baf2..45f8a26af9 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.h +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.h @@ -109,7 +109,7 @@ enum CELL_SSPLAYER_STATE_ON = 0x20, }; -typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples); +typedef s32(*CellSurMixerNotifyCallbackFunction)(vm::ptr arg, u32 counter, u32 samples); struct CellSSPlayerConfig { @@ -180,4 +180,4 @@ struct SSPlayer float m_x; float m_y; float m_z; -}; \ No newline at end of file +}; From 0df3e955c847898e6b62f0e12a9bcc2f60be290e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 13 Sep 2014 01:50:50 +0400 Subject: [PATCH 14/15] Small fix --- rpcs3/Emu/CPU/CPUThread.cpp | 13 ++++++++++--- rpcs3/Emu/SysCalls/Callback.cpp | 8 +++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 6f03ab000b..407055df5e 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -283,11 +283,12 @@ void CPUThread::ExecOnce() void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr(); - if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000) + CPUThread* t = GetCurrentCPUThread(); + if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000 && t) { // TODO: allow recovering from a page fault throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx (%s))", - (u32)addr, (u64)GetCurrentCPUThread()->m_last_syscall, SysCalls::GetHLEFuncName((u32)GetCurrentCPUThread()->m_last_syscall).c_str()); + (u32)addr, (u64)t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str()); } else { @@ -317,7 +318,7 @@ void CPUThread::Task() std::vector trace; #ifdef _WIN32 - _set_se_translator(_se_translator); + auto old_se_translator = _set_se_translator(_se_translator); #else // TODO: linux version #endif @@ -370,6 +371,12 @@ void CPUThread::Task() Emu.Pause(); } +#ifdef _WIN32 + _set_se_translator(old_se_translator); +#else + // TODO: linux version +#endif + for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v); if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str()); diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 8a5bb9c941..1425647de6 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -61,10 +61,16 @@ void CallbackManager::Init() m_cb_thread->SetEntry(cb_shit); m_cb_thread->SetPrio(1001); // ??? m_cb_thread->SetStackSize(0x10000); - m_cb_thread->Run(); thread cb_async_thread("CallbackManager::Async() thread", [this]() { + while (Emu.IsReady()) + { + m_cb_thread->WaitForAnySignal(); + } + + m_cb_thread->Run(); + SetCurrentNamedThread(m_cb_thread); while (!Emu.IsStopped()) From 860d7bd3f1e3f282a8959925d151840f97f2764e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 13 Sep 2014 18:25:02 +0400 Subject: [PATCH 15/15] Small fix 2 --- rpcs3/Emu/CPU/CPUThread.cpp | 4 ++-- rpcs3/Emu/Cell/PPUThread.cpp | 6 ++++-- rpcs3/Emu/Cell/PPUThread.h | 1 - rpcs3/Emu/Cell/SPUThread.cpp | 12 ++++++++---- rpcs3/Emu/SysCalls/Callback.cpp | 21 ++++++--------------- rpcs3/Emu/SysCalls/Callback.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 6 ++++-- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 6 ++++-- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 6 ++++-- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 6 ++++-- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 8 +++++++- 11 files changed, 44 insertions(+), 34 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 407055df5e..d27a608a49 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -287,8 +287,8 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000 && t) { // TODO: allow recovering from a page fault - throw fmt::Format("Access violation: addr = 0x%x (last_syscall=0x%llx (%s))", - (u32)addr, (u64)t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str()); + throw fmt::Format("Access violation: addr = 0x%x (is_alive=%d, last_syscall=0x%llx (%s))", + (u32)addr, t->IsAlive() ? 1 : 0, (u64)t->m_last_syscall, SysCalls::GetHLEFuncName((u32)t->m_last_syscall).c_str()); } else { diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 94752d653b..b0c69f4daa 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -61,8 +61,8 @@ void PPUThread::AddArgv(const std::string& arg) void PPUThread::InitRegs() { - const u32 pc = vm::read32(entry); - const u32 rtoc = vm::read32(entry + 4); + const u32 pc = entry ? vm::read32(entry) : 0; + const u32 rtoc = entry ? vm::read32(entry + 4) : 0; //ConLog.Write("entry = 0x%x", entry); //ConLog.Write("rtoc = 0x%x", rtoc); @@ -226,6 +226,7 @@ u64 PPUThread::FastCall2(u64 addr, u64 rtoc) { auto old_status = m_status; auto old_PC = PC; + auto old_stack = GPR[1]; // only saved and restored (may be wrong) auto old_rtoc = GPR[2]; auto old_LR = LR; auto old_thread = GetCurrentNamedThread(); @@ -240,6 +241,7 @@ u64 PPUThread::FastCall2(u64 addr, u64 rtoc) m_status = old_status; PC = old_PC; + GPR[1] = old_stack; GPR[2] = old_rtoc; LR = old_LR; SetCurrentNamedThread(old_thread); diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index fd30fdca16..19f16b1d61 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -792,7 +792,6 @@ public: u64 FastCall2(u64 addr, u64 rtoc); void FastStop(); -protected: virtual void DoReset() override; virtual void DoRun() override; virtual void DoPause() override; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index b82f9047d6..985f1c5528 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -556,13 +556,17 @@ void SPUThread::WriteChannel(u32 ch, const u128& r) m_intrtag[2].stat |= 1; if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread)) { - if (t->GetType() == CPU_THREAD_PPU && !t->IsAlive()) + if (t->GetType() == CPU_THREAD_PPU) { + if (t->IsAlive()) + { + LOG_ERROR(Log::SPU, "%s(%s): interrupt thread was alive", __FUNCTION__, spu_ch_name[ch]); + Emu.Pause(); + return; + } PPUThread& ppu = *(PPUThread*)t; - ppu.FastStop(); - ppu.Run(); ppu.GPR[3] = ppu.m_interrupt_arg; - ppu.FastCall2(ppu.PC, ppu.GPR[2]); + ppu.FastCall2(vm::read32(ppu.entry), vm::read32(ppu.entry + 4)); } } } diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 1425647de6..310316a6cd 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -51,26 +51,17 @@ void CallbackManager::Init() { std::lock_guard lock(m_mutex); - m_cb_thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); - - u32 cb_shit = Memory.MainMem.AllocAlign(8); - vm::write32(cb_shit, Emu.m_ppu_thr_stop); - vm::write32(cb_shit + 4, 0); - + m_cb_thread = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); m_cb_thread->SetName("Callback Thread"); - m_cb_thread->SetEntry(cb_shit); - m_cb_thread->SetPrio(1001); // ??? + m_cb_thread->SetEntry(0); + m_cb_thread->SetPrio(1001); m_cb_thread->SetStackSize(0x10000); + m_cb_thread->InitStack(); + m_cb_thread->InitRegs(); + m_cb_thread->DoRun(); thread cb_async_thread("CallbackManager::Async() thread", [this]() { - while (Emu.IsReady()) - { - m_cb_thread->WaitForAnySignal(); - } - - m_cb_thread->Run(); - SetCurrentNamedThread(m_cb_thread); while (!Emu.IsStopped()) diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index f5747e6ac5..7f5f00a3b7 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -5,7 +5,7 @@ class CallbackManager { std::vector> m_cb_list; std::vector> m_async_list; - CPUThread* m_cb_thread; + PPUThread* m_cb_thread; std::mutex m_mutex; public: diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 9a6ced9dae..17af4d56b7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -251,10 +251,12 @@ u32 adecOpen(AudioDecoder* data) adec.adecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback"); - adec.adecCb->SetEntry(0x10000); + adec.adecCb->SetEntry(0); adec.adecCb->SetPrio(1001); adec.adecCb->SetStackSize(0x10000); - adec.adecCb->Run(); + adec.adecCb->InitStack(); + adec.adecCb->InitRegs(); + adec.adecCb->DoRun(); thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]() { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index a3422b0e11..ee89639795 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -299,10 +299,12 @@ u32 dmuxOpen(Demuxer* data) dmux.dmuxCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback"); - dmux.dmuxCb->SetEntry(0x10000); + dmux.dmuxCb->SetEntry(0); dmux.dmuxCb->SetPrio(1001); dmux.dmuxCb->SetStackSize(0x10000); - dmux.dmuxCb->Run(); + dmux.dmuxCb->InitStack(); + dmux.dmuxCb->InitRegs(); + dmux.dmuxCb->DoRun(); thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]() { diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 9d89d2c984..1da760f52b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -186,10 +186,12 @@ u32 vdecOpen(VideoDecoder* data) vdec.vdecCb = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback"); - vdec.vdecCb->SetEntry(0x10000); + vdec.vdecCb->SetEntry(0); vdec.vdecCb->SetPrio(1001); vdec.vdecCb->SetStackSize(0x10000); - vdec.vdecCb->Run(); + vdec.vdecCb->InitStack(); + vdec.vdecCb->InitRegs(); + vdec.vdecCb->DoRun(); thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]() { diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index d3b540cd60..2042eb1e78 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -332,10 +332,12 @@ int cellSurMixerCreate(vm::ptr config) PPUThread& cb_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); cb_thread.SetName("Surmixer Callback Thread"); - cb_thread.SetEntry(0x10000); + cb_thread.SetEntry(0); cb_thread.SetPrio(1001); cb_thread.SetStackSize(0x10000); - cb_thread.Run(); + cb_thread.InitStack(); + cb_thread.InitRegs(); + cb_thread.DoRun(); while (port.m_is_audio_port_opened) { diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index b1cf660cc3..1114a15d8b 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -174,7 +174,7 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM; } - CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); + PPUThread& new_thread = *(PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); *thread_id = new_thread.GetId(); new_thread.SetEntry(entry); @@ -193,6 +193,12 @@ s32 sys_ppu_thread_create(vm::ptr> thread_id, u32 entry, u64 arg, s32 new_thread.Run(); new_thread.Exec(); } + else + { + new_thread.InitStack(); + new_thread.InitRegs(); + new_thread.DoRun(); + } return CELL_OK; }