diff --git a/rpcs3/Emu/Audio/AudioDumper.cpp b/rpcs3/Emu/Audio/AudioDumper.cpp index f906b3531a..dbd282e7ae 100644 --- a/rpcs3/Emu/Audio/AudioDumper.cpp +++ b/rpcs3/Emu/Audio/AudioDumper.cpp @@ -23,16 +23,22 @@ void AudioDumper::WriteHeader() size_t AudioDumper::WriteData(const void* buffer, size_t size) { + for (u32 i = 0; i < size / 8; i++) + { + if (((u64*)buffer)[i]) goto process; + } + for (u32 i = 0; i < size % 8; i++) + { + if (((u8*)buffer)[i + (size & ~7)]) goto process; + } + return size; // ignore empty data +process: size_t ret = m_output.Write(buffer, size); + m_header.Size += ret; + m_header.RIFF.Size += ret; return ret; } -void AudioDumper::UpdateHeader(size_t size) -{ - m_header.Size += size; - m_header.RIFF.Size += size; -} - void AudioDumper::Finalize() { m_output.Seek(0); diff --git a/rpcs3/Emu/Audio/AudioDumper.h b/rpcs3/Emu/Audio/AudioDumper.h index 6d1d8568e1..f9ac030476 100644 --- a/rpcs3/Emu/Audio/AudioDumper.h +++ b/rpcs3/Emu/Audio/AudioDumper.h @@ -64,6 +64,5 @@ public: bool Init(); void WriteHeader(); size_t WriteData(const void* buffer, size_t size); - void UpdateHeader(size_t size); void Finalize(); }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index a2805567c4..2db1e956df 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -9,6 +9,7 @@ extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libswresample/swresample.h" } #include "cellAdec.h" @@ -16,7 +17,7 @@ extern "C" void cellAdec_init(); Module cellAdec(0x0006, cellAdec_init); -int adecRead(void* opaque, u8* buf, int buf_size) +int adecRawRead(void* opaque, u8* buf, int buf_size) { AudioDecoder& adec = *(AudioDecoder*)opaque; @@ -61,8 +62,9 @@ next: adec.reader.addr = adec.task.au.addr; adec.reader.size = adec.task.au.size; + //ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", adec.task.au.size, adec.task.au.pts); - adec.last_pts = adec.task.au.pts; + if (adec.last_pts > adec.task.au.pts) adec.last_pts = adec.task.au.pts; } break; default: @@ -95,6 +97,89 @@ next: } } +int adecRead(void* opaque, u8* buf, int buf_size) +{ + AudioDecoder& adec = *(AudioDecoder*)opaque; + + int res = 0; + + if (adec.reader.rem_size && adec.reader.rem) + { + if (buf_size < (int)adec.reader.rem_size) + { + ConLog.Error("adecRead: too small buf_size (rem_size = %d, buf_size = %d)", adec.reader.rem_size, buf_size); + Emu.Pause(); + return 0; + } + + memcpy(buf, adec.reader.rem, adec.reader.rem_size); + free(adec.reader.rem); + adec.reader.rem = nullptr; + buf += adec.reader.rem_size; + buf_size -= adec.reader.rem_size; + res += adec.reader.rem_size; + adec.reader.rem_size = 0; + } + + while (buf_size) + { + u8 header[8]; + if (adecRawRead(opaque, header, 8) < 8) break; + if (header[0] != 0x0f || header[1] != 0xd0) + { + ConLog.Error("adecRead: 0x0FD0 header not found"); + Emu.Pause(); + return 0; + } + + if (!adec.reader.init) + { + OMAHeader oma(1 /* atrac3p id */, header[2], header[3]); + if (buf_size < sizeof(oma) + 8) + { + ConLog.Error("adecRead: OMAHeader writing failed"); + Emu.Pause(); + return 0; + } + + memcpy(buf, &oma, sizeof(oma)); + buf += sizeof(oma); + buf_size -= sizeof(oma); + res += sizeof(oma); + + adec.reader.init = true; + } + else + { + } + + u32 size = (((header[2] & 0x3) << 8) | header[3]) * 8 + 8; // data to be read before next header + + //ConLog.Write("*** audio block read: size = 0x%x", size); + + if (buf_size < (int)size) + { + if (adecRawRead(opaque, buf, buf_size) < buf_size) break; // ??? + res += buf_size; + size -= buf_size; + buf_size = 0; + + adec.reader.rem = (u8*)malloc(size); + adec.reader.rem_size = size; + if (adecRawRead(opaque, adec.reader.rem, size) < (int)size) break; // ??? + } + else + { + if (adecRawRead(opaque, buf, size) < (int)size) break; // ??? + buf += size; + buf_size -= size; + res += size; + } + } + + return res; +} + u32 adecOpen(AudioDecoder* data) { AudioDecoder& adec = *data; @@ -146,6 +231,10 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = 0; adec.reader.size = 0; + adec.reader.init = false; + if (adec.reader.rem) free(adec.reader.rem); + adec.reader.rem = nullptr; + adec.reader.rem_size = 0; adec.is_running = true; adec.just_started = true; } @@ -175,8 +264,9 @@ u32 adecOpen(AudioDecoder* data) adec.reader.addr = task.au.addr; adec.reader.size = task.au.size; + //ConLog.Write("Audio AU: size = 0x%x, pts = 0x%llx", task.au.size, task.au.pts); - adec.last_pts = task.au.pts; + if (adec.last_pts > task.au.pts || adec.just_started) adec.last_pts = task.au.pts; struct AVPacketHolder : AVPacket { @@ -212,11 +302,11 @@ u32 adecOpen(AudioDecoder* data) if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); - } + }*/ if (adec.just_started) // deferred initialization { - err = avformat_open_input(&adec.fmt, NULL, NULL, NULL); + err = avformat_open_input(&adec.fmt, NULL, av_find_input_format("oma"), NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_open_input() failed"); @@ -230,7 +320,7 @@ u32 adecOpen(AudioDecoder* data) Emu.Pause(); break; } - err = avformat_find_stream_info(adec.fmt, NULL); + /*err = avformat_find_stream_info(adec.fmt, NULL); if (err) { ConLog.Error("adecDecodeAu: avformat_find_stream_info() failed"); @@ -242,6 +332,12 @@ u32 adecOpen(AudioDecoder* data) ConLog.Error("adecDecodeAu: no stream found"); Emu.Pause(); break; + }*/ + if (!avformat_new_stream(adec.fmt, codec)) + { + ConLog.Error("adecDecodeAu: avformat_new_stream() failed"); + Emu.Pause(); + break; } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data @@ -259,7 +355,7 @@ u32 adecOpen(AudioDecoder* data) break; } adec.just_started = false; - }*/ + } bool last_frame = false; @@ -271,7 +367,7 @@ u32 adecOpen(AudioDecoder* data) return; } - if (!adec.ctx) // fake + /*if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; @@ -285,7 +381,7 @@ u32 adecOpen(AudioDecoder* data) adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; - } + }*/ last_frame = av_read_frame(adec.fmt, &au) < 0; if (last_frame) @@ -336,13 +432,16 @@ u32 adecOpen(AudioDecoder* data) if (got_frame) { - ConLog.Write("got_frame (%d, pts=0x%llx, dts=0x%llx)", got_frame, au.pts, au.dts); - - frame.pts = task.au.pts; // ??? + frame.pts = adec.last_pts; + adec.last_pts += (u64)frame.data->nb_samples * 90000 / 48000; // ??? frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; - frame.size = 32768; // ???? + frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float); + + //ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d)", + //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate); + adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction @@ -569,26 +668,69 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) AdecFrame af; adec->frames.Pop(af); - //AVFrame& frame = *af.data; + AVFrame* frame = af.data; int result = CELL_OK; if (!Memory.IsGoodAddr(outBuffer_addr, af.size)) { result = CELL_ADEC_ERROR_FATAL; + goto end; } - else + + if (!af.data) // fake: empty data { - // 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; - } + /*u8* buf = (u8*)malloc(4096); + memset(buf, 0, 4096); + Memory.CopyFromReal(outBuffer_addr, buf, 4096); + free(buf);*/ + goto end; } + // copy data + SwrContext* swr = nullptr; + u8* out = nullptr; + + if (frame->format != AV_SAMPLE_FMT_FLTP) + { + ConLog.Error("cellAdecGetPcm(%d): unsupported frame format(%d)", handle, frame->format); + Emu.Pause(); + goto end; + } + + out = (u8*)malloc(af.size); + + /*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000, + frame->channel_layout, (AVSampleFormat)frame->format, frame->sample_rate, 0, NULL); + + if (!swr) + { + ConLog.Error("cellAdecGetPcm(%d): swr_alloc_set_opts() failed", handle); + Emu.Pause(); + goto end; + } + // something is wrong + swr_convert(swr, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples); */ + + // reverse byte order, extract data: + float* in_f[2]; + in_f[0] = (float*)frame->extended_data[0]; + in_f[1] = (float*)frame->extended_data[1]; + be_t* out_f = (be_t*)out; + for (u32 i = 0; i < af.size / 8; i++) + { + out_f[i*2] = in_f[0][i]; + out_f[i*2+1] = in_f[1][i]; + } + + if (!Memory.CopyFromReal(outBuffer_addr, out, af.size)) + { + ConLog.Error("cellAdecGetPcm(%d): data copying failed (addr=0x%x)", handle, outBuffer_addr); + Emu.Pause(); + } + +end: + if (out) free(out); + if (swr) swr_free(&swr); if (af.data) { @@ -620,7 +762,7 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) return CELL_ADEC_ERROR_EMPTY; } - //AVFrame& frame = *af.data; + AVFrame* frame = af.data; mem_ptr_t pcm(adec->memAddr + adec->memBias); @@ -635,16 +777,17 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) pcm->startAddr = 0x00000312; // invalid address (no output) pcm->size = af.size; pcm->status = CELL_OK; - pcm->auInfo.pts.lower = af.pts; // ??? + 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->samplingFreq = frame->sample_rate; // ??? + atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ??? atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? + if (frame->channels != 2) ConLog.Error("cellAdecGetPcmItem: unsupported channel count (%d)", frame->channels); pcmItem_ptr = pcm.GetAddr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index 793a78905a..66364a6084 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1036,6 +1036,40 @@ struct AdecFrame int adecRead(void* opaque, u8* buf, int buf_size); +struct OMAHeader // OMA Header +{ + u32 magic; // 0x01334145 + u16 size; // 96 << 8 + u16 unk0; // 0xffff + u64 unk1; // 0x00500f0100000000ULL + u64 unk2; // 0xcef5000000000400ULL + u64 unk3; // 0x1c458024329192d2ULL + u8 codecId; // 1 for ATRAC3P + u8 reserved0; // 0 + u8 code1; + u8 code2; + u32 reserved1; // 0 + u64 reserved[7]; // 0 + + OMAHeader(u8 id, u8 code1, u8 code2) + : magic(0x01334145) + , size(96 << 8) + , unk0(0xffff) + , unk1(0x00500f0100000000ULL) + , unk2(0xcef5000000000400ULL) + , unk3(0x1c458024329192d2ULL) + , codecId(id) + , reserved0(0) + , code1(code1) + , code2(code2) + , reserved1(0) + { + memset(reserved, 0, sizeof(reserved)); + } +}; + +static_assert(sizeof(OMAHeader) == 96, "Wrong OMAHeader size"); + class AudioDecoder { public: @@ -1053,6 +1087,21 @@ public: { u32 addr; u32 size; + bool init; + u8* rem; + u32 rem_size; + + AudioReader() + : rem(nullptr) + , rem_size(0) + { + } + + ~AudioReader() + { + if (rem) free(rem); + rem = nullptr; + } } reader; SQueue frames; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp index f6ff6404b2..59fc40a276 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAudio.cpp @@ -118,29 +118,37 @@ int cellAudioInit() index = (position + 1) % port.block; // write new value } + u32 k = port.channel / 2; + if (first_mix) { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) { // reverse byte order (TODO: use port.m_param.level) - buffer[i] = buffer2[i]; + buffer[i] = buffer2[i*k]; + buffer[i+1] = buffer2[i*k+1]; // convert the data from float to u16 assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f); + assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f); oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1)); + oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1)); } first_mix = false; } else { - for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i++) + for (u32 i = 0; i < (sizeof(buffer) / sizeof(float)); i += 2) { - buffer[i] = (buffer[i] + buffer2[i]) * 0.5; // TODO: valid mixing + buffer[i] = (buffer[i] + buffer2[i*k]) * 0.5; // TODO: valid mixing + buffer[i+1] = (buffer[i+1] + buffer2[i*k+1]) * 0.5; // convert the data from float to u16 assert(buffer[i] >= -4.0f && buffer[i] <= 4.0f); + assert(buffer[i+1] >= -4.0f && buffer[i+1] <= 4.0f); oal_buffer[oal_buffer_offset + i] = (u16)(buffer[i] * ((1 << 13) - 1)); + oal_buffer[oal_buffer_offset + i + 1] = (u16)(buffer[i+1] * ((1 << 13) - 1)); } } } @@ -176,8 +184,6 @@ int cellAudioInit() ConLog.Error("Port aborted: cannot write file!"); goto abort; } - - m_dump.UpdateHeader(sizeof(buffer)); } } ConLog.Write("Audio finished"); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index bc09f6777b..93617de1ed 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 = 0x3000000; // 0x45fa49 from ps3 + attr->memSize = 0x2000000/2; // 0x45fa49 from ps3 else - attr->memSize = 0x200000; // 0x73d9 from ps3 + attr->memSize = 0x80000; // 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); @@ -131,7 +131,7 @@ u32 dmuxOpen(Demuxer* data) } // read additional header: - stream.peek(ch); + stream.peek(ch); // ??? //stream.skip(4); //pes.size += 4; @@ -148,26 +148,18 @@ u32 dmuxOpen(Demuxer* data) Sleep(1); } - /*if (es.hasunseen()) // hack, probably useless + if (es.hasunseen()) // hack, probably useless { stream = backup; continue; - }*/ - - //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + } stream.skip(4); len -= 4; - u32 abc; - stream.peek(abc); - if (abc == 0x5548D00F) - { - stream.skip(8); - len -= 8; - } es.push(stream, len - pes.size - 3, pes); es.finish(stream); + //ConLog.Write("*** AT3+ AU sent (len=0x%x, pts=0x%llx)", len - pes.size - 3, pes.pts); mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND; @@ -213,11 +205,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)); @@ -298,7 +290,7 @@ u32 dmuxOpen(Demuxer* data) { case dmuxSetStream: { - if (stream.discontinuity) + if (task.stream.discontinuity) { for (u32 i = 0; i < 192; i++) { diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index ce55c27eb5..5d0efac76f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -541,7 +541,7 @@ public: const u32 GetMaxAU() const { - return 640 * 1024 + 128; + return (fidMajor == 0xbd) ? 2048 : 640 * 1024 + 128; } volatile bool hasunseen() @@ -573,6 +573,11 @@ public: peek_addr = last_addr; } + mem_ptr_t info(last_addr); + /*if (fidMajor == 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x", + wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), + (u32)info->auSize, last_addr, (u32)info->ptsLower);*/ + u32 new_addr = a128(last_addr + 128 + last_size); if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { @@ -681,6 +686,11 @@ public: wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/ if (!peek_addr) return false; + mem_ptr_t info(peek_addr); + /*if (fidMajor == 0xbd) ConLog.Warning("es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", + wxString(update_index ? "Get" : "Peek").wx_str(), + wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek_addr, (u32)info->ptsLower);*/ + out_data = peek_addr; out_spec = out_data + sizeof(CellDmuxAuInfoEx); if (no_ex) out_data += 64; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 5ea762662f..a582f6d34c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -66,9 +66,10 @@ next: vdec.reader.addr = vdec.task.addr; vdec.reader.size = vdec.task.size; + //ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", vdec.task.size, vdec.task.pts, vdec.task.dts); - vdec.last_pts = vdec.task.pts; - vdec.last_dts = vdec.task.dts; + if (vdec.last_pts > vdec.task.pts) vdec.last_pts = vdec.task.pts; + if (vdec.last_dts > vdec.task.dts) vdec.last_dts = vdec.task.dts; } break; default: @@ -205,9 +206,10 @@ u32 vdecOpen(VideoDecoder* data) vdec.reader.addr = task.addr; vdec.reader.size = task.size; + //ConLog.Write("Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts); - vdec.last_pts = task.pts; - vdec.last_dts = task.dts; + if (vdec.last_pts > task.pts || vdec.just_started) vdec.last_pts = task.pts; + if (vdec.last_dts > task.dts || vdec.just_started) vdec.last_dts = task.dts; struct AVPacketHolder : AVPacket { @@ -350,11 +352,12 @@ u32 vdecOpen(VideoDecoder* data) if (got_picture) { - //ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, au.pts, au.dts); - frame.dts = vdec.last_dts; vdec.last_dts += 3003; // + duration??? frame.pts = vdec.last_pts; vdec.last_pts += 3003; frame.userdata = task.userData; + + //ConLog.Write("got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts); + vdec.frames.Push(frame); // !!!!!!!! frame.data = nullptr; // to prevent destruction diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 92ead9c6a4..31faab3f8d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -1,6 +1,12 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" + +extern "C" +{ +#include "libswscale/swscale.h" +} + #include "cellVpost.h" void cellVpost_init(); @@ -93,13 +99,15 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinWidth; u32 h = ctrlParam->inHeight; + u32 ow = ctrlParam->outWidth; + u32 oh = ctrlParam->outHeight; if (!Memory.IsGoodAddr(inPicBuff_addr, w*h*3/2)) { return CELL_VPOST_ERROR_E_ARG_INPICBUF_INVALID; } - if (!Memory.IsGoodAddr(outPicBuff_addr, w*h*4)) + if (!Memory.IsGoodAddr(outPicBuff_addr, ow*oh*4)) { return CELL_VPOST_ERROR_E_ARG_OUTPICBUF_INVALID; } @@ -110,13 +118,21 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinWindow; // ignored + if (ctrlParam->inWindow.x) ConLog.Warning("*** inWindow.x = %d", (u32)ctrlParam->inWindow.x); + if (ctrlParam->inWindow.y) ConLog.Warning("*** inWindow.y = %d", (u32)ctrlParam->inWindow.y); + if (ctrlParam->inWindow.width != w) ConLog.Warning("*** inWindow.width = %d", (u32)ctrlParam->inWindow.width); + if (ctrlParam->inWindow.height != h) ConLog.Warning("*** inWindow.height = %d", (u32)ctrlParam->inWindow.height); ctrlParam->outWindow; // ignored + if (ctrlParam->outWindow.x) ConLog.Warning("*** outWindow.x = %d", (u32)ctrlParam->outWindow.x); + if (ctrlParam->outWindow.y) ConLog.Warning("*** outWindow.y = %d", (u32)ctrlParam->outWindow.y); + if (ctrlParam->outWindow.width != ow) ConLog.Warning("*** outWindow.width = %d", (u32)ctrlParam->outWindow.width); + if (ctrlParam->outWindow.height != oh) ConLog.Warning("*** outWindow.height = %d", (u32)ctrlParam->outWindow.height); ctrlParam->execType; // ignored ctrlParam->scalerType; // ignored ctrlParam->ipcType; // ignored - picInfo->inWidth = ctrlParam->inWidth; // copy - picInfo->inHeight = ctrlParam->inHeight; // copy + picInfo->inWidth = w; // copy + picInfo->inHeight = h; // copy picInfo->inDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->inScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->inPicFmt = CELL_VPOST_PIC_FMT_IN_YUV420_PLANAR; // fixed @@ -125,24 +141,25 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tinQuantRange = ctrlParam->inQuantRange; // copy picInfo->inColorMatrix = ctrlParam->inColorMatrix; // copy - picInfo->outWidth = picInfo->inWidth; // TODO (resampling) - picInfo->outHeight = picInfo->inHeight; // TODO + picInfo->outWidth = ow; // copy + picInfo->outHeight = oh; // copy picInfo->outDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->outScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->outPicFmt = CELL_VPOST_PIC_FMT_OUT_RGBA_ILV; // TODO - picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ??? - picInfo->outPicStruct = picInfo->inPicStruct; // ??? - picInfo->outQuantRange = ctrlParam->inQuantRange; // ??? - picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ??? + picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ignored + picInfo->outPicStruct = picInfo->inPicStruct; // ignored + picInfo->outQuantRange = ctrlParam->inQuantRange; // ignored + picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ignored picInfo->userData = ctrlParam->userData; // copy picInfo->reserved1 = 0; picInfo->reserved2 = 0; - + 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); // RGBA interleaved output + u8* pA = (u8*)malloc(w*h); + u32* res = (u32*)malloc(ow*oh*4); // RGBA interleaved output const u8 alpha = ctrlParam->outAlpha; if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h)) @@ -163,6 +180,20 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t 255) B = 255; res[i*w+j] = ((u32)alpha << 24) | (B << 16) | (G << 8) | (R); - } + }*/ - if (!Memory.CopyFromReal(outPicBuff_addr, res, w*h*4)) + if (!Memory.CopyFromReal(outPicBuff_addr, res, ow*oh*4)) { cellVpost.Error("cellVpostExec: data copying failed(result)"); Emu.Pause(); @@ -190,6 +221,7 @@ int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_tm_mutex.GetOwner() != tid) { + sys_cond.Warning("sys_cond_wait(cond_id=%d) failed (EPERM)", cond_id); return CELL_EPERM; } cond->m_queue.push(tid); + if (mutex->recursive != 1) + { + sys_cond.Warning("sys_cond_wait(cond_id=%d): associated mutex had wrong recursive value (%d)", cond_id, mutex->recursive); + } mutex->recursive = 0; - mutex->m_mutex.unlock(tid); + mutex->m_mutex.unlock(tid, mutex->protocol == SYS_SYNC_PRIORITY ? mutex->m_queue.pop_prio() : mutex->m_queue.pop()); u32 counter = 0; const u32 max_counter = timeout ? (timeout / 1000) : ~0; while (true) { - if (cond->signal.GetOwner() == tid) + if (cond->signal.unlock(tid, tid) == SMR_OK) { - mutex->m_mutex.lock(tid); + if (SMutexResult res = mutex->m_mutex.trylock(tid)) + { + if (res != SMR_FAILED) + { + goto abort; + } + mutex->m_queue.push(tid); + + switch (mutex->m_mutex.lock(tid)) + { + case SMR_OK: + mutex->m_queue.invalidate(tid); + case SMR_SIGNAL: + break; + default: + goto abort; + } + } mutex->recursive = 1; cond->signal.unlock(tid); return CELL_OK; @@ -186,13 +208,16 @@ int sys_cond_wait(u32 cond_id, u64 timeout) if (counter++ > max_counter) { cond->m_queue.invalidate(tid); - GetCurrentPPUThread().owned_mutexes--; + GetCurrentPPUThread().owned_mutexes--; // ??? return CELL_ETIMEDOUT; } if (Emu.IsStopped()) { - ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id); - return CELL_OK; + goto abort; } } + +abort: + ConLog.Warning("sys_cond_wait(id=%d) aborted", cond_id); + return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp index d0d2b3f962..e09bc1874e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -63,7 +63,7 @@ int sys_mutex_destroy(u32 mutex_id) return CELL_ESRCH; } - if ((u32&)mutex->cond_count) // check if associated condition variable exists + if (mutex->cond_count) // check if associated condition variable exists { return CELL_EPERM; } @@ -99,9 +99,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - u32 owner = mutex->m_mutex.GetOwner(); - if (owner == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (mutex->is_recursive) { @@ -116,7 +114,7 @@ int sys_mutex_lock(u32 mutex_id, u64 timeout) return CELL_EDEADLK; } } - else if (owner) + else if (u32 owner = mutex->m_mutex.GetOwner()) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { @@ -170,9 +168,7 @@ int sys_mutex_trylock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - u32 owner = mutex->m_mutex.GetOwner(); - if (owner == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (mutex->is_recursive) { @@ -187,7 +183,7 @@ int sys_mutex_trylock(u32 mutex_id) return CELL_EDEADLK; } } - else if (owner) + else if (u32 owner = mutex->m_mutex.GetOwner()) { if (CPUThread* tt = Emu.GetCPU().GetThread(owner)) { @@ -219,8 +215,7 @@ int sys_mutex_unlock(u32 mutex_id) PPUThread& t = GetCurrentPPUThread(); u32 tid = t.GetId(); - _mm_mfence(); - if (mutex->m_mutex.GetOwner() == tid) + if (mutex->m_mutex.unlock(tid, tid) == SMR_OK) { if (!mutex->recursive || (mutex->recursive != 1 && !mutex->is_recursive)) {