1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00
This commit is contained in:
elisha464 2014-01-28 20:02:20 +02:00
commit 7e591deaf3
15 changed files with 1140 additions and 483 deletions

View File

@ -767,14 +767,13 @@ private:
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;
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;
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)
{

View File

@ -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)
{

View File

@ -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;

View File

@ -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())
{

View File

@ -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;
}

View 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;
};

View File

@ -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)
{
CELL_PAMF_ATTRIBUTE_VERIFY_ON = 1,
CELL_PAMF_ATTRIBUTE_MINIMUM_HEADER = 2,
};
typedef enum {
CELL_PAMF_STREAM_TYPE_AVC = 0,
CELL_PAMF_STREAM_TYPE_M2V = 1,
CELL_PAMF_STREAM_TYPE_ATRAC3PLUS = 2,
CELL_PAMF_STREAM_TYPE_PAMF_LPCM = 3,
CELL_PAMF_STREAM_TYPE_AC3 = 4,
CELL_PAMF_STREAM_TYPE_USER_DATA = 5,
CELL_PAMF_STREAM_TYPE_VIDEO = 20,
CELL_PAMF_STREAM_TYPE_AUDIO = 21,
} CellPamfStreamType;
// Timestamp information (time in increments of 90 kHz)
struct CellCodecTimeStamp {
be_t<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
case CELL_PAMF_STREAM_TYPE_AVC:
switch (ch)
{
//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;
//};
};
struct PamfHeader
case 0:
{
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
pEsFilterId->filterIdMajor = 0xe0; //fake info
pEsFilterId->filterIdMinor = 0;
pEsFilterId->supplementalInfo1 = 0x01;
pEsFilterId->supplementalInfo2 = 0;
}
break;
case 1:
{
//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];
};
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)
{
//TODO: get stream type correctly
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
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;
}
}
u8 pamfGetStreamChannel(mem_ptr_t<CellPamfReader> pSelf, u8 stream)
{
cellPamf.Warning("TODO: pamfGetStreamChannel");
//TODO: get stream channel correctly
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
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;
}
@ -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)
@ -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 (u8 i = 0; i < pAddr->stream_count; i++)
{
const u8 type = pamfGetStreamType(pSelf, i);
for (int i = 0; i < pAddr->stream_count; i++)
if (type == streamType)
{
switch (pAddr->stream_headers[i].type)
{
case 0x1b: if (streamType == CELL_PAMF_STREAM_TYPE_AVC ||
streamType == CELL_PAMF_STREAM_TYPE_VIDEO) found++; break;
case 0xdc: if (streamType == CELL_PAMF_STREAM_TYPE_ATRAC3PLUS ||
streamType == CELL_PAMF_STREAM_TYPE_AUDIO) found++; break;
case 0x80: if (streamType == CELL_PAMF_STREAM_TYPE_PAMF_LPCM ||
streamType == CELL_PAMF_STREAM_TYPE_AUDIO) found++; break;
case 0xdd: if (streamType == CELL_PAMF_STREAM_TYPE_USER_DATA) found++; break;
default:
cellPamf.Error("cellPamfReaderSetStreamWithTypeAndIndex: unsupported stream type found(0x%x)",
pAddr->stream_headers[i].type);
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;

View 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];
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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
{
u32 owner;
u32 waiter;
};
SysCallBase sc_lwmutex("sys_lwmutex");
union lwmutex_variable
{
lwmutex_lock_info info;
u64 all_info;
};
std::mutex g_lwmutex;
struct lwmutex
int sys_lwmutex_create(mem_ptr_t<sys_lwmutex_t> lwmutex, mem_ptr_t<sys_lwmutex_attribute_t> attr)
{
lwmutex_variable lock_var;
u32 attribute;
u32 recursive_count;
u32 sleep_queue;
u32 pad;
};
sc_lwmutex.Log("sys_lwmutex_create(lwmutex_addr=0x%x, lwmutex_attr_addr=0x%x)",
lwmutex.GetAddr(), attr.GetAddr());
struct lwmutex_attr
{
u32 attr_protocol;
u32 attr_recursive;
char name[8];
};
if (!lwmutex.IsGood() || !attr.IsGood()) return CELL_EFAULT;
SysCallBase sc_lwmutex("sys_wmutex");
int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr)
switch ((u32)attr->attr_recursive)
{
if(!Memory.IsGoodAddr(lwmutex_addr, 4) || !Memory.IsGoodAddr(lwmutex_attr_addr))
{
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))
{ // global lock
std::lock_guard<std::mutex> lock(g_lwmutex);
if ((u32)lwmutex->attribute & SYS_SYNC_RECURSIVE)
{
re(lmtx.recursive_count, re(lmtx.recursive_count) + 1);
if (id == (u32)lwmutex->owner)
{
lwmutex->recursive_count = lwmutex->recursive_count + 1;
if (lwmutex->recursive_count == 0xffffffff) return CELL_EKRESOURCE;
return CELL_OK;
}
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)
else // recursive not allowed
{
thr.Wait(true);
re(lmtx.lock_var.info.waiter, thr.GetId());
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
}
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
{
ConLog.Warning("lwmutex has waiter!");
return CELL_EBUSY;
}
return CELL_OK;
}
}
int sys_lwmutex_trylock(u64 lwmutex_addr)
int sys_lwmutex_unlock(mem_ptr_t<sys_lwmutex_t> lwmutex)
{
//sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr);
lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr];
sc_lwmutex.Log("sys_lwmutex_unlock(lwmutex_addr=0x%x)", lwmutex.GetAddr());
if(lmtx.lock_var.info.owner) return CELL_EBUSY;
if (!lwmutex.IsGood()) return CELL_EFAULT;
return CELL_OK;
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;
}
int sys_lwmutex_unlock(u64 lwmutex_addr)
else
{
//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)
lwmutex->recursive_count = (u32)lwmutex->recursive_count - 1;
if (!lwmutex->recursive_count)
{
if(lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter)
{
lmtx.lock_var.info.waiter = 0;
CPUThread* thr = Emu.GetCPU().GetThread(lmtx.lock_var.info.owner);
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;
}
}
}

View 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];
};

View File

@ -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" />

View File

@ -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" />