diff --git a/.gitignore b/.gitignore index e3ceeff00f..cea62cad43 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ /bin/VertexProgram.txt /bin/BreakPoints.dat /bin/textures +/bin/*.lib +/bin/*.exp rpcs3/git-version.h # Copyrighted files diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 6bd33d6b86..b71fc5eeea 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -117,10 +117,12 @@ thread::thread() } void thread::start(std::function func) -{ // got a crash related with strings - m_thr = std::thread([this, func]() +{ + std::string name = m_name; + + m_thr = std::thread([func, name]() { - NamedThreadBase info(m_name); + NamedThreadBase info(name); g_tls_this_thread = &info; try @@ -130,7 +132,7 @@ void thread::start(std::function func) catch(...) { ConLog.Error("Crash :("); - std::terminate(); + //std::terminate(); } }); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index fe558d0ae8..d11dfa1c52 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 = 0x500000; // 0x45fa49 from ps3 + attr->memSize = 0x600000; // 0x45fa49 from ps3 else attr->memSize = 0x10000; // 0x73d9 from ps3 @@ -40,16 +40,13 @@ u32 dmuxOpen(Demuxer* data) DemuxerTask task; DemuxerStream stream; - /* - ElementaryStream* esAVC[16]; memset(esAVC, 0, sizeof(esAVC)); - ElementaryStream* esM2V[16]; memset(esM2V, 0, sizeof(esM2V)); - ElementaryStream* esDATA[16]; memset(esDATA, 0, sizeof(esDATA)); - ElementaryStream* esATRAX[48]; memset(esATRAX, 0, sizeof(esATRAX)); - ElementaryStream* esAC3[48]; memset(esAC3, 0, sizeof(esAC3)); - ElementaryStream* esLPCM[48]; memset(esLPCM, 0, sizeof(esLPCM)); - */ ElementaryStream* esALL[192]; memset(esALL, 0, sizeof(esALL)); - ElementaryStream** esAVC = &esALL[0]; + ElementaryStream** esAVC = &esALL[0]; // AVC (max 16) + ElementaryStream** esM2V = &esALL[16]; // MPEG-2 (max 16) + ElementaryStream** esDATA = &esALL[32]; // user data (max 16) + ElementaryStream** esATX = &esALL[48]; // ATRAC3+ (max 48) + ElementaryStream** esAC3 = &esALL[96]; // AC3 (max 48) + ElementaryStream** esPCM = &esALL[144]; // LPCM (max 48) u32 cb_add = 0; @@ -124,6 +121,8 @@ u32 dmuxOpen(Demuxer* data) continue; } + DemuxerStream backup = stream; + stream.skip(4); stream.get(len); PesHeader pes(stream); @@ -136,6 +135,11 @@ u32 dmuxOpen(Demuxer* data) if (pes.size && es.hasdata()) // new AU detected { + /*if (es.hasunseen()) + { + stream = backup; + continue; + }*/ es.finish(stream); // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); @@ -149,7 +153,13 @@ u32 dmuxOpen(Demuxer* data) if (pes.size) { - ConLog.Write("*** AVC AU detected (pts=0x%x, dts=0x%x)", pes.pts, pes.dts); + ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + } + + if (es.isfull()) + { + stream = backup; + continue; } es.push(stream, len - pes.size - 3, pes); @@ -173,6 +183,7 @@ u32 dmuxOpen(Demuxer* data) case 0x1dc: case 0x1dd: case 0x1de: case 0x1df: { // unknown + ConLog.Warning("Unknown MPEG stream found"); stream.skip(4); stream.get(len); stream.skip(len); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index d83e1fc754..a61918b01b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -321,7 +321,7 @@ struct DemuxerStream { if (sizeof(T) > size) return false; - out = *mem_ptr_t(addr); + out = *(T*)Memory.VirtualToRealAddr(addr); addr += sizeof(T); size -= sizeof(T); @@ -333,7 +333,7 @@ struct DemuxerStream { if (sizeof(T) > size) return false; - out = *mem_ptr_t(addr); + out = *(T*)Memory.VirtualToRealAddr(addr); return true; } @@ -343,13 +343,17 @@ struct DemuxerStream size = size > count ? size - count : 0; } - u32 get_ts(u8 c) + u64 get_ts(u8 c) { - u16 v1, v2; get(v1); get(v2); - return (((u32) (c & 0x0E)) << 29) | ((v1 >> 1) << 15) | (v2 >> 1); + u8 v[4]; get((u32&)v); + return + (((u64)c & 0x0e) << 29) | + (((u64)v[0]) << 21) | + (((u64)v[1] & 0x7e) << 15) | + (((u64)v[2]) << 7) | ((u64)v[3] >> 1); } - u32 get_ts() + u64 get_ts() { u8 v; get(v); return get_ts(v); @@ -358,8 +362,8 @@ struct DemuxerStream struct PesHeader { - u32 pts; - u32 dts; + u64 pts; + u64 dts; u8 ch; u8 size; @@ -505,6 +509,11 @@ public: { } + volatile bool hasunseen() + { + return peek_addr; + } + volatile bool hasdata() { return last_size; @@ -532,7 +541,7 @@ public: void finish(DemuxerStream& stream) // not multithread-safe { SMutexLocker lock(mutex); - + //ConLog.Write("es::finish(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); if (!first_addr) { first_addr = last_addr; @@ -556,6 +565,7 @@ public: void push(DemuxerStream& stream, u32 size, PesHeader& pes) { 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()) { ConLog.Error("ElementaryStream::push(): buffer is full"); @@ -565,7 +575,12 @@ public: u32 data_addr = last_addr + 128 + last_size; last_size += size; - Memory.Copy(data_addr, stream.addr, size); + if (!Memory.Copy(data_addr, stream.addr, size)) + { + ConLog.Error("ElementaryStream::push(): data copying failed"); + Emu.Pause(); + return; + } stream.skip(size); mem_ptr_t info(last_addr); @@ -573,10 +588,10 @@ public: info->auSize = last_size; if (pes.size) { - info->dts.lower = pes.dts; - info->dts.upper = 0; - info->pts.lower = pes.pts; - info->pts.upper = 0; + info->dts.lower = (u32)pes.dts; + info->dts.upper = (u32)(pes.dts >> 32); + info->pts.lower = (u32)pes.pts; + info->pts.upper = (u32)(pes.pts >> 32); info->isRap = false; // TODO: set valid value info->reserved = 0; info->userData = stream.userdata; @@ -590,10 +605,10 @@ public: inf->auSize = last_size; if (pes.size) { - inf->dtsLower = pes.dts; - inf->dtsUpper = 0; - inf->ptsLower = pes.pts; - inf->ptsUpper = 0; + inf->dtsLower = (u32)pes.dts; + inf->dtsUpper = (u32)(pes.dts >> 32); + inf->ptsLower = (u32)pes.pts; + inf->ptsUpper = (u32)(pes.pts >> 32); inf->auMaxSize = 0; // ????? inf->userData = stream.userdata; } @@ -607,6 +622,7 @@ public: void release() { SMutexLocker lock(mutex); + ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); if (!canrelease()) { ConLog.Error("ElementaryStream::release(): buffer is empty"); @@ -634,7 +650,8 @@ public: bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index) { SMutexLocker lock(mutex); - ConLog.Write("es::peek(): peek_addr=0x%x", peek_addr); + /*ConLog.Write("es::peek(%sAu%s): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), + wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/ if (!peek_addr) return false; out_data = peek_addr; diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 0bf21a30cf..45cdf7f38a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -1,81 +1,327 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" -#include "cellVdec.h" +#include "cellPamf.h" extern "C" { -#include "libavformat\avformat.h" +#include "libavcodec\avcodec.h" } +#include "cellVdec.h" + void cellVdec_init(); Module cellVdec(0x0005, cellVdec_init); +u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 */, mem_ptr_t attr) +{ + switch (type) // TODO: check profile levels + { + case CELL_VDEC_CODEC_TYPE_AVC: cellVdec.Warning("cellVdecQueryAttr: AVC (profile=%d)", profile); break; + case CELL_VDEC_CODEC_TYPE_MPEG2: cellVdec.Error("TODO: MPEG2 not supported"); break; + case CELL_VDEC_CODEC_TYPE_DIVX: cellVdec.Error("TODO: DIVX not supported"); break; + default: return CELL_VDEC_ERROR_ARG; + } + + // TODO: check values + attr->decoderVerLower = 0x280000; // from dmux + attr->decoderVerUpper = 0x260000; + attr->memSize = 64 * 1024 * 1024; + attr->cmdDepth = 15; + return CELL_OK; +} + +u32 vdecOpen(VideoDecoder* data) +{ + VideoDecoder& vdec = *data; + + u32 vdec_id = cellVdec.GetNewId(data); + + vdec.id = vdec_id; + + thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]() + { + ConLog.Write("Video Decoder enter()"); + + VdecTask task; + + while (true) + { + if (Emu.IsStopped()) + { + break; + } + + if (vdec.job.IsEmpty() && vdec.is_running) + { + // TODO: default task (not needed?) + Sleep(1); + continue; + } + + if (!vdec.job.Pop(task)) + { + break; + } + + switch (task.type) + { + case vdecStartSeq: + { + // TODO: reset data + ConLog.Warning("vdecStartSeq()"); + vdec.is_running = true; + } + break; + + case vdecEndSeq: + { + // TODO: send callback + ConLog.Warning("vdecEndSeq()"); + vdec.is_running = false; + } + break; + + case vdecDecodeAu: + { + struct vdecPacket : AVPacket + { + vdecPacket(u32 size) + { + av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE); + memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + } + + ~vdecPacket() + { + av_free_packet(this); + } + + } au(task.size); + + au.pts = task.pts; + au.dts = task.dts; + + if (task.mode != CELL_VDEC_DEC_MODE_NORMAL) + { + ConLog.Error("vdecDecodeAu: unsupported decoding mode(%d)", task.mode); + break; + } + + if (!Memory.CopyToReal(au.data, task.addr, task.size)) + { + ConLog.Error("vdecDecodeAu: AU data accessing failed(addr=0x%x, size=0x%x)", task.addr, task.size); + break; + } + + int got_picture = 0; + + int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au); + if (decode < 0) + { + ConLog.Error("vdecDecodeAu: AU decoding error(%d)", decode); + break; + } + + ConLog.Write("Frame decoded (%d)", decode); + } + break; + + case vdecClose: + { + vdec.is_finished = true; + ConLog.Write("Video Decoder exit"); + return; + } + + case vdecSetFrameRate: + { + ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc); + } + + default: + ConLog.Error("Video Decoder error: unknown task(%d)", task.type); + return; + } + } + + ConLog.Warning("Video Decoder aborted"); + }); + + t.detach(); + + return vdec_id; +} + int cellVdecQueryAttr(const mem_ptr_t type, mem_ptr_t attr) { - cellVdec.Error("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); - return CELL_OK; + cellVdec.Warning("cellVdecQueryAttr(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); + + if (!type.IsGood() || !attr.IsGood()) + { + return CELL_VDEC_ERROR_FATAL; + } + + return vdecQueryAttr(type->codecType, type->profileLevel, 0, attr); } int cellVdecQueryAttrEx(const mem_ptr_t type, mem_ptr_t attr) { - cellVdec.Error("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); - return CELL_OK; + cellVdec.Warning("cellVdecQueryAttrEx(type_addr=0x%x, attr_addr=0x%x)", type.GetAddr(), attr.GetAddr()); + + if (!type.IsGood() || !attr.IsGood()) + { + return CELL_VDEC_ERROR_FATAL; + } + + return vdecQueryAttr(type->codecType, type->profileLevel, type->codecSpecificInfo_addr, attr); } int cellVdecOpen(const mem_ptr_t type, const mem_ptr_t res, const mem_ptr_t cb, mem32_t handle) { - cellVdec.Error("cellVdecOpen(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", + cellVdec.Warning("cellVdecOpen(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_VDEC_ERROR_FATAL; + } + + if (!Memory.IsGoodAddr(res->memAddr, res->memSize) || !Memory.IsGoodAddr(cb->cbFunc)) + { + return CELL_VDEC_ERROR_FATAL; + } + + handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + return CELL_OK; } int cellVdecOpenEx(const mem_ptr_t type, const mem_ptr_t res, const mem_ptr_t cb, mem32_t handle) { - cellVdec.Error("cellVdecOpenEx(type_addr=0x%x, res_addr=0x%x, cb_addr=0x%x, handle_addr=0x%x)", + cellVdec.Warning("cellVdecOpenEx(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_VDEC_ERROR_FATAL; + } + + if (!Memory.IsGoodAddr(res->memAddr, res->memSize) || !Memory.IsGoodAddr(cb->cbFunc)) + { + return CELL_VDEC_ERROR_FATAL; + } + + handle = vdecOpen(new VideoDecoder(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg)); + return CELL_OK; } int cellVdecClose(u32 handle) { - cellVdec.Error("cellVdecClose(handle=0x%x)", handle); + cellVdec.Warning("cellVdecClose(handle=%d)", handle); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + vdec->job.Push(VdecTask(vdecClose)); + + while (!vdec->is_finished) + { + if (Emu.IsStopped()) + { + ConLog.Warning("cellVdecClose(%d) aborted", handle); + break; + } + Sleep(1); + } + + Emu.GetIdManager().RemoveID(handle); return CELL_OK; } int cellVdecStartSeq(u32 handle) { - cellVdec.Error("cellVdecStartSeq(handle=0x%x)", handle); + cellVdec.Log("cellVdecStartSeq(handle=%d)", handle); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + vdec->job.Push(VdecTask(vdecStartSeq)); return CELL_OK; } int cellVdecEndSeq(u32 handle) { - cellVdec.Error("cellVdecEndSeq(handle=0x%x)", handle); + cellVdec.Log("cellVdecEndSeq(handle=%d)", handle); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + vdec->job.Push(VdecTask(vdecEndSeq)); return CELL_OK; } int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t auInfo) { - cellVdec.Error("cellVdecDecodeAu(handle=0x%x, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.GetAddr()); + cellVdec.Log("cellVdecDecodeAu(handle=%d, mode=0x%x, auInfo_addr=0x%x)", handle, mode, auInfo.GetAddr()); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + // TODO: check info + VdecTask task(vdecDecodeAu); + task.mode = mode; + task.addr = auInfo->startAddr; + task.size = auInfo->size; + task.dts = (u64)auInfo->dts.lower | ((u64)auInfo->dts.upper << 32); + task.pts = (u64)auInfo->pts.lower | ((u64)auInfo->pts.upper << 32); + task.userData = auInfo->userData; + task.specData = auInfo->codecSpecificData; + + vdec->job.Push(task); return CELL_OK; } int cellVdecGetPicture(u32 handle, const mem_ptr_t format, u32 out_addr) { - cellVdec.Error("cellVdecGetPicture(handle=0x%x, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); + cellVdec.Error("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); return CELL_OK; } int cellVdecGetPicItem(u32 handle, const u32 picItem_ptr_addr) { - cellVdec.Error("cellVdecGetPicItem(handle=0x%x, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr); + cellVdec.Error("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr); return CELL_OK; } int cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc) { - cellVdec.Error("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc); + cellVdec.Log("cellVdecSetFrameRate(handle=%d, frc=0x%x)", handle, frc); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + // TODO: check frc value and set frame rate + VdecTask task(vdecSetFrameRate); + task.frc = frc; + + vdec->job.Push(task); return CELL_OK; } @@ -92,4 +338,6 @@ void cellVdec_init() cellVdec.AddFunc(0x807c861a, cellVdecGetPicture); cellVdec.AddFunc(0x17c702b9, cellVdecGetPicItem); cellVdec.AddFunc(0xe13ef6fc, cellVdecSetFrameRate); + + 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 771924fea5..69de466bca 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -1,5 +1,6 @@ #pragma once -#include "cellPamf.h" + +#include "Utilities/SQueue.h" // Error Codes enum @@ -30,7 +31,7 @@ enum CellVdecMsgType }; // Decoder Operation Mode -enum CellVdecDecodeMode +enum CellVdecDecodeMode : u32 { CELL_VDEC_DEC_MODE_NORMAL, CELL_VDEC_DEC_MODE_B_SKIP, @@ -164,11 +165,13 @@ struct CellVdecPicFormat u8 alpha; }; +typedef mem_func_ptr_t CellVdecCbMsg; + // Callback Function Information struct CellVdecCb { - be_t> cbFunc; - be_t cbArg_addr; + be_t cbFunc; + be_t cbArg; }; // Max CC Data Length @@ -634,4 +637,109 @@ struct CellVdecMpeg2Info u8 ccDataLength[2]; u8 ccData[2][128]; be_t reserved[2]; +}; + +/* Video Decoder Thread Classes */ + +enum VdecJobType : u32 +{ + vdecStartSeq, + vdecEndSeq, + vdecDecodeAu, + vdecSetFrameRate, + vdecClose, +}; + +struct VdecTask +{ + VdecJobType type; + union + { + u32 frc; + CellVdecDecodeMode mode; + }; + u32 addr; + u32 size; + u64 pts; + u64 dts; + u64 userData; + u64 specData; + + VdecTask(VdecJobType type) + : type(type) + { + } + + VdecTask() + { + } +}; + +class VideoDecoder +{ +public: + SQueue job; + u32 id; + volatile bool is_running; + volatile bool is_finished; + + AVCodec* codec; + AVCodecContext* ctx; + AVFrame* frame; + + const u32 type; + const u32 profile; + const u32 memAddr; + const u32 memSize; + const u32 cbFunc; + const u32 cbArg; + + VideoDecoder(u32 type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) + : type(type) + , profile(profile) + , memAddr(addr) + , memSize(size) + , cbFunc(func) + , cbArg(arg) + , is_finished(false) + , is_running(false) + { + codec = avcodec_find_decoder(AV_CODEC_ID_H264); + if (!codec) + { + ConLog.Error("VideoDecoder(): avcodec_find_decoder failed"); + Emu.Pause(); + return; + } + ctx = avcodec_alloc_context3(codec); + if (!ctx) + { + ConLog.Error("VideoDecoder(): avcodec_alloc_context3 failed"); + Emu.Pause(); + return; + } + if (int err = avcodec_open2(ctx, codec, NULL)) // 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; + } + } + + ~VideoDecoder() + { + if (frame) av_frame_free(&frame); + if (ctx) + { + avcodec_close(ctx); + av_free(ctx); + } + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index a2a7c2e4d3..2a42841c31 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -28,7 +28,7 @@ int sys_lwmutex_create(mem_ptr_t lwmutex, mem_ptr_tattribute = attr->attr_protocol | attr->attr_recursive; - lwmutex->all_info() = 0; + lwmutex->all_info() = ~0; lwmutex->mutex.initialize(); //lwmutex->waiter = lwmutex->owner.GetOwner(); lwmutex->pad = 0; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.h index 4acde466bd..971363a92f 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, 0xffffffff, 0> mutex; + /* volatile */ SMutexBase, ~0, 0> mutex; /* volatile */ be_t waiter; // not used u64 &all_info(){return *(reinterpret_cast(this));} be_t attribute; diff --git a/rpcs3/Gui/ConLog.cpp b/rpcs3/Gui/ConLog.cpp index 33a324dd9e..7b5ee9300c 100644 --- a/rpcs3/Gui/ConLog.cpp +++ b/rpcs3/Gui/ConLog.cpp @@ -136,11 +136,22 @@ void LogWriter::WriteToLog(std::string prefix, std::string value, std::string co if(wxThread::IsMain()) #endif { - while(LogBuffer.IsBusy()) wxYieldIfNeeded(); + while(LogBuffer.IsBusy()) + { + // need extra break condition? + wxYieldIfNeeded(); + } } else { - while(LogBuffer.IsBusy()) Sleep(1); + while (LogBuffer.IsBusy()) + { + if (Emu.IsStopped()) + { + break; + } + Sleep(1); + } } //if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush();