mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-24 19:52:37 +01:00
commit
65eb873597
@ -121,6 +121,7 @@ struct AudioPortConfig
|
||||
|
||||
struct AudioConfig //custom structure
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
enum
|
||||
{
|
||||
AUDIO_PORT_COUNT = 8,
|
||||
@ -131,15 +132,14 @@ struct AudioConfig //custom structure
|
||||
bool m_is_audio_initialized;
|
||||
bool m_is_audio_finalized;
|
||||
u32 m_port_in_use;
|
||||
u64 event_key;
|
||||
u64 counter;
|
||||
u64 start_time;
|
||||
Array<u64> m_keys;
|
||||
|
||||
AudioConfig()
|
||||
: m_is_audio_initialized(false)
|
||||
, m_is_audio_finalized(false)
|
||||
, m_port_in_use(0)
|
||||
, event_key(0x80004d494f323221)
|
||||
, counter(0)
|
||||
{
|
||||
memset(&m_ports, 0, sizeof(AudioPortConfig) * AUDIO_PORT_COUNT);
|
||||
|
@ -393,7 +393,7 @@ s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("ExecAsCallback() aborted");
|
||||
ConLog.Warning("ExecAsCallback(wait=%s) aborted", wxString(wait ? "true" : "false").wx_str());
|
||||
return CELL_EABORT; // doesn't mean anything
|
||||
}
|
||||
Sleep(1);
|
||||
|
@ -18,6 +18,7 @@ enum
|
||||
|
||||
MFC_BARRIER_MASK = 0x01,
|
||||
MFC_FENCE_MASK = 0x02,
|
||||
MFC_LIST_MASK = 0x04,
|
||||
MFC_MASK_CMD = 0xffff,
|
||||
};
|
||||
|
||||
@ -165,7 +166,7 @@ struct DMAC
|
||||
//returns true if the command should be deleted from the queue
|
||||
if (cmd & (MFC_BARRIER_MASK | MFC_FENCE_MASK)) _mm_mfence();
|
||||
|
||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
|
||||
switch(cmd & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK | MFC_LIST_MASK))
|
||||
{
|
||||
case MFC_PUT_CMD:
|
||||
Memory.Copy(ea, ls_offset + lsa, size);
|
||||
@ -176,7 +177,7 @@ struct DMAC
|
||||
return true;
|
||||
|
||||
default:
|
||||
ConLog.Error("Unknown DMA cmd.");
|
||||
ConLog.Error("DMAC::ProcessCmd(): Unknown DMA cmd.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1206,6 +1206,13 @@ private:
|
||||
{
|
||||
DisAsm_R2_INT2_RC("rldimi", ra, rs, sh, mb, rc);
|
||||
}
|
||||
void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc)
|
||||
{
|
||||
if (is_r)
|
||||
DisAsm_R3_INT2_RC("rldcr", ra, rs, rb, m_eb, 0, rc);
|
||||
else
|
||||
DisAsm_R3_INT2_RC("rldcl", ra, rs, rb, m_eb, 0, rc);
|
||||
}
|
||||
void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
|
||||
{
|
||||
DisAsm_CR1_R2(wxString::Format("cmp%s", wxString(l ? "d" : "w").wx_str()), crfd, ra, rb);
|
||||
|
@ -193,7 +193,7 @@ namespace PPU_instr
|
||||
static CodeField<26, 31> GD_04; //0x3f
|
||||
static CodeField<21, 31> GD_04_0;//0x7ff
|
||||
static CodeField<21, 30> GD_13; //0x3ff
|
||||
static CodeField<28, 29> GD_1e; //0x3
|
||||
static CodeField<27, 29> GD_1e; //0x7
|
||||
static CodeField<21, 30> GD_1f; //0x3ff
|
||||
static CodeField<30, 31> GD_3a; //0x3
|
||||
static CodeField<26, 30> GD_3b; //0x1f
|
||||
@ -441,6 +441,7 @@ namespace PPU_instr
|
||||
bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC);
|
||||
bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC);
|
||||
bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC);
|
||||
bind_instr(g1e_list, RLDC_LR, RA, RS, RB, mb, AA, RC);
|
||||
|
||||
/*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB);
|
||||
/*0x004*/bind_instr(g1f_list, TW, TO, RA, RB);
|
||||
|
@ -2238,6 +2238,17 @@ private:
|
||||
CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl64(CPU.GPR[rs], sh) & mask);
|
||||
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
|
||||
}
|
||||
void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc)
|
||||
{
|
||||
if (is_r) // rldcr
|
||||
{
|
||||
RLDICR(ra, rs, CPU.GPR[rb], m_eb, rc);
|
||||
}
|
||||
else // rldcl
|
||||
{
|
||||
RLDICL(ra, rs, CPU.GPR[rb], m_eb, rc);
|
||||
}
|
||||
}
|
||||
void CMP(u32 crfd, u32 l, u32 ra, u32 rb)
|
||||
{
|
||||
CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]);
|
||||
@ -2765,7 +2776,7 @@ private:
|
||||
}
|
||||
void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, bool rc)
|
||||
{
|
||||
CPU.GPR[rd] = (s64)(s32)((s32)CPU.GPR[ra] * (s32)CPU.GPR[rb]);
|
||||
CPU.GPR[rd] = (s64)((s64)(s32)CPU.GPR[ra] * (s64)(s32)CPU.GPR[rb]);
|
||||
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]);
|
||||
if(oe) UNK("mullwo");
|
||||
}
|
||||
@ -2948,7 +2959,7 @@ private:
|
||||
if (RB == 0 || ((u64)RA == (1ULL << 63) && RB == -1))
|
||||
{
|
||||
if(oe) UNK("divdo");
|
||||
CPU.GPR[rd] = (((u64)RA & (1ULL << 63)) && RB == 0) ? -1 : 0;
|
||||
CPU.GPR[rd] = /*(((u64)RA & (1ULL << 63)) && RB == 0) ? -1 :*/ 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2965,11 +2976,11 @@ private:
|
||||
if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1))
|
||||
{
|
||||
if(oe) UNK("divwo");
|
||||
CPU.GPR[rd] = (((u32)RA & (1 << 31)) && RB == 0) ? -1 : 0;
|
||||
CPU.GPR[rd] = /*(((u32)RA & (1 << 31)) && RB == 0) ? -1 :*/ 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.GPR[rd] = (s64)(RA / RB);
|
||||
CPU.GPR[rd] = (u32)(RA / RB);
|
||||
}
|
||||
|
||||
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[rd]);
|
||||
@ -3080,18 +3091,34 @@ private:
|
||||
void SRAW(u32 ra, u32 rs, u32 rb, bool rc)
|
||||
{
|
||||
s32 RS = CPU.GPR[rs];
|
||||
s32 RB = CPU.GPR[rb];
|
||||
CPU.GPR[ra] = RS >> RB;
|
||||
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << RB) != RS);
|
||||
u8 shift = CPU.GPR[rb] & 63;
|
||||
if (shift > 31)
|
||||
{
|
||||
CPU.GPR[ra] = 0 - (RS < 0);
|
||||
CPU.XER.CA = (RS < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.GPR[ra] = RS >> shift;
|
||||
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << shift) != RS);
|
||||
}
|
||||
|
||||
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
|
||||
}
|
||||
void SRAD(u32 ra, u32 rs, u32 rb, bool rc)
|
||||
{
|
||||
s64 RS = CPU.GPR[rs];
|
||||
s64 RB = CPU.GPR[rb];
|
||||
CPU.GPR[ra] = RS >> RB;
|
||||
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << RB) != RS);
|
||||
u8 shift = CPU.GPR[rb] & 127;
|
||||
if (shift > 63)
|
||||
{
|
||||
CPU.GPR[ra] = 0 - (RS < 0);
|
||||
CPU.XER.CA = (RS < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPU.GPR[ra] = RS >> shift;
|
||||
CPU.XER.CA = (RS < 0) & ((CPU.GPR[ra] << shift) != RS);
|
||||
}
|
||||
|
||||
if(rc) CPU.UpdateCR0<s64>(CPU.GPR[ra]);
|
||||
}
|
||||
@ -3165,6 +3192,7 @@ private:
|
||||
void EXTSW(u32 ra, u32 rs, bool rc)
|
||||
{
|
||||
CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs];
|
||||
//CPU.XER.CA = ((s64)CPU.GPR[ra] < 0); // ???
|
||||
if(rc) CPU.UpdateCR0<s32>(CPU.GPR[ra]);
|
||||
}
|
||||
/*0x3d6*///ICBI
|
||||
|
@ -250,6 +250,7 @@ namespace PPU_opcodes
|
||||
RLDICR = 0x1,
|
||||
RLDIC = 0x2,
|
||||
RLDIMI = 0x3,
|
||||
RLDC_LR = 0x4,
|
||||
};
|
||||
|
||||
enum G_1fOpcodes //Field 21 - 30
|
||||
@ -645,6 +646,7 @@ public:
|
||||
virtual void RLDICR(u32 ra, u32 rs, u32 sh, u32 me, bool rc) = 0;
|
||||
virtual void RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0;
|
||||
virtual void RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, bool rc) = 0;
|
||||
virtual void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, bool is_r, bool rc) = 0;
|
||||
virtual void CMP(u32 crfd, u32 l, u32 ra, u32 rb) = 0;
|
||||
virtual void TW(u32 to, u32 ra, u32 rb) = 0;
|
||||
virtual void LVSL(u32 vd, u32 ra, u32 rb) = 0;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "PPCThread.h"
|
||||
#include "Emu/event.h"
|
||||
#include "Emu/SysCalls/lv2/SC_SPU_Thread.h"
|
||||
#include "MFC.h"
|
||||
#include <mutex>
|
||||
|
||||
@ -484,6 +485,22 @@ public:
|
||||
Channel<1> AtomicStat;
|
||||
} Prxy;
|
||||
|
||||
struct StalledList
|
||||
{
|
||||
u32 lsa;
|
||||
u64 ea;
|
||||
u16 tag;
|
||||
u16 size;
|
||||
u32 cmd;
|
||||
MFCReg* MFCArgs;
|
||||
|
||||
StalledList()
|
||||
: MFCArgs(nullptr)
|
||||
{
|
||||
}
|
||||
} StallList[32];
|
||||
Channel<1> StallStat;
|
||||
|
||||
struct
|
||||
{
|
||||
Channel<1> Out_MBox;
|
||||
@ -505,6 +522,66 @@ public:
|
||||
|
||||
DMAC dmac;
|
||||
|
||||
void ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFCArgs)
|
||||
{
|
||||
u32 list_addr = ea & 0x3ffff;
|
||||
u32 list_size = size / 8;
|
||||
lsa &= 0x3fff0;
|
||||
|
||||
struct list_element
|
||||
{
|
||||
be_t<u16> s; // Stall-and-Notify bit (0x8000)
|
||||
be_t<u16> ts; // List Transfer Size
|
||||
be_t<u32> ea; // External Address Low
|
||||
};
|
||||
|
||||
u32 result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
|
||||
for (u32 i = 0; i < list_size; i++)
|
||||
{
|
||||
mem_ptr_t<list_element> rec(dmac.ls_offset + list_addr + i * 8);
|
||||
|
||||
u32 size = rec->ts;
|
||||
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
||||
{
|
||||
ConLog.Error("DMA List: invalid transfer size(%d)", size);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 addr = rec->ea;
|
||||
result = dmac.Cmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
if (result == MFC_PPU_DMA_CMD_SEQUENCE_ERROR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Ini.HLELogging.GetValue() || rec->s)
|
||||
ConLog.Write("*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)",
|
||||
i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf));
|
||||
|
||||
lsa += max(size, (u32)16);
|
||||
|
||||
if (rec->s & se16(0x8000))
|
||||
{
|
||||
StallStat.PushUncond_OR(1 << tag);
|
||||
|
||||
if (StallList[tag].MFCArgs)
|
||||
{
|
||||
ConLog.Error("DMA List: existing stalled list found (tag=%d)", tag);
|
||||
}
|
||||
StallList[tag].MFCArgs = &MFCArgs;
|
||||
StallList[tag].cmd = cmd;
|
||||
StallList[tag].ea = (ea & ~0xffffffff) | (list_addr + (i + 1) * 8);
|
||||
StallList[tag].lsa = lsa;
|
||||
StallList[tag].size = (list_size - i - 1) * 8;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MFCArgs.CMDStatus.SetValue(result);
|
||||
}
|
||||
|
||||
void EnqMfcCmd(MFCReg& MFCArgs)
|
||||
{
|
||||
u32 cmd = MFCArgs.CMDStatus.GetValue();
|
||||
@ -528,7 +605,7 @@ public:
|
||||
lsa, ea, tag, size, cmd);
|
||||
if (op & MFC_PUT_CMD)
|
||||
{
|
||||
SMutexLocker lock(reservation.mutex);
|
||||
SMutexLocker lock(reservation.mutex); // should be removed
|
||||
MFCArgs.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size));
|
||||
if ((reservation.addr + reservation.size > ea && reservation.addr <= ea + size) ||
|
||||
(ea + size > reservation.addr && ea <= reservation.addr + reservation.size))
|
||||
@ -543,6 +620,19 @@ public:
|
||||
}
|
||||
break;
|
||||
|
||||
case MFC_PUTL_CMD:
|
||||
case MFC_GETL_CMD:
|
||||
{
|
||||
if (Ini.HLELogging.GetValue()) ConLog.Write("DMA %s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
|
||||
wxString(op & MFC_PUT_CMD ? "PUTL" : "GETL").wx_str(),
|
||||
wxString(op & MFC_BARRIER_MASK ? "B" : "").wx_str(),
|
||||
wxString(op & MFC_FENCE_MASK ? "F" : "").wx_str(),
|
||||
lsa, ea, tag, size, cmd);
|
||||
|
||||
ListCmd(lsa, ea, tag, size, cmd, MFCArgs);
|
||||
}
|
||||
break;
|
||||
|
||||
case MFC_GETLLAR_CMD:
|
||||
case MFC_PUTLLC_CMD:
|
||||
case MFC_PUTLLUC_CMD:
|
||||
@ -628,6 +718,9 @@ public:
|
||||
case MFC_RdTagStat:
|
||||
return Prxy.TagStatus.GetCount();
|
||||
|
||||
case MFC_RdListStallStat:
|
||||
return StallStat.GetCount();
|
||||
|
||||
case MFC_WrTagUpdate:
|
||||
return Prxy.TagStatus.GetCount(); // hack
|
||||
|
||||
@ -751,6 +844,24 @@ public:
|
||||
EnqMfcCmd(MFC1);
|
||||
break;
|
||||
|
||||
case MFC_WrListStallAck:
|
||||
{
|
||||
if (v >= 32)
|
||||
{
|
||||
ConLog.Error("MFC_WrListStallAck error: invalid tag(%d)", v);
|
||||
return;
|
||||
}
|
||||
StalledList temp = StallList[v];
|
||||
if (!temp.MFCArgs)
|
||||
{
|
||||
ConLog.Error("MFC_WrListStallAck error: empty tag(%d)", v);
|
||||
return;
|
||||
}
|
||||
StallList[v].MFCArgs = nullptr;
|
||||
ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str());
|
||||
break;
|
||||
@ -790,6 +901,10 @@ public:
|
||||
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
|
||||
break;
|
||||
|
||||
case MFC_RdListStallStat:
|
||||
while (!StallStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", wxString(__FUNCTION__).wx_str(), ch, wxString(spu_ch_name[ch]).wx_str());
|
||||
break;
|
||||
|
@ -20,14 +20,66 @@ int adecRead(void* opaque, u8* buf, int buf_size)
|
||||
{
|
||||
AudioDecoder& adec = *(AudioDecoder*)opaque;
|
||||
|
||||
if (adec.reader.size < (u32)buf_size)
|
||||
int res = 0;
|
||||
|
||||
next:
|
||||
if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/)
|
||||
{
|
||||
while (adec.job.IsEmpty())
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("adecRead() aborted");
|
||||
return 0;
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
switch (adec.job.Peek().type)
|
||||
{
|
||||
case adecEndSeq:
|
||||
{
|
||||
buf_size = adec.reader.size;
|
||||
}
|
||||
break;
|
||||
case adecDecodeAu:
|
||||
{
|
||||
if (!Memory.CopyToReal(buf, adec.reader.addr, adec.reader.size))
|
||||
{
|
||||
ConLog.Error("adecRead: data reading failed (reader.size=0x%x)", adec.reader.size);
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf += adec.reader.size;
|
||||
buf_size -= adec.reader.size;
|
||||
res += adec.reader.size;
|
||||
|
||||
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg);
|
||||
|
||||
adec.job.Pop(adec.task);
|
||||
|
||||
adec.reader.addr = adec.task.au.addr;
|
||||
adec.reader.size = adec.task.au.size;
|
||||
|
||||
adec.last_pts = adec.task.au.pts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
goto next;
|
||||
}
|
||||
else if (adec.reader.size < (u32)buf_size)
|
||||
{
|
||||
buf_size = adec.reader.size;
|
||||
}
|
||||
|
||||
if (!buf_size)
|
||||
{
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
else if (!Memory.CopyToReal(buf, adec.reader.addr, buf_size))
|
||||
{
|
||||
@ -39,7 +91,7 @@ int adecRead(void* opaque, u8* buf, int buf_size)
|
||||
{
|
||||
adec.reader.addr += buf_size;
|
||||
adec.reader.size -= buf_size;
|
||||
return 0 + buf_size;
|
||||
return res + buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +111,7 @@ u32 adecOpen(AudioDecoder* data)
|
||||
{
|
||||
ConLog.Write("Audio Decoder enter()");
|
||||
|
||||
AdecTask task;
|
||||
AdecTask& task = adec.task;
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -119,10 +171,12 @@ u32 adecOpen(AudioDecoder* data)
|
||||
|
||||
case adecDecodeAu:
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
adec.reader.addr = task.au.addr;
|
||||
adec.reader.size = task.au.size;
|
||||
|
||||
u64 last_pts = task.au.pts;
|
||||
adec.last_pts = task.au.pts;
|
||||
|
||||
struct AVPacketHolder : AVPacket
|
||||
{
|
||||
@ -169,6 +223,13 @@ u32 adecOpen(AudioDecoder* data)
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ???
|
||||
if (!codec)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
err = avformat_find_stream_info(adec.fmt, NULL);
|
||||
if (err)
|
||||
{
|
||||
@ -183,16 +244,8 @@ u32 adecOpen(AudioDecoder* data)
|
||||
break;
|
||||
}
|
||||
adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder(adec.ctx->codec_id); // ???
|
||||
if (!codec)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
|
||||
AVDictionary* opts;
|
||||
AVDictionary* opts = nullptr;
|
||||
av_dict_set(&opts, "refcounted_frames", "1", 0);
|
||||
{
|
||||
SMutexGeneralLocker lock(g_mutex_avcodec_open2);
|
||||
@ -206,10 +259,18 @@ u32 adecOpen(AudioDecoder* data)
|
||||
break;
|
||||
}
|
||||
adec.just_started = false;
|
||||
}
|
||||
}*/
|
||||
|
||||
while (av_read_frame(adec.fmt, &au) >= 0)*/ while (true)
|
||||
bool last_frame = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("adecDecodeAu aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!adec.ctx) // fake
|
||||
{
|
||||
AdecFrame frame;
|
||||
@ -221,23 +282,28 @@ u32 adecOpen(AudioDecoder* data)
|
||||
frame.data = nullptr;
|
||||
adec.frames.Push(frame);
|
||||
|
||||
/*Callback cb;
|
||||
cb.SetAddr(adec.cbFunc);
|
||||
cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
|
||||
cb.Branch(false);*/
|
||||
adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
struct VdecFrameHolder : AdecFrame
|
||||
last_frame = av_read_frame(adec.fmt, &au) < 0;
|
||||
if (last_frame)
|
||||
{
|
||||
VdecFrameHolder()
|
||||
//break;
|
||||
av_free(au.data);
|
||||
au.data = NULL;
|
||||
au.size = 0;
|
||||
}
|
||||
|
||||
struct AdecFrameHolder : AdecFrame
|
||||
{
|
||||
AdecFrameHolder()
|
||||
{
|
||||
data = av_frame_alloc();
|
||||
}
|
||||
|
||||
~VdecFrameHolder()
|
||||
~AdecFrameHolder()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
@ -259,15 +325,18 @@ u32 adecOpen(AudioDecoder* data)
|
||||
|
||||
int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au);
|
||||
|
||||
if (decode < 0)
|
||||
if (decode <= 0)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode);
|
||||
break;
|
||||
if (!last_frame && decode < 0)
|
||||
{
|
||||
ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode);
|
||||
}
|
||||
if (!got_frame && adec.reader.size == 0) break;
|
||||
}
|
||||
|
||||
if (got_frame)
|
||||
{
|
||||
ConLog.Write("got_frame (%d, vdec: pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts);
|
||||
ConLog.Write("got_frame (%d, pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts);
|
||||
|
||||
frame.pts = task.au.pts; // ???
|
||||
frame.auAddr = task.au.addr;
|
||||
|
@ -1064,6 +1064,9 @@ public:
|
||||
const u32 cbArg;
|
||||
u32 memBias;
|
||||
|
||||
AdecTask task;
|
||||
u64 last_pts;
|
||||
|
||||
CPUThread* adecCb;
|
||||
|
||||
AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg)
|
||||
|
@ -60,6 +60,8 @@ int cellAudioInit()
|
||||
memset(buffer2, 0, sizeof(buffer2));
|
||||
memset(oal_buffer.get(), 0, oal_buffer_size * sizeof(u16));
|
||||
|
||||
Array<u64> keys;
|
||||
|
||||
if(m_audio_out)
|
||||
{
|
||||
m_audio_out->Init();
|
||||
@ -144,8 +146,16 @@ int cellAudioInit()
|
||||
}
|
||||
|
||||
// send aftermix event (normal audio event)
|
||||
// TODO: check event source
|
||||
Emu.GetEventManager().SendEvent(m_config.event_key, 0x10103000e010e07, 0, 0, 0);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
||||
keys.SetCount(m_config.m_keys.GetCount());
|
||||
memcpy(keys.GetPtr(), m_config.m_keys.GetPtr(), sizeof(u64) * keys.GetCount());
|
||||
}
|
||||
for (u32 i = 0; i < keys.GetCount(); i++)
|
||||
{
|
||||
// TODO: check event source
|
||||
Emu.GetEventManager().SendEvent(keys[i], 0x10103000e010e07, 0, 0, 0);
|
||||
}
|
||||
|
||||
oal_buffer_offset += sizeof(buffer) / sizeof(float);
|
||||
|
||||
@ -441,22 +451,27 @@ int cellAudioCreateNotifyEventQueue(mem32_t id, mem64_t key)
|
||||
{
|
||||
cellAudio.Warning("cellAudioCreateNotifyEventQueue(id_addr=0x%x, key_addr=0x%x)", id.GetAddr(), key.GetAddr());
|
||||
|
||||
while (Emu.GetEventManager().CheckKey(m_config.event_key))
|
||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
||||
|
||||
u64 event_key = 0;
|
||||
while (Emu.GetEventManager().CheckKey((event_key << 48) | 0x80004d494f323221))
|
||||
{
|
||||
m_config.event_key++; // experimental
|
||||
event_key++; // experimental
|
||||
//return CELL_AUDIO_ERROR_EVENT_QUEUE;
|
||||
}
|
||||
event_key = (event_key << 48) | 0x80004d494f323221; // left part: 0x8000, 0x8001, 0x8002 ...
|
||||
|
||||
EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, m_config.event_key, m_config.event_key, 32);
|
||||
EventQueue* eq = new EventQueue(SYS_SYNC_FIFO, SYS_PPU_QUEUE, event_key, event_key, 32);
|
||||
|
||||
if (!Emu.GetEventManager().RegisterKey(eq, m_config.event_key))
|
||||
if (!Emu.GetEventManager().RegisterKey(eq, event_key))
|
||||
{
|
||||
delete eq;
|
||||
return CELL_AUDIO_ERROR_EVENT_QUEUE;
|
||||
}
|
||||
|
||||
m_config.m_keys.AddCpy(event_key);
|
||||
id = cellAudio.GetNewId(eq);
|
||||
key = m_config.event_key;
|
||||
key = event_key;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -471,7 +486,9 @@ int cellAudioSetNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio.Warning("cellAudioSetNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
//m_config.event_key = key;
|
||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
||||
|
||||
m_config.m_keys.AddCpy(key);
|
||||
|
||||
/*EventQueue* eq;
|
||||
if (!Emu.GetEventManager().GetEventQueue(key, eq))
|
||||
@ -494,13 +511,30 @@ int cellAudioRemoveNotifyEventQueue(u64 key)
|
||||
{
|
||||
cellAudio.Warning("cellAudioRemoveNotifyEventQueue(key=0x%llx)", key);
|
||||
|
||||
EventQueue* eq;
|
||||
if (!Emu.GetEventManager().GetEventQueue(key, eq))
|
||||
std::lock_guard<std::mutex> lock(m_config.m_mutex);
|
||||
|
||||
bool found = false;
|
||||
for (u32 i = 0; i < m_config.m_keys.GetCount(); i++)
|
||||
{
|
||||
if (m_config.m_keys[i] == key)
|
||||
{
|
||||
m_config.m_keys.RemoveAt(i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// ???
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}
|
||||
|
||||
m_config.event_key = 0x80004d494f323221;
|
||||
/*EventQueue* eq;
|
||||
if (!Emu.GetEventManager().GetEventQueue(key, eq))
|
||||
{
|
||||
return CELL_AUDIO_ERROR_PARAM;
|
||||
}*/
|
||||
|
||||
// TODO: disconnect port
|
||||
|
||||
|
@ -18,7 +18,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
|
||||
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
||||
{
|
||||
if (esFilterId->filterIdMajor >= 0xe0)
|
||||
attr->memSize = 0x1000000; // 0x45fa49 from ps3
|
||||
attr->memSize = 0x3000000; // 0x45fa49 from ps3
|
||||
else
|
||||
attr->memSize = 0x200000; // 0x73d9 from ps3
|
||||
|
||||
@ -156,6 +156,16 @@ u32 dmuxOpen(Demuxer* data)
|
||||
|
||||
//ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
|
||||
|
||||
stream.skip(4);
|
||||
len -= 4;
|
||||
u32 abc;
|
||||
stream.peek(abc);
|
||||
if (abc == 0x5548D00F)
|
||||
{
|
||||
stream.skip(8);
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
es.push(stream, len - pes.size - 3, pes);
|
||||
es.finish(stream);
|
||||
|
||||
@ -231,7 +241,7 @@ u32 dmuxOpen(Demuxer* data)
|
||||
continue;
|
||||
}
|
||||
|
||||
//hack: reconstruction of MPEG2-PS stream for vdec module (seems it works without it too)
|
||||
//reconstruction of MPEG2-PS stream for vdec module
|
||||
stream = backup;
|
||||
es.push(stream, len + 6 /*- pes.size - 3*/, pes);
|
||||
}
|
||||
@ -288,18 +298,32 @@ u32 dmuxOpen(Demuxer* data)
|
||||
{
|
||||
case dmuxSetStream:
|
||||
{
|
||||
if (stream.discontinuity)
|
||||
{
|
||||
for (u32 i = 0; i < 192; i++)
|
||||
{
|
||||
if (esALL[i])
|
||||
{
|
||||
esALL[i]->reset();
|
||||
}
|
||||
}
|
||||
updates_count = 0;
|
||||
updates_signaled = 0;
|
||||
}
|
||||
|
||||
if (updates_count != updates_signaled)
|
||||
{
|
||||
ConLog.Error("dmuxSetStream: stream update inconsistency (input=%d, signaled=%d)", updates_count, updates_signaled);
|
||||
return;
|
||||
}
|
||||
|
||||
updates_count++;
|
||||
stream = task.stream;
|
||||
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
|
||||
stream.addr, stream.size, stream.discontinuity, stream.userdata);
|
||||
if (stream.discontinuity) for (u32 i = 0; i < 192; i++)
|
||||
{
|
||||
if (esALL[i])
|
||||
{
|
||||
esALL[i]->reset();
|
||||
}
|
||||
}
|
||||
updates_count++;
|
||||
|
||||
dmux.is_running = true;
|
||||
dmux.fbSetStream.Push(task.stream.addr); // feedback
|
||||
}
|
||||
break;
|
||||
|
||||
@ -592,12 +616,12 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||
return CELL_DMUX_ERROR_FATAL;
|
||||
}
|
||||
|
||||
while (dmux->is_running) // !!!
|
||||
if (dmux->is_running)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("cellDmuxSetStream(%d) aborted (waiting)", demuxerHandle);
|
||||
break;
|
||||
return CELL_OK;
|
||||
}
|
||||
Sleep(1);
|
||||
return CELL_DMUX_ERROR_BUSY;
|
||||
@ -612,14 +636,16 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||
|
||||
dmux->job.Push(task);
|
||||
|
||||
while (!dmux->is_running)
|
||||
u32 addr;
|
||||
if (!dmux->fbSetStream.Pop(addr))
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("cellDmuxSetStream(%d) aborted", demuxerHandle);
|
||||
break;
|
||||
}
|
||||
Sleep(1);
|
||||
ConLog.Warning("cellDmuxSetStream(%d) aborted (fbSetStream.Pop())", demuxerHandle);
|
||||
return CELL_OK;
|
||||
}
|
||||
if (addr != info.addr)
|
||||
{
|
||||
ConLog.Error("cellDmuxSetStream(%d): wrong stream queued (right=0x%x, queued=0x%x)", demuxerHandle, info.addr, addr);
|
||||
Emu.Pause();
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -921,7 +947,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_
|
||||
|
||||
int cellDmuxReleaseAu(u32 esHandle)
|
||||
{
|
||||
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||
cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||
|
||||
return CELL_OK;
|
||||
|
||||
@ -931,21 +957,8 @@ int cellDmuxReleaseAu(u32 esHandle)
|
||||
return CELL_DMUX_ERROR_ARG;
|
||||
}
|
||||
|
||||
if (!es->canrelease())
|
||||
{
|
||||
cellDmux.Error("cellDmuxReleaseAu: no AU");
|
||||
return CELL_DMUX_ERROR_SEQ;
|
||||
}
|
||||
|
||||
/*DemuxerTask task(dmuxReleaseAu);
|
||||
task.es.es = esHandle;
|
||||
task.es.es_ptr = es;
|
||||
|
||||
es->dmux->job.Push(task);*/
|
||||
|
||||
if (!es->release())
|
||||
{
|
||||
cellDmux.Error("cellDmuxReleaseAu failed");
|
||||
return CELL_DMUX_ERROR_SEQ;
|
||||
}
|
||||
return CELL_OK;
|
||||
@ -953,7 +966,7 @@ int cellDmuxReleaseAu(u32 esHandle)
|
||||
|
||||
int cellDmuxFlushEs(u32 esHandle)
|
||||
{
|
||||
cellDmux.Log("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
|
||||
cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
|
||||
|
||||
ElementaryStream* es;
|
||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||
|
@ -304,11 +304,6 @@ enum
|
||||
PRIVATE_STREAM_2 = 0x000001bf,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAX_AU = 640 * 1024 + 128, // 640 KB
|
||||
};
|
||||
|
||||
struct DemuxerStream
|
||||
{
|
||||
u32 addr;
|
||||
@ -385,7 +380,7 @@ struct PesHeader
|
||||
stream.get(v);
|
||||
if (v != 0xFF) break; // skip padding bytes
|
||||
empty++;
|
||||
if (empty = size) return;
|
||||
if (empty == size) return;
|
||||
};
|
||||
|
||||
if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only
|
||||
@ -460,7 +455,8 @@ struct DemuxerTask
|
||||
class Demuxer
|
||||
{
|
||||
public:
|
||||
SQueue<DemuxerTask> job;
|
||||
SQueue<DemuxerTask, 32> job;
|
||||
SQueue<u32, 16> fbSetStream;
|
||||
const u32 memAddr;
|
||||
const u32 memSize;
|
||||
const u32 cbFunc;
|
||||
@ -491,6 +487,26 @@ class ElementaryStream
|
||||
u32 last_addr; // AU that is being written now
|
||||
u32 last_size; // number of bytes written (after 128b header)
|
||||
u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
|
||||
|
||||
bool is_full()
|
||||
{
|
||||
if (first_addr)
|
||||
{
|
||||
if (first_addr >= last_addr)
|
||||
{
|
||||
return (first_addr - last_addr) <= GetMaxAU();
|
||||
}
|
||||
else
|
||||
{
|
||||
// probably, always false
|
||||
return (last_addr + GetMaxAU()) > (memAddr + memSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Demuxer* dmux;
|
||||
@ -523,6 +539,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
const u32 GetMaxAU() const
|
||||
{
|
||||
return 640 * 1024 + 128;
|
||||
}
|
||||
|
||||
volatile bool hasunseen()
|
||||
{
|
||||
return peek_addr;
|
||||
@ -536,21 +557,7 @@ public:
|
||||
bool isfull()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
if (first_addr)
|
||||
{
|
||||
if (first_addr > last_addr)
|
||||
{
|
||||
return (first_addr - last_addr) < MAX_AU;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (first_addr + MAX_AU) > (memAddr + memSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return is_full();
|
||||
}
|
||||
|
||||
void finish(DemuxerStream& stream) // not multithread-safe
|
||||
@ -565,8 +572,9 @@ public:
|
||||
{
|
||||
peek_addr = last_addr;
|
||||
}
|
||||
|
||||
u32 new_addr = a128(last_addr + 128 + last_size);
|
||||
if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||
if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
last_addr = memAddr;
|
||||
}
|
||||
@ -581,24 +589,8 @@ public:
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
bool is_full;
|
||||
if (first_addr)
|
||||
{
|
||||
if (first_addr > last_addr)
|
||||
{
|
||||
is_full = (first_addr - last_addr) < MAX_AU;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_full = (first_addr + MAX_AU) > (memAddr + memSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
is_full = false;
|
||||
}
|
||||
|
||||
if (is_full)
|
||||
if (is_full())
|
||||
{
|
||||
ConLog.Error("ElementaryStream::push(): buffer is full");
|
||||
Emu.Pause();
|
||||
@ -646,16 +638,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
volatile bool canrelease()
|
||||
{
|
||||
return first_addr;
|
||||
}
|
||||
|
||||
bool release()
|
||||
{
|
||||
SMutexLocker lock(mutex);
|
||||
//ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size);
|
||||
if (!canrelease())
|
||||
if (!first_addr)
|
||||
{
|
||||
ConLog.Error("ElementaryStream::release(): buffer is empty");
|
||||
return false;
|
||||
@ -675,7 +662,7 @@ public:
|
||||
{
|
||||
first_addr = 0;
|
||||
}
|
||||
else if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||
else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
first_addr = memAddr;
|
||||
}
|
||||
@ -706,7 +693,7 @@ public:
|
||||
{
|
||||
peek_addr = 0;
|
||||
}
|
||||
else if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||
else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
{
|
||||
peek_addr = memAddr;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ Module cellSpurs(0x000a, cellSpurs_init);
|
||||
int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus, int spuPriority,
|
||||
int ppuPriority, bool exitIfNoWork)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
|
||||
cellSpurs.Error("_cellSpursAttributeInitialize(attr_addr=0x%x, nSpus=%u, spuPriority=%u, ppuPriority=%u, exitIfNoWork=%u)",
|
||||
attr.GetAddr(), nSpus, spuPriority, ppuPriority, exitIfNoWork);
|
||||
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -18,7 +18,7 @@ int _cellSpursAttributeInitialize(mem_ptr_t<CellSpursAttribute> attr, int nSpus,
|
||||
|
||||
int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribute> attr, u32 container)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)",
|
||||
cellSpurs.Error("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)",
|
||||
attr.GetAddr(), container);
|
||||
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -27,7 +27,7 @@ int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t<CellSpursAttribut
|
||||
|
||||
int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const mem8_t prefix, u32 size)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
|
||||
cellSpurs.Error("cellSpursAttributeSetNamePrefix(attr_addr=0x%x, prefix_addr=0x%x, size=0x%x)",
|
||||
attr.GetAddr(), prefix.GetAddr(), size);
|
||||
if(!attr.IsGood() || !prefix.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
if(size > 15) return CELL_SPURS_CORE_ERROR_INVAL;
|
||||
@ -37,7 +37,7 @@ int cellSpursAttributeSetNamePrefix(mem_ptr_t<CellSpursAttribute> attr, const me
|
||||
|
||||
int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> attr)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr());
|
||||
cellSpurs.Error("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr());
|
||||
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -45,7 +45,7 @@ int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t<CellSpursAttribute> a
|
||||
|
||||
int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr, int type)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
|
||||
cellSpurs.Error("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type);
|
||||
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -54,7 +54,7 @@ int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t<CellSpursAttribute> attr,
|
||||
int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, const u8 priority[8],
|
||||
uint maxSpu, const bool isPreemptible[8])
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])",
|
||||
cellSpurs.Error("cellSpursAttributeEnableSystemWorkload(attr_addr=0x%x, priority[%u], maxSpu=%u, isPreemptible[%u])",
|
||||
attr.GetAddr(), priority, maxSpu, isPreemptible);
|
||||
if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
for (int i=0; i<8; i++)
|
||||
@ -65,7 +65,7 @@ int cellSpursAttributeEnableSystemWorkload(mem_ptr_t<CellSpursAttribute> attr, c
|
||||
|
||||
int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr_t<CellSpursAttribute> attr)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
|
||||
cellSpurs.Error("cellSpursInitializeWithAttribute2(spurs_addr=0x%x, spurs_addr=0x%x)",
|
||||
spurs.GetAddr(), attr.GetAddr());
|
||||
if(!attr.IsGood() || !spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -74,7 +74,7 @@ int cellSpursInitializeWithAttribute2(mem_ptr_t<CellSpurs2> spurs, const mem_ptr
|
||||
|
||||
int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
|
||||
cellSpurs.Error("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr());
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -82,7 +82,7 @@ int cellSpursFinalize(mem_ptr_t<CellSpurs> spurs)
|
||||
|
||||
int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)",
|
||||
cellSpurs.Error("cellSpursGetSpuThreadGroupId(spurs_addr=0x%x, group_addr=0x%x)",
|
||||
spurs.GetAddr(), group.GetAddr());
|
||||
if(!spurs.IsGood() || group.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -91,7 +91,7 @@ int cellSpursGetSpuThreadGroupId(mem_ptr_t<CellSpurs> spurs, mem32_t group)
|
||||
|
||||
int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)",
|
||||
cellSpurs.Error("cellSpursGetNumSpuThread(spurs_addr=0x%x, nThreads_addr=0x%x)",
|
||||
spurs.GetAddr(), nThreads.GetAddr());
|
||||
if(!spurs.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -100,7 +100,7 @@ int cellSpursGetNumSpuThread(mem_ptr_t<CellSpurs> spurs, mem32_t nThreads)
|
||||
|
||||
int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t nThreads)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)",
|
||||
cellSpurs.Error("cellSpursGetSpuThreadId(spurs_addr=0x%x, thread_addr=0x%x, nThreads_addr=0x%x)",
|
||||
spurs.GetAddr(), thread.GetAddr(), nThreads.GetAddr());
|
||||
if(!spurs.IsGood() || !thread.IsGood() || nThreads.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -109,7 +109,7 @@ int cellSpursGetSpuThreadId(mem_ptr_t<CellSpurs> spurs, mem32_t thread, mem32_t
|
||||
|
||||
int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint maxContention)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)",
|
||||
cellSpurs.Error("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)",
|
||||
spurs.GetAddr(), workloadId, maxContention);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -118,7 +118,7 @@ int cellSpursSetMaxContention(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint
|
||||
|
||||
int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU])
|
||||
{
|
||||
cellSpurs.Warning("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])",
|
||||
cellSpurs.Error("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])",
|
||||
spurs.GetAddr(), workloadId, priorities);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -127,7 +127,7 @@ int cellSpursSetPriorities(mem_ptr_t<CellSpurs> spurs, uint workloadId, const u8
|
||||
|
||||
int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId, uint priority)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)",
|
||||
cellSpurs.Error("cellSpursSetPriority(spurs_addr=0x%x, workloadId=%u, spuId=%u, priority=%u)",
|
||||
spurs.GetAddr(), workloadId, spuId, priority);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -136,7 +136,7 @@ int cellSpursSetPriority(mem_ptr_t<CellSpurs> spurs, uint workloadId, uint spuId
|
||||
|
||||
int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isPreemptible[8])
|
||||
{
|
||||
cellSpurs.Warning("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])",
|
||||
cellSpurs.Error("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])",
|
||||
spurs.GetAddr(), isPreemptible);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -145,7 +145,7 @@ int cellSpursSetPreemptionVictimHints(mem_ptr_t<CellSpurs> spurs, const bool isP
|
||||
|
||||
int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t port, int isDynamic)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)",
|
||||
cellSpurs.Error("cellSpursAttachLv2EventQueue(spurs_addr=0x%x, queue=0x%x, port_addr=0x%x, isDynamic=%u)",
|
||||
spurs.GetAddr(), queue, port.GetAddr(), isDynamic);
|
||||
if(!spurs.IsGood() || !port.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -154,7 +154,7 @@ int cellSpursAttachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u32 queue, mem8_t p
|
||||
|
||||
int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port);
|
||||
cellSpurs.Error("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -162,7 +162,7 @@ int cellSpursDetachLv2EventQueue(mem_ptr_t<CellSpurs> spurs, u8 port)
|
||||
|
||||
int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag);
|
||||
cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag);
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -171,7 +171,7 @@ int cellSpursEnableExceptionEventHandler(mem_ptr_t<CellSpurs> spurs, bool flag)
|
||||
int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
|
||||
mem_func_ptr_t<CellSpursGlobalExceptionEventHandler> eaHandler, mem_ptr_t<void> arg)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)",
|
||||
cellSpurs.Error("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, eaHandler_addr=0x%x, arg_addr=0x%x,)",
|
||||
spurs.GetAddr(), eaHandler.GetAddr(), arg.GetAddr());
|
||||
if(!spurs.IsGood() || eaHandler.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
@ -180,7 +180,7 @@ int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs,
|
||||
|
||||
int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr());
|
||||
cellSpurs.Error("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr());
|
||||
if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -188,7 +188,7 @@ int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t<CellSpurs> spurs)
|
||||
|
||||
int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr());
|
||||
cellSpurs.Error("cellSpursGetInfo(spurs_addr=0x%x, info_addr=0x%x)", spurs.GetAddr(), info.GetAddr());
|
||||
if(!spurs.IsGood() || !info.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
@ -197,7 +197,7 @@ int cellSpursGetInfo(mem_ptr_t<CellSpurs> spurs, mem_ptr_t<CellSpursInfo> info)
|
||||
// Task functions
|
||||
int cellSpursGetTasksetId(mem_ptr_t<CellSpursTaskset> taskset, mem32_t workloadId)
|
||||
{
|
||||
cellSpurs.Warning("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr());
|
||||
cellSpurs.Error("cellSpursGetTasksetId(taskset_addr=0x%x, workloadId_addr=0x%x)", taskset.GetAddr(), workloadId.GetAddr());
|
||||
if(!taskset.IsGood() || !taskset.IsGood()) return CELL_SPURS_TASK_ERROR_NULL_POINTER;
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -23,7 +23,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
|
||||
|
||||
int res = 0;
|
||||
|
||||
if (vdec.reader.size < (u32)buf_size && !vdec.just_started)
|
||||
next:
|
||||
if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/)
|
||||
{
|
||||
while (vdec.job.IsEmpty())
|
||||
{
|
||||
@ -74,6 +75,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size)
|
||||
ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
goto next;
|
||||
}
|
||||
else if (vdec.reader.size < (u32)buf_size)
|
||||
{
|
||||
@ -235,14 +238,21 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
|
||||
if (vdec.just_started) // deferred initialization
|
||||
{
|
||||
err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL);
|
||||
err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL);
|
||||
if (err)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: avformat_open_input() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
err = avformat_find_stream_info(vdec.fmt, NULL);
|
||||
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ???
|
||||
if (!codec)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
/*err = avformat_find_stream_info(vdec.fmt, NULL);
|
||||
if (err)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed");
|
||||
@ -254,17 +264,15 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
ConLog.Error("vdecDecodeAu: no stream found");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data
|
||||
|
||||
AVCodec* codec = avcodec_find_decoder(vdec.ctx->codec_id); // ???
|
||||
if (!codec)
|
||||
}*/
|
||||
if (!avformat_new_stream(vdec.fmt, codec))
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed");
|
||||
ConLog.Error("vdecDecodeAu: avformat_new_stream() failed");
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
|
||||
vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data
|
||||
|
||||
AVDictionary* opts = nullptr;
|
||||
av_dict_set(&opts, "refcounted_frames", "1", 0);
|
||||
{
|
||||
@ -292,6 +300,7 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
ConLog.Warning("vdecDecodeAu aborted");
|
||||
return;
|
||||
}
|
||||
|
||||
last_frame = av_read_frame(vdec.fmt, &au) < 0;
|
||||
if (last_frame)
|
||||
{
|
||||
@ -335,7 +344,6 @@ u32 vdecOpen(VideoDecoder* data)
|
||||
if (!last_frame && decode < 0)
|
||||
{
|
||||
ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode);
|
||||
break;
|
||||
}
|
||||
if (!got_picture && vdec.reader.size == 0) break; // video end?
|
||||
}
|
||||
|
@ -185,6 +185,11 @@ void sysPrxForUser_init()
|
||||
sysPrxForUser.AddFunc(0x52aadadf, sys_lwcond_signal_to);
|
||||
sysPrxForUser.AddFunc(0x2a6d9d51, sys_lwcond_wait);
|
||||
|
||||
sysPrxForUser.AddFunc(0x8c2bb498, sys_spinlock_initialize);
|
||||
sysPrxForUser.AddFunc(0xa285139d, sys_spinlock_lock);
|
||||
sysPrxForUser.AddFunc(0x722a0254, sys_spinlock_trylock);
|
||||
sysPrxForUser.AddFunc(0x5267cb35, sys_spinlock_unlock);
|
||||
|
||||
sysPrxForUser.AddFunc(0x67f9fedb, sys_game_process_exitspawn2);
|
||||
sysPrxForUser.AddFunc(0xfc52a7a9, sys_game_process_exitspawn);
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "lv2/SC_Lwcond.h"
|
||||
#include "lv2/SC_Event_flag.h"
|
||||
#include "lv2/SC_Condition.h"
|
||||
#include "lv2/SC_Spinlock.h"
|
||||
#include "Emu/event.h"
|
||||
//#define SYSCALLS_DEBUG
|
||||
|
||||
@ -200,6 +201,12 @@ extern int sys_rwlock_wlock(u32 rw_lock_id, u64 timeout);
|
||||
extern int sys_rwlock_trywlock(u32 rw_lock_id);
|
||||
extern int sys_rwlock_wunlock(u32 rw_lock_id);
|
||||
|
||||
//sys_spinlock
|
||||
extern void sys_spinlock_initialize(mem_ptr_t<spinlock> lock);
|
||||
extern void sys_spinlock_lock(mem_ptr_t<spinlock> lock);
|
||||
extern int sys_spinlock_trylock(mem_ptr_t<spinlock> lock);
|
||||
extern void sys_spinlock_unlock(mem_ptr_t<spinlock> lock);
|
||||
|
||||
//ppu_thread
|
||||
extern void sys_ppu_thread_exit(u64 errorcode);
|
||||
extern int sys_ppu_thread_yield();
|
||||
|
@ -71,48 +71,15 @@ int sys_cond_signal(u32 cond_id)
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
|
||||
|
||||
if (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
{
|
||||
CPUThread* tt = Emu.GetCPU().GetThread(target);
|
||||
bool valid = tt && tt->IsAlive();
|
||||
if (!valid)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal(%d): signal to invalid thread(%d)", cond_id, target);
|
||||
return CELL_OK;
|
||||
}
|
||||
cond->cond.lock(target);
|
||||
|
||||
if (!was_locked) // mutex hasn't been locked (don't care about mutex state)
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
tt = Emu.GetCPU().GetThread(owner);
|
||||
valid = tt && tt->IsAlive();
|
||||
if (!valid)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal(%d): deadlock on invalid thread(%d)", cond_id, owner);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
|
||||
}
|
||||
else // mutex has been locked (should preserve original mutex state)
|
||||
{
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
ConLog.Warning("sys_cond_signal(id=%d) aborted", cond_id);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -129,43 +96,10 @@ int sys_cond_signal_all(u32 cond_id)
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
|
||||
|
||||
while (u32 target = (mutex->protocol == SYS_SYNC_PRIORITY ? cond->m_queue.pop_prio() : cond->m_queue.pop()))
|
||||
{
|
||||
CPUThread* tt = Emu.GetCPU().GetThread(target);
|
||||
bool valid = tt && tt->IsAlive();
|
||||
if (!valid)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal_all(%d): signal to invalid thread(%d)", cond_id, target);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
if (!was_locked)
|
||||
{
|
||||
if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
tt = Emu.GetCPU().GetThread(owner);
|
||||
valid = tt && tt->IsAlive();
|
||||
if (!valid)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal_all(%d): deadlock on invalid thread(%d)", cond_id, owner);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
cond->cond.lock(target);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
@ -197,35 +131,10 @@ int sys_cond_signal_to(u32 cond_id, u32 thread_id)
|
||||
}
|
||||
|
||||
Mutex* mutex = cond->mutex;
|
||||
u32 tid = GetCurrentPPUThread().GetId();
|
||||
|
||||
bool was_locked = (mutex->m_mutex.GetOwner() == tid);
|
||||
|
||||
u32 target = thread_id;
|
||||
{
|
||||
if (!was_locked)
|
||||
{
|
||||
if (u32 owner = mutex->m_mutex.GetOwner())
|
||||
{
|
||||
CPUThread* tt = Emu.GetCPU().GetThread(owner);
|
||||
bool valid = tt && tt->IsAlive();
|
||||
if (!valid)
|
||||
{
|
||||
sys_cond.Error("sys_cond_signal_to(%d): deadlock on invalid thread(%d)", cond_id, owner);
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutex->recursive = 1;
|
||||
mutex->m_mutex.unlock(tid, target);
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
}
|
||||
cond->cond.lock(target);
|
||||
}
|
||||
|
||||
if (Emu.IsStopped())
|
||||
@ -264,15 +173,11 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* switch (mutex->m_mutex.trylock(tid))
|
||||
if (cond->cond.GetOwner() == tid)
|
||||
{
|
||||
case SMR_OK: mutex->m_mutex.unlock(tid); break;
|
||||
case SMR_SIGNAL: mutex->recursive = 1; return CELL_OK;
|
||||
} */
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
_mm_mfence();
|
||||
mutex->m_mutex.lock(tid);
|
||||
mutex->recursive = 1;
|
||||
cond->cond.unlock(tid);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -281,6 +186,7 @@ int sys_cond_wait(u32 cond_id, u64 timeout)
|
||||
if (counter++ > max_counter)
|
||||
{
|
||||
cond->m_queue.invalidate(tid);
|
||||
GetCurrentPPUThread().owned_mutexes--;
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
if (Emu.IsStopped())
|
||||
|
@ -16,6 +16,7 @@ struct sys_cond_attribute
|
||||
struct Cond
|
||||
{
|
||||
Mutex* mutex; // associated with mutex
|
||||
SMutex cond;
|
||||
SleepQueue m_queue;
|
||||
|
||||
Cond(Mutex* mutex, u64 name)
|
||||
|
@ -203,7 +203,7 @@ int sys_event_queue_receive(u32 equeue_id, mem_ptr_t<sys_event_data> event, u64
|
||||
eq->owner.unlock(tid);
|
||||
sys_event.Log(" *** event received: source=0x%llx, d1=0x%llx, d2=0x%llx, d3=0x%llx",
|
||||
(u64)event->source, (u64)event->data1, (u64)event->data2, (u64)event->data3);
|
||||
/* HACK: passing event data in registers */
|
||||
/* passing event data in registers */
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
t.GPR[4] = event->source;
|
||||
t.GPR[5] = event->data1;
|
||||
|
@ -324,10 +324,15 @@ int cellFsMkdir(u32 path_addr, u32 mode)
|
||||
const wxString& ps3_path = Memory.ReadString(path_addr);
|
||||
sys_fs.Log("cellFsMkdir(path=\"%s\", mode=0x%x)", ps3_path.wx_str(), mode);
|
||||
|
||||
vfsDir dir;
|
||||
/*vfsDir dir;
|
||||
if(dir.IsExists(ps3_path))
|
||||
return CELL_EEXIST;
|
||||
if(!dir.Create(ps3_path))
|
||||
return CELL_EBUSY;*/
|
||||
|
||||
if(Emu.GetVFS().ExistsDir(ps3_path))
|
||||
return CELL_EEXIST;
|
||||
if(!Emu.GetVFS().CreateDir(ps3_path))
|
||||
return CELL_EBUSY;
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -198,6 +198,7 @@ bool SleepQueue::finalize()
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -98,8 +98,9 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
|
||||
_mm_mfence();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
if (owner == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
@ -119,22 +120,10 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout)
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
if (!tt->IsAlive())
|
||||
{
|
||||
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
/*mutex->m_mutex.unlock(owner, tid);
|
||||
mutex->recursive = 1;
|
||||
t.owned_mutexes++;
|
||||
return CELL_OK;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
/*mutex->m_mutex.unlock(owner, tid);
|
||||
mutex->recursive = 1;
|
||||
t.owned_mutexes++;
|
||||
return CELL_OK;*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,8 +169,9 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
|
||||
_mm_mfence();
|
||||
u32 owner = mutex->m_mutex.GetOwner();
|
||||
if (owner == tid)
|
||||
{
|
||||
if (mutex->is_recursive)
|
||||
@ -201,22 +191,10 @@ int sys_mutex_trylock(u32 mutex_id)
|
||||
{
|
||||
if (CPUThread* tt = Emu.GetCPU().GetThread(owner))
|
||||
{
|
||||
if (!tt->IsAlive())
|
||||
{
|
||||
if (owner == mutex->m_mutex.GetOwner()) sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
/*mutex->m_mutex.unlock(owner, tid);
|
||||
mutex->recursive = 1;
|
||||
t.owned_mutexes++;
|
||||
return CELL_OK;*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner);
|
||||
/*mutex->m_mutex.unlock(owner, tid);
|
||||
mutex->recursive = 1;
|
||||
t.owned_mutexes++;
|
||||
return CELL_OK;*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,6 +219,7 @@ int sys_mutex_unlock(u32 mutex_id)
|
||||
PPUThread& t = GetCurrentPPUThread();
|
||||
u32 tid = t.GetId();
|
||||
|
||||
_mm_mfence();
|
||||
if (mutex->m_mutex.GetOwner() == tid)
|
||||
{
|
||||
if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive))
|
||||
|
@ -9,32 +9,6 @@
|
||||
static SysCallBase sc_spu("sys_spu");
|
||||
extern SysCallBase sys_event;
|
||||
|
||||
static const u32 g_spu_group_thr_max = 255;
|
||||
|
||||
struct SpuGroupInfo
|
||||
{
|
||||
Array<u32> list;
|
||||
std::atomic<u32> lock;
|
||||
wxString m_name;
|
||||
int m_prio;
|
||||
int m_type;
|
||||
int m_ct;
|
||||
|
||||
SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct)
|
||||
: m_name(name)
|
||||
, m_prio(prio)
|
||||
, m_type(type)
|
||||
, m_ct(ct)
|
||||
, lock(0)
|
||||
{
|
||||
list.SetCount(num);
|
||||
for (u32 i = 0; i < num; i++)
|
||||
{
|
||||
list[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
|
||||
{
|
||||
ELFLoader l(stream);
|
||||
@ -114,7 +88,7 @@ int sys_spu_thread_initialize(mem32_t thread, u32 group, u32 spu_num, mem_ptr_t<
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
if(spu_num >= g_spu_group_thr_max)
|
||||
if(spu_num >= group_info->list.GetCount())
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
@ -287,7 +261,7 @@ int sys_spu_thread_group_create(mem32_t id, u32 num, int prio, mem_ptr_t<sys_spu
|
||||
|
||||
if (!Memory.IsGoodAddr(attr->name_addr, attr->name_len)) return CELL_EFAULT;
|
||||
|
||||
if (num > g_spu_group_thr_max) return CELL_EINVAL;
|
||||
if (num > 256) return CELL_EINVAL;
|
||||
|
||||
if (prio < 16 || prio > 255) return CELL_EINVAL;
|
||||
|
||||
|
@ -55,3 +55,28 @@ struct sys_spu_segment
|
||||
be_t<int> size;
|
||||
be_t<u64> src;
|
||||
};
|
||||
|
||||
struct SpuGroupInfo
|
||||
{
|
||||
Array<u32> list;
|
||||
std::atomic<u32> lock;
|
||||
wxString m_name;
|
||||
int m_prio;
|
||||
int m_type;
|
||||
int m_ct;
|
||||
|
||||
SpuGroupInfo(wxString name, u32 num, int prio, int type, u32 ct)
|
||||
: m_name(name)
|
||||
, m_prio(prio)
|
||||
, m_type(type)
|
||||
, m_ct(ct)
|
||||
, lock(0)
|
||||
{
|
||||
num = 256;
|
||||
list.SetCount(num);
|
||||
for (u32 i = 0; i < num; i++)
|
||||
{
|
||||
list[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
51
rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp
Normal file
51
rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "stdafx.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
#include "Emu/SysCalls/lv2/SC_Spinlock.h"
|
||||
|
||||
SysCallBase sys_spinlock("sys_spinlock");
|
||||
|
||||
void sys_spinlock_initialize(mem_ptr_t<spinlock> lock)
|
||||
{
|
||||
sys_spinlock.Log("sys_spinlock_initialize(lock_addr=0x%x)", lock.GetAddr());
|
||||
|
||||
lock->mutex.initialize();
|
||||
}
|
||||
|
||||
void sys_spinlock_lock(mem_ptr_t<spinlock> lock)
|
||||
{
|
||||
sys_spinlock.Log("sys_spinlock_lock(lock_addr=0x%x)", lock.GetAddr());
|
||||
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
switch (lock->mutex.lock(tid))
|
||||
{
|
||||
case SMR_ABORT: ConLog.Warning("sys_spinlock_lock(0x%x) aborted", lock.GetAddr()); break;
|
||||
case SMR_DEADLOCK: ConLog.Error("sys_spinlock_lock(0x%x) reached deadlock", lock.GetAddr()); break; // ???
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
int sys_spinlock_trylock(mem_ptr_t<spinlock> lock)
|
||||
{
|
||||
sys_spinlock.Log("sys_spinlock_trylock(lock_addr=0x%x)", lock.GetAddr());
|
||||
|
||||
be_t<u32> tid = GetCurrentPPUThread().GetId();
|
||||
switch (lock->mutex.trylock(tid))
|
||||
{
|
||||
case SMR_FAILED: return CELL_EBUSY;
|
||||
case SMR_ABORT: ConLog.Warning("sys_spinlock_trylock(0x%x) aborted", lock.GetAddr()); break;
|
||||
case SMR_DEADLOCK: ConLog.Error("sys_spinlock_trylock(0x%x) reached deadlock", lock.GetAddr()); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
void sys_spinlock_unlock(mem_ptr_t<spinlock> lock)
|
||||
{
|
||||
sys_spinlock.Log("sys_spinlock_unlock(lock_addr=0x%x)", lock.GetAddr());
|
||||
|
||||
switch (lock->mutex.unlock(lock->mutex.GetOwner()))
|
||||
{
|
||||
default: break;
|
||||
}
|
||||
}
|
6
rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h
Normal file
6
rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
struct spinlock
|
||||
{
|
||||
SMutexBE mutex;
|
||||
};
|
@ -277,6 +277,7 @@
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_RSX.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Rwlock.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Semaphore.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Spinlock.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_SPU_Thread.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Time.cpp" />
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Timer.cpp" />
|
||||
|
@ -466,6 +466,9 @@
|
||||
<ClCompile Include="Emu\SysCalls\Modules\cellUserInfo.cpp">
|
||||
<Filter>Emu\SysCalls\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\SysCalls\lv2\SC_Spinlock.cpp">
|
||||
<Filter>Emu\SysCalls\lv2</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
|
Loading…
Reference in New Issue
Block a user