diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index d881fc580c..7dd9b2d636 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -293,7 +293,7 @@ public: }; volatile u64 m_indval; }; - volatile long m_lock; + wxCriticalSection m_lock; public: @@ -305,24 +305,19 @@ public: void Init() { m_index = 0; - m_lock = 0; //simple lock } __forceinline bool Pop(u32& res) { if (max_count > 1 || x86) { - while (_InterlockedExchange(&m_lock, 1)); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); if(!m_index) { - m_lock = 0; //release lock return false; } res = m_value[--m_index]; m_value[m_index] = 0; - _mm_sfence(); - m_lock = 0; return true; } else @@ -342,16 +337,12 @@ public: { if (max_count > 1 || x86) { - while (_InterlockedExchange(&m_lock, 1)); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); if(m_index >= max_count) { - m_lock = 0; //release lock return false; } m_value[m_index++] = value; - _mm_sfence(); - m_lock = 0; return true; } else @@ -370,14 +361,11 @@ public: { if (max_count > 1 || x86) { - while (_InterlockedExchange(&m_lock, 1)); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); if(m_index >= max_count) m_value[max_count-1] = value; //last message is overwritten else m_value[m_index++] = value; - _mm_sfence(); - m_lock = 0; } else { //lock-free @@ -389,14 +377,11 @@ public: { if (max_count > 1 || x86) { - while (_InterlockedExchange(&m_lock, 1)); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); if(m_index >= max_count) m_value[max_count-1] |= value; //last message is logically ORed else m_value[m_index++] = value; - _mm_sfence(); - m_lock = 0; } else { @@ -412,8 +397,7 @@ public: { if (max_count > 1 || x86) { - while (_InterlockedExchange(&m_lock, 1)); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); if(!m_index) res = 0; //result is undefined else @@ -421,8 +405,6 @@ public: res = m_value[--m_index]; m_value[m_index] = 0; } - _mm_sfence(); - m_lock = 0; } else { //lock-free @@ -436,24 +418,30 @@ public: } } - u32 GetCount() const + __forceinline u32 GetCount() { if (max_count > 1 || x86) { - while (m_lock); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); + return m_index; + } + else + { + return m_index; } - return m_index; } - u32 GetFreeCount() const + __forceinline u32 GetFreeCount() { if (max_count > 1 || x86) { - while (m_lock); - _mm_lfence(); + wxCriticalSectionLocker lock(m_lock); + return max_count - m_index; + } + else + { + return max_count - m_index; } - return max_count - m_index; } void SetValue(u32 value) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index e73832909e..c3725f2df8 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -196,6 +196,11 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) res[idx].mount = "/app_home/"; res[idx].device = vfsDevice_LocalFile; + idx = res.Move(new VFSManagerEntry()); + res[idx].path = "$(GameDir)\\..\\"; + res[idx].mount = "/dev_bdvd/"; + res[idx].device = vfsDevice_LocalFile; + idx = res.Move(new VFSManagerEntry()); res[idx].path = ""; res[idx].mount = "/host_root/"; diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index dbd9749677..4e83d11cc7 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -141,10 +141,10 @@ struct Pad , m_device_capability(device_capability) , m_device_type(device_type) - , m_analog_left_x(0) - , m_analog_left_y(0) - , m_analog_right_x(0) - , m_analog_right_y(0) + , m_analog_left_x(128) + , m_analog_left_y(128) + , m_analog_right_x(128) + , m_analog_right_y(128) , m_press_right(0) , m_press_left(0) diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index 68fb88c772..313b91676f 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -90,6 +90,7 @@ static const g_module_list[] = {0x0050, "cellSpursJq"}, {0x0052, "cellPngEnc"}, {0x0053, "cellMusicDecode2"}, + {0x0054, "cellSync"}, {0x0055, "cellSync2"}, {0x0056, "cellNpUtil"}, {0x0057, "cellRudp"}, diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index 48166a6204..980d297d53 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -17,145 +17,532 @@ enum CELL_PAMF_ERROR_EP_NOT_FOUND = 0x80610507, }; -int cellPamfGetHeaderSize(mem8_ptr_t pAddr, u64 fileSize, mem64_t pSize) +// PamfReaderInitialize Attribute Flags +enum +{ + CELL_PAMF_ATTRIBUTE_VERIFY_ON = 1, + CELL_PAMF_ATTRIBUTE_MINIMUM_HEADER = 2, +}; + +typedef enum { + CELL_PAMF_STREAM_TYPE_AVC = 0, + CELL_PAMF_STREAM_TYPE_M2V = 1, + CELL_PAMF_STREAM_TYPE_ATRAC3PLUS = 2, + CELL_PAMF_STREAM_TYPE_PAMF_LPCM = 3, + CELL_PAMF_STREAM_TYPE_AC3 = 4, + CELL_PAMF_STREAM_TYPE_USER_DATA = 5, + CELL_PAMF_STREAM_TYPE_VIDEO = 20, + CELL_PAMF_STREAM_TYPE_AUDIO = 21, +} CellPamfStreamType; + +// Timestamp information (time in increments of 90 kHz) +struct CellCodecTimeStamp { + be_t upper; + be_t lower; +}; + +// Entry point information +struct CellPamfEp { + be_t indexN; + be_t nThRefPictureOffset; + CellCodecTimeStamp pts; + be_t rpnOffset; +}; + +// Entry point iterator +struct CellPamfEpIterator { + be_t isPamf; + be_t index; + be_t num; + be_t pCur_addr; +}; + +struct CellCodecEsFilterId { + be_t filterIdMajor; + be_t filterIdMinor; + be_t supplementalInfo1; + be_t supplementalInfo2; +}; + +// AVC (MPEG4 AVC Video) Specific Information +struct CellPamfAvcInfo { + u8 profileIdc; + u8 levelIdc; + u8 frameMbsOnlyFlag; + u8 videoSignalInfoFlag; + u8 frameRateInfo; + u8 aspectRatioIdc; + be_t sarWidth; //reserved + be_t sarHeight; //reserved + be_t horizontalSize; //multiple of 16 + be_t verticalSize; //multiple of 16 + be_t frameCropLeftOffset; //reserved + be_t frameCropRightOffset; //reserved + be_t frameCropTopOffset; //reserved + be_t frameCropBottomOffset; + u8 videoFormat; //reserved + u8 videoFullRangeFlag; + u8 colourPrimaries; + u8 transferCharacteristics; + u8 matrixCoefficients; + u8 entropyCodingModeFlag; //reserved + u8 deblockingFilterFlag; + u8 minNumSlicePerPictureIdc; //reserved + u8 nfwIdc; //reserved + u8 maxMeanBitrate; //reserved +}; + +// M2V (MPEG2 Video) Specific Information +struct CellPamfM2vInfo { + u8 profileAndLevelIndication; + be_t progressiveSequence; + u8 videoSignalInfoFlag; + u8 frameRateInfo; + u8 aspectRatioIdc; + be_t sarWidth; + be_t sarHeight; + be_t horizontalSize; + be_t verticalSize; + be_t horizontalSizeValue; + be_t verticalSizeValue; + u8 videoFormat; + u8 videoFullRangeFlag; + u8 colourPrimaries; + u8 transferCharacteristics; + u8 matrixCoefficients; +}; + +// LPCM Audio Specific Information +struct CellPamfLpcmInfo { + be_t samplingFrequency; + u8 numberOfChannels; + be_t bitsPerSample; +}; + +// ATRAC3+ Audio Specific Information +struct CellPamfAtrac3plusInfo { + be_t samplingFrequency; + u8 numberOfChannels; +}; + +// AC3 Audio Specific Information +struct CellPamfAc3Info { + be_t samplingFrequency; + u8 numberOfChannels; +}; + +#pragma pack(push, 1) //file data + +struct PamfStreamHeader_AVC { //AVC information + u8 profileIdc; + u8 levelIdc; + u8 unk0; + u8 unk1; //1 + u32 unk2; //0 + be_t horizontalSize; //divided by 16 + be_t verticalSize; //divided by 16 + u32 unk3; //0 + u32 unk4; //0 + u8 unk5; //0xA0 + u8 unk6; //1 + u8 unk7; //1 + u8 unk8; //1 + u8 unk9; //0xB0 + u8 unk10; + u16 unk11; //0 + u32 unk12; //0 +}; + +struct PamfStreamHeader //48 bytes +{ + //TODO: look for correct beginning of stream header + u8 type; //0x1B for video (AVC), 0xDC ATRAC3+, 0x80 LPCM, 0xDD userdata + u8 unk; //0 + u16 unk0; //0 + //TODO: examine stream_ch encoding + u8 stream_id; + u8 private_stream_id; + u16 unk1; //????? + be_t ep_offset; //offset of ep section in header + be_t ep_num; //count of ep + //union { //32 bytes + PamfStreamHeader_AVC AVC; + //}; +}; + +struct PamfHeader +{ + u32 magic; //"PAMF" + u32 version; //"0041" (is it const?) + be_t data_offset; //== 2048 >> 11, PAMF headers seem to be always 2048 bytes in size + be_t data_size; //== ((fileSize - 2048) >> 11) + u64 reserved[8]; + be_t table_size; //== size of mapping-table + u16 reserved1; + be_t start_pts_high; + be_t start_pts_low; //Presentation Time Stamp (start) + be_t end_pts_high; + be_t end_pts_low; //Presentation Time Stamp (end) + be_t mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps) + be_t mux_rate_min; //== 0x0107AC (?????) + u16 reserved2; // ????? + be_t stream_count; //total stream count + be_t unk1; //== 1 (?????) + be_t table_data_size; //== table_size - 0x20 == 0x14 + (0x30 * total_stream_num) (?????) + //TODO: check relative offset of stream structs (could be from 0x0c to 0x14, currently 0x14) + be_t start_pts_high2; //????? (probably same values) + be_t start_pts_low2; //????? + be_t end_pts_high2; //????? + be_t end_pts_low2; //????? + be_t unk2; //== 0x10000 (?????) + be_t unk3; // ????? + be_t unk4; // == total_stream_num + //========================== + PamfStreamHeader stream_headers[256]; +}; + +struct PamfEpHeader { //12 bytes + be_t value0; //mixed indexN (probably left 2 bits) and nThRefPictureOffset + be_t pts_high; + be_t pts_low; + be_t rpnOffset; +}; + +#pragma pack(pop) + +struct CellPamfReader +{ + //this struct can be used in any way, if it is not accessed directly by virtual CPU + //be_t internalData[16]; + u32 pAddr; + int stream; + u64 fileSize; + u32 internalData[28]; +}; + +int cellPamfGetHeaderSize(mem_ptr_t pAddr, u64 fileSize, mem64_t pSize) { cellPamf.Warning("cellPamfGetHeaderSize(pAddr=0x%x, fileSize=%d, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, pSize.GetAddr()); - pSize = 2048; // PAMF headers seem to be always 2048 bytes in size + const u64 size = (u64)pAddr->data_offset << 11; + pSize = size; return CELL_OK; } -int cellPamfGetHeaderSize2(mem8_ptr_t pAddr, u64 fileSize, u32 attribute, mem64_t pSize) +int cellPamfGetHeaderSize2(mem_ptr_t pAddr, u64 fileSize, u32 attribute, mem64_t pSize) { - cellPamf.Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=%d, pSize_addr=0x%x)", + cellPamf.Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, attribute, pSize.GetAddr()); - pSize = 2048; // PAMF headers seem to be always 2048 bytes in size + const u64 size = (u64)pAddr->data_offset << 11; + pSize = size; return CELL_OK; } -int cellPamfGetStreamOffsetAndSize() +int cellPamfGetStreamOffsetAndSize(mem_ptr_t pAddr, u64 fileSize, mem64_t pOffset, mem64_t pSize) +{ + cellPamf.Warning("cellPamfGetStreamOffsetAndSize(pAddr=0x%x, fileSize=%d, pOffset_addr=0x%x, pSize_addr=0x%x)", + pAddr.GetAddr(), fileSize, pOffset.GetAddr(), pSize.GetAddr()); + + pOffset = (u64)pAddr->data_offset << 11; + pSize = (u64)pAddr->data_size << 11; + return CELL_OK; +} + +int cellPamfVerify(mem_ptr_t pAddr, u64 fileSize) +{ + cellPamf.Warning("cellPamfVerify(pAddr=0x%x, fileSize=%d)", pAddr.GetAddr(), fileSize); + return CELL_OK; +} + +int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_t pAddr, u64 fileSize, u32 attribute) +{ + cellPamf.Warning("cellPamfReaderInitialize(pSelf=0x%x, pAddr=0x%x, fileSize=%d, attribute=0x%x)", + pSelf.GetAddr(), pAddr.GetAddr(), fileSize, attribute); + + if (fileSize) + { + pSelf->fileSize = fileSize; + } + else //if fileSize is unknown + { + pSelf->fileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11); + } + pSelf->pAddr = pAddr.GetAddr(); + + if (attribute & CELL_PAMF_ATTRIBUTE_VERIFY_ON) + { + //TODO + } + + pSelf->stream = 0; //??? currently set stream + return CELL_OK; +} + +int cellPamfReaderGetPresentationStartTime(mem_ptr_t pSelf, mem_ptr_t pTimeStamp) +{ + cellPamf.Warning("cellPamfReaderGetPresentationStartTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", + pSelf.GetAddr(), pTimeStamp.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + pTimeStamp->upper = pAddr->start_pts_high; + pTimeStamp->lower = pAddr->start_pts_low; + return CELL_OK; +} + +int cellPamfReaderGetPresentationEndTime(mem_ptr_t pSelf, mem_ptr_t pTimeStamp) +{ + cellPamf.Warning("cellPamfReaderGetPresentationEndTime(pSelf=0x%x, pTimeStamp_addr=0x%x)", + pSelf.GetAddr(), pTimeStamp.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + pTimeStamp->upper = pAddr->end_pts_high; + pTimeStamp->lower = pAddr->end_pts_low; + return CELL_OK; +} + +int cellPamfReaderGetMuxRateBound(mem_ptr_t pSelf) +{ + cellPamf.Warning("cellPamfReaderGetMuxRateBound(pSelf=0x%x)", pSelf.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + return pAddr->mux_rate_max; +} + +int cellPamfReaderGetNumberOfStreams(mem_ptr_t pSelf) +{ + cellPamf.Warning("cellPamfReaderGetNumberOfStreams(pSelf=0x%x)", pSelf.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + return pAddr->stream_count; +} + +int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 streamType) +{ + cellPamf.Warning("cellPamfReaderGetNumberOfSpecificStreams(pSelf=0x%x, streamType=%d)", + pSelf.GetAddr(), streamType); + + const mem_ptr_t pAddr(pSelf->pAddr); + + int counts[6] = {0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < pAddr->stream_count; i++) + { + switch (pAddr->stream_headers[i].type) + { + case 0x1b: counts[CELL_PAMF_STREAM_TYPE_AVC]++; break; + case 0xdc: counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS]++; break; + case 0x80: counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM]++; break; + case 0xdd: counts[CELL_PAMF_STREAM_TYPE_USER_DATA]++; break; + default: + cellPamf.Error("cellPamfReaderGetNumberOfSpecificStreams: unsupported stream type found(0x%x)", + pAddr->stream_headers[i].type); + } + } + + switch (streamType) + { + case CELL_PAMF_STREAM_TYPE_AVC: + case CELL_PAMF_STREAM_TYPE_M2V: + case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: + case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: + case CELL_PAMF_STREAM_TYPE_AC3: + case CELL_PAMF_STREAM_TYPE_USER_DATA: + return counts[streamType]; + case CELL_PAMF_STREAM_TYPE_VIDEO: + return counts[CELL_PAMF_STREAM_TYPE_AVC] + counts[CELL_PAMF_STREAM_TYPE_M2V]; + case CELL_PAMF_STREAM_TYPE_AUDIO: + return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] + + counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; + default: + return 0; + } +} + +int cellPamfReaderSetStreamWithIndex(mem_ptr_t pSelf, u8 streamIndex) +{ + cellPamf.Warning("cellPamfReaderSetStreamWithIndex(pSelf=0x%x, streamIndex=%d)", + pSelf.GetAddr(), streamIndex); + + const mem_ptr_t pAddr(pSelf->pAddr); + if (streamIndex < pAddr->stream_count) + { + pSelf->stream = streamIndex; + return CELL_OK; + } + else + { + return CELL_PAMF_ERROR_INVALID_ARG; + } +} + +int cellPamfReaderSetStreamWithTypeAndChannel(mem_ptr_t pSelf, u8 streamType, u8 ch) +{ + cellPamf.Error("cellPamfReaderSetStreamWithTypeAndChannel(pSelf=0x%x, streamType=%d, ch=%d)", + pSelf.GetAddr(), streamType, ch); + //TODO + return CELL_OK; +} + +int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 streamType, u8 streamIndex) +{ + cellPamf.Warning("cellPamfReaderSetStreamWithTypeAndIndex(pSelf=0x%x, streamType=%d, streamIndex=%d)", + pSelf.GetAddr(), streamType, streamIndex); + + const mem_ptr_t pAddr(pSelf->pAddr); + + u32 found = 0; + + for (int i = 0; i < pAddr->stream_count; i++) + { + switch (pAddr->stream_headers[i].type) + { + case 0x1b: if (streamType == CELL_PAMF_STREAM_TYPE_AVC || + streamType == CELL_PAMF_STREAM_TYPE_VIDEO) found++; break; + case 0xdc: if (streamType == CELL_PAMF_STREAM_TYPE_ATRAC3PLUS || + streamType == CELL_PAMF_STREAM_TYPE_AUDIO) found++; break; + case 0x80: if (streamType == CELL_PAMF_STREAM_TYPE_PAMF_LPCM || + streamType == CELL_PAMF_STREAM_TYPE_AUDIO) found++; break; + case 0xdd: if (streamType == CELL_PAMF_STREAM_TYPE_USER_DATA) found++; break; + default: + cellPamf.Error("cellPamfReaderSetStreamWithTypeAndIndex: unsupported stream type found(0x%x)", + pAddr->stream_headers[i].type); + } + if (found > streamIndex) + { + pSelf->stream = i; + return i; + } + } + + return CELL_PAMF_ERROR_STREAM_NOT_FOUND; +} + +int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t pEsFilterId) +{ + cellPamf.Error("cellPamfStreamTypeToEsFilterId(type=%d, ch=%d, pEsFilterId_addr=0x%x)", + type, ch, pEsFilterId.GetAddr()); + //TODO + pEsFilterId->filterIdMajor = 0; + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; + return CELL_OK; +} + +int cellPamfReaderGetStreamIndex(mem_ptr_t pSelf) +{ + return pSelf->stream; +} + +int cellPamfReaderGetStreamTypeAndChannel(mem_ptr_t pSelf, mem8_t pType, mem8_t pCh) +{ + cellPamf.Warning("cellPamfReaderGetStreamTypeAndChannel(pSelf=0x%x (stream=%d), pType_addr=0x%x, pCh_addr=0x%x", + pSelf.GetAddr(), pSelf->stream, pType.GetAddr(), pCh.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + + switch (pAddr->stream_headers[pSelf->stream].type) + { + case 0x1b: pType = CELL_PAMF_STREAM_TYPE_AVC; break; + case 0xdc: pType = CELL_PAMF_STREAM_TYPE_ATRAC3PLUS; break; + case 0x80: pType = CELL_PAMF_STREAM_TYPE_PAMF_LPCM; break; + case 0xdd: pType = CELL_PAMF_STREAM_TYPE_USER_DATA; break; + default: + pType = 0; + cellPamf.Error("cellPamfReaderGetStreamTypeAndChannel: unsupported stream type found(0x%x)", + pAddr->stream_headers[pSelf->stream].type); + } + + //TODO: get correct channel value + pCh = 0; + return CELL_OK; +} + +int cellPamfReaderGetEsFilterId(mem_ptr_t pSelf, mem_ptr_t pEsFilterId) +{ + cellPamf.Error("cellPamfReaderGetEsFilterId(pSelf=0x%x (stream=%d), pEsFilterId_addr=0x%x)", + pSelf.GetAddr(), pSelf->stream, pEsFilterId.GetAddr()); + //TODO + pEsFilterId->filterIdMajor = 0; + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; + return CELL_OK; +} + +int cellPamfReaderGetStreamInfo(mem_ptr_t pSelf, u32 pInfo_addr, u32 size) +{ + cellPamf.Error("cellPamfReaderGetStreamInfo(pSelf=0x%x (stream=%d), pInfo_addr=0x%x, size=%d)", + pSelf.GetAddr(), pSelf->stream, pInfo_addr, size); + + const mem_ptr_t pAddr(pSelf->pAddr); + + //TODO + switch (pAddr->stream_headers[pSelf->stream].type) + { + case 0x1b: /*CELL_PAMF_STREAM_TYPE_AVC*/ + { + //target structure + mem_ptr_t pInfo(pInfo_addr); + //file data structure (fixed offset 0x98, fixed step 0x30) + mem_ptr_t pAVC(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + if (size != sizeof(CellPamfAvcInfo)) { + cellPamf.Error("cellPamfReaderGetStreamInfo: incorrect AVC data size(%d)", size); + break; + } + //TODO + pInfo->profileIdc = pAVC->profileIdc; + pInfo->levelIdc = pAVC->levelIdc; + + pInfo->horizontalSize = pAVC->horizontalSize; + pInfo->verticalSize = pAVC->verticalSize; + } + break; + case 0xdc: /*CELL_PAMF_STREAM_TYPE_ATRAC3PLUS*/ break; + case 0x80: /*CELL_PAMF_STREAM_TYPE_PAMF_LPCM*/ break; + case 0xdd: /*CELL_PAMF_STREAM_TYPE_USER_DATA*/ break; + default: + cellPamf.Error("cellPamfReaderGetStreamInfo: unsupported stream type found(0x%x)", + pAddr->stream_headers[pSelf->stream].type); + } + + return CELL_OK; +} + +int cellPamfReaderGetNumberOfEp(mem_ptr_t pSelf) +{ + cellPamf.Warning("cellPamfReaderGetNumberOfEp(pSelf=0x%x (stream=%d))", + pSelf.GetAddr(), pSelf->stream); + + const mem_ptr_t pAddr(pSelf->pAddr); + return pAddr->stream_headers[pSelf->stream].ep_num; +} + +int cellPamfReaderGetEpIteratorWithIndex(mem_ptr_t pSelf, u32 epIndex, mem_ptr_t pIt) +{ + cellPamf.Warning("cellPamfReaderGetEpIteratorWithIndex(pSelf=0x%x (stream=%d), epIndex=%d, pIt_addr=0x%x)", + pSelf.GetAddr(), pSelf->stream, epIndex, pIt.GetAddr()); + + const mem_ptr_t pAddr(pSelf->pAddr); + //TODO: + return CELL_OK; +} + +int cellPamfReaderGetEpIteratorWithTimeStamp(mem_ptr_t pSelf, mem_ptr_t pTimeStamp, mem_ptr_t pIt) { UNIMPLEMENTED_FUNC(cellPamf); return CELL_OK; } -int cellPamfVerify() +int cellPamfEpIteratorGetEp(mem_ptr_t pIt, mem_ptr_t pEp) { UNIMPLEMENTED_FUNC(cellPamf); return CELL_OK; } -int cellPamfReaderInitialize() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetPresentationStartTime() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetPresentationEndTime() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetMuxRateBound() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetNumberOfStreams() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetNumberOfSpecificStreams() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderSetStreamWithIndex() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderSetStreamWithTypeAndChannel() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderSetStreamWithTypeAndIndex() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfStreamTypeToEsFilterId() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetStreamIndex() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetStreamTypeAndChannel() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetEsFilterId() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetStreamInfo() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetNumberOfEp() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetEpIteratorWithIndex() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfReaderGetEpIteratorWithTimeStamp() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfEpIteratorGetEp() -{ - UNIMPLEMENTED_FUNC(cellPamf); - return CELL_OK; -} - -int cellPamfEpIteratorMove() +int cellPamfEpIteratorMove(mem_ptr_t pIt, int steps, mem_ptr_t pEp) { UNIMPLEMENTED_FUNC(cellPamf); return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp new file mode 100644 index 0000000000..c6e8d163b4 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -0,0 +1,100 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" + +void cellSync_init(); +Module cellSync(0x0054, cellSync_init); + +// Return Codes +enum +{ + CELL_SYNC_ERROR_AGAIN = 0x80410101, + CELL_SYNC_ERROR_INVAL = 0x80410102, + CELL_SYNC_ERROR_NOMEM = 0x80410104, + CELL_SYNC_ERROR_DEADLK = 0x80410108, + CELL_SYNC_ERROR_PERM = 0x80410109, + CELL_SYNC_ERROR_BUSY = 0x8041010A, + CELL_SYNC_ERROR_STAT = 0x8041010F, + CELL_SYNC_ERROR_ALIGN = 0x80410110, + CELL_SYNC_ERROR_NULL_POINTER = 0x80410111, + CELL_SYNC_ERROR_NOT_SUPPORTED_THREAD = 0x80410112, + CELL_SYNC_ERROR_NO_NOTIFIER = 0x80410113, + CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114, +}; + +int cellSyncMutexInitialize(mem32_t mutex) +{ + const u32 mutex_addr = mutex.GetAddr(); + if (!mutex_addr) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (mutex_addr % 4) + { + return CELL_SYNC_ERROR_ALIGN; + } + mutex = 0; + return CELL_OK; +} + +int cellSyncMutexLock(mem32_t mutex) +{ + const u32 mutex_addr = mutex.GetAddr(); + if (!mutex_addr) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (mutex_addr % 4) + { + return CELL_SYNC_ERROR_ALIGN; + } + while (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24)); + //need to check how does SPU work with these mutexes, also obtainment order is not guaranteed + _mm_lfence(); + return CELL_OK; +} + +int cellSyncMutexTryLock(mem32_t mutex) +{ + const u32 mutex_addr = mutex.GetAddr(); + if (!mutex_addr) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (mutex_addr % 4) + { + return CELL_SYNC_ERROR_ALIGN; + } + //check cellSyncMutexLock + if (_InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 1 << 24)) + { + return CELL_SYNC_ERROR_BUSY; + } + _mm_lfence(); + return CELL_OK; +} + +int cellSyncMutexUnlock(mem32_t mutex) +{ + const u32 mutex_addr = mutex.GetAddr(); + if (!mutex_addr) + { + return CELL_SYNC_ERROR_NULL_POINTER; + } + if (mutex_addr % 4) + { + return CELL_SYNC_ERROR_ALIGN; + } + //check cellSyncMutexLock + _mm_sfence(); + _InterlockedExchange((volatile long*)Memory.VirtualToRealAddr(mutex_addr), 0); + return CELL_OK; +} + +void cellSync_init() +{ + cellSync.AddFunc(0xa9072dee, cellSyncMutexInitialize); + cellSync.AddFunc(0x1bb675c2, cellSyncMutexLock); + cellSync.AddFunc(0xd06918c4, cellSyncMutexTryLock); + cellSync.AddFunc(0x91f2b7b0, cellSyncMutexUnlock); +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index e015d46fda..d73bb69ed4 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -91,16 +91,22 @@ int sys_spu_image_import(mem_ptr_t img, u32 src, u32 type) return CELL_OK; } +int sys_spu_image_close(mem_ptr_t img) +{ + sysPrxForUser.Warning("sys_spu_image_close(img=0x%x)", img.GetAddr()); + return CELL_OK; +} + int sys_raw_spu_load(int id, u32 path_addr, mem32_t entry) { const wxString path = Memory.ReadString(path_addr).mb_str(); sysPrxForUser.Warning("sys_raw_spu_load(id=0x%x, path=0x%x [%s], entry_addr=0x%x)", - id, path_addr, path, entry.GetAddr()); + id, path_addr, path.c_str(), entry.GetAddr()); vfsFile f(path.c_str()); if(!f.IsOpened()) { - sysPrxForUser.Error("sys_raw_spu_load error: '%s' not found!", path); + sysPrxForUser.Error("sys_raw_spu_load error: '%s' not found!", path.c_str()); return CELL_ENOENT; } @@ -166,6 +172,7 @@ void sysPrxForUser_init() sysPrxForUser.AddFunc(0x1ed454ce, sys_spu_elf_get_information); sysPrxForUser.AddFunc(0xdb6b3250, sys_spu_elf_get_segments); sysPrxForUser.AddFunc(0xebe5f72f, sys_spu_image_import); + sysPrxForUser.AddFunc(0xe0da8efd, sys_spu_image_close); sysPrxForUser.AddFunc(0x893305fa, sys_raw_spu_load); sysPrxForUser.AddFunc(0xb995662e, sys_raw_spu_image_load); diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 45242c6bb1..d904646a77 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -155,4 +155,6 @@ void sys_fs_init() sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate); sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate); sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); + + sys_fs.AddFunc(0xc1c507e7, cellFsAioRead); } diff --git a/rpcs3/Emu/SysCalls/Modules/sys_io.cpp b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp index 9485b6f440..e470dee958 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_io.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp @@ -16,6 +16,8 @@ void sys_io_init() sys_io.AddFunc(0x3aaad464, cellPadGetInfo); sys_io.AddFunc(0xa703a51d, cellPadGetInfo2); sys_io.AddFunc(0x578e3c98, cellPadSetPortSetting); + sys_io.AddFunc(0x0e2dfaad, cellPadInfoPressMode); + sys_io.AddFunc(0x78200559, cellPadInfoSensorMode); sys_io.AddFunc(0x433f6ec0, cellKbInit); sys_io.AddFunc(0xbfce3285, cellKbEnd); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index f8093f533c..044dec8f9e 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -95,8 +95,9 @@ static func_caller* sc_table[1024] = null_func, bind_func(sys_spu_image_open), null_func, null_func, null_func, //159 bind_func(sys_raw_spu_create), null_func, null_func, null_func, null_func, //164 null_func, null_func, null_func, null_func, bind_func(sys_spu_initialize), //169 - bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), bind_func(sys_spu_thread_group_start), null_func, //174 - null_func, null_func, null_func, null_func, null_func, //179 + bind_func(sys_spu_thread_group_create), bind_func(sys_spu_thread_set_argument), bind_func(sys_spu_thread_initialize), //172 + bind_func(sys_spu_thread_group_start), bind_func(sys_spu_thread_group_suspend), //174 + null_func, null_func, null_func, bind_func(sys_spu_thread_group_join), null_func, //179 null_func, bind_func(sys_spu_thread_write_ls), bind_func(sys_spu_thread_read_ls), null_func, bind_func(sys_spu_thread_write_snr), //184 null_func, null_func, bind_func(sys_spu_thread_set_spu_cfg), bind_func(sys_spu_thread_get_spu_cfg), null_func, //189 bind_func(sys_spu_thread_write_spu_mb), bind_func(sys_spu_thread_connect_event), null_func, null_func, null_func, //194 diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index f85a2949a3..d9d1eab390 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -225,6 +225,7 @@ extern int cellFsLseek(u32 fd, s64 offset, u32 whence, mem64_t pos); extern int cellFsFtruncate(u32 fd, u64 size); extern int cellFsTruncate(u32 path_addr, u64 size); extern int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size); +extern int cellFsAioRead(mem_ptr_t aio, mem32_t id, u32 func_addr); //cellVideo extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); @@ -244,6 +245,8 @@ extern int cellPadSetActDirect(u32 port_no, u32 param_addr); extern int cellPadGetInfo(u32 info_addr); extern int cellPadGetInfo2(u32 info_addr); extern int cellPadSetPortSetting(u32 port_no, u32 port_setting); +extern int cellPadInfoPressMode(u32 port_no); +extern int cellPadInfoSensorMode(u32 port_no); //cellKb extern int cellKbInit(u32 max_connect); @@ -285,9 +288,11 @@ extern int sys_spu_image_open(mem_ptr_t img, u32 path_addr); extern int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t img, mem_ptr_t attr, mem_ptr_t arg); extern int sys_spu_thread_set_argument(u32 id, mem_ptr_t arg); extern int sys_spu_thread_group_start(u32 id); +extern int sys_spu_thread_group_suspend(u32 id); extern int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t attr); extern int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); extern int sys_spu_thread_connect_event(u32 id, u32 eq, u32 et, u8 spup); +extern int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status); extern int sys_raw_spu_create(mem32_t id, u32 attr_addr); extern int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu); extern int sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index 8e873b7972..a99b13a5b7 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -385,3 +385,49 @@ int cellFsFGetBlockSize(u32 fd, mem64_t sector_size, mem64_t block_size) return CELL_OK; } + +std::atomic g_FsAioReadID = 0; + +int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, u32 func_addr) +{ + sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x, id_addr: 0x%x, func_addr: 0x%x)", aio.GetAddr(), aio_id.GetAddr(), func_addr); + + ID id; + u32 fd = (u32)aio->fd; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsFileBase& orig_file = *(vfsFileBase*)id.m_data; + //open the file again (to prevent access conflicts roughly) + vfsStream file = *Emu.GetVFS().Open(orig_file.GetPath(), vfsRead); + + u64 nbytes = (u64)aio->size; + const u32 buf_addr = (u32)aio->buf_addr; + if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes)) + { + MemoryBlock& block = Memory.GetMemByAddr(buf_addr); + nbytes = block.GetSize() - (buf_addr - block.GetStartAddr()); + } + + //read data immediately (actually it should be read in special thread) + file.Seek((u64)aio->offset); + const u64 res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; + file.Close(); + + //get a unique id for the callback + const u32 xid = g_FsAioReadID++; + aio_id = xid; + + //TODO: init the callback + /*CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); + new_thread.SetEntry(func_addr); + new_thread.SetPrio(1001); + new_thread.SetStackSize(0x10000); + new_thread.SetName("FsAioReadCallback"); + new_thread.SetArg(0, aio.GetAddr()); //xaio + new_thread.SetArg(1, CELL_OK); //error code + new_thread.SetArg(2, xid); //xid (unique id) + new_thread.SetArg(3, res); //size (bytes read) + new_thread.Run(); + new_thread.Exec();*/ + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h index 1ed8d84a01..58e0af41f8 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.h @@ -84,3 +84,12 @@ struct CellFsDirent }; #pragma pack() + +struct CellFsAio +{ + be_t fd; + be_t offset; + be_t buf_addr; + be_t size; + be_t user_data; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index 087c0bff67..e7e1bed3d0 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -221,3 +221,15 @@ int cellPadSetPortSetting(u32 port_no, u32 port_setting) return CELL_OK; } + +int cellPadInfoPressMode(u32 port_no) +{ + sys_io.Log("cellPadInfoPressMode(port_no=%d)", port_no); + return CELL_OK; +} + +int cellPadInfoSensorMode(u32 port_no) +{ + sys_io.Log("cellPadInfoSensorMode(port_no=%d)", port_no); + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index a7fb066862..f0de6b262e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -4,6 +4,7 @@ #include "Emu/SysCalls/SC_FUNC.h" #include "Loader/ELF.h" #include "Emu/Cell/RawSPUThread.h" +#include static SysCallBase sc_spu("sys_spu"); extern SysCallBase sys_event; @@ -14,8 +15,9 @@ struct SpuGroupInfo { CPUThread* threads[g_spu_group_thr_count]; sys_spu_thread_group_attribute& attr; + volatile long lock; - SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr) + SpuGroupInfo(sys_spu_thread_group_attribute& attr) : attr(attr), lock(0) { memset(threads, 0, sizeof(CPUThread*) * g_spu_group_thr_count); } @@ -38,14 +40,14 @@ u32 LoadSpuImage(vfsStream& stream) int sys_spu_image_open(mem_ptr_t img, u32 path_addr) { const wxString path = Memory.ReadString(path_addr).mb_str(); - sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img.GetAddr(), path_addr, path); + sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img.GetAddr(), path_addr, path.c_str()); if(!img.IsGood() || !Memory.IsGoodAddr(path_addr)) { return CELL_EFAULT; } - vfsFile f(path.c_str()); + vfsFile f(path); if(!f.IsOpened()) { sc_spu.Error("sys_spu_image_open error: '%s' not found!", path); @@ -122,7 +124,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t< ConLog.Write("New SPU Thread:"); ConLog.Write("ls_entry = 0x%x", ls_entry); - ConLog.Write("name = %s", wxString(name)); + ConLog.Write("name = %s", name.c_str()); ConLog.Write("a1 = 0x%x", a1); ConLog.Write("a2 = 0x%x", a2); ConLog.Write("a3 = 0x%x", a3); @@ -182,6 +184,31 @@ int sys_spu_thread_group_start(u32 id) return CELL_OK; } +//174 +int sys_spu_thread_group_suspend(u32 id) +{ + sc_spu.Warning("sys_spu_thread_group_suspend(id=0x%x)", id); + + if(!Emu.GetIdManager().CheckID(id)) + { + return CELL_ESRCH; + } + + ID& id_data = Emu.GetIdManager().GetIDData(id); + SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data; + + //Emu.Pause(); + for(int i=0; iPause(); + } + } + + return CELL_OK; +} + //170 int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t attr) { @@ -197,13 +224,46 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_toption.ct.ToLE()); const wxString name = Memory.ReadString(attr->name_addr, attr->name_len).mb_str(); - ConLog.Write("*** name='%s'", name); + ConLog.Write("*** name='%s'", name.c_str()); id = Emu.GetIdManager().GetNewID(wxString::Format("sys_spu_thread_group '%s'", name), new SpuGroupInfo(*attr)); return CELL_OK; } +//178 +int sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status) +{ + sc_spu.Warning("sys_spu_thread_group_join(id=0x%x, cause_addr=0x%x, status_addr=0x%x)", id, cause.GetAddr(), status.GetAddr()); + + if(!Emu.GetIdManager().CheckID(id)) + { + return CELL_ESRCH; + } + + ID& id_data = Emu.GetIdManager().GetIDData(id); + SpuGroupInfo& group_info = *(SpuGroupInfo*)id_data.m_data; + + if (_InterlockedCompareExchange(&group_info.lock, 1, 0)) //get lock + { + return CELL_EBUSY; + } + + cause = SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT; + status = 0; //unspecified because of ALL_THREADS_EXIT + + for(int i=0; iIsStopped()) Sleep(1); + } + } + + _InterlockedExchange(&group_info.lock, 0); //release lock + return CELL_OK; +} + int sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) { UNIMPLEMENTED_FUNC(sc_spu); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h index c4f670c28a..9c82c6aee9 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h @@ -2,6 +2,13 @@ u32 LoadSpuImage(vfsStream& stream); +enum +{ + SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT = 0x0001, + SYS_SPU_THREAD_GROUP_JOIN_ALL_THREADS_EXIT = 0x0002, + SYS_SPU_THREAD_GROUP_JOIN_TERMINATED = 0x0004 +}; + struct sys_spu_thread_group_attribute { be_t name_len; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index f2a7c62f1d..b8f4753d1e 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -277,6 +277,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index f0d7e1d722..0fa202b3e8 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -358,6 +358,9 @@ Emu\Audio + + Emu\SysCalls\Modules + Gui