diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 0ca920f8fd..780db96233 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -766,15 +766,14 @@ private: int nScale = 1 << uimm5; for (uint w = 0; w < 4; w++) - { - // C rounding = Round towards 0 - s64 result = (s64)(CPU.VPR[vb]._f[w] * nScale); + { + float result = CPU.VPR[vb]._f[w] * nScale; if (result > INT_MAX) CPU.VPR[vd]._s32[w] = (int)INT_MAX; else if (result < INT_MIN) CPU.VPR[vd]._s32[w] = (int)INT_MIN; - else + else // C rounding = Round towards 0 CPU.VPR[vd]._s32[w] = (int)result; } } @@ -1597,7 +1596,7 @@ private: { for (uint w = 0; w < 4; w++) { - CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] << (CPU.VPR[vb]._u8[w*4] & 0x1f); + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] << (CPU.VPR[vb]._u32[w] & 0x1f); } } void VSPLTB(u32 vd, u32 uimm5, u32 vb) @@ -2050,9 +2049,10 @@ private: } void SUBFIC(u32 rd, u32 ra, s32 simm16) { - s64 RA = CPU.GPR[ra]; - CPU.GPR[rd] = (s64)simm16 - RA; - CPU.XER.CA = RA <= simm16; + const u64 RA = CPU.GPR[ra]; + const u64 IMM = (u64)(s64)simm16; + CPU.GPR[rd] = IMM - RA; + CPU.XER.CA = RA > IMM; } void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { @@ -2085,8 +2085,10 @@ private: } void BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { - if(!CheckCondition(bo, bi)) return; - CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd), lk); + if (CheckCondition(bo, bi)) + { + CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd), lk); + } if(lk) CPU.LR = CPU.PC + 4; } void SC(s32 sc_code) @@ -2110,8 +2112,10 @@ private: } void BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { - if(!CheckCondition(bo, bi)) return; - CPU.SetBranch(branchTarget(0, CPU.LR), true); + if (CheckCondition(bo, bi)) + { + CPU.SetBranch(branchTarget(0, CPU.LR), true); + } if(lk) CPU.LR = CPU.PC + 4; } void CRNOR(u32 crbd, u32 crba, u32 crbb) @@ -2126,6 +2130,7 @@ private: } void ISYNC() { + _mm_mfence(); } void CRXOR(u32 crbd, u32 crba, u32 crbb) { @@ -2162,8 +2167,8 @@ private: if(bo & 0x10 || CPU.IsCR(bi) == (bo & 0x8)) { CPU.SetBranch(branchTarget(0, CPU.CTR), true); - if(lk) CPU.LR = CPU.PC + 4; } + if(lk) CPU.LR = CPU.PC + 4; } void RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, bool rc) { @@ -2468,6 +2473,7 @@ private: void DCBST(u32 ra, u32 rb) { //UNK("dcbst", false); + _mm_mfence(); } void LWZUX(u32 rd, u32 ra, u32 rb) { @@ -2545,6 +2551,7 @@ private: void DCBF(u32 ra, u32 rb) { //UNK("dcbf", false); + _mm_mfence(); } void LBZX(u32 rd, u32 ra, u32 rb) { @@ -2590,10 +2597,26 @@ private: } void ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - const s64 RA = CPU.GPR[ra]; - const s64 RB = CPU.GPR[rb]; - CPU.GPR[rd] = RA + RB + CPU.XER.CA; - CPU.XER.CA = ((u64)RA + CPU.XER.CA > ~(u64)RB) | ((RA == -1) & CPU.XER.CA); + const u64 RA = CPU.GPR[ra]; + const u64 RB = CPU.GPR[rb]; + if (CPU.XER.CA) + { + if (RA == ~0ULL) //-1 + { + CPU.GPR[rd] = RB; + CPU.XER.CA = 1; + } + else + { + CPU.GPR[rd] = RA + 1 + RB; + CPU.XER.CA = CPU.IsCarry(RA + 1, RB); + } + } + else + { + CPU.GPR[rd] = RA + RB; + CPU.XER.CA = CPU.IsCarry(RA, RB); + } if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("addeo"); } @@ -2687,9 +2710,8 @@ private: } void ADDZE(u32 rd, u32 ra, u32 oe, bool rc) { - const s64 RA = CPU.GPR[ra]; + const u64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + CPU.XER.CA; - CPU.XER.CA = CPU.IsCarry(RA, CPU.XER.CA); if(oe) ConLog.Warning("addzeo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); @@ -2725,7 +2747,7 @@ private: } void MULLD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) { - CPU.GPR[rd] = CPU.GPR[ra] * CPU.GPR[rb]; + CPU.GPR[rd] = (s64)((s64)CPU.GPR[ra] * (s64)CPU.GPR[rb]); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("mulldo"); } @@ -2747,6 +2769,7 @@ private: void DCBTST(u32 th, u32 ra, u32 rb) { //UNK("dcbtst", false); + _mm_mfence(); } void STBUX(u32 rs, u32 ra, u32 rb) { @@ -2766,6 +2789,7 @@ private: void DCBT(u32 ra, u32 rb, u32 th) { //UNK("dcbt", false); + _mm_mfence(); } void LHZX(u32 rd, u32 ra, u32 rb) { @@ -2802,6 +2826,7 @@ private: } void DST(u32 ra, u32 rb, u32 strm, u32 t) { + _mm_mfence(); } void LHAX(u32 rd, u32 ra, u32 rb) { @@ -2830,6 +2855,7 @@ private: } void DSTST(u32 ra, u32 rb, u32 strm, u32 t) { + _mm_mfence(); } void LHAUX(u32 rd, u32 ra, u32 rb) { @@ -2839,8 +2865,7 @@ private: } void STHX(u32 rs, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - Memory.Write16(addr, CPU.GPR[rs]); + Memory.Write16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], CPU.GPR[rs]); } void ORC(u32 ra, u32 rs, u32 rb, bool rc) { @@ -2996,6 +3021,7 @@ private: } void SYNC(u32 l) { + _mm_mfence(); } void LFDX(u32 frd, u32 ra, u32 rb) { @@ -3071,12 +3097,13 @@ private: } void DSS(u32 strm, u32 a) { + _mm_mfence(); } void SRAWI(u32 ra, u32 rs, u32 sh, bool rc) { - s32 RS = CPU.GPR[rs]; + s32 RS = (u32)CPU.GPR[rs]; CPU.GPR[ra] = RS >> sh; - CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << sh) != RS); + CPU.XER.CA = (RS < 0) & ((u32)(CPU.GPR[ra] << sh) != RS); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } @@ -3094,6 +3121,7 @@ private: } void EIEIO() { + _mm_mfence(); } void STVLXL(u32 vs, u32 ra, u32 rb) { @@ -3136,6 +3164,7 @@ private: void DCBZ(u32 ra, u32 rs) { //UNK("dcbz", false); + _mm_mfence(); } void LWZ(u32 rd, u32 ra, s32 d) { diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 0a3f66d911..fa63ae9800 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -720,7 +720,7 @@ public: const u8 IsCR(const u32 bit) const { return (GetCR(bit >> 2) & GetCRBit(bit)) ? 1 : 0; } - bool IsCarry(const u64 a, const u64 b) { return a > (~b); } + bool IsCarry(const u64 a, const u64 b) { return a > (a + b); } void SetFPSCRException(const FPSCR_EXP mask) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index c6aadacdc7..4e876195c9 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -516,11 +516,11 @@ public: case MFC_PUT_CMD: case MFC_GET_CMD: { - /* ConLog.Warning("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", + if (enable_log) ConLog.Write("DMA %s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x", op & MFC_PUT_CMD ? "PUT" : "GET", op & MFC_BARRIER_MASK ? "B" : "", op & MFC_FENCE_MASK ? "F" : "", - lsa, ea, tag, size, cmd); */ + lsa, ea, tag, size, cmd); MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); } break; diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 53c2fe5b49..bd9f4396df 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1454,11 +1454,9 @@ void RSXThread::Task() { wxCriticalSectionLocker lock(m_cs_main); - //u32 put, get; - //se_t::func(put, std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, put)))); - //se_t::func(get, std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, get)))); - const u32 put = re(m_ctrl->put); - const u32 get = re(m_ctrl->get); + u32 put, get; + se_t::func(put, std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, put)))); + se_t::func(get, std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, get)))); if(put == get || !Emu.IsRunning()) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index fa523aa9f2..149076149d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -1,137 +1,148 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" +#include "cellPamf.h" +#include "cellDmux.h" void cellDmux_init(); Module cellDmux(0x0007, cellDmux_init); -// Error Codes -enum +int cellDmuxQueryAttr(mem_ptr_t demuxerType, mem_ptr_t demuxerAttr) { - CELL_DMUX_ERROR_ARG = 0x80610201, - CELL_DMUX_ERROR_SEQ = 0x80610202, - CELL_DMUX_ERROR_BUSY = 0x80610203, - CELL_DMUX_ERROR_EMPTY = 0x80610204, - CELL_DMUX_ERROR_FATAL = 0x80610205, -}; - -int cellDmuxQueryAttr() -{ - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxQueryAttr(demuxerType_addr=0x%x, demuxerAttr_addr=0x%x)", demuxerType.GetAddr(), demuxerAttr.GetAddr()); return CELL_OK; } -int cellDmuxQueryAttr2() +int cellDmuxQueryAttr2(mem_ptr_t demuxerType2, mem_ptr_t demuxerAttr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxQueryAttr2(demuxerType2_addr=0x%x, demuxerAttr_addr=0x%x)", demuxerType2.GetAddr(), demuxerAttr.GetAddr()); return CELL_OK; } -int cellDmuxOpen() +int cellDmuxOpen(mem_ptr_t demuxerType, mem_ptr_t demuxerResource, + mem_ptr_t demuxerCb, u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxOpen(demuxerType_addr=0x%x, demuxerResource_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", + demuxerType.GetAddr(), demuxerResource.GetAddr(), demuxerCb.GetAddr(), demuxerHandle_addr); return CELL_OK; } -int cellDmuxOpenEx() +int cellDmuxOpenEx(mem_ptr_t demuxerType, mem_ptr_t demuxerResourceEx, + mem_ptr_t demuxerCb, u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxOpenEx(demuxerType_addr=0x%x, demuxerResourceEx_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", + demuxerType.GetAddr(), demuxerResourceEx.GetAddr(), demuxerCb.GetAddr(), demuxerHandle_addr); return CELL_OK; } -int cellDmuxOpen2() +int cellDmuxOpen2(mem_ptr_t demuxerType2, mem_ptr_t demuxerResource2, + mem_ptr_t demuxerCb, u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxOpen2(demuxerType2_addr=0x%x, demuxerResource2_addr=0x%x, demuxerCb_addr=0x%x, demuxerHandle_addr=0x%x)", + demuxerType2.GetAddr(), demuxerResource2.GetAddr(), demuxerCb.GetAddr(), demuxerHandle_addr); return CELL_OK; } -int cellDmuxClose() +int cellDmuxClose(u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxClose(demuxerHandle_addr=0x%x)", demuxerHandle_addr); return CELL_OK; } -int cellDmuxSetStream() +int cellDmuxSetStream(u32 demuxerHandle_addr, u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxSetStream(demuxerHandle_addr=0x%x, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx", + demuxerHandle_addr, streamAddress, streamSize, discontinuity, userData); return CELL_OK; } -int cellDmuxResetStream() +int cellDmuxResetStream(u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxResetStream(demuxerHandle_addr=0x%x)", demuxerHandle_addr); return CELL_OK; } -int cellDmuxResetStreamAndWaitDone() +int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxResetStreamAndWaitDone(demuxerHandle_addr=0x%x)", demuxerHandle_addr); return CELL_OK; } -int cellDmuxQueryEsAttr() +int cellDmuxQueryEsAttr(mem_ptr_t demuxerType, mem_ptr_t esFilterId, + u32 esSpecificInfo_addr, mem_ptr_t esAttr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxQueryEsAttr(demuxerType_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)", + demuxerType.GetAddr(), esFilterId.GetAddr(), esSpecificInfo_addr, esAttr.GetAddr()); return CELL_OK; } -int cellDmuxQueryEsAttr2() +int cellDmuxQueryEsAttr2(mem_ptr_t demuxerType2, mem_ptr_t esFilterId, + u32 esSpecificInfo_addr, mem_ptr_t esAttr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxQueryEsAttr2(demuxerType2_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)", + demuxerType2.GetAddr(), esFilterId.GetAddr(), esSpecificInfo_addr, esAttr.GetAddr()); return CELL_OK; } -int cellDmuxEnableEs() +int cellDmuxEnableEs(u32 demuxerHandle_addr, mem_ptr_t esFilterId, + mem_ptr_t esResourceInfo, mem_ptr_t esCb, + u32 esSpecificInfo_addr, u32 esHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxEnableEs(demuxerHandle_addr=0x%x, esFilterId_addr=0x%x, esResourceInfo_addr=0x%x, esCb_addr=0x%x, " + "esSpecificInfo_addr=0x%x, esHandle_addr=0x%x)", demuxerHandle_addr, esFilterId.GetAddr(), esResourceInfo.GetAddr(), + esCb.GetAddr(), esSpecificInfo_addr, esHandle_addr); return CELL_OK; } -int cellDmuxDisableEs() +int cellDmuxDisableEs(u32 esHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxDisableEs(esHandle_addr=0x%x)", esHandle_addr); return CELL_OK; } -int cellDmuxResetEs() +int cellDmuxResetEs(u32 esHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxResetEs(esHandle_addr=0x%x)", esHandle_addr); return CELL_OK; } -int cellDmuxGetAu() +int cellDmuxGetAu(u32 esHandle_addr, u32 auInfo_ptr_addr, u32 auSpecificInfo_ptr_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxGetAu(esHandle_addr=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", + esHandle_addr, auInfo_ptr_addr, auSpecificInfo_ptr_addr); return CELL_OK; } -int cellDmuxPeekAu() +int cellDmuxPeekAu(u32 esHandle_addr, u32 auInfo_ptr_addr, u32 auSpecificInfo_ptr_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxPeekAu(esHandle_addr=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", + esHandle_addr, auInfo_ptr_addr, auSpecificInfo_ptr_addr); return CELL_OK; } -int cellDmuxGetAuEx() +int cellDmuxGetAuEx(u32 esHandle_addr, u32 auInfoEx_ptr_addr, u32 auSpecificInfo_ptr_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxGetAuEx(esHandle_addr=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", + esHandle_addr, auInfoEx_ptr_addr, auSpecificInfo_ptr_addr); return CELL_OK; } -int cellDmuxPeekAuEx() +int cellDmuxPeekAuEx(u32 esHandle_addr, u32 auInfoEx_ptr_addr, u32 auSpecificInfo_ptr_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxPeekAuEx(esHandle_addr=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)", + esHandle_addr, auInfoEx_ptr_addr, auSpecificInfo_ptr_addr); return CELL_OK; } -int cellDmuxReleaseAu() +int cellDmuxReleaseAu(u32 esHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxReleaseAu(esHandle_addr=0x%x)", esHandle_addr); return CELL_OK; } -int cellDmuxFlushEs() +int cellDmuxFlushEs(u32 esHandle_addr) { - UNIMPLEMENTED_FUNC(cellDmux); + cellDmux.Error("cellDmuxFlushEs(esHandle_addr=0x%x)", esHandle_addr); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h new file mode 100644 index 0000000000..77bab0fcdb --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -0,0 +1,168 @@ +#pragma once + +// Error Codes +enum +{ + CELL_DMUX_ERROR_ARG = 0x80610201, + CELL_DMUX_ERROR_SEQ = 0x80610202, + CELL_DMUX_ERROR_BUSY = 0x80610203, + CELL_DMUX_ERROR_EMPTY = 0x80610204, + CELL_DMUX_ERROR_FATAL = 0x80610205, +}; + +enum CellDmuxStreamType +{ + CELL_DMUX_STREAM_TYPE_UNDEF = 0, + CELL_DMUX_STREAM_TYPE_PAMF = 1, + CELL_DMUX_STREAM_TYPE_TERMINATOR = 2, +}; + +enum CellDmuxMsgType +{ + CELL_DMUX_MSG_TYPE_DEMUX_DONE = 0, + CELL_DMUX_MSG_TYPE_FATAL_ERR = 1, + CELL_DMUX_MSG_TYPE_PROG_END_CODE = 2, +}; + +enum CellDmuxEsMsgType +{ + CELL_DMUX_ES_MSG_TYPE_AU_FOUND = 0, + CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE = 1, +}; + +struct CellDmuxMsg +{ + be_t msgType; //CellDmuxMsgType enum + be_t supplementalInfo; +}; + +struct CellDmuxEsMsg +{ + be_t msgType; //CellDmuxEsMsgType enum + be_t supplementalInfo; +}; + +struct CellDmuxType +{ + CellDmuxStreamType streamType; + be_t reserved[2]; //0 +}; + +struct CellDmuxType2 +{ + CellDmuxStreamType streamType; + be_t streamSpecificInfo_addr; +}; + +struct CellDmuxResource +{ + be_t memAddr; + be_t memSize; + be_t ppuThreadPriority; + be_t ppuThreadStackSize; + be_t spuThreadPriority; + be_t numOfSpus; +}; + +struct CellDmuxResourceEx +{ + be_t memAddr; + be_t memSize; + be_t ppuThreadPriority; + be_t ppuThreadStackSize; + be_t spurs_addr; + u8 priority[8]; + be_t maxContention; +}; + +/* +struct CellDmuxResource2Ex +{ + bool isResourceEx; //true + CellDmuxResourceEx resourceEx; +}; + +struct CellDmuxResource2NoEx +{ + bool isResourceEx; //false + CellDmuxResource resource; +}; +*/ + +struct CellDmuxResource2 +{ + bool isResourceEx; + be_t memAddr; + be_t memSize; + be_t ppuThreadPriority; + be_t ppuThreadStackSize; + union + { + struct + { + be_t noex_spuThreadPriority; + be_t noex_numOfSpus; + }; + struct + { + be_t ex_spurs_addr; + u8 ex_priority[8]; + be_t ex_maxContention; + }; + }; +}; + +struct CellDmuxCb +{ + // CellDmuxCbMsg callback + be_t demuxerMsg, u32 cbArg_addr)>> cbMsgFunc; + be_t cbArg_addr; +}; + +struct CellDmuxEsCb +{ + // CellDmuxCbEsMsg callback + be_t esMsg, u32 cbArg_addr)>> cbEsMsgFunc; + be_t cbArg_addr; +}; + +struct CellDmuxAttr +{ + be_t memSize; + be_t demuxerVerUpper; + be_t demuxerVerLower; +}; + +struct CellDmuxEsAttr +{ + be_t memSize; +}; + +struct CellDmuxEsResource +{ + be_t memAddr; + be_t memSize; +}; + +struct CellDmuxAuInfo +{ + be_t auAddr; + be_t auSize; + be_t auMaxSize; + be_t userData; + be_t ptsUpper; + be_t ptsLower; + be_t dtsUpper; + be_t dtsLower; +}; + +struct CellDmuxAuInfoEx +{ + be_t auAddr; + be_t auSize; + be_t reserved; + bool isRap; + be_t userData; + CellCodecTimeStamp pts; + CellCodecTimeStamp dts; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index f97bc3c8d1..1e33d4d572 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -1,233 +1,128 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" +#include "cellPamf.h" void cellPamf_init(); Module cellPamf(0x0012, cellPamf_init); -// Error Codes -enum +int pamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t pEsFilterId) { - CELL_PAMF_ERROR_STREAM_NOT_FOUND = 0x80610501, - CELL_PAMF_ERROR_INVALID_PAMF = 0x80610502, - CELL_PAMF_ERROR_INVALID_ARG = 0x80610503, - CELL_PAMF_ERROR_UNKNOWN_TYPE = 0x80610504, - CELL_PAMF_ERROR_UNSUPPORTED_VERSION = 0x80610505, - CELL_PAMF_ERROR_UNKNOWN_STREAM = 0x80610506, - CELL_PAMF_ERROR_EP_NOT_FOUND = 0x80610507, -}; + //TODO: convert type and ch to EsFilterId + pEsFilterId->filterIdMajor = 0; + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; -// PamfReaderInitialize Attribute Flags -enum + switch (type) + { + case CELL_PAMF_STREAM_TYPE_AVC: + switch (ch) + { + case 0: + { + pEsFilterId->filterIdMajor = 0xe0; //fake info + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0x01; + pEsFilterId->supplementalInfo2 = 0; + } + break; + case 1: + { + pEsFilterId->filterIdMajor = 0xe1; + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0x01; + pEsFilterId->supplementalInfo2 = 0; + } + break; + default: + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_AVC (ch=%d)", ch); + } + break; + case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: + if (ch == 0) + { + pEsFilterId->filterIdMajor = 0xbd; + pEsFilterId->filterIdMinor = 0; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; + } + else + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_ATRAC3PLUS (ch=%d)", ch); + break; + case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: + if (ch == 0) + { + pEsFilterId->filterIdMajor = 0xbd; + pEsFilterId->filterIdMinor = 0x40; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; + } + else + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_LPCM (ch=%d)", ch); + break; + case CELL_PAMF_STREAM_TYPE_USER_DATA: + if (ch == 0) + { + pEsFilterId->filterIdMajor = 0xbd; + pEsFilterId->filterIdMinor = 0x20; + pEsFilterId->supplementalInfo1 = 0; + pEsFilterId->supplementalInfo2 = 0; + } + else + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_USER_DATA (ch=%d)", ch); + break; + case CELL_PAMF_STREAM_TYPE_AC3: + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_AC3 (ch=%d)", ch); + break; + case CELL_PAMF_STREAM_TYPE_M2V: + cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_M2V (ch=%d)", ch); + break; + default: + return CELL_PAMF_ERROR_INVALID_ARG; + } + return CELL_OK; +} + +u8 pamfGetStreamType(mem_ptr_t pSelf, u8 stream) { - CELL_PAMF_ATTRIBUTE_VERIFY_ON = 1, - CELL_PAMF_ATTRIBUTE_MINIMUM_HEADER = 2, -}; + //TODO: get stream type correctly + const mem_ptr_t pAddr(pSelf->pAddr); -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; + switch (pAddr->stream_headers[stream].type) + { + case 0x1b: return CELL_PAMF_STREAM_TYPE_AVC; + case 0xdc: return CELL_PAMF_STREAM_TYPE_ATRAC3PLUS; + case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM; + case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA; + default: + cellPamf.Error("pamfGetStreamType: unsupported stream type found(0x%x)", + pAddr->stream_headers[stream].type); + return 0; + } +} -// 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 +u8 pamfGetStreamChannel(mem_ptr_t pSelf, u8 stream) { - //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; - //}; -}; + cellPamf.Warning("TODO: pamfGetStreamChannel"); + //TODO: get stream channel correctly + const mem_ptr_t pAddr(pSelf->pAddr); -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; // ????? - u8 reserved3; - u8 stream_count; //total stream count (reduced to 1 byte) - 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]; -}; + if ((pAddr->stream_headers[stream].type == 0x1b) && + (pAddr->stream_headers[stream].stream_id == 0xe1)) return 1; + return 0; +} 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()); - const u64 size = (u64)pAddr->data_offset << 11; - pSize = size; + //if ((u32)pAddr->magic != 0x464d4150) + //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + + const u64 offset = (u64)pAddr->data_offset << 11; + pSize = offset /*? offset : 2048*/; //hack return CELL_OK; } @@ -236,19 +131,29 @@ int cellPamfGetHeaderSize2(mem_ptr_t pAddr, u64 fileSize, u32 attrib cellPamf.Warning("cellPamfGetHeaderSize2(pAddr=0x%x, fileSize=%d, attribute=0x%x, pSize_addr=0x%x)", pAddr.GetAddr(), fileSize, attribute, pSize.GetAddr()); - const u64 size = (u64)pAddr->data_offset << 11; - pSize = size; + //if ((u32)pAddr->magic != 0x464d4150) + //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + + const u64 offset = (u64)pAddr->data_offset << 11; + pSize = offset /*? offset : 2048*/; //hack return CELL_OK; } +//u32 hack_LastHeader = 0; + 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()); - const u64 size = (u64)pAddr->data_offset << 11; - pOffset = size; - pSize = (u64)pAddr->data_size << 11; + //if ((u32)pAddr->magic != 0x464d4150) + //return CELL_PAMF_ERROR_UNKNOWN_TYPE; + + const u64 offset = (u64)pAddr->data_offset << 11; + pOffset = offset /*? offset : 2048*/; //hack + const u64 size = (u64)pAddr->data_size << 11; + pSize = size /*? size : (fileSize - 2048)*/; //hack + //if (!(u32)pAddr->magic) hack_LastHeader = pAddr.GetAddr(); return CELL_OK; } @@ -262,7 +167,7 @@ int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_tfileSize = fileSize; @@ -272,7 +177,7 @@ int cellPamfReaderInitialize(mem_ptr_t pSelf, mem_ptr_tfileSize = ((u64)pAddr->data_offset << 11) + ((u64)pAddr->data_size << 11); } pSelf->pAddr = pAddr.GetAddr(); - + //if (hack_LastHeader) memcpy(Memory + pAddr.GetAddr(), Memory + hack_LastHeader, 2048); if (attribute & CELL_PAMF_ATTRIBUTE_VERIFY_ON) { //TODO @@ -288,7 +193,8 @@ int cellPamfReaderGetPresentationStartTime(mem_ptr_t pSelf, mem_ pSelf.GetAddr(), pTimeStamp.GetAddr()); const mem_ptr_t pAddr(pSelf->pAddr); - pTimeStamp->upper = pAddr->start_pts_high; + const u32 upper = (u16)pAddr->start_pts_high; + pTimeStamp->upper = upper; pTimeStamp->lower = pAddr->start_pts_low; return CELL_OK; } @@ -299,7 +205,8 @@ int cellPamfReaderGetPresentationEndTime(mem_ptr_t pSelf, mem_pt pSelf.GetAddr(), pTimeStamp.GetAddr()); const mem_ptr_t pAddr(pSelf->pAddr); - pTimeStamp->upper = pAddr->end_pts_high; + const u32 upper = (u16)pAddr->end_pts_high; + pTimeStamp->upper = upper; pTimeStamp->lower = pAddr->end_pts_low; return CELL_OK; } @@ -329,22 +236,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 int counts[6] = {0, 0, 0, 0, 0, 0}; - /*if (!pAddr->magic) - return 1; /*hack*/ - - for (int i = 0; i < pAddr->stream_count; i++) + for (u8 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); - break; - } + counts[pamfGetStreamType(pSelf, i)]++; } switch (streamType) @@ -362,7 +256,7 @@ int cellPamfReaderGetNumberOfSpecificStreams(mem_ptr_t pSelf, u8 return counts[CELL_PAMF_STREAM_TYPE_ATRAC3PLUS] + counts[CELL_PAMF_STREAM_TYPE_PAMF_LPCM] + counts[CELL_PAMF_STREAM_TYPE_AC3]; default: - return 0; + return 0; } } @@ -372,6 +266,7 @@ int cellPamfReaderSetStreamWithIndex(mem_ptr_t pSelf, u8 streamI pSelf.GetAddr(), streamIndex); const mem_ptr_t pAddr(pSelf->pAddr); + if (streamIndex < pAddr->stream_count) { pSelf->stream = streamIndex; @@ -385,10 +280,31 @@ int cellPamfReaderSetStreamWithIndex(mem_ptr_t pSelf, u8 streamI int cellPamfReaderSetStreamWithTypeAndChannel(mem_ptr_t pSelf, u8 streamType, u8 ch) { - cellPamf.Error("cellPamfReaderSetStreamWithTypeAndChannel(pSelf=0x%x, streamType=%d, ch=%d)", + cellPamf.Warning("cellPamfReaderSetStreamWithTypeAndChannel(pSelf=0x%x, streamType=%d, ch=%d)", pSelf.GetAddr(), streamType, ch); - //TODO - return CELL_OK; + + const mem_ptr_t pAddr(pSelf->pAddr); + + if (streamType > 5) + { + cellPamf.Error("cellPamfReaderSetStreamWithTypeAndChannel: invalid stream type(%d)", streamType); + //it probably doesn't support "any audio" or "any video" argument + return CELL_PAMF_ERROR_INVALID_ARG; + } + + for (u8 i = 0; i < pAddr->stream_count; i++) + { + if (pamfGetStreamType(pSelf, i) == streamType) + { + if (pamfGetStreamChannel(pSelf, i) == ch) + { + pSelf->stream = i; + return i; + } + } + } + + return CELL_PAMF_ERROR_STREAM_NOT_FOUND; } int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 streamType, u8 streamIndex) @@ -400,24 +316,35 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 u32 found = 0; - /*if (!pAddr->magic) - return 0; /*hack*/ - - for (int i = 0; i < pAddr->stream_count; i++) + for (u8 i = 0; i < pAddr->stream_count; i++) { - switch (pAddr->stream_headers[i].type) + const u8 type = pamfGetStreamType(pSelf, i); + + if (type == streamType) { - 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); + found++; } + else switch(streamType) + { + case CELL_PAMF_STREAM_TYPE_VIDEO: + if (type == CELL_PAMF_STREAM_TYPE_AVC || type == CELL_PAMF_STREAM_TYPE_M2V) + { + found++; + } + break; + case CELL_PAMF_STREAM_TYPE_AUDIO: + if (type == CELL_PAMF_STREAM_TYPE_ATRAC3PLUS || type == CELL_PAMF_STREAM_TYPE_AC3 || type == CELL_PAMF_STREAM_TYPE_PAMF_LPCM) + { + found++; + } + break; + default: + if (streamType > 5) + { + return CELL_PAMF_ERROR_INVALID_ARG; + } + } + if (found > streamIndex) { pSelf->stream = i; @@ -430,14 +357,10 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t pSelf, u8 int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t pEsFilterId) { - cellPamf.Error("cellPamfStreamTypeToEsFilterId(type=%d, ch=%d, pEsFilterId_addr=0x%x)", + cellPamf.Warning("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; + + return pamfStreamTypeToEsFilterId(type, ch, pEsFilterId); } int cellPamfReaderGetStreamIndex(mem_ptr_t pSelf) @@ -450,71 +373,123 @@ int cellPamfReaderGetStreamTypeAndChannel(mem_ptr_t pSelf, mem8_ 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; + pType = pamfGetStreamType(pSelf, pSelf->stream); + pCh = pamfGetStreamChannel(pSelf, pSelf->stream); 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)", + cellPamf.Warning("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; + + return pamfStreamTypeToEsFilterId(pamfGetStreamType(pSelf, pSelf->stream), + pamfGetStreamChannel(pSelf, pSelf->stream), pEsFilterId); } 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)", + cellPamf.Warning("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) + memset(Memory + pInfo_addr, 0, size); + + switch (pamfGetStreamType(pSelf, pSelf->stream)) { - case 0x1b: /*CELL_PAMF_STREAM_TYPE_AVC*/ + case 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; + + if (size != sizeof(CellPamfAvcInfo)) + { + cellPamf.Error("cellPamfReaderGetStreamInfo: wrong AVC data size(%d)", size); + return CELL_PAMF_ERROR_INVALID_ARG; } - //TODO + pInfo->profileIdc = pAVC->profileIdc; pInfo->levelIdc = pAVC->levelIdc; - pInfo->horizontalSize = pAVC->horizontalSize; - pInfo->verticalSize = pAVC->verticalSize; + pInfo->frameMbsOnlyFlag = 1; //fake + pInfo->frameRateInfo = (pAVC->unk0 & 0x7) - 1; + pInfo->aspectRatioIdc = 1; //fake + + pInfo->horizontalSize = 16 * (u16)pAVC->horizontalSize; + pInfo->verticalSize = 16 * (u16)pAVC->verticalSize; + + pInfo->videoSignalInfoFlag = 1; //fake + pInfo->colourPrimaries = 1; //fake + pInfo->transferCharacteristics = 1; //fake + pInfo->matrixCoefficients = 1; //fake + //pInfo->deblockingFilterFlag = 1; //??? + + cellPamf.Warning("cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_AVC"); } 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); + case CELL_PAMF_STREAM_TYPE_M2V: + { + //TODO + cellPamf.Error("TODO: cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_M2V"); + } + break; + case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS: + { + mem_ptr_t pInfo(pInfo_addr); + mem_ptr_t pAudio(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + + if (size != sizeof(CellPamfAtrac3plusInfo)) + { + cellPamf.Error("cellPamfReaderGetStreamInfo: wrong ATRAC3+ data size(%d)", size); + return CELL_PAMF_ERROR_INVALID_ARG; + } + + pInfo->numberOfChannels = pAudio->channels; + pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; + } + break; + case CELL_PAMF_STREAM_TYPE_AC3: + { + mem_ptr_t pInfo(pInfo_addr); + mem_ptr_t pAudio(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + + if (size != sizeof(CellPamfAc3Info)) + { + cellPamf.Error("cellPamfReaderGetStreamInfo: wrong AC3 data size(%d)", size); + return CELL_PAMF_ERROR_INVALID_ARG; + } + + pInfo->numberOfChannels = pAudio->channels; + pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; + } + break; + case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: + { + mem_ptr_t pInfo(pInfo_addr); + mem_ptr_t pAudio(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + + if (size != sizeof(CellPamfLpcmInfo)) + { + cellPamf.Error("cellPamfReaderGetStreamInfo: wrong LPCM data size(%d)", size); + return CELL_PAMF_ERROR_INVALID_ARG; + } + + pInfo->numberOfChannels = pAudio->channels; + pInfo->samplingFrequency = CELL_PAMF_FS_48kHz; + + if (pAudio->bps = 0x40) + pInfo->bitsPerSample = CELL_PAMF_BIT_LENGTH_16; + else + //TODO: CELL_PAMF_BIT_LENGTH_24 + cellPamf.Error("cellPamfReaderGetStreamInfo: unknown bps(0x%x)", (u8)pAudio->bps); + } + break; + case CELL_PAMF_STREAM_TYPE_USER_DATA: + { + cellPamf.Error("cellPamfReaderGetStreamInfo: CELL_PAMF_STREAM_TYPE_USER_DATA"); + return CELL_PAMF_ERROR_INVALID_ARG; + } } return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.h b/rpcs3/Emu/SysCalls/Modules/cellPamf.h new file mode 100644 index 0000000000..b88c473af0 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.h @@ -0,0 +1,335 @@ +#pragma once + +// Error Codes +enum +{ + CELL_PAMF_ERROR_STREAM_NOT_FOUND = 0x80610501, + CELL_PAMF_ERROR_INVALID_PAMF = 0x80610502, + CELL_PAMF_ERROR_INVALID_ARG = 0x80610503, + CELL_PAMF_ERROR_UNKNOWN_TYPE = 0x80610504, + CELL_PAMF_ERROR_UNSUPPORTED_VERSION = 0x80610505, + CELL_PAMF_ERROR_UNKNOWN_STREAM = 0x80610506, + CELL_PAMF_ERROR_EP_NOT_FOUND = 0x80610507, +}; + +// PamfReaderInitialize Attribute Flags +enum +{ + CELL_PAMF_ATTRIBUTE_VERIFY_ON = 1, + CELL_PAMF_ATTRIBUTE_MINIMUM_HEADER = 2, +}; + +enum CellPamfStreamType +{ + 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, +}; + +enum +{ + CELL_PAMF_FS_48kHz = 1, +}; + +enum +{ + CELL_PAMF_BIT_LENGTH_16 = 1, + CELL_PAMF_BIT_LENGTH_24 = 3, +}; + +enum +{ + CELL_PAMF_AVC_PROFILE_MAIN = 77, + CELL_PAMF_AVC_PROFILE_HIGH = 100, +}; + +enum +{ + CELL_PAMF_AVC_LEVEL_2P1 = 21, + CELL_PAMF_AVC_LEVEL_3P0 = 30, + CELL_PAMF_AVC_LEVEL_3P1 = 31, + CELL_PAMF_AVC_LEVEL_3P2 = 32, + CELL_PAMF_AVC_LEVEL_4P1 = 41, + CELL_PAMF_AVC_LEVEL_4P2 = 42, +}; + +enum +{ + CELL_PAMF_AVC_FRC_24000DIV1001 = 0, + CELL_PAMF_AVC_FRC_24 = 1, + CELL_PAMF_AVC_FRC_25 = 2, + CELL_PAMF_AVC_FRC_30000DIV1001 = 3, + CELL_PAMF_AVC_FRC_30 = 4, + CELL_PAMF_AVC_FRC_50 = 5, + CELL_PAMF_AVC_FRC_60000DIV1001 = 6, +}; + +enum +{ + CELL_PAMF_M2V_MP_ML = 1, + CELL_PAMF_M2V_MP_H14 = 2, + CELL_PAMF_M2V_MP_HL = 3, + CELL_PAMF_M2V_UNKNOWN = 255, +}; + +enum +{ + CELL_PAMF_M2V_FRC_24000DIV1001 = 1, + CELL_PAMF_M2V_FRC_24 = 2, + CELL_PAMF_M2V_FRC_25 = 3, + CELL_PAMF_M2V_FRC_30000DIV1001 = 4, + CELL_PAMF_M2V_FRC_30 = 5, + CELL_PAMF_M2V_FRC_50 = 6, + CELL_PAMF_M2V_FRC_60000DIV1001 = 7, +}; + +enum +{ + CELL_PAMF_ASPECT_RATIO_1_1 = 1, + CELL_PAMF_ASPECT_RATIO_12_11 = 2, + CELL_PAMF_ASPECT_RATIO_10_11 = 3, + CELL_PAMF_ASPECT_RATIO_16_11 = 4, + CELL_PAMF_ASPECT_RATIO_40_33 = 5, + CELL_PAMF_ASPECT_RATIO_4_3 = 14, +}; + +enum +{ + CELL_PAMF_COLOUR_PRIMARIES_ITR_R_BT_709 = 1, + CELL_PAMF_COLOUR_PRIMARIES_UNSPECIFIED = 2, + CELL_PAMF_COLOUR_PRIMARIES_ITU_R_BT_470_SYS_M = 4, + CELL_PAMF_COLOUR_PRIMARIES_ITU_R_BT_470_SYS_BG = 5, + CELL_PAMF_COLOUR_PRIMARIES_SMPTE_170_M = 6, + CELL_PAMF_COLOUR_PRIMARIES_SMPTE_240_M = 7, + CELL_PAMF_COLOUR_PRIMARIES_GENERIC_FILM = 8, +}; + +enum +{ + CELL_PAMF_TRANSFER_CHARACTERISTICS_ITU_R_BT_709 = 1, + CELL_PAMF_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2, + CELL_PAMF_TRANSFER_CHARACTERISTICS_ITU_R_BT_470_SYS_M = 4, + CELL_PAMF_TRANSFER_CHARACTERISTICS_ITU_R_BT_470_SYS_BG = 5, + CELL_PAMF_TRANSFER_CHARACTERISTICS_SMPTE_170_M = 6, + CELL_PAMF_TRANSFER_CHARACTERISTICS_SMPTE_240_M = 7, + CELL_PAMF_TRANSFER_CHARACTERISTICS_LINEAR = 8, + CELL_PAMF_TRANSFER_CHARACTERISTICS_LOG_100_1 = 9, + CELL_PAMF_TRANSFER_CHARACTERISTICS_LOG_316_1 = 10, +}; + +enum +{ + CELL_PAMF_MATRIX_GBR = 0, + CELL_PAMF_MATRIX_ITU_R_BT_709 = 1, + CELL_PAMF_MATRIX_UNSPECIFIED = 2, + CELL_PAMF_MATRIX_FCC = 4, + CELL_PAMF_MATRIX_ITU_R_BT_470_SYS_BG = 5, + CELL_PAMF_MATRIX_SMPTE_170_M = 6, + CELL_PAMF_MATRIX_SMPTE_240_M = 7, + CELL_PAMF_MATRIX_YCGCO = 8, +}; + +// 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 +{ + bool 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; + be_t verticalSize; + 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; + bool 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 specific 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_M2V { //M2V specific information + u8 unknown[32]; //no information yet +}; + +struct PamfStreamHeader_Audio { //Audio specific information + u16 unknown; //== 0 + u8 channels; //number of channels (1, 2, 6 or 8) + u8 freq; //== 1 (always 48000) + u8 bps; //(LPCM only, 0x40 for 16 bit, ???? for 24) + u8 reserved[27]; //probably nothing +}; + +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 unknown[3]; //0 + //TODO: examine stream_ch encoding + u8 stream_id; + u8 private_stream_id; + u8 unknown1; //????? + u8 unknown2; //????? + //Entry Point Info + be_t ep_offset; //offset of EP section in header + be_t ep_num; //count of EPs + //Specific Info + u8 data[32]; +}; + +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; // ????? + u8 reserved3; + u8 stream_count; //total stream count (reduced to 1 byte) + 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; // == stream_count + //========================== + 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]; +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 30e5884fa7..1f48bbe323 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -457,7 +457,7 @@ int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 as int cellSysutilCheckCallback() { - //cellSysutil.Warning("cellSysutilCheckCallback()"); + cellSysutil.Warning("cellSysutilCheckCallback()"); Emu.GetCallbackManager().m_exit_callback.Check(); return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index cd0d747ba3..c3bf7214fb 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -152,16 +152,21 @@ void fsAioRead(u32 fd, mem_ptr_t aio, int xid, mem_func_ptr_toffset); res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0; + file.Seek(old_pos); error = CELL_OK; } else @@ -185,15 +190,17 @@ int cellFsAioRead(mem_ptr_t aio, mem32_t aio_id, mem_func_ptr_tfd; if(!sys_fs.CheckId(fd, orig_file)) return CELL_ESRCH; - //get a unique id for the callback + //get a unique id for the callback (may be used by cellFsAioCancel) const u32 xid = g_FsAioReadID++; - aio_id = xid; + //read data in another thread (doesn't work correctly): //std::thread t(fsAioRead, fd, aio, xid, func); //t.detach(); //read data immediately (actually it should be read in special thread): fsAioRead(fd, aio, xid, func); + aio_id = xid; + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 4d5307d115..6158e81a1f 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -5,8 +5,8 @@ #include "lv2/SC_Timer.h" #include "lv2/SC_Rwlock.h" #include "lv2/SC_SPU_Thread.h" +#include "lv2/SC_Lwmutex.h" #include "Emu/event.h" - //#define SYSCALLS_DEBUG #define declCPU PPUThread& CPU = GetCurrentPPUThread @@ -148,11 +148,11 @@ extern int sys_semaphore_post(u32 sem, int count); extern int sys_semaphore_get_value(u32 sem, u32 count_addr); //sys_lwmutex -extern int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr); -extern int sys_lwmutex_destroy(u64 lwmutex_addr); -extern int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout); -extern int sys_lwmutex_trylock(u64 lwmutex_addr); -extern int sys_lwmutex_unlock(u64 lwmutex_addr); +extern int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr); +extern int sys_lwmutex_destroy(mem_ptr_t lwmutex); +extern int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout); +extern int sys_lwmutex_trylock(mem_ptr_t lwmutex); +extern int sys_lwmutex_unlock(mem_ptr_t lwmutex); //sys_cond extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index f483e90e00..c1e2779df4 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -1,122 +1,198 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/lv2/SC_Lwmutex.h" +#include -struct lwmutex_lock_info +SysCallBase sc_lwmutex("sys_lwmutex"); + +std::mutex g_lwmutex; + +int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_t attr) { - u32 owner; - u32 waiter; -}; + sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)", + lwmutex.GetAddr(), attr.GetAddr()); -union lwmutex_variable -{ - lwmutex_lock_info info; - u64 all_info; -}; + if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT; -struct lwmutex -{ - lwmutex_variable lock_var; - u32 attribute; - u32 recursive_count; - u32 sleep_queue; - u32 pad; -}; - -struct lwmutex_attr -{ - u32 attr_protocol; - u32 attr_recursive; - char name[8]; -}; - -SysCallBase sc_lwmutex("sys_wmutex"); - -int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr) -{ - if(!Memory.IsGoodAddr(lwmutex_addr, 4) || !Memory.IsGoodAddr(lwmutex_attr_addr)) + switch ((u32)attr->attr_recursive) { - return CELL_EFAULT; + case SYS_SYNC_RECURSIVE: break; + case SYS_SYNC_NOT_RECURSIVE: break; + default: return CELL_EINVAL; } - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - lmtx.lock_var.all_info = 0; - lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr]; + switch ((u32)attr->attr_protocol) + { + case SYS_SYNC_PRIORITY: break; + case SYS_SYNC_RETRY: sc_lwmutex.Error("TODO: SYS_SYNC_RETRY attr"); break; + case SYS_SYNC_PRIORITY_INHERIT: sc_lwmutex.Error("TODO: SYS_SYNC_PRIORITY_INHERIT attr"); break; + case SYS_SYNC_FIFO: sc_lwmutex.Error("TODO: SYS_SYNC_FIFO attr"); break; + default: return CELL_EINVAL; + } + + lwmutex->attribute = (u32)attr->attr_protocol | (u32)attr->attr_recursive; + lwmutex->all_info = 0; + lwmutex->pad = 0; + lwmutex->recursive_count = 0; + lwmutex->sleep_queue = 0; + + sc_lwmutex.Log("*** lwmutex created [%s] (protocol=0x%x, recursive=0x%x)", + attr->name, (u32)attr->attr_protocol, (u32)attr->attr_recursive); return CELL_OK; } -int sys_lwmutex_destroy(u64 lwmutex_addr) +int sys_lwmutex_destroy(mem_ptr_t lwmutex) { - //sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr); - - //lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - //Emu.GetIdManager().RemoveID(lmtx.attribute); + sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr=0x%x)", lwmutex.GetAddr()); return CELL_OK; } -int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout) +int sys_lwmutex_lock(mem_ptr_t lwmutex, u64 timeout) { - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; + sc_lwmutex.Log("sys_lwmutex_lock(lwmutex_addr=0x%x, timeout=%lld)", lwmutex.GetAddr(), timeout); + + if (!lwmutex.IsGood()) return CELL_EFAULT; PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); - if(thr.GetId() == re(lmtx.lock_var.info.owner)) - { - re(lmtx.recursive_count, re(lmtx.recursive_count) + 1); - return CELL_OK; - } + { // global lock + std::lock_guard lock(g_lwmutex); - if(!lmtx.lock_var.info.owner) - { - re(lmtx.lock_var.info.owner, GetCurrentPPUThread().GetId()); - re(lmtx.recursive_count, 1); - } - else if(!lmtx.lock_var.info.waiter) - { - thr.Wait(true); - re(lmtx.lock_var.info.waiter, thr.GetId()); - } - else - { - ConLog.Warning("lwmutex has waiter!"); - return CELL_EBUSY; - } - - return CELL_OK; -} - -int sys_lwmutex_trylock(u64 lwmutex_addr) -{ - //sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr); - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - - if(lmtx.lock_var.info.owner) return CELL_EBUSY; - - return CELL_OK; -} - -int sys_lwmutex_unlock(u64 lwmutex_addr) -{ - //sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr = 0x%llx)", lwmutex_addr); - - lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - - re(lmtx.recursive_count, re(lmtx.recursive_count) - 1); - - if(!lmtx.recursive_count) - { - if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter) + if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE) { - lmtx.lock_var.info.waiter = 0; - CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner); - if(thr) + if (id == (u32)lwmutex->owner) { - thr->Wait(false); + lwmutex->recursive_count = lwmutex->recursive_count + 1; + if (lwmutex->recursive_count == 0xffffffff) return CELL_EKRESOURCE; + return CELL_OK; } } + else // recursive not allowed + { + if (id == (u32)lwmutex->owner) + { + return CELL_EDEADLK; + } + } + + if (!lwmutex->owner) // lock + { + lwmutex->owner = id; + lwmutex->recursive_count = 1; + return CELL_OK; + } + lwmutex->waiter = id; // not used yet } - return CELL_OK; + u32 counter = 0; + const u32 max_counter = timeout ? (timeout / 1000) : 20000; + do // waiting + { + Sleep(1); + + { // global lock + std::lock_guard lock(g_lwmutex); + + if (!lwmutex->owner) // lock + { + lwmutex->owner = id; + lwmutex->recursive_count = 1; + return CELL_OK; + } + lwmutex->waiter = id; // not used yet + } + + if (counter++ > max_counter) + { + if (!timeout) + { // endless waiter + sc_lwmutex.Error("sys_lwmutex_lock(lwmutex_addr=0x%x): TIMEOUT", lwmutex.GetAddr()); + return CELL_OK; + } + else + { + return CELL_ETIMEDOUT; + } + } + } while (true); +} + +int sys_lwmutex_trylock(mem_ptr_t lwmutex) +{ + sc_lwmutex.Log("sys_lwmutex_trylock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + + if (!lwmutex.IsGood()) return CELL_EFAULT; + + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + { // global lock + std::lock_guard lock(g_lwmutex); + + if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE) + { + if (id == (u32)lwmutex->owner) + { + lwmutex->recursive_count = lwmutex->recursive_count + 1; + if (lwmutex->recursive_count == 0xffffffff) return CELL_EKRESOURCE; + return CELL_OK; + } + } + else // recursive not allowed + { + if (id == (u32)lwmutex->owner) + { + return CELL_EDEADLK; + } + } + + if (!lwmutex->owner) // try lock + { + lwmutex->owner = id; + lwmutex->recursive_count = 1; + return CELL_OK; + } + else + { + return CELL_EBUSY; + } + } +} + +int sys_lwmutex_unlock(mem_ptr_t lwmutex) +{ + sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr()); + + if (!lwmutex.IsGood()) return CELL_EFAULT; + + PPCThread& thr = GetCurrentPPUThread(); + const u32 id = thr.GetId(); + + { // global lock + std::lock_guard lock(g_lwmutex); + + if (id != (u32)lwmutex->owner) + { + return CELL_EPERM; + } + else + { + lwmutex->recursive_count = (u32)lwmutex->recursive_count - 1; + if (!lwmutex->recursive_count) + { + lwmutex->waiter = 0; // not used yet + lwmutex->owner = 0; // release + /* CPUThread* thr = Emu.GetCPU().GetThread(lwmutex->owner); + if(thr) + { + thr->Wait(false); + } */ + } + return CELL_OK; + } + } } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h new file mode 100644 index 0000000000..85f0f01fe8 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -0,0 +1,54 @@ +#pragma once + +// attr_protocol (waiting scheduling policy) +enum +{ + // First In, First Out + SYS_SYNC_FIFO = 1, + // Priority Order (doesn't care?) + SYS_SYNC_PRIORITY = 2, + // Basic Priority Inheritance Protocol + SYS_SYNC_PRIORITY_INHERIT = 3, + // ???? + SYS_SYNC_RETRY = 4, + // + SYS_SYNC_ATTR_PROTOCOL_MASK = 0xF, +}; + +// attr_recursive (recursive locks policy) +enum +{ + // Recursive locks are allowed + SYS_SYNC_RECURSIVE = 0x10, + // Recursive locks are NOT allowed + SYS_SYNC_NOT_RECURSIVE = 0x20, + // + SYS_SYNC_ATTR_RECURSIVE_MASK = 0xF0, //??? +}; + +struct sys_lwmutex_t +{ + union // sys_lwmutex_variable_t + { + struct // sys_lwmutex_lock_info_t + { + /* volatile */ be_t owner; + /* volatile */ be_t waiter; + }; + struct + { + /* volatile */ be_t all_info; + }; + }; + be_t attribute; + be_t recursive_count; + be_t sleep_queue; + be_t pad; +}; + +struct sys_lwmutex_attribute_t +{ + be_t attr_protocol; + be_t attr_recursive; + char name[8]; +}; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index a90474b87e..5f76f44462 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -267,6 +267,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 0fa202b3e8..65591d896f 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -367,6 +367,9 @@ Emu\SysCalls\Modules + + Emu\SysCalls\Modules +