mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
Merge branch 'master' of https://github.com/DHrpcs3/rpcs3
This commit is contained in:
commit
7e591deaf3
@ -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<s64>(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<s64>(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<s64>(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<s64>(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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -1454,11 +1454,9 @@ void RSXThread::Task()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_cs_main);
|
||||
|
||||
//u32 put, get;
|
||||
//se_t<u32>::func(put, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, put))));
|
||||
//se_t<u32>::func(get, std::atomic_load((volatile std::atomic<u32>*)((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<u32>::func(put, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, put))));
|
||||
se_t<u32>::func(get, std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, get))));
|
||||
|
||||
if(put == get || !Emu.IsRunning())
|
||||
{
|
||||
|
@ -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<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxAttr> 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<CellDmuxType2> demuxerType2, mem_ptr_t<CellDmuxAttr> 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<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxResource> demuxerResource,
|
||||
mem_ptr_t<CellDmuxCb> 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<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxResourceEx> demuxerResourceEx,
|
||||
mem_ptr_t<CellDmuxCb> 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<CellDmuxType2> demuxerType2, mem_ptr_t<CellDmuxResource2> demuxerResource2,
|
||||
mem_ptr_t<CellDmuxCb> 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<CellDmuxType> demuxerType, mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
||||
u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> 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<CellDmuxType2> demuxerType2, mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
||||
u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> 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<CellCodecEsFilterId> esFilterId,
|
||||
mem_ptr_t<CellDmuxEsResource> esResourceInfo, mem_ptr_t<CellDmuxEsCb> 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;
|
||||
}
|
||||
|
||||
|
168
rpcs3/Emu/SysCalls/Modules/cellDmux.h
Normal file
168
rpcs3/Emu/SysCalls/Modules/cellDmux.h
Normal file
@ -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<CellDmuxMsgType> msgType; //CellDmuxMsgType enum
|
||||
be_t<u64> supplementalInfo;
|
||||
};
|
||||
|
||||
struct CellDmuxEsMsg
|
||||
{
|
||||
be_t<CellDmuxEsMsgType> msgType; //CellDmuxEsMsgType enum
|
||||
be_t<u64> supplementalInfo;
|
||||
};
|
||||
|
||||
struct CellDmuxType
|
||||
{
|
||||
CellDmuxStreamType streamType;
|
||||
be_t<u32> reserved[2]; //0
|
||||
};
|
||||
|
||||
struct CellDmuxType2
|
||||
{
|
||||
CellDmuxStreamType streamType;
|
||||
be_t<u32> streamSpecificInfo_addr;
|
||||
};
|
||||
|
||||
struct CellDmuxResource
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
be_t<u32> spuThreadPriority;
|
||||
be_t<u32> numOfSpus;
|
||||
};
|
||||
|
||||
struct CellDmuxResourceEx
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
be_t<u32> spurs_addr;
|
||||
u8 priority[8];
|
||||
be_t<u32> maxContention;
|
||||
};
|
||||
|
||||
/*
|
||||
struct CellDmuxResource2Ex
|
||||
{
|
||||
bool isResourceEx; //true
|
||||
CellDmuxResourceEx resourceEx;
|
||||
};
|
||||
|
||||
struct CellDmuxResource2NoEx
|
||||
{
|
||||
bool isResourceEx; //false
|
||||
CellDmuxResource resource;
|
||||
};
|
||||
*/
|
||||
|
||||
struct CellDmuxResource2
|
||||
{
|
||||
bool isResourceEx;
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> ppuThreadPriority;
|
||||
be_t<u32> ppuThreadStackSize;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
be_t<u32> noex_spuThreadPriority;
|
||||
be_t<u32> noex_numOfSpus;
|
||||
};
|
||||
struct
|
||||
{
|
||||
be_t<u32> ex_spurs_addr;
|
||||
u8 ex_priority[8];
|
||||
be_t<u32> ex_maxContention;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct CellDmuxCb
|
||||
{
|
||||
// CellDmuxCbMsg callback
|
||||
be_t<mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, mem_ptr_t<CellDmuxMsg> demuxerMsg, u32 cbArg_addr)>> cbMsgFunc;
|
||||
be_t<u32> cbArg_addr;
|
||||
};
|
||||
|
||||
struct CellDmuxEsCb
|
||||
{
|
||||
// CellDmuxCbEsMsg callback
|
||||
be_t<mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, u32 esHandle_addr, mem_ptr_t<CellDmuxEsMsg> esMsg, u32 cbArg_addr)>> cbEsMsgFunc;
|
||||
be_t<u32> cbArg_addr;
|
||||
};
|
||||
|
||||
struct CellDmuxAttr
|
||||
{
|
||||
be_t<u32> memSize;
|
||||
be_t<u32> demuxerVerUpper;
|
||||
be_t<u32> demuxerVerLower;
|
||||
};
|
||||
|
||||
struct CellDmuxEsAttr
|
||||
{
|
||||
be_t<u32> memSize;
|
||||
};
|
||||
|
||||
struct CellDmuxEsResource
|
||||
{
|
||||
be_t<u32> memAddr;
|
||||
be_t<u32> memSize;
|
||||
};
|
||||
|
||||
struct CellDmuxAuInfo
|
||||
{
|
||||
be_t<u32> auAddr;
|
||||
be_t<u32> auSize;
|
||||
be_t<u32> auMaxSize;
|
||||
be_t<u64> userData;
|
||||
be_t<u32> ptsUpper;
|
||||
be_t<u32> ptsLower;
|
||||
be_t<u32> dtsUpper;
|
||||
be_t<u32> dtsLower;
|
||||
};
|
||||
|
||||
struct CellDmuxAuInfoEx
|
||||
{
|
||||
be_t<u32> auAddr;
|
||||
be_t<u32> auSize;
|
||||
be_t<u32> reserved;
|
||||
bool isRap;
|
||||
be_t<u64> userData;
|
||||
CellCodecTimeStamp pts;
|
||||
CellCodecTimeStamp dts;
|
||||
};
|
@ -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<CellCodecEsFilterId> 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<CellPamfReader> pSelf, u8 stream)
|
||||
{
|
||||
CELL_PAMF_ATTRIBUTE_VERIFY_ON = 1,
|
||||
CELL_PAMF_ATTRIBUTE_MINIMUM_HEADER = 2,
|
||||
};
|
||||
//TODO: get stream type correctly
|
||||
const mem_ptr_t<PamfHeader> 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<u32> upper;
|
||||
be_t<u32> lower;
|
||||
};
|
||||
|
||||
// Entry point information
|
||||
struct CellPamfEp {
|
||||
be_t<u32> indexN;
|
||||
be_t<u32> nThRefPictureOffset;
|
||||
CellCodecTimeStamp pts;
|
||||
be_t<u64> rpnOffset;
|
||||
};
|
||||
|
||||
// Entry point iterator
|
||||
struct CellPamfEpIterator {
|
||||
be_t<bool> isPamf;
|
||||
be_t<u32> index;
|
||||
be_t<u32> num;
|
||||
be_t<u32> pCur_addr;
|
||||
};
|
||||
|
||||
struct CellCodecEsFilterId {
|
||||
be_t<u32> filterIdMajor;
|
||||
be_t<u32> filterIdMinor;
|
||||
be_t<u32> supplementalInfo1;
|
||||
be_t<u32> supplementalInfo2;
|
||||
};
|
||||
|
||||
// AVC (MPEG4 AVC Video) Specific Information
|
||||
struct CellPamfAvcInfo {
|
||||
u8 profileIdc;
|
||||
u8 levelIdc;
|
||||
u8 frameMbsOnlyFlag;
|
||||
u8 videoSignalInfoFlag;
|
||||
u8 frameRateInfo;
|
||||
u8 aspectRatioIdc;
|
||||
be_t<u16> sarWidth; //reserved
|
||||
be_t<u16> sarHeight; //reserved
|
||||
be_t<u16> horizontalSize; //multiple of 16
|
||||
be_t<u16> verticalSize; //multiple of 16
|
||||
be_t<u16> frameCropLeftOffset; //reserved
|
||||
be_t<u16> frameCropRightOffset; //reserved
|
||||
be_t<u16> frameCropTopOffset; //reserved
|
||||
be_t<u16> 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<bool> progressiveSequence;
|
||||
u8 videoSignalInfoFlag;
|
||||
u8 frameRateInfo;
|
||||
u8 aspectRatioIdc;
|
||||
be_t<u16> sarWidth;
|
||||
be_t<u16> sarHeight;
|
||||
be_t<u16> horizontalSize;
|
||||
be_t<u16> verticalSize;
|
||||
be_t<u16> horizontalSizeValue;
|
||||
be_t<u16> verticalSizeValue;
|
||||
u8 videoFormat;
|
||||
u8 videoFullRangeFlag;
|
||||
u8 colourPrimaries;
|
||||
u8 transferCharacteristics;
|
||||
u8 matrixCoefficients;
|
||||
};
|
||||
|
||||
// LPCM Audio Specific Information
|
||||
struct CellPamfLpcmInfo {
|
||||
be_t<u32> samplingFrequency;
|
||||
u8 numberOfChannels;
|
||||
be_t<u16> bitsPerSample;
|
||||
};
|
||||
|
||||
// ATRAC3+ Audio Specific Information
|
||||
struct CellPamfAtrac3plusInfo {
|
||||
be_t<u32> samplingFrequency;
|
||||
u8 numberOfChannels;
|
||||
};
|
||||
|
||||
// AC3 Audio Specific Information
|
||||
struct CellPamfAc3Info {
|
||||
be_t<u32> 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<u16> horizontalSize; //divided by 16
|
||||
be_t<u16> 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<CellPamfReader> 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<u32> ep_offset; //offset of ep section in header
|
||||
be_t<u32> ep_num; //count of ep
|
||||
//union { //32 bytes
|
||||
PamfStreamHeader_AVC AVC;
|
||||
//};
|
||||
};
|
||||
cellPamf.Warning("TODO: pamfGetStreamChannel");
|
||||
//TODO: get stream channel correctly
|
||||
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
||||
|
||||
struct PamfHeader
|
||||
{
|
||||
u32 magic; //"PAMF"
|
||||
u32 version; //"0041" (is it const?)
|
||||
be_t<u32> data_offset; //== 2048 >> 11, PAMF headers seem to be always 2048 bytes in size
|
||||
be_t<u32> data_size; //== ((fileSize - 2048) >> 11)
|
||||
u64 reserved[8];
|
||||
be_t<u32> table_size; //== size of mapping-table
|
||||
u16 reserved1;
|
||||
be_t<u16> start_pts_high;
|
||||
be_t<u32> start_pts_low; //Presentation Time Stamp (start)
|
||||
be_t<u16> end_pts_high;
|
||||
be_t<u32> end_pts_low; //Presentation Time Stamp (end)
|
||||
be_t<u32> mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
|
||||
be_t<u32> mux_rate_min; //== 0x0107AC (?????)
|
||||
u16 reserved2; // ?????
|
||||
u8 reserved3;
|
||||
u8 stream_count; //total stream count (reduced to 1 byte)
|
||||
be_t<u16> unk1; //== 1 (?????)
|
||||
be_t<u32> 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<u16> start_pts_high2; //????? (probably same values)
|
||||
be_t<u32> start_pts_low2; //?????
|
||||
be_t<u16> end_pts_high2; //?????
|
||||
be_t<u32> end_pts_low2; //?????
|
||||
be_t<u32> unk2; //== 0x10000 (?????)
|
||||
be_t<u16> unk3; // ?????
|
||||
be_t<u16> unk4; // == total_stream_num
|
||||
//==========================
|
||||
PamfStreamHeader stream_headers[256];
|
||||
};
|
||||
|
||||
struct PamfEpHeader { //12 bytes
|
||||
be_t<u16> value0; //mixed indexN (probably left 2 bits) and nThRefPictureOffset
|
||||
be_t<u16> pts_high;
|
||||
be_t<u32> pts_low;
|
||||
be_t<u32> 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<u64> 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<PamfHeader> 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<PamfHeader> 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<PamfHeader> 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<CellPamfReader> pSelf, mem_ptr_t<PamfHead
|
||||
{
|
||||
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;
|
||||
@ -272,7 +177,7 @@ int cellPamfReaderInitialize(mem_ptr_t<CellPamfReader> pSelf, mem_ptr_t<PamfHead
|
||||
pSelf->fileSize = ((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<CellPamfReader> pSelf, mem_
|
||||
pSelf.GetAddr(), pTimeStamp.GetAddr());
|
||||
|
||||
const mem_ptr_t<PamfHeader> 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<CellPamfReader> pSelf, mem_pt
|
||||
pSelf.GetAddr(), pTimeStamp.GetAddr());
|
||||
|
||||
const mem_ptr_t<PamfHeader> 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<CellPamfReader> 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<CellPamfReader> 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<CellPamfReader> pSelf, u8 streamI
|
||||
pSelf.GetAddr(), streamIndex);
|
||||
|
||||
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
||||
|
||||
if (streamIndex < pAddr->stream_count)
|
||||
{
|
||||
pSelf->stream = streamIndex;
|
||||
@ -385,10 +280,31 @@ int cellPamfReaderSetStreamWithIndex(mem_ptr_t<CellPamfReader> pSelf, u8 streamI
|
||||
|
||||
int cellPamfReaderSetStreamWithTypeAndChannel(mem_ptr_t<CellPamfReader> 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<PamfHeader> 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<CellPamfReader> pSelf, u8 streamType, u8 streamIndex)
|
||||
@ -400,24 +316,35 @@ int cellPamfReaderSetStreamWithTypeAndIndex(mem_ptr_t<CellPamfReader> 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<CellPamfReader> pSelf, u8
|
||||
|
||||
int cellPamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t<CellCodecEsFilterId> 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<CellPamfReader> pSelf)
|
||||
@ -450,71 +373,123 @@ int cellPamfReaderGetStreamTypeAndChannel(mem_ptr_t<CellPamfReader> 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<PamfHeader> 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<CellPamfReader> pSelf, mem_ptr_t<CellCodecEsFilterId> 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<CellPamfReader> 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<PamfHeader> 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<CellPamfAvcInfo> pInfo(pInfo_addr);
|
||||
//file data structure (fixed offset 0x98, fixed step 0x30)
|
||||
mem_ptr_t<PamfStreamHeader_AVC> 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<CellPamfAtrac3plusInfo> pInfo(pInfo_addr);
|
||||
mem_ptr_t<PamfStreamHeader_Audio> 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<CellPamfAc3Info> pInfo(pInfo_addr);
|
||||
mem_ptr_t<PamfStreamHeader_Audio> 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<CellPamfLpcmInfo> pInfo(pInfo_addr);
|
||||
mem_ptr_t<PamfStreamHeader_Audio> 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;
|
||||
|
335
rpcs3/Emu/SysCalls/Modules/cellPamf.h
Normal file
335
rpcs3/Emu/SysCalls/Modules/cellPamf.h
Normal file
@ -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<u32> upper;
|
||||
be_t<u32> lower;
|
||||
};
|
||||
|
||||
// Entry point information
|
||||
struct CellPamfEp {
|
||||
be_t<u32> indexN;
|
||||
be_t<u32> nThRefPictureOffset;
|
||||
CellCodecTimeStamp pts;
|
||||
be_t<u64> rpnOffset;
|
||||
};
|
||||
|
||||
// Entry point iterator
|
||||
struct CellPamfEpIterator
|
||||
{
|
||||
bool isPamf;
|
||||
be_t<u32> index;
|
||||
be_t<u32> num;
|
||||
be_t<u32> pCur_addr;
|
||||
};
|
||||
|
||||
struct CellCodecEsFilterId
|
||||
{
|
||||
be_t<u32> filterIdMajor;
|
||||
be_t<u32> filterIdMinor;
|
||||
be_t<u32> supplementalInfo1;
|
||||
be_t<u32> supplementalInfo2;
|
||||
};
|
||||
|
||||
// AVC (MPEG4 AVC Video) Specific Information
|
||||
struct CellPamfAvcInfo {
|
||||
u8 profileIdc;
|
||||
u8 levelIdc;
|
||||
u8 frameMbsOnlyFlag;
|
||||
u8 videoSignalInfoFlag;
|
||||
u8 frameRateInfo;
|
||||
u8 aspectRatioIdc;
|
||||
be_t<u16> sarWidth; //reserved
|
||||
be_t<u16> sarHeight; //reserved
|
||||
be_t<u16> horizontalSize;
|
||||
be_t<u16> verticalSize;
|
||||
be_t<u16> frameCropLeftOffset; //reserved
|
||||
be_t<u16> frameCropRightOffset; //reserved
|
||||
be_t<u16> frameCropTopOffset; //reserved
|
||||
be_t<u16> 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<u16> sarWidth;
|
||||
be_t<u16> sarHeight;
|
||||
be_t<u16> horizontalSize;
|
||||
be_t<u16> verticalSize;
|
||||
be_t<u16> horizontalSizeValue;
|
||||
be_t<u16> verticalSizeValue;
|
||||
u8 videoFormat;
|
||||
u8 videoFullRangeFlag;
|
||||
u8 colourPrimaries;
|
||||
u8 transferCharacteristics;
|
||||
u8 matrixCoefficients;
|
||||
};
|
||||
|
||||
// LPCM Audio Specific Information
|
||||
struct CellPamfLpcmInfo {
|
||||
be_t<u32> samplingFrequency;
|
||||
u8 numberOfChannels;
|
||||
be_t<u16> bitsPerSample;
|
||||
};
|
||||
|
||||
// ATRAC3+ Audio Specific Information
|
||||
struct CellPamfAtrac3plusInfo {
|
||||
be_t<u32> samplingFrequency;
|
||||
u8 numberOfChannels;
|
||||
};
|
||||
|
||||
// AC3 Audio Specific Information
|
||||
struct CellPamfAc3Info {
|
||||
be_t<u32> 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<u16> horizontalSize; //divided by 16
|
||||
be_t<u16> 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<u32> ep_offset; //offset of EP section in header
|
||||
be_t<u32> ep_num; //count of EPs
|
||||
//Specific Info
|
||||
u8 data[32];
|
||||
};
|
||||
|
||||
struct PamfHeader
|
||||
{
|
||||
u32 magic; //"PAMF"
|
||||
u32 version; //"0041" (is it const?)
|
||||
be_t<u32> data_offset; //== 2048 >> 11, PAMF headers seem to be always 2048 bytes in size
|
||||
be_t<u32> data_size; //== ((fileSize - 2048) >> 11)
|
||||
u64 reserved[8];
|
||||
be_t<u32> table_size; //== size of mapping-table
|
||||
u16 reserved1;
|
||||
be_t<u16> start_pts_high;
|
||||
be_t<u32> start_pts_low; //Presentation Time Stamp (start)
|
||||
be_t<u16> end_pts_high;
|
||||
be_t<u32> end_pts_low; //Presentation Time Stamp (end)
|
||||
be_t<u32> mux_rate_max; //== 0x01D470 (400 bps per unit, == 48000000 bps)
|
||||
be_t<u32> mux_rate_min; //== 0x0107AC (?????)
|
||||
u16 reserved2; // ?????
|
||||
u8 reserved3;
|
||||
u8 stream_count; //total stream count (reduced to 1 byte)
|
||||
be_t<u16> unk1; //== 1 (?????)
|
||||
be_t<u32> 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<u16> start_pts_high2; //????? (probably same values)
|
||||
be_t<u32> start_pts_low2; //?????
|
||||
be_t<u16> end_pts_high2; //?????
|
||||
be_t<u32> end_pts_low2; //?????
|
||||
be_t<u32> unk2; //== 0x10000 (?????)
|
||||
be_t<u16> unk3; // ?????
|
||||
be_t<u16> unk4; // == stream_count
|
||||
//==========================
|
||||
PamfStreamHeader stream_headers[256];
|
||||
};
|
||||
|
||||
struct PamfEpHeader { //12 bytes
|
||||
be_t<u16> value0; //mixed indexN (probably left 2 bits) and nThRefPictureOffset
|
||||
be_t<u16> pts_high;
|
||||
be_t<u32> pts_low;
|
||||
be_t<u32> 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<u64> internalData[16];
|
||||
u32 pAddr;
|
||||
int stream;
|
||||
u64 fileSize;
|
||||
u32 internalData[28];
|
||||
};
|
@ -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;
|
||||
|
@ -152,16 +152,21 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||
|
||||
if(Memory.IsGoodAddr(buf_addr))
|
||||
{
|
||||
/*
|
||||
//open the file again (to prevent access conflicts roughly)
|
||||
vfsLocalFile file(path, vfsRead);
|
||||
*/
|
||||
vfsStream& file = *(vfsStream*)orig_file;
|
||||
if(!Memory.IsGoodAddr(buf_addr, nbytes))
|
||||
{
|
||||
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
|
||||
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
|
||||
}
|
||||
|
||||
const u64 old_pos = file.Tell();
|
||||
file.Seek((u64)aio->offset);
|
||||
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<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
||||
u32 fd = aio->fd;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr);
|
||||
extern int sys_lwmutex_destroy(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
extern int sys_lwmutex_lock(mem_ptr_t<sys_lwmutex_t> lwmutex, u64 timeout);
|
||||
extern int sys_lwmutex_trylock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
extern int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex);
|
||||
|
||||
//sys_cond
|
||||
extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr);
|
||||
|
@ -1,122 +1,198 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/lv2/SC_Lwmutex.h"
|
||||
#include <mutex>
|
||||
|
||||
struct lwmutex_lock_info
|
||||
SysCallBase sc_lwmutex("sys_lwmutex");
|
||||
|
||||
std::mutex g_lwmutex;
|
||||
|
||||
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_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<sys_lwmutex_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<sys_lwmutex_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<std::mutex> 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<std::mutex> 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<sys_lwmutex_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<std::mutex> 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<sys_lwmutex_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<std::mutex> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
54
rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h
Normal file
54
rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h
Normal file
@ -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<u32> owner;
|
||||
/* volatile */ be_t<u32> waiter;
|
||||
};
|
||||
struct
|
||||
{
|
||||
/* volatile */ be_t<u64> all_info;
|
||||
};
|
||||
};
|
||||
be_t<u32> attribute;
|
||||
be_t<u32> recursive_count;
|
||||
be_t<u32> sleep_queue;
|
||||
be_t<u32> pad;
|
||||
};
|
||||
|
||||
struct sys_lwmutex_attribute_t
|
||||
{
|
||||
be_t<u32> attr_protocol;
|
||||
be_t<u32> attr_recursive;
|
||||
char name[8];
|
||||
};
|
@ -267,6 +267,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_VM.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellAudio.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellFont.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellFontFT.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellGame.cpp" />
|
||||
|
@ -367,6 +367,9 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellPamf.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellDmux.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
|
Loading…
Reference in New Issue
Block a user