From c064c701e2d35b10629de79311e69671ef6a9bcc Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 3 Mar 2014 03:02:42 +0400 Subject: [PATCH 1/7] cellAdec draft --- Utilities/SQueue.h | 24 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 183 +++++++++++- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 97 ++++++- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 10 +- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 346 +++++++++++++++-------- rpcs3/Emu/SysCalls/Modules/cellVdec.h | 74 +++-- rpcs3/Emu/SysCalls/Modules/cellVpost.cpp | 11 +- 8 files changed, 548 insertions(+), 199 deletions(-) diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index 1fee6f6727..aa6b3d3851 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -19,11 +19,6 @@ public: { while (true) { - if (Emu.IsStopped()) - { - return false; - } - if (m_mutex.GetOwner() == m_mutex.GetDeadValue()) { return false; @@ -31,6 +26,10 @@ public: if (m_count >= SQSize) { + if (Emu.IsStopped()) + { + return false; + } Sleep(1); continue; } @@ -51,11 +50,6 @@ public: { while (true) { - if (Emu.IsStopped()) - { - return false; - } - if (m_mutex.GetOwner() == m_mutex.GetDeadValue()) { return false; @@ -63,6 +57,10 @@ public: if (!m_count) { + if (Emu.IsStopped()) + { + return false; + } Sleep(1); continue; } @@ -96,4 +94,10 @@ public: SMutexLocker lock(m_mutex); m_count = 0; } + + T& Peek(u32 pos = 0) + { + SMutexLocker lock(m_mutex); + return m_data[(m_pos + pos) % SQSize]; + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 5829ac0e29..ebff0e2de6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -1,64 +1,226 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" +#include "cellPamf.h" + +extern "C" +{ +#include "libavcodec\avcodec.h" +#include "libavformat\avformat.h" +} + #include "cellAdec.h" void cellAdec_init(); Module cellAdec(0x0006, cellAdec_init); +u32 adecOpen(AudioDecoder* data) +{ + AudioDecoder& adec = *data; + + u32 adec_id = cellAdec.GetNewId(data); + + adec.id = adec_id; + + thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]() + { + ConLog.Write("Audio Decoder enter()"); + + AdecTask task; + + while (true) + { + if (Emu.IsStopped()) + { + break; + } + + if (adec.job.IsEmpty() && adec.is_running) + { + Sleep(1); + continue; + } + + if (adec.frames.GetCount() >= 50) + { + Sleep(1); + continue; + } + + if (!adec.job.Pop(task)) + { + break; + } + + switch (task.type) + { + case adecStartSeq: + { + } + break; + + case adecEndSeq: + { + } + break; + + case adecDecodeAu: + { + } + break; + + case adecClose: + { + adec.is_finished = true; + ConLog.Write("Audio Decoder exit"); + return; + } + + default: + ConLog.Error("Audio Decoder error: unknown task(%d)", task.type); + return; + } + } + ConLog.Warning("Audio Decoder aborted"); + }); + + t.detach(); + + return adec_id; +} + +bool adecCheckType(AudioCodecType type) +{ + switch (type) + { + case CELL_ADEC_TYPE_ATRACX: ConLog.Write("*** (???) type: ATRAC3plus"); break; + case CELL_ADEC_TYPE_ATRACX_2CH: ConLog.Write("*** type: ATRAC3plus 2ch"); break; + + case CELL_ADEC_TYPE_ATRACX_6CH: + case CELL_ADEC_TYPE_ATRACX_8CH: + case CELL_ADEC_TYPE_LPCM_PAMF: + case CELL_ADEC_TYPE_AC3: + case CELL_ADEC_TYPE_MP3: + case CELL_ADEC_TYPE_ATRAC3: + case CELL_ADEC_TYPE_MPEG_L2: + case CELL_ADEC_TYPE_CELP: + case CELL_ADEC_TYPE_M4AAC: + case CELL_ADEC_TYPE_CELP8: + cellAdec.Error("Unimplemented audio codec type (%d)", type); + break; + default: + return false; + } + + return true; +} + int cellAdecQueryAttr(mem_ptr_t type, mem_ptr_t attr) { - cellAdec.Error("cellAdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); + cellAdec.Warning("cellAdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); + + if (!type.IsGood() || !attr.IsGood()) + { + return CELL_ADEC_ERROR_FATAL; + } + + if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; + + // TODO: check values + attr->adecVerLower = 0x280000; // from dmux + attr->adecVerUpper = 0x260000; + attr->workMemSize = 4 * 1024 * 1024; + return CELL_OK; } int cellAdecOpen(mem_ptr_t type, mem_ptr_t res, mem_ptr_t cb, mem32_t handle) { - cellAdec.Error("cellAdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", + cellAdec.Warning("cellAdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr()); + + if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood()) + { + return CELL_ADEC_ERROR_FATAL; + } + + if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; + + handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + return CELL_OK; } int cellAdecOpenEx(mem_ptr_t type, mem_ptr_t res, mem_ptr_t cb, mem32_t handle) { - cellAdec.Error("cellAdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", + cellAdec.Warning("cellAdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", type.GetAddr(), res.GetAddr(), cb.GetAddr(), handle.GetAddr()); + + if (!type.IsGood() || !res.IsGood() || !cb.IsGood() || !handle.IsGood()) + { + return CELL_ADEC_ERROR_FATAL; + } + + if (!adecCheckType(type->audioCodecType)) return CELL_ADEC_ERROR_ARG; + + handle = adecOpen(new AudioDecoder(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg)); + return CELL_OK; } int cellAdecClose(u32 handle) { - cellAdec.Error("cellAdecClose(handle=0x%x)", handle); + cellAdec.Warning("cellAdecClose(handle=%d)", handle); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + adec->job.Push(AdecTask(adecClose)); + + while (!adec->is_finished || !adec->frames.IsEmpty()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("cellAdecClose(%d) aborted", handle); + break; + } + Sleep(1); + } + + Emu.GetIdManager().RemoveID(handle); return CELL_OK; } int cellAdecStartSeq(u32 handle, u32 param_addr) { - cellAdec.Error("cellAdecStartSeq(handle=0x%x, param_addr=0x%x)", handle, param_addr); + cellAdec.Error("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); return CELL_OK; } int cellAdecEndSeq(u32 handle) { - cellAdec.Error("cellAdecEndSeq(handle=0x%x)", handle); + cellAdec.Error("cellAdecEndSeq(handle=%d)", handle); return CELL_OK; } int cellAdecDecodeAu(u32 handle, mem_ptr_t auInfo) { - cellAdec.Error("cellAdecDecodeAu(handle=0x%x, auInfo_addr=0x%x)", handle, auInfo.GetAddr()); + cellAdec.Error("cellAdecDecodeAu(handle=%d, auInfo_addr=0x%x)", handle, auInfo.GetAddr()); return CELL_OK; } int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) { - cellAdec.Error("cellAdecGetPcm(handle=0x%x, outBuffer_addr=0x%x)", handle, outBuffer_addr); + cellAdec.Error("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer_addr); return CELL_OK; } int cellAdecGetPcmItem(u32 handle, u32 pcmItem_ptr_addr) { - cellAdec.Error("cellAdecGetPcmItem(handle=0x%x, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr_addr); + cellAdec.Error("cellAdecGetPcmItem(handle=%d, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr_addr); return CELL_OK; } @@ -73,4 +235,7 @@ void cellAdec_init() cellAdec.AddFunc(0x1529e506, cellAdecDecodeAu); cellAdec.AddFunc(0x97ff2af1, cellAdecGetPcm); cellAdec.AddFunc(0xbd75f78b, cellAdecGetPcmItem); + + av_register_all(); + avcodec_register_all(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 2aa17ead21..833042396c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1,5 +1,6 @@ #pragma once -#include "cellPamf.h" + +#include "Utilities/SQueue.h" // Error Codes enum @@ -341,6 +342,17 @@ struct CellAdecResource be_t ppuThreadStackSize; }; +struct CellAdecResourceEx +{ + be_t totalMemSize; + be_t startAddr; + be_t ppuThreadPriority; + be_t ppuThreadStackSize; + be_t spurs_addr; + u8 priority[8]; + be_t maxContention; +}; + // Callback Messages enum CellAdecMsgType { @@ -348,12 +360,14 @@ enum CellAdecMsgType CELL_ADEC_MSG_TYPE_PCMOUT, CELL_ADEC_MSG_TYPE_ERROR, CELL_ADEC_MSG_TYPE_SEQDONE, -}; +}; + +typedef mem_func_ptr_t CellAdecCbMsg; struct CellAdecCb { - be_t> cbFunc; - be_t cbArg_addr; + be_t cbFunc; + be_t cbArg; }; typedef CellCodecTimeStamp CellAdecTimeStamp; @@ -399,17 +413,6 @@ struct CellAdecLpcmInfo be_t outputDataSize; }; -struct CellAdecResourceEx -{ - be_t totalMemSize; - be_t startAddr; - be_t ppuThreadPriority; - be_t ppuThreadStackSize; - be_t spurs_addr; - u8 priority[8]; - be_t maxContention; -}; - // CELP Excitation Mode enum CELP_ExcitationMode { @@ -985,3 +988,67 @@ struct CellAdecMpmcInfo be_t lfePresent; be_t channelCoufiguration; }; + +/* Audio Decoder Thread Classes */ + +enum AdecJobType : u32 +{ + adecStartSeq, + adecEndSeq, + adecDecodeAu, + adecClose, +}; + +struct AdecTask +{ + AdecJobType type; + // ... + + AdecTask(AdecJobType type) + : type(type) + { + } + + AdecTask() + { + } +}; + +struct AdecFrame +{ + // under construction + u64 pts; + u64 userdata; +}; + +class AudioDecoder +{ +public: + SQueue job; + u32 id; + volatile bool is_running; + volatile bool is_finished; + + SQueue frames; + + const AudioCodecType type; + const u32 memAddr; + const u32 memSize; + const u32 cbFunc; + const u32 cbArg; + + AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) + : type(type) + , memAddr(addr) + , memSize(size) + , cbFunc(func) + , cbArg(arg) + , is_running(false) + , is_finished(false) + { + } + + ~AudioDecoder() + { + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index aadfaf1a85..4e1afc2923 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 attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x600000; // 0x45fa49 from ps3 + attr->memSize = 0x6000000; // 0x45fa49 from ps3 else attr->memSize = 0x10000; // 0x73d9 from ps3 @@ -159,7 +159,7 @@ u32 dmuxOpen(Demuxer* data) if (pes.new_au) { - ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + //ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); } if (es.isfull()) @@ -167,8 +167,10 @@ u32 dmuxOpen(Demuxer* data) stream = backup; continue; } - //stream = backup; - es.push(stream, len - pes.size - 3, pes); + + //hack: reconstruction of MPEG2-PS stream for vdec module (seems it works without it too) + stream = backup; + es.push(stream, len + 6 /*- pes.size - 3*/, pes); } else { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 51e805ab07..cd417b5915 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -373,7 +373,7 @@ struct PesHeader , dts(0xffffffffffffffff) , ch(0) , size(0) - , new_au(true) + , new_au(false) { u16 header; stream.get(header); diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index c0dd39dcfe..6333851bd1 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -19,22 +19,54 @@ int vdecRead(void* opaque, u8* buf, int buf_size) { VideoDecoder& vdec = *(VideoDecoder*)opaque; - if (vdec.reader.size < (u32)buf_size) buf_size = vdec.reader.size; + int res = 0; + + /*if (vdec.reader.header_size) + { + assert(vdec.reader.header_size == 14); + res = buf_size; + if (vdec.reader.header_size < (u32)buf_size) + res = vdec.reader.header_size; + + buf[0] = 0; + buf[1] = 0; + buf[2] = 1; + buf[3] = 0xba; + buf[4] = 0x44; + buf[5] = 0; + buf[6] = 0x07; + buf[7] = 0xaa; + buf[8] = 0x75; + buf[9] = 0xb1; + buf[10] = 0x07; + buf[11] = 0x53; + buf[12] = 0x03; + buf[13] = 0xf8; + vdec.reader.header_size -= res; + buf_size -= res; + buf += res; + }*/ + + if (vdec.reader.size < (u32)buf_size) + { + buf_size = vdec.reader.size; + } + if (!buf_size) { - return AVERROR_EOF; + return res; } else if (!Memory.CopyToReal(buf, vdec.reader.addr, buf_size)) { ConLog.Error("vdecRead: data reading failed (buf_size=0x%x)", buf_size); Emu.Pause(); - return 0; + return res; } else { vdec.reader.addr += buf_size; vdec.reader.size -= buf_size; - return buf_size; + return res + buf_size; } } @@ -79,12 +111,11 @@ u32 vdecOpen(VideoDecoder* data) if (vdec.job.IsEmpty() && vdec.is_running) { - // TODO: default task (not needed?) Sleep(1); continue; } - if (vdec.has_picture) // hack + if (vdec.frames.GetCount() >= 50) { Sleep(1); continue; @@ -100,55 +131,34 @@ u32 vdecOpen(VideoDecoder* data) case vdecStartSeq: { // TODO: reset data - ConLog.Warning("vdecStartSeq()"); + ConLog.Warning("vdecStartSeq:"); + + vdec.reader.addr = 0; + vdec.reader.size = 0; vdec.is_running = true; + vdec.just_started = true; } break; case vdecEndSeq: { + ConLog.Warning("vdecEndSeq:"); + Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, 0, vdec.cbArg); - cb.Branch(false); - ConLog.Warning("vdecEndSeq()"); + cb.Branch(true); // ??? + + avcodec_close(vdec.ctx); + avformat_close_input(&vdec.fmt); + vdec.is_running = false; } break; case vdecDecodeAu: { - struct vdecPacket : AVPacket - { - vdecPacket(u32 size) - { - av_init_packet(this); - data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); - memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - this->size = size + FF_INPUT_BUFFER_PADDING_SIZE; - } - - ~vdecPacket() - { - av_free(data); - //av_free_packet(this); - } - - } au(task.size); - - if ((task.pts || task.dts) && task.pts != ~0 && task.dts != ~0) - { - vdec.pts = task.pts; - vdec.dts = task.dts; - au.pts = vdec.pts; - au.dts = vdec.dts; - au.flags = AV_PKT_FLAG_KEY; - } - else - { - au.pts = vdec.pts; - au.dts = vdec.dts; - } + int err; if (task.mode != CELL_VDEC_DEC_MODE_NORMAL) { @@ -159,11 +169,34 @@ u32 vdecOpen(VideoDecoder* data) vdec.reader.addr = task.addr; vdec.reader.size = task.size; - if (!Memory.CopyToReal(au.data, task.addr, task.size)) + u64 last_pts = task.pts, last_dts = task.dts; + + struct AVPacketHolder : AVPacket { - ConLog.Error("vdecDecodeAu: AU data accessing failed(addr=0x%x, size=0x%x)", task.addr, task.size); - break; - } + AVPacketHolder(u32 size) + { + av_init_packet(this); + + if (size) + { + data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + this->size = size + FF_INPUT_BUFFER_PADDING_SIZE; + } + else + { + data = NULL; + size = 0; + } + } + + ~AVPacketHolder() + { + av_free(data); + //av_free_packet(this); + } + + } au(0); /*{ wxFile dump; @@ -172,54 +205,108 @@ u32 vdecOpen(VideoDecoder* data) dump.Close(); }*/ - int got_picture = 0; - - //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED; - //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS; - vdec.ctx->flags2 |= CODEC_FLAG2_LOCAL_HEADER; - vdec.ctx->codec_tag = *(u32*)"DAVC"; - //vdec.ctx->stream_codec_tag = *(u32*)"DAVC"; - - //avcodec_get_frame_defaults(vdec.frame); - - - int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au); - if (decode < 0) + if (vdec.just_started) // deferred initialization { - ConLog.Error("vdecDecodeAu: AU decoding error(%d)", decode); - break; - } - - if (got_picture) - { - ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, vdec.pts, vdec.dts); - - /*if (vdec.out_data[0]) av_freep(vdec.out_data[0]); - - int err = av_image_alloc(vdec.out_data, vdec.linesize, vdec.ctx->width, vdec.ctx->height, vdec.ctx->pix_fmt, 1); - if (err < 0) + err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); + if (err) { - ConLog.Error("vdecDecodeAu: av_image_alloc failed(%d)", err); + ConLog.Error("vdecDecodeAu: avformat_open_input() failed"); Emu.Pause(); return; } + err = avformat_find_stream_info(vdec.fmt, NULL); + if (err) + { + ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed"); + Emu.Pause(); + return; + } + if (!vdec.fmt->nb_streams) + { + ConLog.Error("vdecDecodeAu: no stream found"); + Emu.Pause(); + return; + } + vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data - vdec.buf_size = err; + AVCodec* codec = avcodec_find_decoder(vdec.ctx->codec_id); // ??? + if (!codec) + { + ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed"); + Emu.Pause(); + return; + } - av_image_copy(vdec.out_data, vdec.linesize, (const u8**)(vdec.frame->data), vdec.frame->linesize, - vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height);*/ - vdec.buf_size = a128(av_image_get_buffer_size(vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height, 1)); - - vdec.userdata = task.userData; - vdec.has_picture = true; - - Callback cb; - cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg); - cb.Branch(false); + { + static SMutexGeneral g_mutex_avcodec_open2; + SMutexGeneralLocker lock(g_mutex_avcodec_open2); + // not multithread-safe + err = avcodec_open2(vdec.ctx, codec, &vdec.opts); + } + if (err) + { + ConLog.Error("vdecDecodeAu: avcodec_open2() failed"); + Emu.Pause(); + return; + } + vdec.just_started = false; } - - ConLog.Write("Frame decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, result=0x%x)", au.pts, au.dts, task.addr, decode); + + while (av_read_frame(vdec.fmt, &au) >= 0) + { + struct VdecFrameHolder : VdecFrame + { + VdecFrameHolder() + { + data = av_frame_alloc(); + } + + ~VdecFrameHolder() + { + if (data) + { + av_frame_unref(data); + av_frame_free(&data); + } + } + + } frame; + + if (!frame.data) + { + ConLog.Error("vdecDecodeAu: av_frame_alloc() failed"); + Emu.Pause(); + return; + } + + int got_picture = 0; + + int decode = avcodec_decode_video2(vdec.ctx, frame.data, &got_picture, &au); + + if (decode < 0) + { + ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode); + break; + } + + if (got_picture) + { + ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts); + + frame.dts = last_dts; last_dts += 3003; // + duration??? + frame.pts = last_pts; last_pts += 3003; + frame.userdata = task.userData; + vdec.frames.Push(frame); + frame.data = nullptr; // to prevent destruction + + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg); + cb.Branch(false); + } + } + + ConLog.Write("AU decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, size=0x%x)", task.pts, task.dts, task.addr, task.size); Callback cb; cb.SetAddr(vdec.cbFunc); @@ -331,7 +418,7 @@ int cellVdecClose(u32 handle) vdec->job.Push(VdecTask(vdecClose)); - while (!vdec->is_finished) + while (!vdec->is_finished || !vdec->frames.IsEmpty()) { if (Emu.IsStopped()) { @@ -361,7 +448,7 @@ int cellVdecStartSeq(u32 handle) int cellVdecEndSeq(u32 handle) { - cellVdec.Log("cellVdecEndSeq(handle=%d)", handle); + cellVdec.Warning("cellVdecEndSeq(handle=%d)", handle); VideoDecoder* vdec; if (!Emu.GetIdManager().GetIDData(handle, vdec)) @@ -369,6 +456,28 @@ int cellVdecEndSeq(u32 handle) return CELL_VDEC_ERROR_ARG; } + /*if (!vdec->job.IsEmpty()) + { + Sleep(1); + return CELL_VDEC_ERROR_BUSY; // ??? + } + + if (!vdec->frames.IsEmpty()) + { + Sleep(1); + return CELL_VDEC_ERROR_BUSY; // ??? + }*/ + + while (!vdec->job.IsEmpty() || !vdec->frames.IsEmpty()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("cellVdecEndSeq(%d) aborted", handle); + return CELL_OK; + } + Sleep(1); + } + vdec->job.Push(VdecTask(vdecEndSeq)); return CELL_OK; } @@ -399,7 +508,7 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t format, u32 out_addr) { - cellVdec.Warning("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); + cellVdec.Log("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); VideoDecoder* vdec; if (!Emu.GetIdManager().GetIDData(handle, vdec)) @@ -412,14 +521,16 @@ int cellVdecGetPicture(u32 handle, const mem_ptr_t format, u3 return CELL_VDEC_ERROR_FATAL; } - if (!vdec->has_picture) + if (vdec->frames.IsEmpty()) { return CELL_VDEC_ERROR_EMPTY; } if (out_addr) { - if (!Memory.IsGoodAddr(out_addr, vdec->buf_size)) + u32 buf_size = a128(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1)); + + if (!Memory.IsGoodAddr(out_addr, buf_size)) { return CELL_VDEC_ERROR_FATAL; } @@ -429,54 +540,47 @@ int cellVdecGetPicture(u32 handle, const mem_ptr_t format, u3 cellVdec.Error("cellVdecGetPicture: TODO: unknown formatType(%d)", (u32)format->formatType); return CELL_OK; } + if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709) { cellVdec.Error("cellVdecGetPicture: TODO: unknown colorMatrixType(%d)", (u32)format->colorMatrixType); return CELL_OK; } - AVFrame& frame = *vdec->frame; + VdecFrame vf; - u8* buf = (u8*)malloc(vdec->buf_size); - if (!buf) - { - cellVdec.Error("cellVdecGetPicture: malloc failed (out of memory)"); - Emu.Pause(); - return CELL_OK; - } + vdec->frames.Pop(vf); + + AVFrame& frame = *vf.data; + + u8* buf = (u8*)malloc(buf_size); // TODO: zero padding bytes - int err = av_image_copy_to_buffer(buf, vdec->buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1); + int err = av_image_copy_to_buffer(buf, buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1); if (err < 0) { cellVdec.Error("cellVdecGetPicture: av_image_copy_to_buffer failed(%d)", err); Emu.Pause(); } - if (!Memory.CopyFromReal(out_addr, buf, vdec->buf_size)) + if (!Memory.CopyFromReal(out_addr, buf, buf_size)) { cellVdec.Error("cellVdecGetPicture: data copying failed"); Emu.Pause(); } - /* - u32 size0 = frame.linesize[0] * frame.height; - u32 size1 = frame.linesize[1] * frame.height / 2; - u32 size2 = frame.linesize[2] * frame.height / 2; - ConLog.Write("*** size0=0x%x, size1=0x%x, size2=0x%x, buf_size=0x%x (res=0x%x)", size0, size1, size2, vdec->buf_size, err); - */ - + av_frame_unref(vf.data); + av_frame_free(&vf.data); free(buf); } - vdec->has_picture = false; return CELL_OK; } int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) { - cellVdec.Warning("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.GetAddr()); + cellVdec.Log("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.GetAddr()); VideoDecoder* vdec; if (!Emu.GetIdManager().GetIDData(handle, vdec)) @@ -489,26 +593,31 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) return CELL_VDEC_ERROR_FATAL; } - if (!vdec->has_picture) + VdecFrame& vf = vdec->frames.Peek(); + + if (vdec->frames.IsEmpty()) { + Sleep(1); return CELL_VDEC_ERROR_EMPTY; } + AVFrame& frame = *vf.data; + mem_ptr_t info(vdec->memAddr); info->codecType = vdec->type; info->startAddr = 0x00000123; // invalid value (no address for picture) - info->size = vdec->buf_size; + info->size = a128(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1)); info->auNum = 1; - info->auPts[0].lower = vdec->pts; - info->auPts[0].upper = vdec->pts >> 32; + info->auPts[0].lower = vf.pts; + info->auPts[0].upper = vf.pts >> 32; info->auPts[1].lower = 0xffffffff; info->auPts[1].upper = 0xffffffff; - info->auDts[0].lower = vdec->dts; - info->auDts[0].upper = vdec->dts >> 32; + info->auDts[0].lower = vf.dts; + info->auDts[0].upper = vf.dts >> 32; info->auDts[1].lower = 0xffffffff; info->auDts[1].upper = 0xffffffff; - info->auUserData[0] = vdec->userdata; + info->auUserData[0] = vf.userdata; info->auUserData[1] = 0; info->status = CELL_OK; info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL; @@ -516,9 +625,9 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) mem_ptr_t avc(vdec->memAddr + sizeof(CellVdecPicItem)); - avc->horizontalSize = vdec->frame->width; // ??? - avc->verticalSize = vdec->frame->height; - switch (vdec->frame->pict_type) + avc->horizontalSize = frame.width; + avc->verticalSize = frame.height; + switch (frame.pict_type) { case AV_PICTURE_TYPE_I: avc->pictureType[0] = CELL_VDEC_AVC_PCT_I; break; case AV_PICTURE_TYPE_P: avc->pictureType[0] = CELL_VDEC_AVC_PCT_P; break; @@ -590,5 +699,6 @@ void cellVdec_init() cellVdec.AddFunc(0x17c702b9, cellVdecGetPicItem); cellVdec.AddFunc(0xe13ef6fc, cellVdecSetFrameRate); + av_register_all(); avcodec_register_all(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index f2ca2320fd..8068b2e8b4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -679,6 +679,14 @@ struct VdecTask } }; +struct VdecFrame +{ + AVFrame* data; + u64 dts; + u64 pts; + u64 userdata; +}; + int vdecRead(void* opaque, u8* buf, int buf_size); class VideoDecoder @@ -688,19 +696,12 @@ public: u32 id; volatile bool is_running; volatile bool is_finished; + bool just_started; - AVCodec* codec; AVCodecContext* ctx; - AVFormatContext* fmt; - AVFrame* frame; AVDictionary* opts; + AVFormatContext* fmt; u8* io_buf; - u32 buf_size; - u64 pts; - u64 dts; - u64 pos; - u64 userdata; - volatile bool has_picture; struct VideoReader { @@ -708,6 +709,8 @@ public: u32 size; } reader; + SQueue frames; + const CellVdecCodecType type; const u32 profile; const u32 memAddr; @@ -724,38 +727,24 @@ public: , cbArg(arg) , is_finished(false) , is_running(false) - , has_picture(false) - , pos(0) + , just_started(false) { - codec = avcodec_find_decoder(AV_CODEC_ID_H264); + opts = nullptr; + av_dict_set(&opts, "refcounted_frames", "1", 0); + AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) { - ConLog.Error("VideoDecoder(): avcodec_find_decoder failed"); + ConLog.Error("vdecDecodeAu: avcodec_find_decoder(H264) failed"); Emu.Pause(); return; } - ctx = avcodec_alloc_context3(codec); + ctx = nullptr; /*avcodec_alloc_context3(codec); if (!ctx) { ConLog.Error("VideoDecoder(): avcodec_alloc_context3 failed"); Emu.Pause(); return; - } - opts = nullptr; - int err = avcodec_open2(ctx, codec, &opts); - if (err) // TODO: not multithread safe - { - ConLog.Error("VideoDecoder(): avcodec_open2 failed(%d)", err); - Emu.Pause(); - return; - } - frame = av_frame_alloc(); - if (!frame) - { - ConLog.Error("VideoDecoder(): av_frame_alloc failed"); - Emu.Pause(); - return; - } + }*/ fmt = avformat_alloc_context(); if (!fmt) { @@ -771,23 +760,32 @@ public: Emu.Pause(); return; } - //memset(&out_data, 0, sizeof(out_data)); - //memset(&linesize, 0, sizeof(linesize)); } ~VideoDecoder() { - if (io_buf) av_free(io_buf); + if (!is_finished && ctx) + { + for (u32 i = frames.GetCount() - 1; ~i; i--) + { + VdecFrame& vf = frames.Peek(i); + av_frame_unref(vf.data); + av_frame_free(&vf.data); + } + } + if (io_buf) + { + av_free(io_buf); + } if (fmt) { + if (fmt->pb) av_free(fmt->pb); avformat_free_context(fmt); } - if (frame) av_frame_free(&frame); - if (ctx) + if (!is_finished && ctx) { - avcodec_close(ctx); - av_free(ctx); + //avcodec_close(ctx); // crashes + //avformat_close_input(&fmt); } - //if (out_data[0]) av_freep(out_data[0]); } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 8073080424..586fa349d4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -139,31 +139,34 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_treserved1 = 0; picInfo->reserved2 = 0; - u8* pY = (u8*)malloc(w*h); + u8* pY = (u8*)malloc(w*h); // color planes u8* pU = (u8*)malloc(w*h/4); u8* pV = (u8*)malloc(w*h/4); - u32* res = (u32*)malloc(w*h*4); + u32* res = (u32*)malloc(w*h*4); // RGBA interleaved output const u8 alpha = ctrlParam->outAlpha; if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h)) { cellVpost.Error("cellVpostExec: data copying failed(pY)"); + Emu.Pause(); } if (!Memory.CopyToReal(pU, inPicBuff_addr + w*h, w*h/4)) { cellVpost.Error("cellVpostExec: data copying failed(pU)"); + Emu.Pause(); } if (!Memory.CopyToReal(pV, inPicBuff_addr + w*h + w*h/4, w*h/4)) { cellVpost.Error("cellVpostExec: data copying failed(pV)"); + Emu.Pause(); } for (u32 i = 0; i < h; i++) for (u32 j = 0; j < w; j++) { - float Cr = pV[(i/2)*(w/2)+j/2]; - float Cb = pU[(i/2)*(w/2)+j/2]; + float Cr = pV[(i/2)*(w/2)+j/2] - 128; + float Cb = pU[(i/2)*(w/2)+j/2] - 128; float Y = pY[i*w+j]; int R = Y + 1.5701f * Cr; From 8a4c67deab3e3887fd2c33cdc3e4d6eefbf1db0c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 4 Mar 2014 03:21:34 +0400 Subject: [PATCH 2/7] It can play video, but it can't I don't know how to disable aggressive data caching that occures in vdecRead(). Also ReleaseAu function is disabled because it breaks everything. --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 361 ++++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 77 ++++- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 62 +++- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 69 +++-- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 159 ++++++---- rpcs3/Emu/SysCalls/Modules/cellVdec.h | 35 +-- rpcs3/Emu/SysCalls/Modules/cellVpost.cpp | 2 +- 7 files changed, 630 insertions(+), 135 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index ebff0e2de6..d784a9524d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -3,6 +3,8 @@ #include "Emu/SysCalls/SC_FUNC.h" #include "cellPamf.h" +extern SMutexGeneral g_mutex_avcodec_open2; + extern "C" { #include "libavcodec\avcodec.h" @@ -14,6 +16,33 @@ extern "C" void cellAdec_init(); Module cellAdec(0x0006, cellAdec_init); +int adecRead(void* opaque, u8* buf, int buf_size) +{ + AudioDecoder& adec = *(AudioDecoder*)opaque; + + if (adec.reader.size < (u32)buf_size) + { + buf_size = adec.reader.size; + } + + if (!buf_size) + { + return 0; + } + else if (!Memory.CopyToReal(buf, adec.reader.addr, buf_size)) + { + ConLog.Error("adecRead: data reading failed (buf_size=0x%x)", buf_size); + Emu.Pause(); + return 0; + } + else + { + adec.reader.addr += buf_size; + adec.reader.size -= buf_size; + return 0 + buf_size; + } +} + u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; @@ -56,16 +85,205 @@ u32 adecOpen(AudioDecoder* data) { case adecStartSeq: { + // TODO: reset data + ConLog.Warning("adecStartSeq:"); + + adec.reader.addr = 0; + adec.reader.size = 0; + adec.is_running = true; + adec.just_started = true; } break; case adecEndSeq: { + // TODO: finalize + ConLog.Warning("adecEndSeq:"); + + Callback cb; + cb.SetAddr(adec.cbFunc); + cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); + cb.Branch(true); // ??? + + avcodec_close(adec.ctx); + avformat_close_input(&adec.fmt); + + adec.is_running = false; } break; case adecDecodeAu: { + int err; + + adec.reader.addr = task.au.addr; + adec.reader.size = task.au.size; + + u64 last_pts = task.au.pts; + + struct AVPacketHolder : AVPacket + { + AVPacketHolder(u32 size) + { + av_init_packet(this); + + if (size) + { + data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + this->size = size + FF_INPUT_BUFFER_PADDING_SIZE; + } + else + { + data = NULL; + size = 0; + } + } + + ~AVPacketHolder() + { + av_free(data); + //av_free_packet(this); + } + + } au(0); + + /*{ + wxFile dump; + dump.Open(wxString::Format("audio pts-0x%llx.dump", task.au.pts), wxFile::write); + u8* buf = (u8*)malloc(task.au.size); + 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 + { + err = avformat_open_input(&adec.fmt, NULL, NULL, NULL); + if (err) + { + ConLog.Error("adecDecodeAu: avformat_open_input() failed"); + Emu.Pause(); + break; + } + err = avformat_find_stream_info(adec.fmt, NULL); + if (err) + { + ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed"); + Emu.Pause(); + break; + } + if (!adec.fmt->nb_streams) + { + ConLog.Error("adecDecodeAu: no stream found"); + Emu.Pause(); + 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; + av_dict_set(&opts, "refcounted_frames", "1", 0); + { + SMutexGeneralLocker lock(g_mutex_avcodec_open2); + // not multithread-safe + err = avcodec_open2(adec.ctx, codec, &opts); + } + if (err) + { + ConLog.Error("adecDecodeAu: avcodec_open2() failed"); + Emu.Pause(); + break; + } + adec.just_started = false; + } + + while (av_read_frame(adec.fmt, &au) >= 0)*/ while (true) + { + if (!adec.ctx) // fake + { + AdecFrame frame; + frame.pts = task.au.pts; + frame.auAddr = task.au.addr; + frame.auSize = task.au.size; + frame.userdata = task.au.userdata; + frame.size = 2048; + 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); + + break; + } + + struct VdecFrameHolder : AdecFrame + { + VdecFrameHolder() + { + data = av_frame_alloc(); + } + + ~VdecFrameHolder() + { + if (data) + { + av_frame_unref(data); + av_frame_free(&data); + } + } + + } frame; + + if (!frame.data) + { + ConLog.Error("adecDecodeAu: av_frame_alloc() failed"); + Emu.Pause(); + break; + } + + int got_frame = 0; + + int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au); + + if (decode < 0) + { + ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode); + break; + } + + if (got_frame) + { + ConLog.Write("got_frame (%d, vdec: pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts); + + frame.pts = task.au.pts; // ??? + frame.auAddr = task.au.addr; + frame.auSize = task.au.size; + frame.userdata = task.au.userdata; + frame.size = 32768; // ???? + adec.frames.Push(frame); + frame.data = nullptr; // to prevent destruction + + Callback cb; + cb.SetAddr(adec.cbFunc); + cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); + cb.Branch(false); + } + } + + Callback cb; + cb.SetAddr(adec.cbFunc); + cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); + cb.Branch(false); } break; @@ -78,9 +296,9 @@ u32 adecOpen(AudioDecoder* data) default: ConLog.Error("Audio Decoder error: unknown task(%d)", task.type); - return; } } + adec.is_finished = true; ConLog.Warning("Audio Decoder aborted"); }); @@ -196,31 +414,158 @@ int cellAdecClose(u32 handle) int cellAdecStartSeq(u32 handle, u32 param_addr) { - cellAdec.Error("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); + cellAdec.Log("cellAdecStartSeq(handle=%d, param_addr=0x%x)", handle, param_addr); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + AdecTask task(adecStartSeq); + /*if (adec->type == CELL_ADEC_TYPE_ATRACX_2CH) + { + + } + else*/ + { + cellAdec.Warning("cellAdecStartSeq: (TODO) initialization"); + } + + adec->job.Push(task); return CELL_OK; } int cellAdecEndSeq(u32 handle) { - cellAdec.Error("cellAdecEndSeq(handle=%d)", handle); + cellAdec.Warning("cellAdecEndSeq(handle=%d)", handle); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + adec->job.Push(AdecTask(adecEndSeq)); return CELL_OK; } int cellAdecDecodeAu(u32 handle, mem_ptr_t auInfo) { - cellAdec.Error("cellAdecDecodeAu(handle=%d, auInfo_addr=0x%x)", handle, auInfo.GetAddr()); + cellAdec.Log("cellAdecDecodeAu(handle=%d, auInfo_addr=0x%x)", handle, auInfo.GetAddr()); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + if (!auInfo.IsGood()) + { + return CELL_ADEC_ERROR_FATAL; + } + + AdecTask task(adecDecodeAu); + task.au.auInfo_addr = auInfo.GetAddr(); + task.au.addr = auInfo->startAddr; + task.au.size = auInfo->size; + task.au.pts = ((u64)auInfo->pts.upper << 32) | (u64)auInfo->pts.lower; + task.au.userdata = auInfo->userData; + + adec->job.Push(task); return CELL_OK; } int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) { - cellAdec.Error("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer_addr); - return CELL_OK; + cellAdec.Log("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer_addr); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + if (adec->frames.IsEmpty()) + { + return CELL_ADEC_ERROR_EMPTY; + } + + AdecFrame af; + adec->frames.Pop(af); + //AVFrame& frame = *af.data; + + int result = CELL_OK; + + if (!Memory.IsGoodAddr(outBuffer_addr, af.size)) + { + result = CELL_ADEC_ERROR_FATAL; + } + else + { + // copy data + if (!af.data) // fake: empty data + { + return CELL_OK; + } + } + + if (af.data) + { + av_frame_unref(af.data); + av_frame_free(&af.data); + } + return result; } -int cellAdecGetPcmItem(u32 handle, u32 pcmItem_ptr_addr) +int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) { - cellAdec.Error("cellAdecGetPcmItem(handle=%d, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr_addr); + cellAdec.Log("cellAdecGetPcmItem(handle=%d, pcmItem_ptr_addr=0x%x)", handle, pcmItem_ptr.GetAddr()); + + AudioDecoder* adec; + if (!Emu.GetIdManager().GetIDData(handle, adec)) + { + return CELL_ADEC_ERROR_ARG; + } + + if (!pcmItem_ptr.IsGood()) + { + return CELL_ADEC_ERROR_FATAL; + } + + AdecFrame& af = adec->frames.Peek(); + + if (adec->frames.IsEmpty()) + { + return CELL_ADEC_ERROR_EMPTY; + } + + //AVFrame& frame = *af.data; + + mem_ptr_t pcm(adec->memAddr + adec->memBias); + + adec->memBias += 512; + if (adec->memBias + 512 > adec->memSize) + adec->memBias = 0; + + pcm->pcmHandle = 0; // ??? + pcm->pcmAttr.bsiInfo_addr = pcm.GetAddr() + sizeof(CellAdecPcmItem); + pcm->startAddr = 0x00000312; // invalid address (no output) + pcm->size = af.size; + pcm->status = CELL_OK; + pcm->auInfo.pts.lower = af.pts; // ??? + pcm->auInfo.pts.upper = af.pts >> 32; + pcm->auInfo.size = af.auSize; + pcm->auInfo.startAddr = af.auAddr; + pcm->auInfo.userData = af.userdata; + + mem_ptr_t atx(pcm.GetAddr() + sizeof(CellAdecPcmItem)); + atx->samplingFreq = 48000; // ??? + atx->nbytes = 2048; // ??? + atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? + + pcmItem_ptr = pcm.GetAddr(); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 833042396c..50ace2eb07 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1002,7 +1002,17 @@ enum AdecJobType : u32 struct AdecTask { AdecJobType type; - // ... + union + { + struct + { + u32 auInfo_addr; + u32 addr; + u32 size; + u64 pts; + u64 userdata; + } au; + }; AdecTask(AdecJobType type) : type(type) @@ -1016,11 +1026,16 @@ struct AdecTask struct AdecFrame { - // under construction + AVFrame* data; u64 pts; u64 userdata; + u32 auAddr; + u32 auSize; + u32 size; }; +int adecRead(void* opaque, u8* buf, int buf_size); + class AudioDecoder { public: @@ -1028,6 +1043,17 @@ public: u32 id; volatile bool is_running; volatile bool is_finished; + bool just_started; + + AVCodecContext* ctx; + AVFormatContext* fmt; + u8* io_buf; + + struct AudioReader + { + u32 addr; + u32 size; + } reader; SQueue frames; @@ -1036,19 +1062,66 @@ public: const u32 memSize; const u32 cbFunc; const u32 cbArg; + u32 memBias; AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) : type(type) , memAddr(addr) , memSize(size) + , memBias(0) , cbFunc(func) , cbArg(arg) , is_running(false) , is_finished(false) + , just_started(false) + , ctx(nullptr) + , fmt(nullptr) { + AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); + if (!codec) + { + ConLog.Error("AudioDecoder(): avcodec_find_decoder(ATRAC3P) failed"); + Emu.Pause(); + return; + } + fmt = avformat_alloc_context(); + if (!fmt) + { + ConLog.Error("AudioDecoder(): avformat_alloc_context failed"); + Emu.Pause(); + return; + } + io_buf = (u8*)av_malloc(4096); + fmt->pb = avio_alloc_context(io_buf, 4096, 0, this, adecRead, NULL, NULL); + if (!fmt->pb) + { + ConLog.Error("AudioDecoder(): avio_alloc_context failed"); + Emu.Pause(); + return; + } } ~AudioDecoder() { + if (ctx) + { + for (u32 i = frames.GetCount() - 1; ~i; i--) + { + AdecFrame& af = frames.Peek(i); + av_frame_unref(af.data); + av_frame_free(&af.data); + } + avcodec_close(ctx); + avformat_close_input(&fmt); + } + if (fmt) + { + if (io_buf) + { + av_free(io_buf); + } + if (fmt->pb) av_free(fmt->pb); + avformat_free_context(fmt); + } } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 4e1afc2923..326f2923c9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x6000000; // 0x45fa49 from ps3 + attr->memSize = 0x2000000; // 0x45fa49 from ps3 else - attr->memSize = 0x10000; // 0x73d9 from ps3 + attr->memSize = 0x400000; // 0x73d9 from ps3 cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); @@ -102,12 +102,51 @@ u32 dmuxOpen(Demuxer* data) case PRIVATE_STREAM_1: { + DemuxerStream backup = stream; + // audio AT3+ (and probably LPCM or user data) stream.skip(4); stream.get(len); - // skipping... - stream.skip(len); + PesHeader pes(stream); + + if (!pes.new_au) // temporarily + { + ConLog.Error("No pts info found"); + } + + // read additional header: + stream.peek(ch); + //stream.skip(4); + //pes.size += 4; + + if (esATX[ch]) + { + ElementaryStream& es = *esATX[ch]; + if (es.isfull()) + { + stream = backup; + Sleep(1); + continue; + } + + //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + + es.push(stream, len - pes.size - 3, pes); + es.finish(stream); + + mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); + esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; + esMsg->supplementalInfo = stream.userdata; + Callback cb; + cb.SetAddr(es.cbFunc); + cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); + cb.Branch(false); + } + else + { + stream.skip(len - pes.size - 3); + } } break; @@ -133,12 +172,6 @@ u32 dmuxOpen(Demuxer* data) stream.get(len); PesHeader pes(stream); - if (!pes.new_au && !es.hasdata()) // fatal error - { - ConLog.Error("PES not found"); - return; - } - if (pes.new_au && es.hasdata()) // new AU detected { if (es.hasunseen()) // hack, probably useless @@ -285,6 +318,13 @@ task: { esAVC[es.fidMajor - 0xe0] = task.es.es_ptr; } + else if (es.fidMajor == 0xbd && + es.fidMinor == 0 && + es.sup1 == 0 && + es.sup2 == 0) + { + esATX[0] = task.es.es_ptr; + } else { ConLog.Warning("dmuxEnableEs: (TODO) unsupported filter (0x%x, 0x%x, 0x%x, 0x%x)", es.fidMajor, es.fidMinor, es.sup1, es.sup2); @@ -853,7 +893,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ int cellDmuxReleaseAu(u32 esHandle) { - cellDmux.Warning("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle); + cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index cd417b5915..d03b4e7e00 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -329,11 +329,11 @@ struct DemuxerStream } template - bool peek(T& out) + bool peek(T& out, u32 shift = 0) { - if (sizeof(T) > size) return false; + if (sizeof(T) + shift > size) return false; - out = *(T*)Memory.VirtualToRealAddr(addr); + out = *(T*)Memory.VirtualToRealAddr(addr + shift); return true; } @@ -364,14 +364,12 @@ struct PesHeader { u64 pts; u64 dts; - u8 ch; u8 size; bool new_au; PesHeader(DemuxerStream& stream) : pts(0xffffffffffffffff) , dts(0xffffffffffffffff) - , ch(0) , size(0) , new_au(false) { @@ -380,29 +378,40 @@ struct PesHeader stream.get(size); if (size) { - //ConLog.Write(">>>>> Pes Header (size=%d)", size); - if (size < 10) - { - stream.skip(size); - return; - } - new_au = true; + u8 empty = 0; u8 v; - stream.get(v); - if ((v & 0xF0) != 0x30) + while (true) { - ConLog.Error("Pts not found"); - Emu.Pause(); - } - pts = stream.get_ts(v); - stream.get(v); - if ((v & 0xF0) != 0x10) + stream.get(v); + if (v != 0xFF) break; // skip padding bytes + empty++; + if (empty = size) return; + }; + + if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only { - ConLog.Error("Dts not found"); - Emu.Pause(); + new_au = true; + pts = stream.get_ts(v); + stream.skip(size - empty - 5); + } + else + { + new_au = true; + if ((v & 0xF0) != 0x30 || (size - empty) < 10) + { + ConLog.Error("PesHeader(): pts not found"); + Emu.Pause(); + } + pts = stream.get_ts(v); + stream.get(v); + if ((v & 0xF0) != 0x10) + { + ConLog.Error("PesHeader(): dts not found"); + Emu.Pause(); + } + dts = stream.get_ts(v); + stream.skip(size - empty - 10); } - dts = stream.get_ts(v); - stream.skip(size - 10); } } }; @@ -497,8 +506,8 @@ public: ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, u32 cbFunc, u32 cbArg, u32 spec) : dmux(dmux) - , memAddr(addr) - , memSize(size) + , memAddr(a128(addr)) + , memSize(size - (addr - memAddr)) , fidMajor(fidMajor) , fidMinor(fidMinor) , sup1(sup1) @@ -508,7 +517,7 @@ public: , spec(spec) , first_addr(0) , peek_addr(0) - , last_addr(a128(addr)) + , last_addr(memAddr) , last_size(0) { } @@ -590,7 +599,7 @@ public: mem_ptr_t info(last_addr); info->auAddr = last_addr + 128; info->auSize = last_size; - if (pes.size) + if (pes.new_au) { info->dts.lower = (u32)pes.dts; info->dts.upper = (u32)(pes.dts >> 32); @@ -607,7 +616,7 @@ public: mem_ptr_t inf(last_addr + 64); inf->auAddr = last_addr + 128; inf->auSize = last_size; - if (pes.size) + if (pes.new_au) { inf->dtsLower = (u32)pes.dts; inf->dtsUpper = (u32)(pes.dts >> 32); @@ -687,7 +696,7 @@ public: SMutexLocker lock(mutex); first_addr = 0; peek_addr = 0; - last_addr = a128(memAddr); + last_addr = memAddr; last_size = 0; } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 6333851bd1..f325f3faa3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -3,6 +3,8 @@ #include "Emu/SysCalls/SC_FUNC.h" #include "cellPamf.h" +SMutexGeneral g_mutex_avcodec_open2; + extern "C" { #include "libavcodec\avcodec.h" @@ -21,35 +23,56 @@ int vdecRead(void* opaque, u8* buf, int buf_size) int res = 0; - /*if (vdec.reader.header_size) - { - assert(vdec.reader.header_size == 14); - res = buf_size; - if (vdec.reader.header_size < (u32)buf_size) - res = vdec.reader.header_size; - - buf[0] = 0; - buf[1] = 0; - buf[2] = 1; - buf[3] = 0xba; - buf[4] = 0x44; - buf[5] = 0; - buf[6] = 0x07; - buf[7] = 0xaa; - buf[8] = 0x75; - buf[9] = 0xb1; - buf[10] = 0x07; - buf[11] = 0x53; - buf[12] = 0x03; - buf[13] = 0xf8; - vdec.reader.header_size -= res; - buf_size -= res; - buf += res; - }*/ - if (vdec.reader.size < (u32)buf_size) { - buf_size = vdec.reader.size; + while (vdec.job.IsEmpty()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("vdecRead() aborted"); + return 0; + } + Sleep(1); + } + + switch (vdec.job.Peek().type) + { + case vdecEndSeq: + { + buf_size = vdec.reader.size; + } + break; + case vdecDecodeAu: + { + if (!Memory.CopyToReal(buf, vdec.reader.addr, vdec.reader.size)) + { + ConLog.Error("vdecRead: data reading failed (reader.size=0x%x)", vdec.reader.size); + Emu.Pause(); + return 0; + } + + buf += vdec.reader.size; + buf_size -= vdec.reader.size; + res += vdec.reader.size; + + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); + cb.Branch(false); + + vdec.job.Pop(vdec.task); + + vdec.reader.addr = vdec.task.addr; + vdec.reader.size = vdec.task.size; + + vdec.last_pts = vdec.task.pts; + vdec.last_dts = vdec.task.dts; + } + break; + default: + ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type); + return 0; + } } if (!buf_size) @@ -60,7 +83,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size) { ConLog.Error("vdecRead: data reading failed (buf_size=0x%x)", buf_size); Emu.Pause(); - return res; + return 0; } else { @@ -100,7 +123,7 @@ u32 vdecOpen(VideoDecoder* data) { ConLog.Write("Video Decoder enter()"); - VdecTask task; + VdecTask& task = vdec.task; while (true) { @@ -142,11 +165,12 @@ u32 vdecOpen(VideoDecoder* data) case vdecEndSeq: { + // TODO: finalize ConLog.Warning("vdecEndSeq:"); Callback cb; cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, 0, vdec.cbArg); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); cb.Branch(true); // ??? avcodec_close(vdec.ctx); @@ -169,7 +193,8 @@ u32 vdecOpen(VideoDecoder* data) vdec.reader.addr = task.addr; vdec.reader.size = task.size; - u64 last_pts = task.pts, last_dts = task.dts; + vdec.last_pts = task.pts; + vdec.last_dts = task.dts; struct AVPacketHolder : AVPacket { @@ -198,13 +223,6 @@ u32 vdecOpen(VideoDecoder* data) } au(0); - /*{ - wxFile dump; - dump.Open(wxString::Format("0x%llx-0x%llx.dump", au.pts, au.dts), wxFile::write); - dump.Write(au.data, task.size + FF_INPUT_BUFFER_PADDING_SIZE); - dump.Close(); - }*/ - if (vdec.just_started) // deferred initialization { err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); @@ -212,20 +230,20 @@ u32 vdecOpen(VideoDecoder* data) { ConLog.Error("vdecDecodeAu: avformat_open_input() failed"); Emu.Pause(); - return; + break; } err = avformat_find_stream_info(vdec.fmt, NULL); if (err) { ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed"); Emu.Pause(); - return; + break; } if (!vdec.fmt->nb_streams) { ConLog.Error("vdecDecodeAu: no stream found"); Emu.Pause(); - return; + break; } vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data @@ -234,26 +252,37 @@ u32 vdecOpen(VideoDecoder* data) { ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed"); Emu.Pause(); - return; + break; } + AVDictionary* opts = nullptr; + av_dict_set(&opts, "refcounted_frames", "1", 0); { - static SMutexGeneral g_mutex_avcodec_open2; SMutexGeneralLocker lock(g_mutex_avcodec_open2); // not multithread-safe - err = avcodec_open2(vdec.ctx, codec, &vdec.opts); + err = avcodec_open2(vdec.ctx, codec, &opts); } if (err) { ConLog.Error("vdecDecodeAu: avcodec_open2() failed"); Emu.Pause(); - return; + break; } vdec.just_started = false; } - while (av_read_frame(vdec.fmt, &au) >= 0) + bool last_frame = false; + + while (true) { + last_frame = av_read_frame(vdec.fmt, &au) < 0; + if (last_frame) + { + av_free(au.data); + au.data = NULL; + au.size = 0; + } + struct VdecFrameHolder : VdecFrame { VdecFrameHolder() @@ -276,41 +305,43 @@ u32 vdecOpen(VideoDecoder* data) { ConLog.Error("vdecDecodeAu: av_frame_alloc() failed"); Emu.Pause(); - return; + break; } int got_picture = 0; int decode = avcodec_decode_video2(vdec.ctx, frame.data, &got_picture, &au); - if (decode < 0) + if (decode <= 0) { - ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode); - break; + 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? } if (got_picture) { - ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts); + //ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts); - frame.dts = last_dts; last_dts += 3003; // + duration??? - frame.pts = last_pts; last_pts += 3003; + frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration??? + frame.pts = vdec.last_pts; vdec.last_pts += 3003; frame.userdata = task.userData; vdec.frames.Push(frame); frame.data = nullptr; // to prevent destruction Callback cb; cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); cb.Branch(false); } } - ConLog.Write("AU decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, size=0x%x)", task.pts, task.dts, task.addr, task.size); - Callback cb; cb.SetAddr(vdec.cbFunc); - cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, 0, vdec.cbArg); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); cb.Branch(false); } break; @@ -325,15 +356,15 @@ u32 vdecOpen(VideoDecoder* data) case vdecSetFrameRate: { ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc); - return; } + break; default: ConLog.Error("Video Decoder error: unknown task(%d)", task.type); - return; } } + vdec.is_finished = true; ConLog.Warning("Video Decoder aborted"); }); @@ -603,7 +634,11 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) AVFrame& frame = *vf.data; - mem_ptr_t info(vdec->memAddr); + mem_ptr_t info(vdec->memAddr + vdec->memBias); + + vdec->memBias += 512; + if (vdec->memBias + 512 > vdec->memSize) + vdec->memBias = 0; info->codecType = vdec->type; info->startAddr = 0x00000123; // invalid value (no address for picture) @@ -621,9 +656,9 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) info->auUserData[1] = 0; info->status = CELL_OK; info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL; - info->picInfo_addr = vdec->memAddr + sizeof(CellVdecPicItem); + info->picInfo_addr = info.GetAddr() + sizeof(CellVdecPicItem); - mem_ptr_t avc(vdec->memAddr + sizeof(CellVdecPicItem)); + mem_ptr_t avc(info.GetAddr() + sizeof(CellVdecPicItem)); avc->horizontalSize = frame.width; avc->verticalSize = frame.height; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 8068b2e8b4..7542607d59 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -699,7 +699,6 @@ public: bool just_started; AVCodecContext* ctx; - AVDictionary* opts; AVFormatContext* fmt; u8* io_buf; @@ -717,34 +716,31 @@ public: const u32 memSize; const u32 cbFunc; const u32 cbArg; + u32 memBias; + + VdecTask task; // reference to current task variable + u64 last_pts, last_dts; VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) : type(type) , profile(profile) , memAddr(addr) , memSize(size) + , memBias(0) , cbFunc(func) , cbArg(arg) , is_finished(false) , is_running(false) , just_started(false) + , ctx(nullptr) { - opts = nullptr; - av_dict_set(&opts, "refcounted_frames", "1", 0); AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) { - ConLog.Error("vdecDecodeAu: avcodec_find_decoder(H264) failed"); + ConLog.Error("VideoDecoder(): avcodec_find_decoder(H264) failed"); Emu.Pause(); return; } - ctx = nullptr; /*avcodec_alloc_context3(codec); - if (!ctx) - { - ConLog.Error("VideoDecoder(): avcodec_alloc_context3 failed"); - Emu.Pause(); - return; - }*/ fmt = avformat_alloc_context(); if (!fmt) { @@ -764,7 +760,7 @@ public: ~VideoDecoder() { - if (!is_finished && ctx) + if (ctx) { for (u32 i = frames.GetCount() - 1; ~i; i--) { @@ -772,20 +768,17 @@ public: av_frame_unref(vf.data); av_frame_free(&vf.data); } - } - if (io_buf) - { - av_free(io_buf); + avcodec_close(ctx); + avformat_close_input(&fmt); } if (fmt) { + if (io_buf) + { + av_free(io_buf); + } if (fmt->pb) av_free(fmt->pb); avformat_free_context(fmt); } - if (!is_finished && ctx) - { - //avcodec_close(ctx); // crashes - //avformat_close_input(&fmt); - } } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 586fa349d4..92ead9c6a4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -77,7 +77,7 @@ int cellVpostClose(u32 handle) int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t ctrlParam, u32 outPicBuff_addr, mem_ptr_t picInfo) { - cellVpost.Warning("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)", + cellVpost.Log("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)", handle, inPicBuff_addr, ctrlParam.GetAddr(), outPicBuff_addr, picInfo.GetAddr()); VpostInstance* vpost; From 384536ba4f122d96873e95c970b6474f25b284bb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 4 Mar 2014 23:18:17 +0400 Subject: [PATCH 3/7] prx_mem memory leak fixed CPUThread::ExecAsCallback (experimental) --- Utilities/SMutex.h | 10 ++++-- rpcs3/Emu/CPU/CPUThread.cpp | 41 +++++++++++++++++++++++++ rpcs3/Emu/CPU/CPUThread.h | 2 ++ rpcs3/Emu/Cell/PPUThread.cpp | 5 +-- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 35 ++++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 3 ++ rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 31 ++++++++++++------- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 2 ++ rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 36 ++++++++++++++++------ rpcs3/Emu/SysCalls/Modules/cellVdec.h | 5 ++- rpcs3/Emu/System.cpp | 2 ++ 11 files changed, 133 insertions(+), 39 deletions(-) diff --git a/Utilities/SMutex.h b/Utilities/SMutex.h index b92d67e614..5aa9a98f07 100644 --- a/Utilities/SMutex.h +++ b/Utilities/SMutex.h @@ -145,15 +145,19 @@ public: { if (!tid) { - ConLog.Error("SMutexLockerBase: thread id == 0"); - Emu.Pause(); + if (!Emu.IsStopped()) + { + ConLog.Error("SMutexLockerBase: thread id == 0"); + Emu.Pause(); + } + return; } sm.lock(tid); } ~SMutexLockerBase() { - sm.unlock(tid); + if (tid) sm.unlock(tid); } }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 2d98e28e4b..e2ce343447 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -360,3 +360,44 @@ void CPUThread::Task() if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str()); } + +int CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe +{ + while (m_alive) + { + if (Emu.IsStopped()) + { + ConLog.Warning("ExecAsCallback() aborted"); + return CELL_ECANCELED; // doesn't mean anything + } + Sleep(1); + } + + Stop(); + Reset(); + + SetEntry(pc); + SetPrio(1001); + SetStackSize(0x10000); + SetExitStatus(CELL_OK); + + SetArg(0, a1); + SetArg(1, a2); + SetArg(2, a3); + SetArg(3, a4); + Run(); + + Exec(); + + while (wait && m_alive) + { + if (Emu.IsStopped()) + { + ConLog.Warning("ExecAsCallback() aborted"); + return CELL_EABORT; // doesn't mean anything + } + Sleep(1); + } + + return wait * m_exit_status; +} \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 88470283bc..4c0e94ed01 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -234,6 +234,8 @@ public: return pc + 4; } + int ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); + protected: virtual void DoReset()=0; virtual void DoRun()=0; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 91dce7d6a8..1c1c903b50 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -118,14 +118,11 @@ void PPUThread::InitRegs() GPR[6] = m_args[3]; } - u32 prx_mem = Memory.PRXMem.AllocAlign(0x10000); - Memory.Write64(prx_mem, 0xDEADBEEFABADCAFE); - GPR[0] = pc; GPR[8] = entry; GPR[11] = 0x80; GPR[12] = Emu.GetMallocPageSize(); - GPR[13] = prx_mem + 0x7060; + GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; GPR[28] = GPR[4]; GPR[29] = GPR[3]; GPR[31] = GPR[5]; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index d784a9524d..d616ce0c82 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -47,6 +47,8 @@ u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; + adec.adecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 adec_id = cellAdec.GetNewId(data); adec.id = adec_id; @@ -70,11 +72,11 @@ u32 adecOpen(AudioDecoder* data) continue; } - if (adec.frames.GetCount() >= 50) + /*if (adec.frames.GetCount() >= 50) { Sleep(1); continue; - } + }*/ if (!adec.job.Pop(task)) { @@ -100,10 +102,11 @@ u32 adecOpen(AudioDecoder* data) // TODO: finalize ConLog.Warning("adecEndSeq:"); - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); - cb.Branch(true); // ??? + cb.Branch(true); // ???*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, true, adec.id, CELL_ADEC_MSG_TYPE_SEQDONE, CELL_OK, adec.cbArg); avcodec_close(adec.ctx); avformat_close_input(&adec.fmt); @@ -214,14 +217,15 @@ u32 adecOpen(AudioDecoder* data) frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; - frame.size = 2048; + frame.size = 4096; frame.data = nullptr; adec.frames.Push(frame); - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; } @@ -273,17 +277,19 @@ u32 adecOpen(AudioDecoder* data) adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); } } - Callback cb; + /*Callback cb; cb.SetAddr(adec.cbFunc); cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, task.au.auInfo_addr, adec.cbArg); } break; @@ -408,6 +414,7 @@ int cellAdecClose(u32 handle) Sleep(1); } + if (adec->adecCb) Emu.GetCPU().RemoveThread(adec->adecCb->GetId()); Emu.GetIdManager().RemoveID(handle); return CELL_OK; } @@ -506,6 +513,10 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) // copy data if (!af.data) // fake: empty data { + u8* buf = (u8*)malloc(4096); + memset(buf, 0, 4096); + Memory.CopyFromReal(outBuffer_addr, buf, 4096); + free(buf); return CELL_OK; } } @@ -546,7 +557,9 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) adec->memBias += 512; if (adec->memBias + 512 > adec->memSize) + { adec->memBias = 0; + } pcm->pcmHandle = 0; // ??? pcm->pcmAttr.bsiInfo_addr = pcm.GetAddr() + sizeof(CellAdecPcmItem); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 50ace2eb07..63b355bc68 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1064,6 +1064,8 @@ public: const u32 cbArg; u32 memBias; + CPUThread* adecCb; + AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) : type(type) , memAddr(addr) @@ -1071,6 +1073,7 @@ public: , memBias(0) , cbFunc(func) , cbArg(arg) + , adecCb(nullptr) , is_running(false) , is_finished(false) , just_started(false) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 326f2923c9..29f3d83424 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -20,7 +20,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_tfilterIdMajor >= 0xe0) attr->memSize = 0x2000000; // 0x45fa49 from ps3 else - attr->memSize = 0x400000; // 0x73d9 from ps3 + attr->memSize = 0x100000; // 0x73d9 from ps3 cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); @@ -30,6 +30,8 @@ u32 dmuxOpen(Demuxer* data) { Demuxer& dmux = *data; + dmux.dmuxCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 dmux_id = cellDmux.GetNewId(data); dmux.id = dmux_id; @@ -138,10 +140,11 @@ u32 dmuxOpen(Demuxer* data) mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } else { @@ -184,10 +187,11 @@ u32 dmuxOpen(Demuxer* data) mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } if (pes.new_au) @@ -292,10 +296,12 @@ task: mem_ptr_t dmuxMsg(a128(dmux.memAddr) + (cb_add ^= 16)); dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(dmux.cbFunc); cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); - cb.Branch(task.type == dmuxResetStreamAndWaitDone); + cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ + dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, task.type == dmuxResetStreamAndWaitDone, + dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); dmux.is_running = false; } break; @@ -370,20 +376,22 @@ task: mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE; esMsg->supplementalInfo = stream.userdata; - Callback cb; + /*Callback cb; cb.SetAddr(es.cbFunc); cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + dmux.dmuxCb->ExecAsCallback(es.cbFunc, false, dmux.id, es.id, esMsg.GetAddr(), es.cbArg); } break; @@ -549,6 +557,7 @@ int cellDmuxClose(u32 demuxerHandle) Sleep(1); } + if (dmux->dmuxCb) Emu.GetCPU().RemoveThread(dmux->dmuxCb->GetId()); Emu.GetIdManager().RemoveID(demuxerHandle); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index d03b4e7e00..5da56f721e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -470,6 +470,7 @@ public: volatile bool is_finished; volatile bool is_running; + CPUThread* dmuxCb; Demuxer(u32 addr, u32 size, u32 func, u32 arg) : is_finished(false) @@ -478,6 +479,7 @@ public: , memSize(size) , cbFunc(func) , cbArg(arg) + , dmuxCb(nullptr) { } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index f325f3faa3..daad045b0f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -55,10 +55,11 @@ int vdecRead(void* opaque, u8* buf, int buf_size) buf_size -= vdec.reader.size; res += vdec.reader.size; - Callback cb; + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); vdec.job.Pop(vdec.task); @@ -73,6 +74,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size) ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type); return 0; } + //buf_size = vdec.reader.size; } if (!buf_size) @@ -115,6 +117,8 @@ u32 vdecOpen(VideoDecoder* data) { VideoDecoder& vdec = *data; + vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + u32 vdec_id = cellVdec.GetNewId(data); vdec.id = vdec_id; @@ -168,10 +172,11 @@ u32 vdecOpen(VideoDecoder* data) // TODO: finalize ConLog.Warning("vdecEndSeq:"); - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg); - cb.Branch(true); // ??? + cb.Branch(true); // ???*/ avcodec_close(vdec.ctx); avformat_close_input(&vdec.fmt); @@ -268,6 +273,8 @@ u32 vdecOpen(VideoDecoder* data) Emu.Pause(); break; } + //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED; + //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS; vdec.just_started = false; } @@ -275,9 +282,15 @@ u32 vdecOpen(VideoDecoder* data) while (true) { + if (Emu.IsStopped()) + { + ConLog.Warning("vdecDecodeAu aborted"); + return; + } last_frame = av_read_frame(vdec.fmt, &au) < 0; if (last_frame) { + //break; av_free(au.data); au.data = NULL; au.size = 0; @@ -329,20 +342,22 @@ u32 vdecOpen(VideoDecoder* data) frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration??? frame.pts = vdec.last_pts; vdec.last_pts += 3003; frame.userdata = task.userData; - vdec.frames.Push(frame); + vdec.frames.Push(frame); // !!!!!!!! frame.data = nullptr; // to prevent destruction - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ } } - Callback cb; + vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); + /*Callback cb; cb.SetAddr(vdec.cbFunc); cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg); - cb.Branch(false); + cb.Branch(false);*/ } break; @@ -459,6 +474,7 @@ int cellVdecClose(u32 handle) Sleep(1); } + if (vdec->vdecCb) Emu.GetCPU().RemoveThread(vdec->vdecCb->GetId()); Emu.GetIdManager().RemoveID(handle); return CELL_OK; } @@ -638,7 +654,9 @@ int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) vdec->memBias += 512; if (vdec->memBias + 512 > vdec->memSize) + { vdec->memBias = 0; + } info->codecType = vdec->type; info->startAddr = 0x00000123; // invalid value (no address for picture) diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 7542607d59..96534cdbe2 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -718,9 +718,11 @@ public: const u32 cbArg; u32 memBias; - VdecTask task; // reference to current task variable + VdecTask task; // current task variable u64 last_pts, last_dts; + CPUThread* vdecCb; + VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) : type(type) , profile(profile) @@ -733,6 +735,7 @@ public: , is_running(false) , just_started(false) , ctx(nullptr) + , vdecCb(nullptr) { AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e910413c66..08f356707e 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -267,6 +267,8 @@ void Emulator::Load() ppu_thr_exit_data += ADDI(11, 0, 41); ppu_thr_exit_data += SC(2); ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); + + Memory.Write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); } break; From e86a8496003c622df84b00b4f87488ae2048166c Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 6 Mar 2014 15:40:50 +0400 Subject: [PATCH 4/7] libmixer draft and some hacks --- rpcs3/Emu/Cell/PPUInterpreter.h | 13 +- rpcs3/Emu/SysCalls/Callback.cpp | 4 +- rpcs3/Emu/SysCalls/Modules.cpp | 1 + rpcs3/Emu/SysCalls/Modules.h | 40 +++ rpcs3/Emu/SysCalls/Modules/cellAudio.cpp | 240 +------------- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 65 ++-- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 404 +++++++++++++++++++++++ rpcs3/Emu/SysCalls/Modules/libmixer.h | 63 ++++ rpcs3/Emu/SysCalls/Static.cpp | 63 ++++ rpcs3/Emu/SysCalls/SysCalls.h | 4 + rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 14 +- rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 7 +- rpcs3/Loader/ELF64.cpp | 1 + rpcs3/rpcs3.vcxproj | 2 + rpcs3/rpcs3.vcxproj.filters | 6 + 16 files changed, 662 insertions(+), 269 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/Modules/libmixer.cpp create mode 100644 rpcs3/Emu/SysCalls/Modules/libmixer.h create mode 100644 rpcs3/Emu/SysCalls/Static.cpp diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 8f2e11ba1d..b6dd47706a 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -71,10 +71,16 @@ private: if(Ini.HLELogging.GetValue()) { - ConLog.Warning("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); + ConLog.Warning("SysCall[0x%llx] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); if(CPU.GPR[11] > 1024) SysCalls::DoFunc(CPU.GPR[11]); } + /*else if ((s64)CPU.GPR[3] < 0) // probably, error code + { + ConLog.Error("SysCall[0x%llx] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); + if(CPU.GPR[11] > 1024) + SysCalls::DoFunc(CPU.GPR[11]); + }*/ #ifdef HLE_CALL_DEBUG ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); #endif @@ -2088,6 +2094,11 @@ private: { case 0x1: UNK(wxString::Format("HyperCall %d", CPU.GPR[0])); break; case 0x2: SysCall(); break; + case 0x3: + StaticExecute(CPU.GPR[11]); + ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx", + wxString(g_static_funcs_list[CPU.GPR[11]].name).wx_str(), CPU.GPR[3], CPU.PC); + break; case 0x22: UNK("HyperCall LV1"); break; default: UNK(wxString::Format("Unknown sc: %x", sc_code)); } diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index f64851b6c3..73e7896744 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -53,7 +53,7 @@ void Callback::Branch(bool wait) { m_has_data = false; - static SMutexGeneral cb_mutex; + static std::mutex cb_mutex; CPUThread& thr = Emu.GetCallbackThread(); @@ -69,7 +69,7 @@ again: Sleep(1); } - SMutexGeneralLocker lock(cb_mutex); + std::lock_guard lock(cb_mutex); if (thr.IsAlive()) { diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index bdecfc62b8..07404f49ad 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -8,6 +8,7 @@ uint g_max_module_id = 0; uint g_module_2_count = 0; ArrayF g_modules_funcs_list; std::mutex g_funcs_lock; +ArrayF g_static_funcs_list; struct ModuleInfo { diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index faef27d9b7..165f59a49d 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -25,6 +25,21 @@ struct ModuleFunc } }; +struct SFuncOp +{ + u32 crc; + u32 mask; +}; + +struct SFunc +{ + func_caller* func; + char* name; + Array ops; +}; + +extern ArrayF g_static_funcs_list; + class Module { std::string m_name; @@ -94,6 +109,8 @@ public: } template __forceinline void AddFunc(u32 id, T func); + + template __forceinline void AddFuncSub(const u64 ops[], char* name, T func); }; template @@ -102,6 +119,29 @@ __forceinline void Module::AddFunc(u32 id, T func) m_funcs_list.Move(new ModuleFunc(id, bind_func(func))); } +template +__forceinline void Module::AddFuncSub(const u64 ops[], char* name, T func) +{ + if (!ops[0]) return; + + SFunc* sf = new SFunc; + sf->func = bind_func(func); + sf->name = name; + + // TODO: check for self-inclusions, use CRC + + for (u32 i = 0; ops[i]; i++) + { + SFuncOp op; + op.mask = ops[i] >> 32; + op.crc = ops[i] & op.mask; + op.mask = re(op.mask); + op.crc = re(op.crc); + sf->ops.AddCpy(op); + } + g_static_funcs_list.Add(sf); +} + bool IsLoadedFunc(u32 id); bool CallFunc(u32 num); bool UnloadFunc(u32 id); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index 8c5915d6ff..dc2f7789d5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -4,9 +4,8 @@ #include "Emu/Audio/cellAudio.h" void cellAudio_init(); -void cellAudio_load(); void cellAudio_unload(); -Module cellAudio(0x0011, cellAudio_init, cellAudio_load, cellAudio_unload); +Module cellAudio(0x0011, cellAudio_init, nullptr, cellAudio_unload); extern u64 get_system_time(); @@ -135,7 +134,7 @@ struct CellAudioPortConfig struct AudioPortConfig { - SMutex m_mutex; + SMutexGeneral m_mutex; bool m_is_audio_port_opened; bool m_is_audio_port_started; u8 channel; @@ -179,64 +178,6 @@ struct AudioConfig //custom structure } } m_config; -//libmixer datatypes -typedef void * CellAANHandle; - -struct CellSSPlayerConfig -{ - be_t channels; - be_t outputMode; -}; - -struct CellSSPlayerWaveParam -{ - void *addr; - be_t format; - be_t samples; - be_t loopStartOffset; - be_t startOffset; -}; - -struct CellSSPlayerCommonParam -{ - be_t loopMode; - be_t attackMode; -}; - -struct CellSurMixerPosition -{ - be_t x; - be_t y; - be_t z; -}; - -struct CellSSPlayerRuntimeInfo -{ - be_t level; - be_t speed; - CellSurMixerPosition position; -}; - -struct CellSurMixerConfig -{ - be_t priority; - be_t chStrips1; - be_t chStrips2; - be_t chStrips6; - be_t chStrips8; -}; - -struct CellSurMixerChStripParam -{ - be_t param; - void *attribute; - be_t dBSwitch; - be_t floatVal; - be_t intVal; -}; - -CellSSPlayerWaveParam current_SSPlayerWaveParam; - //libsnd3 datatypes struct CellSnd3DataCtx { @@ -368,7 +309,7 @@ int cellAudioInit() memset(Memory + buf_addr, 0, block_size * sizeof(float)); { - SMutexLocker lock(port.m_mutex); + SMutexGeneralLocker lock(port.m_mutex); port.counter = m_config.counter; port.tag++; // absolute index of block that will be read index = (position + 1) % port.block; // write new value @@ -621,7 +562,7 @@ int cellAudioGetPortTimestamp(u32 portNum, u64 tag, mem64_t stamp) AudioPortConfig& port = m_config.m_ports[portNum]; - SMutexLocker lock(port.m_mutex); + SMutexGeneralLocker lock(port.m_mutex); stamp = m_config.start_time + (port.counter + (tag - port.tag)) * 256000000 / 48000; @@ -655,7 +596,7 @@ int cellAudioGetPortBlockTag(u32 portNum, u64 blockNo, mem64_t tag) return CELL_AUDIO_ERROR_PARAM; } - SMutexLocker lock(port.m_mutex); + SMutexGeneralLocker lock(port.m_mutex); u64 tag_base = port.tag; if (tag_base % port.block > blockNo) @@ -796,168 +737,6 @@ int cellAudioUnsetPersonalDevice(int iPersonalStream) return CELL_OK; } - -//Callback Functions -typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples); //Currently unused. - -// libmixer Functions, NOT active in this moment -int cellAANConnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellAANDisconnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellAANAddData(CellAANHandle handle, u32 port, u32 offset, float *addr, u32 samples) -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config) -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerRemove(CellAANHandle handle) -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerSetWave() //CellAANHandle handle, CellSSPlayerWaveParam *waveInfo, CellSSPlayerCommonParam *commonInfo //mem_class_t waveInfo -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerPlay() //CellAANHandle handle, CellSSPlayerRuntimeInfo *info -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerStop() //CellAANHandle handle, u32 mode -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSSPlayerSetParam() //CellAANHandle handle, CellSSPlayerRuntimeInfo *info -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -s32 cellSSPlayerGetState() //CellAANHandle handle -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerCreate() //const CellSurMixerConfig *config -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerGetAANHandle() //CellAANHandle *handle -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerChStripGetAANPortNo() //u32 *port, u32 type, u32 index -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerSetNotifyCallback() //CellSurMixerNotifyCallbackFunction callback, void *arg -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerRemoveNotifyCallback() //CellSurMixerNotifyCallbackFunction callback -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerStart() -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerSurBusAddData() //u32 busNo, u32 offset, float *addr, u32 samples -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerSetParameter() //u32 param, float value -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerChStripSetParameter() //u32 type, u32 index, CellSurMixerChStripParam *param -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerPause() //u32 switch -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerGetCurrentBlockTag() //u64 *tag -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -int cellSurMixerGetTimestamp() //u64 tag, u64 *stamp -{ - UNIMPLEMENTED_FUNC(cellAudio); - return 0; -} - -void cellSurMixerBeep(); //void *arg - -float cellSurMixerUtilGetLevelFromDB() //float dB -{ - UNIMPLEMENTED_FUNC(cellAudio); - return CELL_OK; //it's NOT real value - //TODO; -} - -float cellSurMixerUtilGetLevelFromDBIndex() //int index -{ - UNIMPLEMENTED_FUNC(cellAudio); - return CELL_OK; //it's NOT real value - //TODO; -} - -float cellSurMixerUtilNoteToRatio() //unsigned char refNote, unsigned char note -{ - UNIMPLEMENTED_FUNC(cellAudio); - return CELL_OK; //it's NOT real value - //TODO -} - -int cellSurMixerFinalize(); //Currently unused. Returns 0 (in the current release). - //*libsnd3 Functions, NOT active in this moment s32 cellSnd3Init() //u32 maxVoice, u32 samples, CellSnd3RequestQueueCtx *queue { @@ -1399,14 +1178,7 @@ void cellAudio_init() //TODO: Find addresses for libmixer, libsnd3 and libsynth2 functions } -void cellAudio_load() -{ - m_config.m_is_audio_initialized = false; - m_config.Clear(); -} - void cellAudio_unload() { - m_config.m_is_audio_initialized = false; - m_config.Clear(); + //StaticFinalize(); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 29f3d83424..a664683a29 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -52,6 +52,9 @@ u32 dmuxOpen(Demuxer* data) u32 cb_add = 0; + u32 updates_count = 0; + u32 updates_signaled = 0; + while (true) { if (Emu.IsStopped()) @@ -68,9 +71,17 @@ u32 dmuxOpen(Demuxer* data) if (!stream.peek(code)) { + dmux.is_running = false; // demuxing finished - task.type = dmuxResetStream; - goto task; + mem_ptr_t dmuxMsg(a128(dmux.memAddr) + (cb_add ^= 16)); + dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; + dmuxMsg->supplementalInfo = stream.userdata; + /*Callback cb; + cb.SetAddr(dmux.cbFunc); + cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); + cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ + dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); + updates_signaled++; } else switch (code.ToLE()) { @@ -125,11 +136,14 @@ u32 dmuxOpen(Demuxer* data) if (esATX[ch]) { ElementaryStream& es = *esATX[ch]; - if (es.isfull()) + while (es.isfull()) { - stream = backup; + if (Emu.IsStopped()) + { + ConLog.Warning("esATX[%d] was full, waiting aborted", ch); + return; + } Sleep(1); - continue; } //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); @@ -163,10 +177,14 @@ u32 dmuxOpen(Demuxer* data) if (esAVC[ch]) { ElementaryStream& es = *esAVC[ch]; - if (es.isfull()) + while (es.isfull()) { + if (Emu.IsStopped()) + { + ConLog.Warning("esAVC[%d] was full, waiting aborted", ch); + return; + } Sleep(1); - continue; } DemuxerStream backup = stream; @@ -177,11 +195,11 @@ u32 dmuxOpen(Demuxer* data) if (pes.new_au && es.hasdata()) // new AU detected { - if (es.hasunseen()) // hack, probably useless + /*if (es.hasunseen()) // hack, probably useless { stream = backup; continue; - } + }*/ es.finish(stream); // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); @@ -257,24 +275,11 @@ u32 dmuxOpen(Demuxer* data) { break; // Emu is stopped } -task: + switch (task.type) { case dmuxSetStream: { - bool do_wait = false; - for (u32 i = 0; i < 192; i++) - { - if (esALL[i]) - { - if (esALL[i]->hasunseen()) // hack, probably useless - { - do_wait = true; - break; - } - } - } - if (do_wait) continue; 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); @@ -285,6 +290,7 @@ task: esALL[i]->reset(); } } + updates_count++; dmux.is_running = true; } break; @@ -292,7 +298,6 @@ task: case dmuxResetStream: case dmuxResetStreamAndWaitDone: { - // TODO: send CELL_DMUX_MSG_TYPE_DEMUX_DONE callback and provide waiting condition mem_ptr_t dmuxMsg(a128(dmux.memAddr) + (cb_add ^= 16)); dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; dmuxMsg->supplementalInfo = stream.userdata; @@ -302,6 +307,7 @@ task: cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, task.type == dmuxResetStreamAndWaitDone, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); + updates_signaled++; dmux.is_running = false; } break; @@ -578,10 +584,15 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize return CELL_DMUX_ERROR_FATAL; } - if (dmux->is_running) + while (dmux->is_running) // hack { - Sleep(1); // performance hack - return CELL_DMUX_ERROR_BUSY; + if (Emu.IsStopped()) + { + ConLog.Warning("cellDmuxSetStream(%d) aborted (waiting)", demuxerHandle); + break; + } + Sleep(1); + //return CELL_DMUX_ERROR_BUSY; } DemuxerTask task(dmuxSetStream); diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp new file mode 100644 index 0000000000..81ed26a5a8 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -0,0 +1,404 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" +#include "libmixer.h" + +void libmixer_init(); +Module libmixer("libmixer", libmixer_init); + +int cellAANAddData(u32 handle, u32 port, u32 offset, u32 addr, u32 samples) +{ + libmixer.Error("cellAANAddData(handle=0x%x, port=0x%x, offset=0x%x, addr=0x%x, samples=0x%x)", + handle, port, offset, addr, samples); + return CELL_OK; +} + +// libmixer Functions, NOT active in this moment +/*int cellAANConnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellAANDisconnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config) +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerRemove(CellAANHandle handle) +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerSetWave() //CellAANHandle handle, CellSSPlayerWaveParam *waveInfo, CellSSPlayerCommonParam *commonInfo //mem_class_t waveInfo +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerPlay() //CellAANHandle handle, CellSSPlayerRuntimeInfo *info +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerStop() //CellAANHandle handle, u32 mode +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSSPlayerSetParam() //CellAANHandle handle, CellSSPlayerRuntimeInfo *info +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +s32 cellSSPlayerGetState() //CellAANHandle handle +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +}*/ + +int cellSurMixerCreate(const mem_ptr_t config) +{ + libmixer.Error("cellSurMixerCreate(config_addr=0x%x)", config.GetAddr()); + return CELL_OK; +} + +int cellSurMixerGetAANHandle(mem32_t handle) +{ + libmixer.Error("cellSurMixerGetAANHandle(handle_addr=0x%x)", handle.GetAddr()); + return CELL_OK; +} + +int cellSurMixerChStripGetAANPortNo(mem32_t port, u32 type, u32 index) +{ + libmixer.Error("cellSurMixerChStripGetAANPortNo(port_addr=0x%x, type=0x%x, index=0x%x)", port.GetAddr(), type, index); + return CELL_OK; +} + +int cellSurMixerSetNotifyCallback(u32 func, u32 arg) +{ + libmixer.Error("cellSurMixerSetNotifyCallback(func_addr=0x%x, arg=0x%x)", func, arg); + return CELL_OK; +} + +int cellSurMixerRemoveNotifyCallback(u32 func) +{ + libmixer.Error("cellSurMixerSetNotifyCallback(func_addr=0x%x)", func); + return CELL_OK; +} + +int cellSurMixerStart() +{ + libmixer.Error("cellSurMixerStart()"); + return CELL_OK; +} + +int cellSurMixerSetParameter(u32 param, float value) +{ + libmixer.Error("cellSurMixerSetParameter(param=0x%x, value=%f)", param, value); + return CELL_OK; +} + +int cellSurMixerFinalize() +{ + libmixer.Error("cellSurMixerFinalize()"); + return CELL_OK; +} + +/*int cellSurMixerSurBusAddData() //u32 busNo, u32 offset, float *addr, u32 samples +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSurMixerChStripSetParameter() //u32 type, u32 index, CellSurMixerChStripParam *param +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSurMixerPause() //u32 switch +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSurMixerGetCurrentBlockTag() //u64 *tag +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +int cellSurMixerGetTimestamp() //u64 tag, u64 *stamp +{ + UNIMPLEMENTED_FUNC(libmixer); + return 0; +} + +void cellSurMixerBeep(); //void *arg + +float cellSurMixerUtilGetLevelFromDB() //float dB +{ + UNIMPLEMENTED_FUNC(libmixer); + return CELL_OK; //it's NOT real value + //TODO; +} + +float cellSurMixerUtilGetLevelFromDBIndex() //int index +{ + UNIMPLEMENTED_FUNC(libmixer); + return CELL_OK; //it's NOT real value + //TODO; +} + +float cellSurMixerUtilNoteToRatio() //unsigned char refNote, unsigned char note +{ + UNIMPLEMENTED_FUNC(libmixer); + return CELL_OK; //it's NOT real value + //TODO +}*/ + +void libmixer_init() +{ + static const u64 cellAANAddData_table[] = { + // TODO + 0xffffffff7c691b78, + 0xffffffff7c0802a6, + 0xfffffffff821ff91, + 0xfffffffff8010080, + 0xffffffff7c802378, + 0xffffffff7caa2b78, + 0xffffffff81690000, + 0xffffffff7c050378, + 0xffffffff7cc43378, + // 78 63 00 20 clrldi r3,r3,32 # 20 // may be included + 0xffffffff7d465378, + 0xffffffff812b0030, + 0xffffffff80090000, + 0xfffffffff8410028, + 0xffffffff7c0903a6, + 0xffffffff80490004, + 0xffffffff4e800421, + 0xffffffffe8410028, + 0xffffffffe8010080, + 0xffffffff7c6307b4, + 0xffffffff7c0803a6, + 0xffffffff38210070, + 0xffffffff4e800020, + 0 + }; + libmixer.AddFuncSub(cellAANAddData_table, "cellAANAddData", cellAANAddData); + + static const u64 cellSurMixerCreate_table[] = { + 0xffffffff2f830000, + 0xffffffff7c0802a6, + 0xfffffffff821ff51, + 0xfffffffffbc100a0, + 0xfffffffffb210078, + 0xfffffffffb410080, + 0xfffffffffb610088, + 0xfffffffffb810090, + 0xfffffffffba10098, + 0xfffffffffbe100a8, + 0xfffffffff80100c0, + 0xffffffff7c7e1b78, + 0xf000000040000000, // bne + 0xffffffff3fe08031, + 0xffffffff63ff0003, + 0xffffffffe80100c0, + 0xffffffff7fe307b4, + 0xffffffffeb210078, + 0xffffffffeb410080, + 0xffffffff7c0803a6, + 0xffffffffeb610088, + 0xffffffffeb810090, + 0xffffffffeba10098, + 0xffffffffebc100a0, + 0xffffffffebe100a8, + 0xffffffff382100b0, + 0 + }; + libmixer.AddFuncSub(cellSurMixerCreate_table, "cellSurMixerCreate", cellSurMixerCreate); + + static const u64 cellSurMixerGetAANHandle_table[] = { + // first instruction ignored + 0xffffffff3d607fce, + 0xffffffff616bfffe, + 0xffffffff812a0018, + 0xffffffff7d2afe70, + 0xffffffff91230000, + 0xffffffff7d404a78, + 0xffffffff7c005050, + 0xffffffff7c00fe70, + 0xffffffff7c035838, + 0xffffffff3c638031, + 0xffffffff38630002, + 0xffffffff7c6307b4, + 0xffffffff4e800020, + 0 + }; + libmixer.AddFuncSub(cellSurMixerGetAANHandle_table, "cellSurMixerGetAANHandle", cellSurMixerGetAANHandle); + + static const u64 cellSurMixerChStripGetAANPortNo_table[] = { + // first instruction ignored + 0xffffffff7c661b78, + 0xffffffff3c608031, + 0xffffffff78c60020, + 0xffffffff78840020, + 0xffffffff60630002, + 0xffffffff80090018, + 0xffffffff78a50020, + 0xffffffff2f800000, + 0xffffffff4d9e0020, + 0xffffffff78030020, + 0xf000000040000000, // b + 0 + }; + libmixer.AddFuncSub(cellSurMixerChStripGetAANPortNo_table, "cellSurMixerChStripGetAANPortNo", cellSurMixerChStripGetAANPortNo); + + static const u64 cellSurMixerSetNotifyCallback_table[] = { + // first instruction ignored + 0xffffffff7c0802a6, + 0xfffffffff821ff81, + 0xfffffffff8010090, + 0xffffffff7c6b1b78, + 0xffffffff3c608031, + 0xffffffff812a0018, + 0xffffffff7c882378, + 0xffffffff60630003, + 0xffffffff2f890000, + 0xffffffff2f0b0000, + 0xffffff00409e0020, // bne + 0xffffffff3c608031, + 0xffffffff60630002, + 0xffffffffe8010090, + 0xffffffff7c6307b4, + 0xffffffff38210080, + 0xffffffff7c0803a6, + 0xffffffff4e800020, + 0xffffff00419affec, // beq + 0xf0000000800a001c, // lwz + 0xffffffff79290020, + 0xffffffff38810070, + 0xffffffff2f800000, + 0xffffffff7d234b78, + 0 + }; + libmixer.AddFuncSub(cellSurMixerSetNotifyCallback_table, "cellSurMixerSetNotifyCallback", cellSurMixerSetNotifyCallback); + + static const u64 cellSurMixerRemoveNotifyCallback_table[] = { + // first instruction ignored + 0xffffffff7c0802a6, + 0xfffffffff821ff81, + 0xfffffffff8010090, + 0xffffffff7c6a1b78, + 0xffffffff3d208031, + 0xffffffff806b0018, + 0xffffffff61290002, + 0xffffffff2f830000, + 0xf0000000409e0018, // bne + 0xffffffffe8010090, + 0xffffffff7d2307b4, + 0xffffffff38210080, + 0xffffffff7c0803a6, + 0xffffffff4e800020, + 0 + }; + libmixer.AddFuncSub(cellSurMixerRemoveNotifyCallback_table, "cellSurMixerRemoveNotifyCallback", cellSurMixerRemoveNotifyCallback); + + static const u64 cellSurMixerStart_table[] = { + 0xfffffffff821ff71, + 0xffffffff7c0802a6, + 0xfffffffffbc10080, + 0xf000000083c20000, // lwz + 0xfffffffff80100a0, + 0xfffffffffba10078, + 0xfffffffffbe10088, + 0xffffffff801e0018, + 0xffffffff2f800000, + 0xf0000000409e002c, // bne + 0xffffffff3fe08031, + 0xffffffff63ff0002, + 0xffffffffe80100a0, + 0xffffffff7fe307b4, + 0xffffffffeba10078, + 0xffffffffebc10080, + 0xffffffff7c0803a6, + 0xffffffffebe10088, + 0xffffffff38210090, + 0xffffffff4e800020, + 0 + }; + libmixer.AddFuncSub(cellSurMixerStart_table, "cellSurMixerStart", cellSurMixerStart); + + static const u64 cellSurMixerSetParameter_table[] = { + 0xfffffffff821ff81, + 0xffffffff7c0802a6, + 0xfffffffffbc10070, + 0xfffffffffc000890, + 0xf000000083c28250, // lwz + 0xffffffff3d208031, + 0xfffffffff8010090, + 0xfffffffffbe10078, + 0xffffffff61290002, + 0xffffffff7c7f1b78, + 0xffffffff801e0018, + 0xffffffff2f800000, + 0xffff0000409e0020, // bne + 0xffffffffe8010090, + 0xffffffff7d2307b4, + 0xffffffffebc10070, + 0xffffffffebe10078, + 0xffffffff7c0803a6, + 0xffffffff38210080, + 0xffffffff4e800020, + 0xffffffff801e001c, + 0xffffffff2b03001f, + 0xffffffff2f800000, + 0xffff0000419cffd8, // blt + 0xffffffff2b83002b, + 0xffff000040990008, // ble + 0xffff0000409d0054, // ble + 0 + }; + libmixer.AddFuncSub(cellSurMixerSetParameter_table, "cellSurMixerSetParameter", cellSurMixerSetParameter); + + static const u64 cellSurMixerFinalize_table[] = { + 0xfffffffff821ff91, + 0xffffffff7c0802a6, + 0xfffffffff8010080, + 0xffffff004bfffde1, // bl + 0xffffffffe8010080, + 0xffffffff38600000, + 0xffffffff38210070, + 0xffffffff7c0803a6, + 0xffffffff4e800020, + 0xfffffffff821ff71, + 0xffffffff7c0802a6, + 0xfffffffffba10078, + 0xf000000083a28250, // lwz + 0xfffffffff80100a0, + 0xffffffff817d0018, + 0xffffffff7d635b78, + 0xffffffff812b0000, + 0xffffffff81490000, + 0xffffffff800a0000, + 0xfffffffff8410028, + 0xffffffff7c0903a6, + 0xffffffff804a0004, + 0xffffffff4e800421, + 0 + }; + libmixer.AddFuncSub(cellSurMixerFinalize_table, "cellSurMixerFinalize", cellSurMixerFinalize); +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.h b/rpcs3/Emu/SysCalls/Modules/libmixer.h new file mode 100644 index 0000000000..24c30c7b70 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.h @@ -0,0 +1,63 @@ +#pragma once + + +//Callback Functions +typedef int (*CellSurMixerNotifyCallbackFunction)(void *arg, u32 counter, u32 samples); //Currently unused. + +//libmixer datatypes +typedef void * CellAANHandle; + +struct CellSSPlayerConfig +{ + be_t channels; + be_t outputMode; +}; + +struct CellSSPlayerWaveParam +{ + void *addr; + be_t format; + be_t samples; + be_t loopStartOffset; + be_t startOffset; +}; + +struct CellSSPlayerCommonParam +{ + be_t loopMode; + be_t attackMode; +}; + +struct CellSurMixerPosition +{ + be_t x; + be_t y; + be_t z; +}; + +struct CellSSPlayerRuntimeInfo +{ + be_t level; + be_t speed; + CellSurMixerPosition position; +}; + +struct CellSurMixerConfig +{ + be_t priority; + be_t chStrips1; + be_t chStrips2; + be_t chStrips6; + be_t chStrips8; +}; + +struct CellSurMixerChStripParam +{ + be_t param; + void *attribute; + be_t dBSwitch; + be_t floatVal; + be_t intVal; +}; + +CellSSPlayerWaveParam current_SSPlayerWaveParam; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Static.cpp b/rpcs3/Emu/SysCalls/Static.cpp new file mode 100644 index 0000000000..6d653a7b1c --- /dev/null +++ b/rpcs3/Emu/SysCalls/Static.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" +#include "Modules.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" + +extern ArrayF g_static_funcs_list; + +void StaticAnalyse(void* ptr, u32 size) +{ + u32* data = (u32*)ptr; size /= 4; + + // TODO: optimize search + for (u32 i = 0; i < size; i++) + { + for (u32 j = 0; j < g_static_funcs_list.GetCount(); j++) + { + if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc && (i + g_static_funcs_list[j].ops.GetCount()) < size) + { + bool found = true; + for (u32 k = i + 1, x = 1; x < g_static_funcs_list[j].ops.GetCount(); k++, x++) + { + // skip NOP + if (data[k] == se32(0x60000000)) + { + k++; + continue; + } + + if ((data[k] & g_static_funcs_list[j].ops[x].mask) != g_static_funcs_list[j].ops[x].crc) + { + found = false; + break; + } + } + if (found) + { + ConLog.Success("Function '%s' hooked", wxString(g_static_funcs_list[j].name).wx_str()); + data[i] = re(0x39600000 | j); // li r11, j + data[i+1] = se32(0x44000003); // sc 3 + data[i+2] = se32(0x4e800020); // blr + i += g_static_funcs_list[j].ops.GetCount(); // ??? + } + } + } + } +} + +void StaticExecute(u32 code) +{ + if (code < g_static_funcs_list.GetCount()) + { + (*g_static_funcs_list[code].func)(); + } + else + { + ConLog.Error("StaticExecute(%d): unknown function or illegal opcode", code); + } +} + +void StaticFinalize() +{ + g_static_funcs_list.Clear(); +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 51242b9b30..988c1391e3 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -433,3 +433,7 @@ public: }; //extern SysCalls SysCallsManager; + +void StaticAnalyse(void* ptr, u32 size); +void StaticExecute(u32 code); +void StaticFinalize(); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 2a42841c31..76a0cf4ebc 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -57,7 +57,7 @@ int sys_lwmutex_destroy(mem_ptr_t lwmutex) { case CELL_OK: lwmutex->all_info() = 0; - lwmutex->attribute = 0; + lwmutex->attribute = 0xDEADBEEF; lwmutex->sleep_queue = 0; Emu.GetIdManager().RemoveID(sq_id); default: return res; @@ -205,7 +205,17 @@ bool SleepQueue::finalize() int sys_lwmutex_t::trylock(be_t tid) { - if (!attribute.ToBE()) return CELL_EINVAL; + if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL; + + while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0) + { + if (Emu.IsStopped()) + { + ConLog.Warning("(hack) sys_lwmutex_t::trylock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute); + return CELL_ESRCH; + } + Sleep(1); + } if (tid == mutex.GetOwner()) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 04e2c958d3..5c4f5b9761 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -52,12 +52,12 @@ int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) { case SYS_MEMORY_PAGE_SIZE_1M: if(size & 0xfffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 1); + addr = Memory.Alloc(size, 0x100000); break; case SYS_MEMORY_PAGE_SIZE_64K: if(size & 0xffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 1); + addr = Memory.Alloc(size, 0x10000); break; default: return CELL_EINVAL; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index 4ae474631b..d3921cbcc0 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -37,7 +37,12 @@ int sys_mutex_create(mem32_t mutex_id, mem_ptr_t attr) return CELL_EINVAL; } - mutex_id = sys_mtx.GetNewId(new Mutex((u32)attr->protocol, is_recursive, attr->name_u64)); + u32 tid = GetCurrentPPUThread().GetId(); + Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64); + u32 id = sys_mtx.GetNewId(mutex); + mutex->m_mutex.lock(tid); + mutex_id = id; + mutex->m_mutex.unlock(tid); sys_mtx.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d", wxString(attr->name, 8).wx_str(), (u32)attr->protocol, wxString(is_recursive ? "true" : "false").wx_str(), mutex_id.GetValue()); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 0abf3866ea..6604d86d64 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -246,6 +246,7 @@ bool ELF64Loader::LoadPhdrData(u64 offset) { elf64_f.Seek(phdr_arr[i].p_offset); elf64_f.Read(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz); + StaticAnalyse(&Memory[offset + phdr_arr[i].p_vaddr], phdr_arr[i].p_filesz); } } break; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 9e53606cac..c6395389c0 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -301,11 +301,13 @@ + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 28561ebfcf..3eb2bd8980 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -436,6 +436,12 @@ Crypto + + Emu\SysCalls + + + Emu\SysCalls\Modules + From 05c6a96d27800c9e826b8ea38ab967d535b794dc Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 6 Mar 2014 15:50:45 +0400 Subject: [PATCH 5/7] Conflicts fixed --- Utilities/BEType.h | 3 +- Utilities/SMutex.cpp | 3 +- Utilities/SQueue.h | 4 +- rpcs3/CMakeLists.txt | 10 +- rpcs3/Crypto/unpkg.cpp | 4 +- rpcs3/Crypto/unself.cpp | 4 +- rpcs3/Crypto/unself.h | 24 +-- rpcs3/Emu/Cell/PPUInterpreter.h | 4 +- rpcs3/Emu/GS/GL/GLGSRender.h | 2 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellAdec.h | 16 +- rpcs3/Emu/SysCalls/Modules/cellL10n.cpp | 206 ++++++++++++++++++++- rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp | 18 +- rpcs3/Emu/SysCalls/Modules/cellRtc.cpp | 37 +--- rpcs3/Emu/SysCalls/Modules/cellRtc.h | 36 ++++ rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 6 +- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp | 77 +++----- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h | 84 +++++++++ rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 2 +- rpcs3/cmake_modules/FindFFMPEG.cmake | 79 ++++++++ rpcs3/rpcs3.vcxproj | 2 + rpcs3/rpcs3.vcxproj.filters | 8 + 22 files changed, 501 insertions(+), 132 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/Modules/cellRtc.h create mode 100644 rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h create mode 100644 rpcs3/cmake_modules/FindFFMPEG.cmake diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 5f17abc11b..02c47ed76d 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -50,10 +50,11 @@ class be_t public: typedef T type; + #ifdef _WIN32 be_t(){} #else - be_t() noexcept = default + be_t() noexcept = default; #endif be_t(const T& value) diff --git a/Utilities/SMutex.cpp b/Utilities/SMutex.cpp index 1f48903f4e..1d9bcb03f2 100644 --- a/Utilities/SMutex.cpp +++ b/Utilities/SMutex.cpp @@ -1,6 +1,7 @@ #include #include + __forceinline void SM_Sleep() { Sleep(1); @@ -8,7 +9,7 @@ __forceinline void SM_Sleep() __forceinline size_t SM_GetCurrentThreadId() { - return std::this_thread::get_id().hash(); + return std::hash()(std::this_thread::get_id()); } __forceinline u32 SM_GetCurrentCPUThreadId() diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index aa6b3d3851..8c0201d257 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -15,7 +15,7 @@ public: { } - bool Push(T& data) + bool Push(const T& data) { while (true) { @@ -100,4 +100,4 @@ public: SMutexLocker lock(m_mutex); return m_data[(m_pos + pos) % SQSize]; } -}; \ No newline at end of file +}; diff --git a/rpcs3/CMakeLists.txt b/rpcs3/CMakeLists.txt index 345ab3c3bc..ba436d5957 100644 --- a/rpcs3/CMakeLists.txt +++ b/rpcs3/CMakeLists.txt @@ -1,5 +1,4 @@ cmake_minimum_required(VERSION 2.8) - project(rpcs3) if (CMAKE_COMPILER_IS_GNUCXX) @@ -10,6 +9,7 @@ if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(-fpermissive) # TODO: remove me endif() +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules) SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/../bin") add_definitions(-DGL_GLEXT_PROTOTYPES) @@ -17,16 +17,19 @@ add_definitions(-DGLX_GLXEXT_PROTOTYPES) find_package(wxWidgets COMPONENTS core base net aui gl REQUIRED) find_package(OpenGL REQUIRED) +find_package(FFMPEG REQUIRED) find_package(ZLIB REQUIRED) include("${wxWidgets_USE_FILE}") include_directories( ${wxWidgets_INCLUDE_DIRS} +${FFMPEG_INCLUDE_DIR} ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/Emu ${CMAKE_SOURCE_DIR}/Gui ${CMAKE_SOURCE_DIR}/Loader +${CMAKE_SOURCE_DIR}/Crypto ${CMAKE_SOURCE_DIR}/.. ) @@ -39,8 +42,11 @@ ${CMAKE_SOURCE_DIR}/Ini.cpp ${CMAKE_SOURCE_DIR}/Emu/* ${CMAKE_SOURCE_DIR}/Gui/* ${CMAKE_SOURCE_DIR}/Loader/* +${CMAKE_SOURCE_DIR}/Crypto/* ${CMAKE_SOURCE_DIR}/../Utilities/* ) add_executable(rpcs3 ${RPCS3_SRC}) -target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES}) \ No newline at end of file + +target_link_libraries(rpcs3 ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES}) + diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index df59689dd4..52cd20c772 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -188,7 +188,7 @@ int Unpack(wxFile& pkg_f, std::string src, std::string dst) PKGHeader* m_header = (PKGHeader*) malloc (sizeof(PKGHeader)); wxFile dec_pkg_f; - std::string decryptedFile = wxGetCwd() + "/dev_hdd1/" + src + ".dec"; + std::string decryptedFile = wxGetCwd().ToStdString() + "/dev_hdd1/" + src + ".dec"; dec_pkg_f.Create(decryptedFile, true); @@ -219,4 +219,4 @@ int Unpack(wxFile& pkg_f, std::string src, std::string dst) wxRemoveFile(decryptedFile); return 0; -} \ No newline at end of file +} diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 2923615a0b..df298b434c 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -525,7 +525,7 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key) return false; } - ConLog.Write("Loading RAP file %s", ci_str + ".rap"); + ConLog.Write("Loading RAP file %s", ci_str.wc_str() + wchar_t(".rap")); rap_file.Read(rap_key, 0x10); rap_file.Close(); @@ -671,4 +671,4 @@ bool DecryptSelf(const std::string& elf, const std::string& self) } return true; -} \ No newline at end of file +} diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index a6f2a42c97..3c0dd395e3 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -205,7 +205,7 @@ struct ControlInfo for (int i = 0; i < 20; i++) digest_str += wxString::Format("%02x", file_digest_30.digest[i]); - ConLog.Write("Digest: %s", digest_str); + ConLog.Write("Digest: %s", digest_str.wc_str()); ConLog.Write("Unknown: 0x%llx", file_digest_30.unknown); } else if (size == 0x40) @@ -218,8 +218,8 @@ struct ControlInfo digest_str2 += wxString::Format("%02x", file_digest_40.digest2[i]); } - ConLog.Write("Digest1: %s", digest_str1); - ConLog.Write("Digest2: %s", digest_str2); + ConLog.Write("Digest1: %s", digest_str1.wc_str()); + ConLog.Write("Digest2: %s", digest_str2.wc_str()); ConLog.Write("Unknown: 0x%llx", file_digest_40.unknown); } } @@ -242,10 +242,10 @@ struct ControlInfo ConLog.Write("Unknown1: 0x%08x", npdrm.unknown1); ConLog.Write("License: 0x%08x", npdrm.license); ConLog.Write("Type: 0x%08x", npdrm.type); - ConLog.Write("ContentID: %s", contentid_str); - ConLog.Write("Digest: %s", digest_str); - ConLog.Write("Inverse digest: %s", invdigest_str); - ConLog.Write("XOR digest: %s", xordigest_str); + ConLog.Write("ContentID: %s", contentid_str.wc_str()); + ConLog.Write("Digest: %s", digest_str.wc_str()); + ConLog.Write("Inverse digest: %s", invdigest_str.wc_str()); + ConLog.Write("XOR digest: %s", xordigest_str.wc_str()); ConLog.Write("Unknown2: 0x%llx", npdrm.unknown2); ConLog.Write("Unknown3: 0x%llx", npdrm.unknown3); } @@ -282,10 +282,10 @@ struct MetadataInfo iv_pad_str += wxString::Format("%02x", iv_pad[i]); } - ConLog.Write("Key: %s", key_str); - ConLog.Write("Key pad: %s", key_pad_str); - ConLog.Write("IV: %s", iv_str); - ConLog.Write("IV pad: %s", iv_pad_str); + ConLog.Write("Key: %s", key_str.wc_str()); + ConLog.Write("Key pad: %s", key_pad_str.wc_str()); + ConLog.Write("IV: %s", iv_str.wc_str()); + ConLog.Write("IV pad: %s", iv_pad_str.wc_str()); } }; @@ -505,4 +505,4 @@ public: extern bool IsSelf(const std::string& path); extern bool IsSelfElf32(const std::string& path); extern bool CheckDebugSelf(const std::string& self, const std::string& elf); -extern bool DecryptSelf(const std::string& elf, const std::string& self); \ No newline at end of file +extern bool DecryptSelf(const std::string& elf, const std::string& self); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index b6dd47706a..32fbdd0a3b 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1895,8 +1895,6 @@ private: } void VSUM2SWS(u32 vd, u32 va, u32 vb) { - CPU.VPR[vd].Clear(); - for (uint n = 0; n < 2; n++) { s64 sum = (s64)CPU.VPR[va]._s32[n*2] + CPU.VPR[va]._s32[n*2 + 1] + CPU.VPR[vb]._s32[n*2]; @@ -1914,6 +1912,8 @@ private: else CPU.VPR[vd]._s32[n*2] = (s32)sum; } + CPU.VPR[vd]._s32[1] = 0; + CPU.VPR[vd]._s32[3] = 0; } void VSUM4SBS(u32 vd, u32 va, u32 vb) { diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index e3875f665d..5f503bde02 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -306,7 +306,7 @@ public: static const wxString& dir_path = "textures"; static const wxString& file_fmt = dir_path + "\\" + "tex[%d].png"; - if(!wxDirExists(dir_path)) wxMkDir(dir_path); + if(!wxDirExists(dir_path)) wxMkdir(dir_path); u32 count = 0; while(wxFileExists(wxString::Format(file_fmt, count))) count++; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index d616ce0c82..76550a38e3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -7,8 +7,8 @@ extern SMutexGeneral g_mutex_avcodec_open2; extern "C" { -#include "libavcodec\avcodec.h" -#include "libavformat\avformat.h" +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" } #include "cellAdec.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 63b355bc68..bab8ccd6c9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -527,12 +527,12 @@ struct CellAdecParamM4Aac be_t configNumber; union { - struct { struct + struct mp { struct mp2 { be_t adifProgramNumber; // 0 } adifConfig; }; - struct { struct + struct mp3 { struct mp4 { be_t samplingFreqIndex; be_t profile; // LC profile (1) @@ -560,8 +560,8 @@ struct CellAdecM4AacInfo be_t pad1; // TODO: check alignment union { - struct { - struct + struct mp5 { + struct m6 { be_t copyrightIdPresent; char copyrightId[9]; @@ -574,8 +574,8 @@ struct CellAdecM4AacInfo } adif; }; - struct { - struct + struct mp7 { + struct mp8 { be_t id; be_t layer; @@ -598,7 +598,7 @@ struct CellAdecM4AacInfo be_t pad2; // TODO: check alignment - struct + struct mp9 { be_t matrixMixdownPresent; be_t mixdownIndex; @@ -1127,4 +1127,4 @@ public: avformat_free_context(fmt); } } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp index 6989f8b8b5..f78f667030 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp @@ -5,7 +5,211 @@ void cellL10n_init(); Module cellL10n(0x001e, cellL10n_init); +// L10nResult +enum +{ + ConversionOK, + SRCIllegal, + DSTExhausted, + ConverterUnknown, +}; + +int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t utf8_len) +{ + cellL10n.Warning("UTF16stoUTF8s(utf16_addr=0x%x, utf16_len_addr=0x%x, utf8_addr=0x%x, utf8_len_addr=0x%x)", + utf16.GetAddr(), utf16_len.GetAddr(), utf8.GetAddr(), utf8_len.GetAddr()); + + if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) + return SRCIllegal; + + std::wstring wstr = (wchar_t*)Memory.VirtualToRealAddr(utf16); + std::string str; + + int len = min((int)utf16_len.GetValue(), (int)wstr.size()); + int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); + + if (!utf8.IsGood()) + utf8_len = size; + if (utf8_len.GetValue() < size) + return DSTExhausted; + +#ifdef WIN32 + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &str[0], size, NULL, NULL); +#else + // TODO +#endif + + Memory.WriteString(utf8, str); + return ConversionOK; +} + void cellL10n_init() { - // (TODO: Get addresses of cellL10n functions) + // NOTE: I think this module should be LLE'd instead of implementing all its functions + + // cellL10n.AddFunc(0x005200e6, UCS2toEUCJP); + // cellL10n.AddFunc(0x01b0cbf4, l10n_convert); + // cellL10n.AddFunc(0x0356038c, UCS2toUTF32); + // cellL10n.AddFunc(0x05028763, jis2kuten); + // cellL10n.AddFunc(0x058addc8, UTF8toGB18030); + // cellL10n.AddFunc(0x060ee3b2, JISstoUTF8s); + // cellL10n.AddFunc(0x07168a83, SjisZen2Han); + // cellL10n.AddFunc(0x0bc386c8, ToSjisLower); + // cellL10n.AddFunc(0x0bedf77d, UCS2toGB18030); + // cellL10n.AddFunc(0x0bf867e2, HZstoUCS2s); + // cellL10n.AddFunc(0x0ce278fd, UCS2stoHZs); + // cellL10n.AddFunc(0x0d90a48d, UCS2stoSJISs); + // cellL10n.AddFunc(0x0f624540, kuten2eucjp); + // cellL10n.AddFunc(0x14ee3649, sjis2jis); + // cellL10n.AddFunc(0x14f504b8, EUCKRstoUCS2s); + // cellL10n.AddFunc(0x16eaf5f1, UHCstoEUCKRs); + // cellL10n.AddFunc(0x1758053c, jis2sjis); + // cellL10n.AddFunc(0x1906ce6b, jstrnchk); + // cellL10n.AddFunc(0x1ac0d23d, L10nConvert); + // cellL10n.AddFunc(0x1ae2acee, EUCCNstoUTF8s); + // cellL10n.AddFunc(0x1cb1138f, GBKstoUCS2s); + // cellL10n.AddFunc(0x1da42d70, eucjphan2zen); + // cellL10n.AddFunc(0x1ec712e0, ToSjisHira); + // cellL10n.AddFunc(0x1fb50183, GBKtoUCS2); + // cellL10n.AddFunc(0x21948c03, eucjp2jis); + // cellL10n.AddFunc(0x21aa3045, UTF32stoUTF8s); + // cellL10n.AddFunc(0x24fd32a9, sjishan2zen); + // cellL10n.AddFunc(0x256b6861, UCS2toSBCS); + // cellL10n.AddFunc(0x262a5ae2, UTF8stoGBKs); + // cellL10n.AddFunc(0x28724522, UTF8toUCS2); + // cellL10n.AddFunc(0x2ad091c6, UCS2stoUTF8s); + // cellL10n.AddFunc(0x2b84030c, EUCKRstoUTF8s); + // cellL10n.AddFunc(0x2efa7294, UTF16stoUTF32s); + // cellL10n.AddFunc(0x2f9eb543, UTF8toEUCKR); + // cellL10n.AddFunc(0x317ab7c2, UTF16toUTF8); + // cellL10n.AddFunc(0x32689828, ARIBstoUTF8s); + // cellL10n.AddFunc(0x33435818, SJISstoUTF8s); + // cellL10n.AddFunc(0x33f8b35c, sjiszen2han); + // cellL10n.AddFunc(0x3968f176, ToEucJpLower); + // cellL10n.AddFunc(0x398a3dee, MSJIStoUTF8); + // cellL10n.AddFunc(0x3a20bc34, UCS2stoMSJISs); + // cellL10n.AddFunc(0x3dabd5a7, EUCJPtoUTF8); + // cellL10n.AddFunc(0x3df65b64, eucjp2sjis); + // cellL10n.AddFunc(0x408a622b, ToEucJpHira); + // cellL10n.AddFunc(0x41b4a5ae, UHCstoUCS2s); + // cellL10n.AddFunc(0x41ccf033, ToEucJpKata); + // cellL10n.AddFunc(0x42838145, HZstoUTF8s); + // cellL10n.AddFunc(0x4931b44e, UTF8toMSJIS); + // cellL10n.AddFunc(0x4b3bbacb, BIG5toUTF8); + // cellL10n.AddFunc(0x511d386b, EUCJPstoSJISs); + // cellL10n.AddFunc(0x52b7883f, UTF8stoBIG5s); + // cellL10n.AddFunc(0x53558b6b, UTF16stoUCS2s); + // cellL10n.AddFunc(0x53764725, UCS2stoGB18030s); + // cellL10n.AddFunc(0x53c71ac2, EUCJPtoSJIS); + // cellL10n.AddFunc(0x54f59807, EUCJPtoUCS2); + // cellL10n.AddFunc(0x55f6921c, UCS2stoGBKs); + // cellL10n.AddFunc(0x58246762, EUCKRtoUHC); + // cellL10n.AddFunc(0x596df41c, UCS2toSJIS); + // cellL10n.AddFunc(0x5a4ab223, MSJISstoUTF8s); + // cellL10n.AddFunc(0x5ac783dc, EUCJPstoUTF8s); + // cellL10n.AddFunc(0x5b684dfb, UCS2toBIG5); + // cellL10n.AddFunc(0x5cd29270, UTF8stoEUCKRs); + // cellL10n.AddFunc(0x5e1d9330, UHCstoUTF8s); + // cellL10n.AddFunc(0x60ffa0ec, GB18030stoUCS2s); + // cellL10n.AddFunc(0x6122e000, SJIStoUTF8); + // cellL10n.AddFunc(0x6169f205, JISstoSJISs); + // cellL10n.AddFunc(0x61fb9442, UTF8toUTF16); + // cellL10n.AddFunc(0x62b36bcf, UTF8stoMSJISs); + // cellL10n.AddFunc(0x63219199, EUCKRtoUTF8); + // cellL10n.AddFunc(0x638c2fc1, SjisHan2Zen); + // cellL10n.AddFunc(0x64a10ec8, UCS2toUTF16); + // cellL10n.AddFunc(0x65444204, UCS2toMSJIS); + // cellL10n.AddFunc(0x6621a82c, sjis2kuten); + // cellL10n.AddFunc(0x6a6f25d1, UCS2toUHC); + // cellL10n.AddFunc(0x6c62d879, UTF32toUCS2); + // cellL10n.AddFunc(0x6de4b508, ToSjisUpper); + // cellL10n.AddFunc(0x6e0705c4, UTF8toEUCJP); + // cellL10n.AddFunc(0x6e5906fd, UCS2stoEUCJPs); + // cellL10n.AddFunc(0x6fc530b3, UTF16toUCS2); + // cellL10n.AddFunc(0x714a9b4a, UCS2stoUTF16s); + // cellL10n.AddFunc(0x71804d64, UCS2stoEUCCNs); + // cellL10n.AddFunc(0x72632e53, SBCSstoUTF8s); + // cellL10n.AddFunc(0x73f2cd21, SJISstoJISs); + // cellL10n.AddFunc(0x74496718, SBCStoUTF8); + // cellL10n.AddFunc(0x74871fe0, UTF8toUTF32); + // cellL10n.AddFunc(0x750c363d, jstrchk); + // cellL10n.AddFunc(0x7c5bde1c, UHCtoEUCKR); + // cellL10n.AddFunc(0x7c912bda, kuten2jis); + // cellL10n.AddFunc(0x7d07a1c2, UTF8toEUCCN); + // cellL10n.AddFunc(0x8171c1cc, EUCCNtoUTF8); + // cellL10n.AddFunc(0x82d5ecdf, EucJpZen2Han); + // cellL10n.AddFunc(0x8555fe15, UTF32stoUTF16s); + // cellL10n.AddFunc(0x860fc741, GBKtoUTF8); + // cellL10n.AddFunc(0x867f7b8b, ToEucJpUpper); + // cellL10n.AddFunc(0x88f8340b, UCS2stoJISs); + // cellL10n.AddFunc(0x89236c86, UTF8stoGB18030s); + // cellL10n.AddFunc(0x8a56f148, EUCKRstoUHCs); + // cellL10n.AddFunc(0x8ccdba38, UTF8stoUTF32s); + // cellL10n.AddFunc(0x8f472054, UTF8stoEUCCNs); + // cellL10n.AddFunc(0x90e9b5d2, EUCJPstoUCS2s); + // cellL10n.AddFunc(0x91a99765, UHCtoUCS2); + // cellL10n.AddFunc(0x931ff25a, L10nConvertStr); + // cellL10n.AddFunc(0x949bb14c, GBKstoUTF8s); + // cellL10n.AddFunc(0x9557ac9b, UTF8toUHC); + // cellL10n.AddFunc(0x9768b6d3, UTF32toUTF8); + // cellL10n.AddFunc(0x9874020d, sjis2eucjp); + // cellL10n.AddFunc(0x9a0e7d23, UCS2toEUCCN); + // cellL10n.AddFunc(0x9a13d6b8, UTF8stoUHCs); + // cellL10n.AddFunc(0x9a72059d, EUCKRtoUCS2); + // cellL10n.AddFunc(0x9b1210c6, UTF32toUTF16); + // cellL10n.AddFunc(0x9cd8135b, EUCCNstoUCS2s); + // cellL10n.AddFunc(0x9ce52809, SBCSstoUCS2s); + // cellL10n.AddFunc(0x9cf1ab77, UTF8stoJISs); + // cellL10n.AddFunc(0x9d14dc46, ToSjisKata); + // cellL10n.AddFunc(0x9dcde367, jis2eucjp); + // cellL10n.AddFunc(0x9ec52258, BIG5toUCS2); + // cellL10n.AddFunc(0xa0d463c0, UCS2toGBK); + // cellL10n.AddFunc(0xa19fb9de, UTF16toUTF32); + // cellL10n.AddFunc(0xa298cad2, l10n_convert_str); + // cellL10n.AddFunc(0xa34fa0eb, EUCJPstoJISs); + // cellL10n.AddFunc(0xa5146299, UTF8stoARIBs); + // cellL10n.AddFunc(0xa609f3e9, JISstoEUCJPs); + // cellL10n.AddFunc(0xa60ff5c9, EucJpHan2Zen); + // cellL10n.AddFunc(0xa963619c, isEucJpKigou); + // cellL10n.AddFunc(0xa9a76fb8, UCS2toUTF8); + // cellL10n.AddFunc(0xaf18d499, GB18030toUCS2); + // cellL10n.AddFunc(0xb3361be6, UHCtoUTF8); + // cellL10n.AddFunc(0xb6e45343, MSJIStoUCS2); + // cellL10n.AddFunc(0xb7cef4a6, UTF8toGBK); + // cellL10n.AddFunc(0xb7e08f7a, kuten2sjis); + // cellL10n.AddFunc(0xb9cf473d, UTF8toSBCS); + // cellL10n.AddFunc(0xbdd44ee3, SJIStoUCS2); + // cellL10n.AddFunc(0xbe42e661, eucjpzen2han); + // cellL10n.AddFunc(0xbe8d5485, UCS2stoARIBs); + // cellL10n.AddFunc(0xbefe3869, isSjisKigou); + // cellL10n.AddFunc(0xc62b758d, UTF8stoEUCJPs); + // cellL10n.AddFunc(0xc7bdcb4c, UCS2toEUCKR); + // cellL10n.AddFunc(0xc944fa56, SBCStoUCS2); + // cellL10n.AddFunc(0xc9b78f58, MSJISstoUCS2s); + // cellL10n.AddFunc(0xcc1633cc, l10n_get_converter); + // cellL10n.AddFunc(0xd02ef83d, GB18030stoUTF8s); + // cellL10n.AddFunc(0xd8721e2c, SJISstoEUCJPs); + // cellL10n.AddFunc(0xd8cb24cb, UTF32stoUCS2s); + // cellL10n.AddFunc(0xd990858b, BIG5stoUTF8s); + // cellL10n.AddFunc(0xd9fb1224, EUCCNtoUCS2); + // cellL10n.AddFunc(0xda67b37f, UTF8stoSBCSs); + // cellL10n.AddFunc(0xdc54886c, UCS2stoEUCKRs); + // cellL10n.AddFunc(0xdd5ebdeb, UTF8stoSJISs); + // cellL10n.AddFunc(0xdefa1c17, UTF8stoHZs); + // cellL10n.AddFunc(0xe2eabb32, eucjp2kuten); + // cellL10n.AddFunc(0xe6d9e234, UTF8toBIG5); + cellL10n.AddFunc(0xe6f5711b, UTF16stoUTF8s); + // cellL10n.AddFunc(0xe956dc64, JISstoUCS2s); + // cellL10n.AddFunc(0xeabc3d00, GB18030toUTF8); + // cellL10n.AddFunc(0xeb3dc670, UTF8toSJIS); + // cellL10n.AddFunc(0xeb41cc68, ARIBstoUCS2s); + // cellL10n.AddFunc(0xeb685b83, UCS2stoUTF32s); + // cellL10n.AddFunc(0xebae29c0, UCS2stoSBCSs); + // cellL10n.AddFunc(0xee6c6a39, UCS2stoBIG5s); + // cellL10n.AddFunc(0xf1dcfa71, UCS2stoUHCs); + // cellL10n.AddFunc(0xf439728e, SJIStoEUCJP); + // cellL10n.AddFunc(0xf7681b9a, UTF8stoUTF16s); + // cellL10n.AddFunc(0xf9b1896d, SJISstoUCS2s); + // cellL10n.AddFunc(0xfa4a675a, BIG5stoUCS2s); + // cellL10n.AddFunc(0xfdbf6ac5, UTF8stoUCS2s); } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp index 9dc8a2364b..6c4dfa6e4c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellNetCtl.cpp @@ -45,6 +45,15 @@ enum CELL_NET_CTL_ERROR_DHCP_LEASE_TIME = 0x80130504, }; +// Network connection states +enum +{ + CELL_NET_CTL_STATE_Disconnected = 0, + CELL_NET_CTL_STATE_Connecting = 1, + CELL_NET_CTL_STATE_IPObtaining = 2, + CELL_NET_CTL_STATE_IPObtained = 3, +}; + int cellNetCtlInit() { UNIMPLEMENTED_FUNC(cellNetCtl); @@ -57,9 +66,14 @@ int cellNetCtlTerm() return CELL_OK; } -int cellNetCtlGetState() +int cellNetCtlGetState(mem32_t state) { - UNIMPLEMENTED_FUNC(cellNetCtl); + cellNetCtl.Log("cellNetCtlGetState(state_addr=0x%x)", state.GetAddr()); + + if (!state.IsGood()) + return CELL_NET_CTL_ERROR_INVALID_ADDR; + + state = CELL_NET_CTL_STATE_Disconnected; // TODO: Allow other states return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp b/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp index eb03cc225f..9162c06cb7 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellRtc.cpp @@ -2,44 +2,11 @@ #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" +#include "cellRtc.h" + void cellRtc_init(); Module cellRtc(0x0009, cellRtc_init); -// Return Codes -enum -{ - CELL_RTC_ERROR_NOT_INITIALIZED = 0x80010601, - CELL_RTC_ERROR_INVALID_POINTER = 0x80010602, - CELL_RTC_ERROR_INVALID_VALUE = 0x80010603, - CELL_RTC_ERROR_INVALID_ARG = 0x80010604, - CELL_RTC_ERROR_NOT_SUPPORTED = 0x80010605, - CELL_RTC_ERROR_NO_CLOCK = 0x80010606, - CELL_RTC_ERROR_BAD_PARSE = 0x80010607, - CELL_RTC_ERROR_INVALID_YEAR = 0x80010621, - CELL_RTC_ERROR_INVALID_MONTH = 0x80010622, - CELL_RTC_ERROR_INVALID_DAY = 0x80010623, - CELL_RTC_ERROR_INVALID_HOUR = 0x80010624, - CELL_RTC_ERROR_INVALID_MINUTE = 0x80010625, - CELL_RTC_ERROR_INVALID_SECOND = 0x80010626, - CELL_RTC_ERROR_INVALID_MICROSECOND = 0x80010627, -}; - -struct CellRtcTick -{ - u64 tick; -}; - -struct CellRtcDateTime -{ - u16 year; - u16 month; - u16 day; - u16 hour; - u16 minute; - u16 second; - u32 microsecond; -}; - long convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, int years) { return (seconds + minutes*60 + hours*3600 + days*86400 + (years-70)*31536000 + ((years-69)/4)*86400 - ((years-1)/100)*86400 + ((years+299)/400)*86400); diff --git a/rpcs3/Emu/SysCalls/Modules/cellRtc.h b/rpcs3/Emu/SysCalls/Modules/cellRtc.h new file mode 100644 index 0000000000..5e9483c917 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellRtc.h @@ -0,0 +1,36 @@ +#pragma once + +// Return Codes +enum +{ + CELL_RTC_ERROR_NOT_INITIALIZED = 0x80010601, + CELL_RTC_ERROR_INVALID_POINTER = 0x80010602, + CELL_RTC_ERROR_INVALID_VALUE = 0x80010603, + CELL_RTC_ERROR_INVALID_ARG = 0x80010604, + CELL_RTC_ERROR_NOT_SUPPORTED = 0x80010605, + CELL_RTC_ERROR_NO_CLOCK = 0x80010606, + CELL_RTC_ERROR_BAD_PARSE = 0x80010607, + CELL_RTC_ERROR_INVALID_YEAR = 0x80010621, + CELL_RTC_ERROR_INVALID_MONTH = 0x80010622, + CELL_RTC_ERROR_INVALID_DAY = 0x80010623, + CELL_RTC_ERROR_INVALID_HOUR = 0x80010624, + CELL_RTC_ERROR_INVALID_MINUTE = 0x80010625, + CELL_RTC_ERROR_INVALID_SECOND = 0x80010626, + CELL_RTC_ERROR_INVALID_MICROSECOND = 0x80010627, +}; + +struct CellRtcTick +{ + u64 tick; +}; + +struct CellRtcDateTime +{ + u16 year; + u16 month; + u16 day; + u16 hour; + u16 minute; + u16 second; + u32 microsecond; +}; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index daad045b0f..5eff43752a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -7,9 +7,9 @@ SMutexGeneral g_mutex_avcodec_open2; extern "C" { -#include "libavcodec\avcodec.h" -#include "libavformat\avformat.h" -#include "libavutil\imgutils.h" +#include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include "libavutil/imgutils.h" } #include "cellVdec.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp index d889553017..bae2bf372b 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp @@ -3,61 +3,14 @@ #include "Emu/SysCalls/SC_FUNC.h" #include "sceNp.h" +#include "sceNpTrophy.h" #include "Loader/TRP.h" void sceNpTrophy_unload(); void sceNpTrophy_init(); Module sceNpTrophy(0xf035, sceNpTrophy_init, nullptr, sceNpTrophy_unload); -enum -{ - SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED = 0x80022901, - SCE_NP_TROPHY_ERROR_NOT_INITIALIZED = 0x80022902, - SCE_NP_TROPHY_ERROR_NOT_SUPPORTED = 0x80022903, - SCE_NP_TROPHY_ERROR_CONTEXT_NOT_REGISTERED = 0x80022904, - SCE_NP_TROPHY_ERROR_OUT_OF_MEMORY = 0x80022905, - SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT = 0x80022906, - SCE_NP_TROPHY_ERROR_EXCEEDS_MAX = 0x80022907, - SCE_NP_TROPHY_ERROR_INSUFFICIENT = 0x80022909, - SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT = 0x8002290a, - SCE_NP_TROPHY_ERROR_INVALID_FORMAT = 0x8002290b, - SCE_NP_TROPHY_ERROR_BAD_RESPONSE = 0x8002290c, - SCE_NP_TROPHY_ERROR_INVALID_GRADE = 0x8002290d, - SCE_NP_TROPHY_ERROR_INVALID_CONTEXT = 0x8002290e, - SCE_NP_TROPHY_ERROR_PROCESSING_ABORTED = 0x8002290f, - SCE_NP_TROPHY_ERROR_ABORT = 0x80022910, - SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE = 0x80022911, - SCE_NP_TROPHY_ERROR_LOCKED = 0x80022912, - SCE_NP_TROPHY_ERROR_HIDDEN = 0x80022913, - SCE_NP_TROPHY_ERROR_CANNOT_UNLOCK_PLATINUM = 0x80022914, - SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED = 0x80022915, - SCE_NP_TROPHY_ERROR_INVALID_TYPE = 0x80022916, - SCE_NP_TROPHY_ERROR_INVALID_HANDLE = 0x80022917, - SCE_NP_TROPHY_ERROR_INVALID_NP_COMM_ID = 0x80022918, - SCE_NP_TROPHY_ERROR_UNKNOWN_NP_COMM_ID = 0x80022919, - SCE_NP_TROPHY_ERROR_DISC_IO = 0x8002291a, - SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST = 0x8002291b, - SCE_NP_TROPHY_ERROR_UNSUPPORTED_FORMAT = 0x8002291c, - SCE_NP_TROPHY_ERROR_ALREADY_INSTALLED = 0x8002291d, - SCE_NP_TROPHY_ERROR_BROKEN_DATA = 0x8002291e, - SCE_NP_TROPHY_ERROR_VERIFICATION_FAILURE = 0x8002291f, - SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID = 0x80022920, - SCE_NP_TROPHY_ERROR_UNKNOWN_TROPHY_ID = 0x80022921, - SCE_NP_TROPHY_ERROR_UNKNOWN_TITLE = 0x80022922, - SCE_NP_TROPHY_ERROR_UNKNOWN_FILE = 0x80022923, - SCE_NP_TROPHY_ERROR_DISC_NOT_MOUNTED = 0x80022924, - SCE_NP_TROPHY_ERROR_SHUTDOWN = 0x80022925, - SCE_NP_TROPHY_ERROR_TITLE_ICON_NOT_FOUND = 0x80022926, - SCE_NP_TROPHY_ERROR_TROPHY_ICON_NOT_FOUND = 0x80022927, - SCE_NP_TROPHY_ERROR_INSUFFICIENT_DISK_SPACE = 0x80022928, - SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE = 0x8002292a, - SCE_NP_TROPHY_ERROR_SAVEDATA_USER_DOES_NOT_MATCH = 0x8002292b, - SCE_NP_TROPHY_ERROR_TROPHY_ID_DOES_NOT_EXIST = 0x8002292c, - SCE_NP_TROPHY_ERROR_SERVICE_UNAVAILABLE = 0x8002292d, - SCE_NP_TROPHY_ERROR_UNKNOWN = 0x800229ff, -}; - - +// Internal Structs struct sceNpTrophyInternalContext { // TODO @@ -115,15 +68,15 @@ int sceNpTrophyCreateContext(mem32_t context, mem_ptr_t co { if (entry->flags & DirEntry_TypeDir) { - std::shared_ptr f(Emu.GetVFS().OpenFile("/app_home/TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead)); + vfsStream* stream = Emu.GetVFS().OpenFile("/app_home/TROPDIR/" + entry->name + "/TROPHY.TRP", vfsRead); - if (f && f->IsOpened()) + if (stream && stream->IsOpened()) { sceNpTrophyInternalContext ctxt; - ctxt.trp_stream = f.get(); + ctxt.trp_stream = stream; ctxt.trp_name = entry->name; s_npTrophyInstance.contexts.push_back(ctxt); - f = nullptr; + stream = nullptr; return CELL_OK; } } @@ -253,9 +206,23 @@ int sceNpTrophyGetTrophyIcon() return CELL_OK; } -int sceNpTrophyGetTrophyInfo() +int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, mem_ptr_t details, mem_ptr_t data) { - UNIMPLEMENTED_FUNC(sceNpTrophy); + sceNpTrophy.Warning("sceNpTrophyGetTrophyInfo(context=%u, handle=%u, trophyId=%d, details_addr=0x%x, data_addr=0x%x)", + context, handle, trophyId, details.GetAddr(), data.GetAddr()); + + if (!s_npTrophyInstance.m_bInitialized) + return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED; + if (!details.IsGood() || !data.IsGood()) + return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT; + // TODO: There are other possible errors + + // sceNpTrophyInternalContext& ctxt = s_npTrophyInstance.contexts[context]; + memcpy(details->name, "Some Trophy", SCE_NP_TROPHY_NAME_MAX_SIZE); + memcpy(details->description, "Hey! Implement a XML reader, and load the description from TROP.SFM", SCE_NP_TROPHY_DESCR_MAX_SIZE); + details->hidden = false; + details->trophyId = trophyId; + details->trophyGrade = SCE_NP_TROPHY_GRADE_GOLD; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h new file mode 100644 index 0000000000..2bcf4b15c8 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.h @@ -0,0 +1,84 @@ +#pragma once +#include "cellRtc.h" + +enum +{ + SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED = 0x80022901, + SCE_NP_TROPHY_ERROR_NOT_INITIALIZED = 0x80022902, + SCE_NP_TROPHY_ERROR_NOT_SUPPORTED = 0x80022903, + SCE_NP_TROPHY_ERROR_CONTEXT_NOT_REGISTERED = 0x80022904, + SCE_NP_TROPHY_ERROR_OUT_OF_MEMORY = 0x80022905, + SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT = 0x80022906, + SCE_NP_TROPHY_ERROR_EXCEEDS_MAX = 0x80022907, + SCE_NP_TROPHY_ERROR_INSUFFICIENT = 0x80022909, + SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT = 0x8002290a, + SCE_NP_TROPHY_ERROR_INVALID_FORMAT = 0x8002290b, + SCE_NP_TROPHY_ERROR_BAD_RESPONSE = 0x8002290c, + SCE_NP_TROPHY_ERROR_INVALID_GRADE = 0x8002290d, + SCE_NP_TROPHY_ERROR_INVALID_CONTEXT = 0x8002290e, + SCE_NP_TROPHY_ERROR_PROCESSING_ABORTED = 0x8002290f, + SCE_NP_TROPHY_ERROR_ABORT = 0x80022910, + SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE = 0x80022911, + SCE_NP_TROPHY_ERROR_LOCKED = 0x80022912, + SCE_NP_TROPHY_ERROR_HIDDEN = 0x80022913, + SCE_NP_TROPHY_ERROR_CANNOT_UNLOCK_PLATINUM = 0x80022914, + SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED = 0x80022915, + SCE_NP_TROPHY_ERROR_INVALID_TYPE = 0x80022916, + SCE_NP_TROPHY_ERROR_INVALID_HANDLE = 0x80022917, + SCE_NP_TROPHY_ERROR_INVALID_NP_COMM_ID = 0x80022918, + SCE_NP_TROPHY_ERROR_UNKNOWN_NP_COMM_ID = 0x80022919, + SCE_NP_TROPHY_ERROR_DISC_IO = 0x8002291a, + SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST = 0x8002291b, + SCE_NP_TROPHY_ERROR_UNSUPPORTED_FORMAT = 0x8002291c, + SCE_NP_TROPHY_ERROR_ALREADY_INSTALLED = 0x8002291d, + SCE_NP_TROPHY_ERROR_BROKEN_DATA = 0x8002291e, + SCE_NP_TROPHY_ERROR_VERIFICATION_FAILURE = 0x8002291f, + SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID = 0x80022920, + SCE_NP_TROPHY_ERROR_UNKNOWN_TROPHY_ID = 0x80022921, + SCE_NP_TROPHY_ERROR_UNKNOWN_TITLE = 0x80022922, + SCE_NP_TROPHY_ERROR_UNKNOWN_FILE = 0x80022923, + SCE_NP_TROPHY_ERROR_DISC_NOT_MOUNTED = 0x80022924, + SCE_NP_TROPHY_ERROR_SHUTDOWN = 0x80022925, + SCE_NP_TROPHY_ERROR_TITLE_ICON_NOT_FOUND = 0x80022926, + SCE_NP_TROPHY_ERROR_TROPHY_ICON_NOT_FOUND = 0x80022927, + SCE_NP_TROPHY_ERROR_INSUFFICIENT_DISK_SPACE = 0x80022928, + SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE = 0x8002292a, + SCE_NP_TROPHY_ERROR_SAVEDATA_USER_DOES_NOT_MATCH = 0x8002292b, + SCE_NP_TROPHY_ERROR_TROPHY_ID_DOES_NOT_EXIST = 0x8002292c, + SCE_NP_TROPHY_ERROR_SERVICE_UNAVAILABLE = 0x8002292d, + SCE_NP_TROPHY_ERROR_UNKNOWN = 0x800229ff, +}; + +enum +{ + SCE_NP_TROPHY_TITLE_MAX_SIZE = 128, + SCE_NP_TROPHY_GAME_DESCR_MAX_SIZE = 1024, + SCE_NP_TROPHY_NAME_MAX_SIZE = 128, + SCE_NP_TROPHY_DESCR_MAX_SIZE = 1024, +}; + +enum +{ + SCE_NP_TROPHY_GRADE_UNKNOWN = 0, + SCE_NP_TROPHY_GRADE_PLATINUM = 1, + SCE_NP_TROPHY_GRADE_GOLD = 2, + SCE_NP_TROPHY_GRADE_SILVER = 3, + SCE_NP_TROPHY_GRADE_BRONZE = 4, +}; + +struct SceNpTrophyDetails +{ + s32 trophyId; // SceNpTrophyId + u32 trophyGrade; // SceNpTrophyGrade + u8 name[SCE_NP_TROPHY_NAME_MAX_SIZE]; + u8 description[SCE_NP_TROPHY_DESCR_MAX_SIZE]; + bool hidden; + u8 reserved[3]; +}; + +struct SceNpTrophyData { + CellRtcTick timestamp; + s32 trophyId; // SceNpTrophyId + bool unlocked; + u8 reserved[3]; +}; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index 0c51ef825d..80b425bf02 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -472,7 +472,7 @@ int cellFsGetFreeSize(u32 path_addr, mem32_t block_size, mem64_t block_count) sys_fs.Warning("cellFsGetFreeSize(path=\"%s\", block_size_addr=0x%x, block_count_addr=0x%x)", ps3_path.wx_str(), block_size.GetAddr(), block_count.GetAddr()); - if (Memory.IsGoodAddr(path_addr) || !block_size.IsGood() || !block_count.IsGood()) + if (!Memory.IsGoodAddr(path_addr) || !block_size.IsGood() || !block_count.IsGood()) return CELL_EFAULT; if (ps3_path.empty()) diff --git a/rpcs3/cmake_modules/FindFFMPEG.cmake b/rpcs3/cmake_modules/FindFFMPEG.cmake new file mode 100644 index 0000000000..6be21cd8ab --- /dev/null +++ b/rpcs3/cmake_modules/FindFFMPEG.cmake @@ -0,0 +1,79 @@ +# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) +# Once done this will define +# +# FFMPEG_FOUND - system has ffmpeg or libav +# FFMPEG_INCLUDE_DIR - the ffmpeg include directory +# FFMPEG_LIBRARIES - Link these to use ffmpeg +# FFMPEG_LIBAVCODEC +# FFMPEG_LIBAVFORMAT +# FFMPEG_LIBAVUTIL +# +# Copyright (c) 2008 Andreas Schneider +# Modified for other libraries by Lasse Kärkkäinen +# Modified for Hedgewars by Stepik777 +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# + +if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + # in cache already + set(FFMPEG_FOUND TRUE) +else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(_FFMPEG_AVCODEC libavcodec) + pkg_check_modules(_FFMPEG_AVFORMAT libavformat) + pkg_check_modules(_FFMPEG_AVUTIL libavutil) + endif (PKG_CONFIG_FOUND) + + find_path(FFMPEG_AVCODEC_INCLUDE_DIR + NAMES libavcodec/avcodec.h + PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} /usr/include /usr/local/include /opt/local/include /sw/include + PATH_SUFFIXES ffmpeg libav + ) + + find_library(FFMPEG_LIBAVCODEC + NAMES avcodec + PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib + ) + + find_library(FFMPEG_LIBAVFORMAT + NAMES avformat + PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib + ) + + find_library(FFMPEG_LIBAVUTIL + NAMES avutil + PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib + ) + + if (FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT) + set(FFMPEG_FOUND TRUE) + endif() + + if (FFMPEG_FOUND) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) + + set(FFMPEG_LIBRARIES + ${FFMPEG_LIBAVCODEC} + ${FFMPEG_LIBAVFORMAT} + ${FFMPEG_LIBAVUTIL} + ) + + endif (FFMPEG_FOUND) + + if (FFMPEG_FOUND) + if (NOT FFMPEG_FIND_QUIETLY) + message(STATUS "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") + endif (NOT FFMPEG_FIND_QUIETLY) + else (FFMPEG_FOUND) + if (FFMPEG_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libavcodec or libavformat or libavutil") + endif (FFMPEG_FIND_REQUIRED) + endif (FFMPEG_FOUND) + +endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index c6395389c0..536f9ac22e 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -291,6 +291,8 @@ + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 3eb2bd8980..f54b21548b 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -436,9 +436,17 @@ Crypto + Emu\SysCalls + + Emu\SysCalls\Modules + + + + Emu\SysCalls\Modules + Emu\SysCalls\Modules From 3127543b6e0f1763e5336611c036c07b3a457aad Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 7 Mar 2014 16:03:42 +0400 Subject: [PATCH 6/7] sys_ppu_thread_join, sys_ppu_thread_exit fixed Some diagnostic messages in mutexes --- rpcs3/Emu/CPU/CPUThread.cpp | 2 +- rpcs3/Emu/CPU/CPUThread.h | 8 +-- rpcs3/Emu/Cell/PPUInterpreter.h | 7 +- rpcs3/Emu/Cell/PPUThread.cpp | 1 + rpcs3/Emu/Cell/PPUThread.h | 3 + rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 15 +++- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 88 ++++++++++++++++++++++-- rpcs3/Emu/SysCalls/Static.cpp | 4 +- rpcs3/Emu/SysCalls/SysCalls.h | 4 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 32 ++++++++- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h | 2 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 71 ++++++++++++++----- rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp | 39 ++++++----- 13 files changed, 220 insertions(+), 56 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index e2ce343447..1ec31434b2 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -361,7 +361,7 @@ void CPUThread::Task() if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str()); } -int CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe +s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) // not multithread-safe { while (m_alive) { diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 4c0e94ed01..3c2bbafd3e 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -57,7 +57,7 @@ protected: u64 m_stack_size; u64 m_stack_point; - u32 m_exit_status; + u64 m_exit_status; CPUDecoder* m_dec; @@ -80,10 +80,10 @@ public: void SetName(const std::string& name); void SetPrio(const u64 prio) { m_prio = prio; } void SetOffset(const u64 offset) { m_offset = offset; } - void SetExitStatus(const u32 status) { m_exit_status = status; } + void SetExitStatus(const u64 status) { m_exit_status = status; } u64 GetOffset() const { return m_offset; } - u32 GetExitStatus() const { return m_exit_status; } + u64 GetExitStatus() const { return m_exit_status; } u64 GetPrio() const { return m_prio; } std::string GetName() const { return NamedThreadBase::GetThreadName(); } @@ -234,7 +234,7 @@ public: return pc + 4; } - int ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); + s64 ExecAsCallback(u64 pc, bool wait, u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); protected: virtual void DoReset()=0; diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 32fbdd0a3b..708e4d3408 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -2096,8 +2096,11 @@ private: case 0x2: SysCall(); break; case 0x3: StaticExecute(CPU.GPR[11]); - ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx", - wxString(g_static_funcs_list[CPU.GPR[11]].name).wx_str(), CPU.GPR[3], CPU.PC); + if (Ini.HLELogging.GetValue()) + { + ConLog.Write("'%s' done with code[0x%llx]! #pc: 0x%llx", + wxString(g_static_funcs_list[CPU.GPR[11]].name).wx_str(), CPU.GPR[3], CPU.PC); + } break; case 0x22: UNK("HyperCall LV1"); break; default: UNK(wxString::Format("Unknown sc: %x", sc_code)); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 1c1c903b50..bd6c6570e5 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -17,6 +17,7 @@ PPUThread& GetCurrentPPUThread() PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU) { + owned_mutexes = 0; Reset(); } diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index b4a12efedf..fbb53bf1ae 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -525,6 +525,9 @@ static const s32 MAX_INT_VALUE = 0x7fffffff; class PPUThread : public PPCThread { +public: + std::atomic owned_mutexes; + public: PPCdouble FPR[32]; //Floating Point Register FPSCRhdr FPSCR; //Floating Point Status and Control Register diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index a664683a29..96ad7083a6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -80,8 +80,8 @@ u32 dmuxOpen(Demuxer* data) cb.SetAddr(dmux.cbFunc); cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ - dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); - updates_signaled++; + //dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); + //updates_signaled++; } else switch (code.ToLE()) { @@ -584,6 +584,17 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize return CELL_DMUX_ERROR_FATAL; } + if (dmux->is_running) // maximum hack + { + mem_ptr_t dmuxMsg(a128(dmux->memAddr) + 128); + dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; + dmuxMsg->supplementalInfo = 0; // !!! + Callback cb; + cb.SetAddr(dmux->cbFunc); + cb.Handle(dmux->id, dmuxMsg.GetAddr(), dmux->cbArg); + cb.Branch(true); + } + while (dmux->is_running) // hack { if (Emu.IsStopped()) diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index 81ed26a5a8..cb2b3bb547 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -13,20 +13,21 @@ int cellAANAddData(u32 handle, u32 port, u32 offset, u32 addr, u32 samples) return CELL_OK; } -// libmixer Functions, NOT active in this moment -/*int cellAANConnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) +int cellAANConnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) { - UNIMPLEMENTED_FUNC(libmixer); + libmixer.Error("cellAANConnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcrPortNo=0x%x)", + receive, receivePortNo, source, sourcePortNo); return 0; } -int cellAANDisconnect(CellAANHandle receive, u32 receivePortNo, CellAANHandle source, u32 sourcePortNo) +int cellAANDisconnect(u32 receive, u32 receivePortNo, u32 source, u32 sourcePortNo) { - UNIMPLEMENTED_FUNC(libmixer); + libmixer.Error("cellAANDisconnect(receive=0x%x, receivePortNo=0x%x, source=0x%x, sourcrPortNo=0x%x)", + receive, receivePortNo, source, sourcePortNo); return 0; } -int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config) +/*int cellSSPlayerCreate(CellAANHandle *handle, CellSSPlayerConfig *config) { UNIMPLEMENTED_FUNC(libmixer); return 0; @@ -182,7 +183,6 @@ void libmixer_init() 0xffffffff81690000, 0xffffffff7c050378, 0xffffffff7cc43378, - // 78 63 00 20 clrldi r3,r3,32 # 20 // may be included 0xffffffff7d465378, 0xffffffff812b0030, 0xffffffff80090000, @@ -200,6 +200,80 @@ void libmixer_init() }; libmixer.AddFuncSub(cellAANAddData_table, "cellAANAddData", cellAANAddData); + u64 cellAANConnect_table[39] = { + 0xfffffffff821ff71, + 0xffffffff7c0802a6, + 0xffffffff2f830000, + 0xfffffffff80100a0, + 0xffffffff3c008031, + 0xffffffff7c691b78, + 0xffffffff7c8a2378, + 0xffffffff60000003, + 0xffffff00409e0018, // bne + 0xffffffff7c0307b4, + 0xffffffffe80100a0, + 0xffffffff38210090, + 0xffffffff7c0803a6, + 0xffffffff4e800020, + 0xffffffff2f850000, + 0xffffffff78630020, + 0xffffffff38810070, + 0xffffff00419effe0, // beq + 0xffffffff81690000, + 0xffffffff38000001, + 0xffffffff91210074, + 0xffffffff90a10070, + 0xffffffff90c10078, + 0xffffffff9141007c, + 0xffffffff812b0018, // [24] + 0xffffffff90010080, + 0xffffffff80090000, + 0xfffffffff8410028, + 0xffffffff7c0903a6, + 0xffffffff80490004, + 0xffffffff4e800421, + 0xffffffffe8410028, + 0xffffffff7c601b78, + 0xffffffff7c0307b4, + 0xffffffffe80100a0, + 0xffffffff38210090, + 0xffffffff7c0803a6, + 0xffffffff4e800020, + 0, // [38] + }; + libmixer.AddFuncSub(cellAANConnect_table, "cellAANConnect", cellAANConnect); + cellAANConnect_table[24] = 0xffffffff812b001c; + libmixer.AddFuncSub(cellAANConnect_table, "cellAANDisconnect", cellAANDisconnect); + + static const u64 cellAANAddData_table1[] = { + // TODO + 0xffffffff7c691b78, + 0xffffffff7c0802a6, + 0xfffffffff821ff91, + 0xfffffffff8010080, + 0xffffffff7c802378, + 0xffffffff7caa2b78, + 0xffffffff81690000, + 0xffffffff7c050378, + 0xffffffff7cc43378, + 0xffffffff78630020, // clrldi r3,r3,32 + 0xffffffff7d465378, + 0xffffffff812b0030, + 0xffffffff80090000, + 0xfffffffff8410028, + 0xffffffff7c0903a6, + 0xffffffff80490004, + 0xffffffff4e800421, + 0xffffffffe8410028, + 0xffffffffe8010080, + 0xffffffff7c6307b4, + 0xffffffff7c0803a6, + 0xffffffff38210070, + 0xffffffff4e800020, + 0 + }; + libmixer.AddFuncSub(cellAANAddData_table1, "cellAANAddData(1)", cellAANAddData); + static const u64 cellSurMixerCreate_table[] = { 0xffffffff2f830000, 0xffffffff7c0802a6, diff --git a/rpcs3/Emu/SysCalls/Static.cpp b/rpcs3/Emu/SysCalls/Static.cpp index 6d653a7b1c..2628a77272 100644 --- a/rpcs3/Emu/SysCalls/Static.cpp +++ b/rpcs3/Emu/SysCalls/Static.cpp @@ -9,6 +9,8 @@ void StaticAnalyse(void* ptr, u32 size) { u32* data = (u32*)ptr; size /= 4; + return; // disabled + // TODO: optimize search for (u32 i = 0; i < size; i++) { @@ -38,7 +40,7 @@ void StaticAnalyse(void* ptr, u32 size) data[i] = re(0x39600000 | j); // li r11, j data[i+1] = se32(0x44000003); // sc 3 data[i+2] = se32(0x4e800020); // blr - i += g_static_funcs_list[j].ops.GetCount(); // ??? + i += 2; // ??? } } } diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 988c1391e3..c97518f7a4 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -201,9 +201,9 @@ extern int sys_rwlock_trywlock(u32 rw_lock_id); extern int sys_rwlock_wunlock(u32 rw_lock_id); //ppu_thread -extern void sys_ppu_thread_exit(int errorcode); +extern void sys_ppu_thread_exit(u64 errorcode); extern int sys_ppu_thread_yield(); -extern int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr); +extern int sys_ppu_thread_join(u32 thread_id, mem64_t vptr); extern int sys_ppu_thread_detach(u32 thread_id); extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr); extern int sys_ppu_thread_set_priority(u32 thread_id, int prio); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 76a0cf4ebc..524c600033 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -207,17 +207,40 @@ int sys_lwmutex_t::trylock(be_t tid) { if (attribute.ToBE() == se32(0xDEADBEEF)) return CELL_EINVAL; + be_t owner_tid = mutex.GetOwner(); + + if (owner_tid != mutex.GetFreeValue()) + { + if (CPUThread* tt = Emu.GetCPU().GetThread(owner_tid)) + { + if (!tt->IsAlive()) + { + sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid); + mutex.unlock(owner_tid, tid); + recursive_count = 1; + return CELL_OK; + } + } + else + { + sc_lwmutex.Error("sys_lwmutex_t::(try)lock(%d): deadlock on invalid thread(%d)", (u32)sleep_queue, (u32)owner_tid); + mutex.unlock(owner_tid, tid); + recursive_count = 1; + return CELL_OK; + } + } + while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0) { if (Emu.IsStopped()) { - ConLog.Warning("(hack) sys_lwmutex_t::trylock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute); + ConLog.Warning("(hack) sys_lwmutex_t::(try)lock aborted (waiting for recursive attribute, attr=0x%x)", (u32)attribute); return CELL_ESRCH; } Sleep(1); } - if (tid == mutex.GetOwner()) + if (tid == owner_tid) { if (attribute.ToBE() & se32(SYS_SYNC_RECURSIVE)) { @@ -247,6 +270,11 @@ int sys_lwmutex_t::unlock(be_t tid) } else { + if (!recursive_count || (recursive_count.ToBE() != se32(1) && (attribute.ToBE() & se32(SYS_SYNC_NOT_RECURSIVE)))) + { + sc_lwmutex.Error("sys_lwmutex_t::unlock(%d): wrong recursive value (%d)", (u32)sleep_queue, (u32)recursive_count); + recursive_count = 1; + } recursive_count -= 1; if (!recursive_count.ToBE()) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 971363a92f..4a5481d0ce 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -65,7 +65,7 @@ struct SleepQueue struct sys_lwmutex_t { - /* volatile */ SMutexBase, ~0, 0> mutex; + /* volatile */ SMutexBase> mutex; /* volatile */ be_t waiter; // not used u64 &all_info(){return *(reinterpret_cast(this));} be_t attribute; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index d3921cbcc0..90c64b963f 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -95,7 +95,8 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) return CELL_ESRCH; } - u32 tid = GetCurrentPPUThread().GetId(); + PPUThread& t = GetCurrentPPUThread(); + u32 tid = t.GetId(); u32 owner = mutex->m_mutex.GetOwner(); if (owner == tid) @@ -113,17 +114,32 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) return CELL_EDEADLK; } } - else if (owner && !Emu.GetIdManager().CheckID(owner)) + else if (owner) { - sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - return CELL_OK; + if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) + { + if (!tt->IsAlive()) + { + 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; + } } switch (mutex->m_mutex.trylock(tid)) { - case SMR_OK: mutex->recursive = 1; return CELL_OK; + case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK; case SMR_FAILED: break; default: goto abort; } @@ -135,7 +151,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) case SMR_OK: mutex->m_queue.invalidate(tid); case SMR_SIGNAL: - mutex->recursive = 1; return CELL_OK; + mutex->recursive = 1; t.owned_mutexes++; return CELL_OK; case SMR_TIMEOUT: mutex->m_queue.invalidate(tid); return CELL_ETIMEDOUT; default: @@ -161,7 +177,8 @@ int sys_mutex_trylock(u32 mutex_id) return CELL_ESRCH; } - u32 tid = GetCurrentPPUThread().GetId(); + PPUThread& t = GetCurrentPPUThread(); + u32 tid = t.GetId(); u32 owner = mutex->m_mutex.GetOwner(); if (owner == tid) @@ -179,17 +196,32 @@ int sys_mutex_trylock(u32 mutex_id) return CELL_EDEADLK; } } - else if (owner && !Emu.GetIdManager().CheckID(owner)) + else if (owner) { - sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - mutex->m_mutex.unlock(owner, tid); - mutex->recursive = 1; - return CELL_OK; + if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) + { + if (!tt->IsAlive()) + { + 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; + } } switch (mutex->m_mutex.trylock(tid)) { - case SMR_OK: mutex->recursive = 1; return CELL_OK; + case SMR_OK: mutex->recursive = 1; t.owned_mutexes++; return CELL_OK; } return CELL_EBUSY; @@ -205,18 +237,21 @@ int sys_mutex_unlock(u32 mutex_id) return CELL_ESRCH; } - u32 tid = GetCurrentPPUThread().GetId(); + PPUThread& t = GetCurrentPPUThread(); + u32 tid = t.GetId(); if (mutex->m_mutex.GetOwner() == tid) { - if (!mutex->recursive || (mutex->recursive > 1 && !mutex->is_recursive)) + if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) { - sys_mtx.Warning("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive); + sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive); + mutex->recursive = 1; } mutex->recursive--; if (!mutex->recursive) { mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()); + t.owned_mutexes--; } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index fb39296f6e..30c31bea17 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -10,24 +10,21 @@ enum SYS_PPU_THREAD_DONE_INIT, }; -void sys_ppu_thread_exit(int errorcode) +void sys_ppu_thread_exit(u64 errorcode) { - if(errorcode == 0) - { - sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode); - } - else - { - sysPrxForUser.Warning("sys_ppu_thread_exit(errorcode=%d)", errorcode); - } + sysPrxForUser.Log("sys_ppu_thread_exit(0x%llx)", errorcode); PPUThread& thr = GetCurrentPPUThread(); + u32 tid = thr.GetId(); + + if (thr.owned_mutexes) + { + ConLog.Error("Owned mutexes found (%d)", thr.owned_mutexes); + thr.owned_mutexes = 0; + } + thr.SetExitStatus(errorcode); thr.Stop(); - - //Emu.GetCPU().RemoveThread(thr.GetId()); - - //throw errorcode; } int sys_ppu_thread_yield() @@ -37,14 +34,24 @@ int sys_ppu_thread_yield() return CELL_OK; } -int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr) +int sys_ppu_thread_join(u32 thread_id, mem64_t vptr) { - sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr_addr); + sysPrxForUser.Warning("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr.GetAddr()); CPUThread* thr = Emu.GetCPU().GetThread(thread_id); if(!thr) return CELL_ESRCH; - GetCurrentPPUThread().Wait(*thr); + while (thr->IsAlive()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("sys_ppu_thread_join(%d) aborted", thread_id); + return CELL_OK; + } + Sleep(1); + } + + vptr = thr->GetExitStatus(); return CELL_OK; } From 1c302433af31ab4b57271f3fd620318b6fb32c93 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 8 Mar 2014 01:31:08 +0400 Subject: [PATCH 7/7] cellSpurs draft added --- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 2 + rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 46 ++-- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 41 +++- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 235 ++++++++++++++++++ rpcs3/Emu/SysCalls/Modules/cellSpurs.h | 296 +++++++++++++++++++++++ rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 9 +- rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp | 54 ++++- rpcs3/Emu/SysCalls/lv2/SC_Event.cpp | 12 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp | 18 +- rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h | 2 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp | 23 +- rpcs3/Emu/SysCalls/lv2/SC_Mutex.h | 18 ++ rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 9 +- 14 files changed, 696 insertions(+), 70 deletions(-) create mode 100644 rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp create mode 100644 rpcs3/Emu/SysCalls/Modules/cellSpurs.h diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 76550a38e3..94a754d8e4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -53,6 +53,8 @@ u32 adecOpen(AudioDecoder* data) adec.id = adec_id; + adec.adecCb->SetName("Audio Decoder[" + std::to_string(adec_id) + "] Callback"); + thread t("Audio Decoder[" + std::to_string(adec_id) + "] Thread", [&]() { ConLog.Write("Audio Decoder enter()"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 96ad7083a6..36b8ffef44 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x2000000; // 0x45fa49 from ps3 + attr->memSize = 0x1000000; // 0x45fa49 from ps3 else - attr->memSize = 0x100000; // 0x73d9 from ps3 + attr->memSize = 0x200000; // 0x73d9 from ps3 cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); @@ -36,6 +36,8 @@ u32 dmuxOpen(Demuxer* data) dmux.id = dmux_id; + dmux.dmuxCb->SetName("Demuxer[" + std::to_string(dmux_id) + "] Callback"); + thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]() { ConLog.Write("Demuxer enter (mem=0x%x, size=0x%x, cb=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc, dmux.cbArg); @@ -80,8 +82,8 @@ u32 dmuxOpen(Demuxer* data) cb.SetAddr(dmux.cbFunc); cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); cb.Branch(task.type == dmuxResetStreamAndWaitDone);*/ - //dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); - //updates_signaled++; + dmux.dmuxCb->ExecAsCallback(dmux.cbFunc, true, dmux.id, dmuxMsg.GetAddr(), dmux.cbArg); + updates_signaled++; } else switch (code.ToLE()) { @@ -146,6 +148,12 @@ u32 dmuxOpen(Demuxer* data) Sleep(1); } + /*if (es.hasunseen()) // hack, probably useless + { + stream = backup; + continue; + }*/ + //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); es.push(stream, len - pes.size - 3, pes); @@ -365,11 +373,11 @@ u32 dmuxOpen(Demuxer* data) } break; - case dmuxReleaseAu: + /*case dmuxReleaseAu: { task.es.es_ptr->release(); } - break; + break;*/ case dmuxFlushEs: { @@ -584,18 +592,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize return CELL_DMUX_ERROR_FATAL; } - if (dmux->is_running) // maximum hack - { - mem_ptr_t dmuxMsg(a128(dmux->memAddr) + 128); - dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE; - dmuxMsg->supplementalInfo = 0; // !!! - Callback cb; - cb.SetAddr(dmux->cbFunc); - cb.Handle(dmux->id, dmuxMsg.GetAddr(), dmux->cbArg); - cb.Branch(true); - } - - while (dmux->is_running) // hack + while (dmux->is_running) // !!! { if (Emu.IsStopped()) { @@ -603,7 +600,7 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize break; } Sleep(1); - //return CELL_DMUX_ERROR_BUSY; + return CELL_DMUX_ERROR_BUSY; } DemuxerTask task(dmuxSetStream); @@ -938,14 +935,19 @@ int cellDmuxReleaseAu(u32 esHandle) { cellDmux.Error("cellDmuxReleaseAu: no AU"); return CELL_DMUX_ERROR_SEQ; - //return CELL_OK; } - DemuxerTask task(dmuxReleaseAu); + /*DemuxerTask task(dmuxReleaseAu); task.es.es = esHandle; task.es.es_ptr = es; - es->dmux->job.Push(task); + es->dmux->job.Push(task);*/ + + if (!es->release()) + { + cellDmux.Error("cellDmuxReleaseAu failed"); + return CELL_DMUX_ERROR_SEQ; + } return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index 5da56f721e..cc504fe2f0 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -426,7 +426,6 @@ enum DemuxerJobType dmuxEnableEs, dmuxDisableEs, dmuxResetEs, - dmuxReleaseAu, dmuxFlushEs, dmuxClose, }; @@ -534,8 +533,9 @@ public: return last_size; } - bool isfull() // not multithread-safe + bool isfull() { + SMutexLocker lock(mutex); if (first_addr) { if (first_addr > last_addr) @@ -581,7 +581,24 @@ 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); - if (isfull()) + 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) { ConLog.Error("ElementaryStream::push(): buffer is full"); Emu.Pause(); @@ -634,20 +651,26 @@ public: return first_addr; } - void release() + 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); + //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()) { ConLog.Error("ElementaryStream::release(): buffer is empty"); - Emu.Pause(); - return; + return false; } u32 size = a128(Memory.Read32(first_addr + 4) + 128); u32 new_addr = first_addr + size; - if (peek_addr <= first_addr) peek_addr = new_addr; + + if (peek_addr == first_addr) + { + ConLog.Error("ElementaryStream::release(): buffer has not been seen yet"); + return false; + } + + //if (peek_addr <= first_addr) peek_addr = new_addr; if (new_addr == last_addr) { first_addr = 0; @@ -660,6 +683,8 @@ public: { first_addr = new_addr; } + + return true; } bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp new file mode 100644 index 0000000000..e6e9bbd98e --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -0,0 +1,235 @@ +#include "stdafx.h" +#include "cellSpurs.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" + +void cellSpurs_init(); +Module cellSpurs(0x000a, cellSpurs_init); + +int _cellSpursAttributeInitialize(mem_ptr_t attr, int nSpus, int spuPriority, + int ppuPriority, bool exitIfNoWork) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursAttributeSetMemoryContainerForSpuThread(mem_ptr_t attr, u32 container) +{ + cellSpurs.Warning("cellSpursAttributeSetMemoryContainerForSpuThread(attr_addr=0x%x, container=0x%x)", + attr.GetAddr(), container); + if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursAttributeSetNamePrefix(mem_ptr_t attr, const mem8_t prefix, u32 size) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursAttributeEnableSpuPrintfIfAvailable(mem_ptr_t attr) +{ + cellSpurs.Warning("cellSpursAttributeEnableSpuPrintfIfAvailable(attr_addr=0x%x)", attr.GetAddr()); + if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursAttributeSetSpuThreadGroupType(mem_ptr_t attr, int type) +{ + cellSpurs.Warning("cellSpursAttributeSetSpuThreadGroupType(attr_addr=0x%x, type=%u)", attr.GetAddr(), type); + if(!attr.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursAttributeEnableSystemWorkload(mem_ptr_t attr, const u8 priority[8], + uint maxSpu, const bool isPreemptible[8]) +{ + cellSpurs.Warning("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<9; i++) + if(priority[i] != 1 || maxSpu == 0) return CELL_SPURS_CORE_ERROR_INVAL; + + return CELL_OK; +} + +int cellSpursInitializeWithAttribute2(mem_ptr_t spurs, const mem_ptr_t attr) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursFinalize(mem_ptr_t spurs) +{ + cellSpurs.Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.GetAddr()); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursGetSpuThreadGroupId(mem_ptr_t spurs, mem32_t group) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursGetNumSpuThread(mem_ptr_t spurs, mem32_t nThreads) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursGetSpuThreadId(mem_ptr_t spurs, mem32_t thread, mem32_t nThreads) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursSetMaxContention(mem_ptr_t spurs, uint workloadId, uint maxContention) +{ + cellSpurs.Warning("cellSpursSetMaxContention(spurs_addr=0x%x, workloadId=%u, maxContention=%u)", + spurs.GetAddr(), workloadId, maxContention); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursSetPriorities(mem_ptr_t spurs, uint workloadId, const u8 priorities[CELL_SPURS_MAX_SPU]) +{ + cellSpurs.Warning("cellSpursSetPriorities(spurs_addr=0x%x, workloadId=%u, priorities[%u])", + spurs.GetAddr(), workloadId, priorities); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursSetPriority(mem_ptr_t spurs, uint workloadId, uint spuId, uint priority) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursSetPreemptionVictimHints(mem_ptr_t spurs, const bool isPreemptible[8]) +{ + cellSpurs.Warning("cellSpursSetPreemptionVictimHints(spurs_addr=0x%x, isPreemptible[%u])", + spurs.GetAddr(), isPreemptible); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursAttachLv2EventQueue(mem_ptr_t spurs, u32 queue, mem8_t port, int isDynamic) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursDetachLv2EventQueue(mem_ptr_t spurs, u8 port) +{ + cellSpurs.Warning("cellSpursDetachLv2EventQueue(spurs_addr=0x%x, port=0x%x)", spurs.GetAddr(), port); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursEnableExceptionEventHandler(mem_ptr_t spurs, bool flag) +{ + cellSpurs.Warning("cellSpursEnableExceptionEventHandler(spurs_addr=0x%x, flag=%u)", spurs.GetAddr(), flag); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursSetGlobalExceptionEventHandler(mem_ptr_t spurs, + mem_func_ptr_t eaHandler, mem_ptr_t arg) +{ + cellSpurs.Warning("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; + + return CELL_OK; +} + +int cellSpursUnsetGlobalExceptionEventHandler(mem_ptr_t spurs) +{ + cellSpurs.Warning("cellSpursUnsetGlobalExceptionEventHandler(spurs_addr=0x%x)", spurs.GetAddr()); + if(!spurs.IsGood()) return CELL_SPURS_CORE_ERROR_NULL_POINTER; + + return CELL_OK; +} + +int cellSpursGetInfo(mem_ptr_t spurs, mem_ptr_t info) +{ + cellSpurs.Warning("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; +} + +// Task functions +int cellSpursGetTasksetId(mem_ptr_t taskset, mem32_t workloadId) +{ + cellSpurs.Warning("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; +} + + + + +void cellSpurs_init() +{ + //libspurs core functions + cellSpurs.AddFunc(0x95180230, _cellSpursAttributeInitialize); + cellSpurs.AddFunc(0x82275c1c, cellSpursAttributeSetMemoryContainerForSpuThread); + cellSpurs.AddFunc(0x07529113, cellSpursAttributeSetNamePrefix); + cellSpurs.AddFunc(0x1051d134, cellSpursAttributeEnableSpuPrintfIfAvailable); + cellSpurs.AddFunc(0xa839a4d9, cellSpursAttributeSetSpuThreadGroupType); + cellSpurs.AddFunc(0x9dcbcb5d, cellSpursAttributeEnableSystemWorkload); + cellSpurs.AddFunc(0x30aa96c4, cellSpursInitializeWithAttribute2); + cellSpurs.AddFunc(0xca4c4600, cellSpursFinalize); + cellSpurs.AddFunc(0x39c173fb, cellSpursGetSpuThreadGroupId); + cellSpurs.AddFunc(0xc56defb5, cellSpursGetNumSpuThread); + cellSpurs.AddFunc(0x6c960f6d, cellSpursGetSpuThreadId); + cellSpurs.AddFunc(0x84d2f6d5,cellSpursSetMaxContention); + cellSpurs.AddFunc(0x80a29e27,cellSpursSetPriorities); + //cellSpurs.AddFunc(,cellSpursSetPriority); + cellSpurs.AddFunc(0x4de203e2, cellSpursSetPreemptionVictimHints); + cellSpurs.AddFunc(0xb9bc6207, cellSpursAttachLv2EventQueue); + cellSpurs.AddFunc(0x4e66d483, cellSpursDetachLv2EventQueue); + cellSpurs.AddFunc(0x32b94add, cellSpursEnableExceptionEventHandler); + cellSpurs.AddFunc(0x7517724a, cellSpursSetGlobalExceptionEventHandler); + cellSpurs.AddFunc(0x861237f8, cellSpursUnsetGlobalExceptionEventHandler); + cellSpurs.AddFunc(0x1f402f8f, cellSpursGetInfo); + + //libspurs task functions +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.h b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h new file mode 100644 index 0000000000..af9f4c4e6c --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.h @@ -0,0 +1,296 @@ +#pragma once + +// return codes +enum +{ + CELL_SPURS_CORE_ERROR_AGAIN = 0x80410701, + CELL_SPURS_CORE_ERROR_INVAL = 0x80410702, + CELL_SPURS_CORE_ERROR_NOMEM = 0x80410704, + CELL_SPURS_CORE_ERROR_SRCH = 0x80410705, + CELL_SPURS_CORE_ERROR_PERM = 0x80410709, + CELL_SPURS_CORE_ERROR_BUSY = 0x8041070A, + CELL_SPURS_CORE_ERROR_STAT = 0x8041070F, + CELL_SPURS_CORE_ERROR_ALIGN = 0x80410710, + CELL_SPURS_CORE_ERROR_NULL_POINTER = 0x80410711, +}; + +//defines +enum SPURSKernelInterfaces +{ + CELL_SPURS_MAX_SPU = 8, + CELL_SPURS_MAX_WORKLOAD = 16, + CELL_SPURS_MAX_WORKLOAD2 = 32, + CELL_SPURS_MAX_PRIORITY = 16, + CELL_SPURS_NAME_MAX_LENGTH = 15, + CELL_SPURS_SIZE = 4096, + CELL_SPURS_SIZE2 = 8192, + CELL_SPURS_ALIGN = 128, + CELL_SPURS_ATTRIBUTE_SIZE = 512, + CELL_SPURS_ATTRIBUTE_ALIGN = 8, + CELL_SPURS_INTERRUPT_VECTOR = 0x0, + CELL_SPURS_LOCK_LINE = 0x80, + CELL_SPURS_KERNEL_DMA_TAG_ID = 31, +}; + +enum RangeofEventQueuePortNumbers +{ + CELL_SPURS_STATIC_PORT_RANGE_BOTTOM = 15, + CELL_SPURS_DYNAMIC_PORT_RANGE_TOP = 16, + CELL_SPURS_DYNAMIC_PORT_RANGE_BOTTOM = 63, +}; + +enum SPURSTraceTypes +{ + CELL_SPURS_TRACE_TAG_LOAD = 0x2a, + CELL_SPURS_TRACE_TAG_MAP = 0x2b, + CELL_SPURS_TRACE_TAG_START = 0x2c, + CELL_SPURS_TRACE_TAG_STOP = 0x2d, + CELL_SPURS_TRACE_TAG_USER = 0x2e, + CELL_SPURS_TRACE_TAG_GUID = 0x2f, +}; + +struct CellSpursInfo +{ + be_t nSpus; + be_t spuThreadGroupPriority; + be_t ppuThreadPriority; + bool exitIfNoWork; + bool spurs2; + be_t traceBuffer_addr; //void *traceBuffer; + be_t traceBufferSize; + be_t traceMode; + be_t spuThreadGroup; //typedef u32 sys_spu_thread_group_t; + be_t spuThreads[8]; //typedef u32 sys_spu_thread_t; + be_t spursHandlerThread0; + be_t spursHandlerThread1; + char namePrefix[CELL_SPURS_NAME_MAX_LENGTH+1]; + be_t namePrefixLength; + be_t deadlineMissCounter; + be_t deadlineMeetCounter; + //u8 padding[]; +}; + +struct CellSpursExceptionInfo +{ + be_t spu_thread; + be_t spu_npc; + be_t cause; + be_t option; +}; + +struct CellSpursTraceInfo +{ + be_t spu_thread[8]; + be_t count[8]; + be_t spu_thread_grp; + be_t nspu; + //u8 padding[]; +}; + +__declspec(align(8)) struct CellTraceHeader +{ + u8 tag; + u8 length; + u8 cpu; + u8 thread; + be_t time; +}; + +struct CellSpursTracePacket +{ + struct header_struct + { + u8 tag; + u8 length; + u8 spu; + u8 workload; + be_t time; + } header; + + struct data_struct + { + struct load_struct + { + be_t ea; + be_t ls; + be_t size; + } load; + + struct map_struct + { + be_t offset; + be_t ls; + be_t size; + } map; + + struct start_struct + { + char module[4]; + be_t level; + be_t ls; + } start; + + be_t user; + be_t guid; + } data; +}; + +__declspec(align(128)) struct CellSpurs +{ + u8 skip[CELL_SPURS_SIZE]; +}; + +__declspec(align(128)) struct CellSpurs2 +{ + u8 skip[CELL_SPURS_SIZE2 - CELL_SPURS_SIZE]; +}; + +__declspec(align(8)) struct CellSpursAttribute +{ + u8 skip[CELL_SPURS_ATTRIBUTE_SIZE]; +}; + + +//typedef unsigned CellSpursWorkloadId; + +typedef void (*CellSpursGlobalExceptionEventHandler)(mem_ptr_t spurs, const mem_ptr_t info, + uint id, mem_ptr_t arg); + + +// task datatypes and constans +enum TaskConstants +{ + CELL_SPURS_MAX_TASK = 128, + CELL_SPURS_TASK_TOP = 0x3000, + CELL_SPURS_TASK_BOTTOM = 0x40000, + CELL_SPURS_MAX_TASK_NAME_LENGTH = 32, +}; + +enum +{ + CELL_SPURS_TASK_ERROR_AGAIN = 0x80410901, + CELL_SPURS_TASK_ERROR_INVAL = 0x80410902, + CELL_SPURS_TASK_ERROR_NOMEM = 0x80410904, + CELL_SPURS_TASK_ERROR_SRCH = 0x80410905, + CELL_SPURS_TASK_ERROR_NOEXEC = 0x80410907, + CELL_SPURS_TASK_ERROR_PERM = 0x80410909, + CELL_SPURS_TASK_ERROR_BUSY = 0x8041090A, + CELL_SPURS_TASK_ERROR_FAULT = 0x8041090D, + CELL_SPURS_TASK_ERROR_STAT = 0x8041090F, + CELL_SPURS_TASK_ERROR_ALIGN = 0x80410910, + CELL_SPURS_TASK_ERROR_NULL_POINTER = 0x80410911, + CELL_SPURS_TASK_ERROR_FATAL = 0x80410914, + CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920, +}; + + +__declspec(align(128)) struct CellSpursTaskset +{ + u8 skip[6400]; +}; + +typedef void(*CellSpursTasksetExceptionEventHandler)(mem_ptr_t spurs, mem_ptr_t taskset, + uint idTask, const mem_ptr_t info, mem_ptr_t arg); + + +struct CellSpursTasksetInfo +{ + //CellSpursTaskInfo taskInfo[CELL_SPURS_MAX_TASK]; + be_t argument; + be_t idWorkload; + be_t idLastScheduledTask; //typedef unsigned CellSpursTaskId + be_t name_addr; + CellSpursTasksetExceptionEventHandler exceptionEventHandler; + be_t exceptionEventHandlerArgument_addr; //void *exceptionEventHandlerArgument + be_t sizeTaskset; + //be_t reserved[]; +}; + + +/* +#define CELL_SPURS_TASKSET_CLASS0_SIZE (128 * 50) +#define _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE (128 + 128 * 16 + 128 * 15) +#define CELL_SPURS_TASKSET_CLASS1_SIZE (CELL_SPURS_TASKSET_CLASS0_SIZE + _CELL_SPURS_TASKSET_CLASS1_EXTENDED_SIZE) +#define CELL_SPURS_TASKSET2_SIZE (CELL_SPURS_TASKSET_CLASS1_SIZE) +#define CELL_SPURS_TASKSET2_ALIGN 128 +#define CELL_SPURS_TASKSET_ALIGN 128 +#define CELL_SPURS_TASKSET_SIZE CELL_SPURS_TASKSET_CLASS0_SIZE +*/ + +__declspec(align(128)) struct CellSpursTaskset2 +{ + be_t skip[10496]; +}; + +struct CellSpursTasksetAttribute2 +{ + be_t revision; + be_t name_addr; + be_t argTaskset; + u8 priority[8]; + be_t maxContention; + be_t enableClearLs; + be_t CellSpursTaskNameBuffer_addr; //??? *taskNameBuffer + //be_t __reserved__[]; +}; + +struct CellSpursTaskNameBuffer +{ + char taskName[CELL_SPURS_MAX_TASK][CELL_SPURS_MAX_TASK_NAME_LENGTH]; +}; + +struct CellSpursTraceTaskData +{ + be_t incident; + be_t task; +}; + +struct CellSpursTaskArgument +{ + be_t u32[4]; + be_t u64[2]; +}; + +struct CellSpursTaskLsPattern +{ + be_t u32[4]; + be_t u64[2]; +}; + +struct CellSpursTaskAttribute2 +{ + be_t revision; + be_t sizeContext; + be_t eaContext; + CellSpursTaskLsPattern lsPattern; //??? + be_t name_addr; + //be_t __reserved__[]; +}; + +__declspec(align(128)) struct CellSpursTaskExitCode +{ + unsigned char skip[128]; +}; + +struct CellSpursTaskInfo +{ + CellSpursTaskLsPattern lsPattern; + CellSpursTaskArgument argument; + const be_t eaElf_addr; //void *eaElf + const be_t eaContext_addr; //void *eaContext + be_t sizeContext; + be_t state; + be_t hasSignal; + const be_t CellSpursTaskExitCode_addr; + u8 guid[8]; + //be_t reserved[]; +}; + +struct CellSpursTaskBinInfo +{ + be_t eaElf; + be_t sizeContext; + be_t __reserved__; + CellSpursTaskLsPattern lsPattern; +}; + diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 5eff43752a..31fab366d6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -23,7 +23,7 @@ int vdecRead(void* opaque, u8* buf, int buf_size) int res = 0; - if (vdec.reader.size < (u32)buf_size) + if (vdec.reader.size < (u32)buf_size && !vdec.just_started) { while (vdec.job.IsEmpty()) { @@ -74,7 +74,10 @@ int vdecRead(void* opaque, u8* buf, int buf_size) ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type); return 0; } - //buf_size = vdec.reader.size; + } + else if (vdec.reader.size < (u32)buf_size) + { + buf_size = vdec.reader.size; } if (!buf_size) @@ -123,6 +126,8 @@ u32 vdecOpen(VideoDecoder* data) vdec.id = vdec_id; + vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback"); + thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]() { ConLog.Write("Video Decoder enter()"); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp index 97555928d8..8f0785ab96 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -77,8 +77,26 @@ int sys_cond_signal(u32 cond_id) 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; + } + if (!was_locked) // mutex hasn't been locked (don't care about mutex state) { + 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); @@ -117,8 +135,26 @@ int sys_cond_signal_all(u32 cond_id) 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); @@ -130,11 +166,11 @@ int sys_cond_signal_all(u32 cond_id) mutex->m_mutex.lock(tid); mutex->recursive = 1; } - } - if (Emu.IsStopped()) - { - ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id); + if (Emu.IsStopped()) + { + ConLog.Warning("sys_cond_signal_all(id=%d) aborted", cond_id); + } } return CELL_OK; @@ -169,6 +205,16 @@ int sys_cond_signal_to(u32 cond_id, u32 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); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp index 2e0e9abc2b..b662ee10c5 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Event.cpp @@ -74,17 +74,17 @@ int sys_event_queue_destroy(u32 equeue_id, int mode) u32 tid = GetCurrentPPUThread().GetId(); - eq->sq.m_mutex.lock(tid); + eq->sq.m_mutex.lock(); eq->owner.lock(tid); // check if some threads are waiting for an event if (!mode && eq->sq.list.GetCount()) { eq->owner.unlock(tid); - eq->sq.m_mutex.unlock(tid); + eq->sq.m_mutex.unlock(); return CELL_EBUSY; } eq->owner.unlock(tid, ~0); - eq->sq.m_mutex.unlock(tid); + eq->sq.m_mutex.unlock(); while (eq->sq.list.GetCount()) { Sleep(1); @@ -136,18 +136,18 @@ int sys_event_queue_tryreceive(u32 equeue_id, mem_ptr_t event_ar u32 tid = GetCurrentPPUThread().GetId(); - eq->sq.m_mutex.lock(tid); + eq->sq.m_mutex.lock(); eq->owner.lock(tid); if (eq->sq.list.GetCount()) { number = 0; eq->owner.unlock(tid); - eq->sq.m_mutex.unlock(tid); + eq->sq.m_mutex.unlock(); return CELL_OK; } number = eq->events.pop_all((sys_event_data*)(Memory + event_array.GetAddr()), size); eq->owner.unlock(tid); - eq->sq.m_mutex.unlock(tid); + eq->sq.m_mutex.unlock(); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 524c600033..10cd0af5ff 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -99,13 +99,13 @@ int sys_lwmutex_unlock(mem_ptr_t lwmutex) void SleepQueue::push(u32 tid) { - SMutexLocker lock(m_mutex); + std::lock_guard lock(m_mutex); list.AddCpy(tid); } u32 SleepQueue::pop() // SYS_SYNC_FIFO { - SMutexLocker lock(m_mutex); + std::lock_guard lock(m_mutex); while (true) { @@ -125,7 +125,7 @@ u32 SleepQueue::pop() // SYS_SYNC_FIFO u32 SleepQueue::pop_prio() // SYS_SYNC_PRIORITY { - SMutexLocker lock(m_mutex); + std::lock_guard lock(m_mutex); while (true) { @@ -171,7 +171,7 @@ u32 SleepQueue::pop_prio_inherit() // (TODO) bool SleepQueue::invalidate(u32 tid) { - SMutexLocker lock(m_mutex); + std::lock_guard lock(m_mutex); if (tid) for (u32 i = 0; i < list.GetCount(); i++) { @@ -187,15 +187,13 @@ bool SleepQueue::invalidate(u32 tid) bool SleepQueue::finalize() { - u32 tid = GetCurrentPPUThread().GetId(); - - m_mutex.lock(tid); + if (!m_mutex.try_lock()) return false; for (u32 i = 0; i < list.GetCount(); i++) { if (list[i]) { - m_mutex.unlock(tid); + m_mutex.unlock(); return false; } } @@ -230,7 +228,7 @@ int sys_lwmutex_t::trylock(be_t tid) } } - while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0) + /*while ((attribute.ToBE() & se32(SYS_SYNC_ATTR_RECURSIVE_MASK)) == 0) { if (Emu.IsStopped()) { @@ -238,7 +236,7 @@ int sys_lwmutex_t::trylock(be_t tid) return CELL_ESRCH; } Sleep(1); - } + }*/ if (tid == owner_tid) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 4a5481d0ce..2fa724b52d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h @@ -47,7 +47,7 @@ struct SleepQueue q_rec(u32 tid, u64 prio): tid(tid), prio(prio) {} }; */ Array list; - SMutex m_mutex; + std::mutex m_mutex; u64 m_name; SleepQueue(u64 name = 0) diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index 90c64b963f..ce1b3f51d3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -41,6 +41,7 @@ int sys_mutex_create(mem32_t mutex_id, mem_ptr_t attr) Mutex* mutex = new Mutex((u32)attr->protocol, is_recursive, attr->name_u64); u32 id = sys_mtx.GetNewId(mutex); mutex->m_mutex.lock(tid); + mutex->id = id; mutex_id = id; mutex->m_mutex.unlock(tid); sys_mtx.Warning("*** mutex created [%s] (protocol=0x%x, recursive=%s): id = %d", @@ -120,20 +121,20 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) { if (!tt->IsAlive()) { - sys_mtx.Error("sys_mutex_lock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - mutex->m_mutex.unlock(owner, tid); + 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; + 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->m_mutex.unlock(owner, tid); mutex->recursive = 1; t.owned_mutexes++; - return CELL_OK; + return CELL_OK;*/ } } @@ -202,20 +203,20 @@ int sys_mutex_trylock(u32 mutex_id) { if (!tt->IsAlive()) { - sys_mtx.Error("sys_mutex_trylock(%d): deadlock on invalid thread(%d)", mutex_id, owner); - mutex->m_mutex.unlock(owner, tid); + 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; + 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->m_mutex.unlock(owner, tid); mutex->recursive = 1; t.owned_mutexes++; - return CELL_OK; + return CELL_OK;*/ } } @@ -244,7 +245,7 @@ int sys_mutex_unlock(u32 mutex_id) { if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) { - sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value (%d)", mutex_id, mutex->recursive); + sys_mtx.Error("sys_mutex_unlock(%d): wrong recursive value fixed (%d)", mutex_id, mutex->recursive); mutex->recursive = 1; } mutex->recursive--; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h index 2366d1656a..735f20a240 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h @@ -18,6 +18,7 @@ struct sys_mutex_attribute struct Mutex { + u32 id; SMutex m_mutex; SleepQueue m_queue; u32 recursive; // recursive locks count @@ -33,4 +34,21 @@ struct Mutex , cond_count(0) { } + + ~Mutex() + { + if (u32 owner = m_mutex.GetOwner()) + { + ConLog.Write("Mutex(%d) was owned by thread %d (recursive=%d)", id, owner, recursive); + } + + if (!m_queue.m_mutex.try_lock()) return; + + for (u32 i = 0; i < m_queue.list.GetCount(); i++) + { + if (u32 owner = m_queue.list[i]) ConLog.Write("Mutex(%d) was waited by thread %d", id, owner); + } + + m_queue.m_mutex.unlock(); + } }; \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 536f9ac22e..c9c01f1c6d 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -297,6 +297,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 6db42d3034..197dd9a6cc 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -436,22 +436,19 @@ Crypto - - Emu\SysCalls - Emu\SysCalls\Modules - - Emu\SysCalls\Modules - + Emu\SysCalls\Modules + + Emu\SysCalls\Modules