From a33575b1152b77b0ce9d31acc411812ea436d311 Mon Sep 17 00:00:00 2001 From: Nekotekina <fbx@3mf.ru> Date: Mon, 10 Mar 2014 03:07:53 +0400 Subject: [PATCH 1/5] Compilation fix --- rpcs3/Emu/Cell/PPUThread.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index fbb53bf1ae..0302180399 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -526,7 +526,7 @@ static const s32 MAX_INT_VALUE = 0x7fffffff; class PPUThread : public PPCThread { public: - std::atomic<u32> owned_mutexes; + u32 owned_mutexes; public: PPCdouble FPR[32]; //Floating Point Register diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h index af9f4c4e6c..bc9f70b848 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -87,7 +87,8 @@ struct CellSpursTraceInfo //u8 padding[]; }; -__declspec(align(8)) struct CellTraceHeader +//__declspec(align(8)) +struct CellTraceHeader { u8 tag; u8 length; @@ -135,17 +136,20 @@ struct CellSpursTracePacket } data; }; -__declspec(align(128)) struct CellSpurs +//__declspec(align(128)) +struct CellSpurs { u8 skip[CELL_SPURS_SIZE]; }; -__declspec(align(128)) struct CellSpurs2 +//__declspec(align(128)) +struct CellSpurs2 { u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE]; }; -__declspec(align(8)) struct CellSpursAttribute +//__declspec(align(8)) +struct CellSpursAttribute { u8 skip[CELL_SPURS_ATTRIBUTE_SIZE]; }; @@ -184,7 +188,8 @@ enum }; -__declspec(align(128)) struct CellSpursTaskset +//__declspec(align(128)) +struct CellSpursTaskset { u8 skip[6400]; }; @@ -217,7 +222,8 @@ struct CellSpursTasksetInfo #define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE */ -__declspec(align(128)) struct CellSpursTaskset2 +//__declspec(align(128)) +struct CellSpursTaskset2 { be_t<u8> skip[10496]; }; @@ -267,7 +273,8 @@ struct CellSpursTaskAttribute2 //be_t<u32> __reserved__[]; }; -__declspec(align(128)) struct CellSpursTaskExitCode +//__declspec(align(128)) +struct CellSpursTaskExitCode { unsigned char skip[128]; }; From 7f7d5a57c80a1308ae206890267359c9a7d2242f Mon Sep 17 00:00:00 2001 From: Nekotekina <fbx@3mf.ru> Date: Tue, 11 Mar 2014 20:20:01 +0400 Subject: [PATCH 2/5] rldcr, rldcl instructions Some intructions fixed --- rpcs3/Emu/CPU/CPUThread.cpp | 2 +- rpcs3/Emu/Cell/PPUDisAsm.h | 7 +++++ rpcs3/Emu/Cell/PPUInstrTable.h | 3 ++- rpcs3/Emu/Cell/PPUInterpreter.h | 48 ++++++++++++++++++++++++++------- rpcs3/Emu/Cell/PPUOpcodes.h | 2 ++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 1ec31434b2..ec21cc80a1 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -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); diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index a5cbf1775b..c904350589 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -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); diff --git a/rpcs3/Emu/Cell/PPUInstrTable.h b/rpcs3/Emu/Cell/PPUInstrTable.h index e82c02abdb..a65c9224a0 100644 --- a/rpcs3/Emu/Cell/PPUInstrTable.h +++ b/rpcs3/Emu/Cell/PPUInstrTable.h @@ -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); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index ea916d43b1..474cc75f25 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -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]); @@ -2766,7 +2777,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"); } @@ -2949,7 +2960,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 { @@ -2966,11 +2977,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]); @@ -3077,18 +3088,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]); } @@ -3162,6 +3189,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 diff --git a/rpcs3/Emu/Cell/PPUOpcodes.h b/rpcs3/Emu/Cell/PPUOpcodes.h index 71a8d3b2f1..2d18686ecf 100644 --- a/rpcs3/Emu/Cell/PPUOpcodes.h +++ b/rpcs3/Emu/Cell/PPUOpcodes.h @@ -250,6 +250,7 @@ namespace PPU_opcodes RLDICR = 0x1, RLDIC = 0x2, RLDIMI = 0x3, + RLDC_LR = 0x4, }; enum G_1fOpcodes //Field 21 - 30 @@ -644,6 +645,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; From 8cc6a287a7a599df34581fbd937e45ef2ccc8685 Mon Sep 17 00:00:00 2001 From: Nekotekina <fbx@3mf.ru> Date: Thu, 13 Mar 2014 13:17:45 +0400 Subject: [PATCH 3/5] Update --- rpcs3/Emu/CPU/CPUThread.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 117 +++++++++++++++++++----- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 3 + rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 81 +++++++++------- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 83 +++++++---------- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 30 +++--- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 1 + 7 files changed, 198 insertions(+), 119 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index ec21cc80a1..9df0cc6a9e 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -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(wait=%s) aborted", wxString(wait ? "true" : false).wx_str()); + ConLog.Warning("ExecAsCallback(wait=%s) aborted", wxString(wait ? "true" : "false").wx_str()); return CELL_EABORT; // doesn't mean anything } Sleep(1); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 94a754d8e4..4147d21aaa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -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 /*&& !vdec.just_started*/) + { + while (adec.job.IsEmpty()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("vdecRead() 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,12 +171,12 @@ u32 adecOpen(AudioDecoder* data) case adecDecodeAu: { - int err; + 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 { @@ -160,7 +212,7 @@ u32 adecOpen(AudioDecoder* data) if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); - } + }*/ if (adec.just_started) // deferred initialization { @@ -171,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) { @@ -185,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); @@ -210,9 +261,17 @@ u32 adecOpen(AudioDecoder* data) adec.just_started = false; } - while (av_read_frame(adec.fmt, &au) >= 0)*/ while (true) + bool last_frame = false; + + while (true) { - if (!adec.ctx) // fake + if (Emu.IsStopped()) + { + ConLog.Warning("adecDecodeAu aborted"); + return; + } + + /*if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; @@ -223,13 +282,18 @@ 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; + }*/ + + last_frame = av_read_frame(adec.fmt, &au) < 0; + if (last_frame) + { + //break; + av_free(au.data); + au.data = NULL; + au.size = 0; } struct VdecFrameHolder : AdecFrame @@ -261,10 +325,13 @@ 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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index bab8ccd6c9..793a78905a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -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) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 36b8ffef44..bc09f6777b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -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)) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index cc504fe2f0..ce55c27eb5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -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; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 31fab366d6..5ea762662f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -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? } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 10cd0af5ff..ab987cb8cd 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -198,6 +198,7 @@ bool SleepQueue::finalize() } } + m_mutex.unlock(); return true; } From 2c447f686dc575d3264b8b7a26eb2e829a9fc2bb Mon Sep 17 00:00:00 2001 From: Nekotekina <fbx@3mf.ru> Date: Thu, 13 Mar 2014 20:11:16 +0400 Subject: [PATCH 4/5] sys_spinlock implemented --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 20 ++++---- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 44 ++++++++--------- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 5 ++ rpcs3/Emu/SysCalls/SysCalls.h | 7 +++ rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp | 51 ++++++++++++++++++++ rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h | 6 +++ rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 ++ 8 files changed, 105 insertions(+), 32 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp create mode 100644 rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 4147d21aaa..a2805567c4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -23,13 +23,13 @@ int adecRead(void* opaque, u8* buf, int buf_size) int res = 0; next: - if (adec.reader.size < (u32)buf_size /*&& !vdec.just_started*/) + if (adec.reader.size < (u32)buf_size /*&& !adec.just_started*/) { while (adec.job.IsEmpty()) { if (Emu.IsStopped()) { - ConLog.Warning("vdecRead() aborted"); + ConLog.Warning("adecRead() aborted"); return 0; } Sleep(1); @@ -212,7 +212,7 @@ u32 adecOpen(AudioDecoder* data) if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); - }*/ + } if (adec.just_started) // deferred initialization { @@ -259,7 +259,7 @@ u32 adecOpen(AudioDecoder* data) break; } adec.just_started = false; - } + }*/ bool last_frame = false; @@ -271,7 +271,7 @@ u32 adecOpen(AudioDecoder* data) return; } - /*if (!adec.ctx) // fake + if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; @@ -285,7 +285,7 @@ u32 adecOpen(AudioDecoder* data) adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; - }*/ + } last_frame = av_read_frame(adec.fmt, &au) < 0; if (last_frame) @@ -296,14 +296,14 @@ u32 adecOpen(AudioDecoder* data) au.size = 0; } - struct VdecFrameHolder : AdecFrame + struct AdecFrameHolder : AdecFrame { - VdecFrameHolder() + AdecFrameHolder() { data = av_frame_alloc(); } - ~VdecFrameHolder() + ~AdecFrameHolder() { if (data) { @@ -336,7 +336,7 @@ u32 adecOpen(AudioDecoder* data) 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; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index aca92144af..c211fa07d3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -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; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 175ea47fb5..945e925063 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -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); diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 9d75580371..0b06490c51 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -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(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp new file mode 100644 index 0000000000..90d9a35a3a --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.cpp @@ -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; + } +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h new file mode 100644 index 0000000000..0ff4af4029 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Spinlock.h @@ -0,0 +1,6 @@ +#pragma once + +struct spinlock +{ + SMutexBE mutex; +}; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 1dfb346159..a02f6bf916 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -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" /> diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index b10d1cb470..7e4015ba55 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -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" /> From 60d922da110d71d3ab701fb8f4312687583670d2 Mon Sep 17 00:00:00 2001 From: Nekotekina <fbx@3mf.ru> Date: Sat, 15 Mar 2014 19:43:14 +0400 Subject: [PATCH 5/5] DMA List commands cellAudio: multiple queue support sys_cond simplified cellFsMkdir (?) --- rpcs3/Emu/Audio/cellAudio.h | 4 +- rpcs3/Emu/Cell/MFC.h | 5 +- rpcs3/Emu/Cell/SPUThread.h | 117 ++++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 56 ++++++++--- rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp | 112 ++-------------------- rpcs3/Emu/SysCalls/lv2/SC_Condition.h | 1 + rpcs3/Emu/SysCalls/lv2/SC_Event.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 7 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 31 +----- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp | 30 +----- rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h | 25 +++++ 11 files changed, 215 insertions(+), 175 deletions(-) diff --git a/rpcs3/Emu/Audio/cellAudio.h b/rpcs3/Emu/Audio/cellAudio.h index 7d492b0ba9..dc371c9c67 100644 --- a/rpcs3/Emu/Audio/cellAudio.h +++ b/rpcs3/Emu/Audio/cellAudio.h @@ -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); diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index 6016924ae5..bef241c7b8 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -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; } } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index fcaccd72c9..cfed36752e 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -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; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 1fb6dc72ff..f6ff6404b2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -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 diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index 8f0785ab96..cc6a1d7c9d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -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()) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h index dc849948b4..460923a504 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.h @@ -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) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index b662ee10c5..d6ea1a26a3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -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; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index dfbe386ca0..c006439d1e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -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; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index ce1b3f51d3..d0d2b3f962 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -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)) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 02b898207e..170343883c 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -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; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h index 7d674155e4..1721b9c232 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.h @@ -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; + } + } +}; \ No newline at end of file