diff --git a/rpcs3/Emu/Cell/MFC.h b/rpcs3/Emu/Cell/MFC.h index 839987cd68..5ddf7a073a 100644 --- a/rpcs3/Emu/Cell/MFC.h +++ b/rpcs3/Emu/Cell/MFC.h @@ -21,6 +21,15 @@ enum MFC_MASK_CMD = 0xffff, }; +// Atomic Status Update +enum +{ + MFC_PUTLLC_SUCCESS = 0, + MFC_PUTLLC_FAILURE = 1, //reservation was lost + MFC_PUTLLUC_SUCCESS = 2, + MFC_GETLLAR_SUCCESS = 4, +}; + enum { MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF, diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 7dd9b2d636..c6aadacdc7 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -2,6 +2,9 @@ #include "PPCThread.h" #include "Emu/event.h" #include "MFC.h" +#include + +extern std::mutex g_SyncMutex; //can provide compatability for CellSyncMutex through SPU<>PPU and SPU<>SPU static const char* spu_reg_name[128] = { @@ -293,7 +296,7 @@ public: }; volatile u64 m_indval; }; - wxCriticalSection m_lock; + std::mutex m_lock; public: @@ -311,7 +314,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(!m_index) { return false; @@ -322,7 +325,7 @@ public: } else { //lock-free - if(!m_index) + if ((m_indval & 0xffffffff) == 0) return false; else { @@ -337,7 +340,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) { return false; @@ -347,11 +350,12 @@ public: } else { //lock-free - if(m_index) + if (m_indval & 0xffffffff) return false; else { - m_indval = ((u64)value << 32) | 1; + const u64 new_value = ((u64)value << 32) | 1; + m_indval = new_value; return true; } } @@ -361,7 +365,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) m_value[max_count-1] = value; //last message is overwritten else @@ -369,7 +373,8 @@ public: } else { //lock-free - m_indval = ((u64)value << 32) | 1; + const u64 new_value = ((u64)value << 32) | 1; + m_indval = new_value; } } @@ -377,7 +382,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(m_index >= max_count) m_value[max_count-1] |= value; //last message is logically ORed else @@ -397,7 +402,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); if(!m_index) res = 0; //result is undefined else @@ -422,7 +427,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); return m_index; } else @@ -435,7 +440,7 @@ public: { if (max_count > 1 || x86) { - wxCriticalSectionLocker lock(m_lock); + std::lock_guard lock(m_lock); return max_count - m_index; } else @@ -470,6 +475,7 @@ public: Channel<1> QueryType; Channel<1> QueryMask; Channel<1> TagStatus; + Channel<1> AtomicStat; } Prxy; struct @@ -519,6 +525,29 @@ public: } break; + case MFC_GETLLAR_CMD: + case MFC_PUTLLC_CMD: + case MFC_PUTLLUC_CMD: + { + if (op == MFC_GETLLAR_CMD) + { + g_SyncMutex.lock(); + } + + ConLog.Warning("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x", + op == MFC_GETLLAR_CMD ? "GETLLAR" : op == MFC_PUTLLC_CMD ? "PUTLLC" : "PUTLLUC", + lsa, ea, tag, size, cmd); + + dmac.ProcessCmd(op == MFC_GETLLAR_CMD ? MFC_GET_CMD : MFC_PUT_CMD, tag, lsa, ea, 128); + Prxy.AtomicStat.PushUncond(op == MFC_GETLLAR_CMD ? MFC_GETLLAR_SUCCESS : op == MFC_PUTLLC_CMD ? MFC_PUTLLC_SUCCESS : MFC_PUTLLUC_SUCCESS); + + if (op == MFC_PUTLLC_CMD || op == MFC_PUTLLUC_CMD) + { + g_SyncMutex.unlock(); + } + } + break; + default: ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)", op, cmd, lsa, ea, tag, size); @@ -549,6 +578,9 @@ public: case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); + case MFC_RdAtomicStat: + return Prxy.AtomicStat.GetCount(); + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; @@ -641,6 +673,10 @@ public: //ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); break; + case MFC_RdAtomicStat: + while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1); + break; + default: ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h index d46182fc51..2a09f20b74 100644 --- a/rpcs3/Emu/FS/VFS.h +++ b/rpcs3/Emu/FS/VFS.h @@ -20,7 +20,11 @@ struct VFSManagerEntry char* mount; vfsDeviceType device; - VFSManagerEntry() : device(vfsDevice_LocalFile) + VFSManagerEntry() + : device(vfsDevice_LocalFile) + , device_path("") + , path("") + , mount("") { } }; diff --git a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp index 6dca47ffe7..96232ebd02 100644 --- a/rpcs3/Emu/GS/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/GLVertexProgram.cpp @@ -151,7 +151,7 @@ wxString GLVertexDecompilerThread::GetSRC(const u32 n, bool isSca) return ret; } -void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask) +void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask, bool set_dst) { if(d0.cond == 0) return; enum @@ -179,7 +179,7 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask } //ConLog.Error("cond! %d (%d %s %d %d)", d0.cond, d0.dst_tmp, cond, d1.input_src, d1.const_src); - cond = wxString::Format("if(tmp%d.x %s 0) ", d0.dst_tmp, cond.mb_str()); + cond = wxString::Format("if(rc %s 0) ", cond.mb_str()); } wxString value = src_mask ? code + GetMask(is_sca) : code; @@ -189,40 +189,100 @@ void GLVertexDecompilerThread::AddCode(bool is_sca, wxString code, bool src_mask value = "clamp(" + value + ", 0.0, 1.0)"; } - wxString dest; - if(d3.dst == 5 || d3.dst == 6) + if(set_dst) { - int num = d3.dst == 5 ? 0 : 3; - - if(d3.vec_writemask_x) + wxString dest; + if(d0.cond_update_enable_0) { - ConLog.Error("Bad clip mask."); + dest = m_parr.AddParam(PARAM_NONE, "float", "rc"); + } + else if(d3.dst == 5 || d3.dst == 6) + { + int num = d3.dst == 5 ? 0 : 3; + + if(d3.vec_writemask_x) + { + ConLog.Error("Bad clip mask."); + } + + //if(d3.vec_writemask_y) num += 0; + if(d3.vec_writemask_z) num += 1; + else if(d3.vec_writemask_w) num += 2; + + dest = wxString::Format(GetDST(is_sca), num); + } + else + { + dest = GetDST(is_sca) + GetMask(is_sca); } - //if(d3.vec_writemask_y) num += 0; - if(d3.vec_writemask_z) num += 1; - else if(d3.vec_writemask_w) num += 2; - - dest = wxString::Format(GetDST(is_sca), num); + code = cond + dest + " = " + value; } else { - dest = GetDST(is_sca) + GetMask(is_sca); + code = cond + value; } - code = cond + dest + " = " + value; - - main += "\t" + code + ";\n"; + m_body.Add(code + wxString::Format(";//%d %d %d %d", d0.cond_reg_sel_1, d0.cond_test_enable, d0.cond_update_enable_0, d0.cond_update_enable_1)); } -void GLVertexDecompilerThread::AddVecCode(const wxString& code, bool src_mask) +wxString GLVertexDecompilerThread::GetFunc() { - AddCode(false, code, src_mask); + u32 offset = (d2.iaddrh << 3) | d3.iaddrl; + wxString name = wxString::Format("func%u", offset); + + for(uint i=0; i=0; --i) + { + fp += wxString::Format("void %s();\n", m_funcs[i].name.mb_str()); + } + + wxString f = wxEmptyString; + + f += wxString::Format("void %s()\n{\n\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n%s}\n", m_funcs[0].name.mb_str(), BuildFuncBody(m_funcs[0]).mb_str()); + + for(uint i=1; i m_funcs; + + //wxString main; wxString& m_shader; Array& m_data; GLParamArray& m_parr; @@ -138,6 +148,10 @@ struct GLVertexDecompilerThread : public ThreadBase , m_shader(shader) , m_parr(parr) { + m_funcs.Add(new FuncInfo()); + m_funcs[0].offset = 0; + m_funcs[0].name = "main"; + //m_cur_func->body = "\tgl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"; } wxString GetMask(bool is_sca); @@ -145,9 +159,11 @@ struct GLVertexDecompilerThread : public ThreadBase wxString GetScaMask(); wxString GetDST(bool is_sca = false); wxString GetSRC(const u32 n, bool is_sca = false); - void AddCode(bool is_sca, wxString code, bool src_mask = true); - void AddVecCode(const wxString& code, bool src_mask = true); - void AddScaCode(const wxString& code); + wxString GetFunc(); + void AddCode(bool is_sca, wxString code, bool src_mask = true, bool set_dst = true); + void AddVecCode(const wxString& code, bool src_mask = true, bool set_dst = true); + void AddScaCode(const wxString& code, bool set_dst = true); + wxString BuildFuncBody(const FuncInfo& func); wxString BuildCode(); virtual void Task(); diff --git a/rpcs3/Emu/GS/GSManager.h b/rpcs3/Emu/GS/GSManager.h index 7ab4fda396..bafa6961c3 100644 --- a/rpcs3/Emu/GS/GSManager.h +++ b/rpcs3/Emu/GS/GSManager.h @@ -51,6 +51,8 @@ public: void Init(); void Close(); + bool IsInited() const { return m_render != nullptr; } + GSInfo& GetInfo() { return m_info; } GSRender& GetRender() { assert(m_render); return *m_render; } diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index c8f4c84c19..626b7c4236 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -104,6 +104,41 @@ u32 RSXVertexData::GetTypeSize() index = (cmd - a) / m; \ case a \ +#define case_32(a, m) \ + case a + m: \ + case a + m * 2: \ + case a + m * 3: \ + case a + m * 4: \ + case a + m * 5: \ + case a + m * 6: \ + case a + m * 7: \ + case a + m * 8: \ + case a + m * 9: \ + case a + m * 10: \ + case a + m * 11: \ + case a + m * 12: \ + case a + m * 13: \ + case a + m * 14: \ + case a + m * 15: \ + case a + m * 16: \ + case a + m * 17: \ + case a + m * 18: \ + case a + m * 19: \ + case a + m * 20: \ + case a + m * 21: \ + case a + m * 22: \ + case a + m * 23: \ + case a + m * 24: \ + case a + m * 25: \ + case a + m * 26: \ + case a + m * 27: \ + case a + m * 28: \ + case a + m * 29: \ + case a + m * 30: \ + case a + m * 31: \ + index = (cmd - a) / m; \ + case a \ + void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u32 count) { #if CMD_DEBUG @@ -170,6 +205,13 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 //ConLog.Warning("texture addr = 0x%x #offset = 0x%x, location=%d", tex_addr, offset, location); tex.SetOffset(tex_addr); tex.SetFormat(cubemap, dimension, format, mipmap); + + if(!tex.m_width || !tex.m_height) + { + gcmBuffer* buffers = (gcmBuffer*)Memory.GetMemFromAddr(m_gcm_buffers_addr); + if(!tex.m_width) tex.m_width = re(buffers[m_gcm_current_buffer].width); + if(!tex.m_height) tex.m_height = re(buffers[m_gcm_current_buffer].height); + } } break; @@ -308,10 +350,24 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 { RSXTexture& tex = m_textures[index]; - const u16 height = args[0] & 0xffff; - const u16 width = args[0] >> 16; + u16 height = args[0] & 0xffff; + u16 width = args[0] >> 16; CMD_LOG("width=%d, height=%d", width, height); + + if(!width || !height) + { + ConLog.Warning("Bad texture rect: %dx%d (%dx%d)", width, height, tex.m_width, tex.m_height); + for(int i=0; idata.Clear(); @@ -677,8 +735,10 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, mem32_ptr_t& args, const u3 } break; - case NV4097_SET_TRANSFORM_PROGRAM: + case_32(NV4097_SET_TRANSFORM_PROGRAM, 4): { + //ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM[%d](%d)", index, count); + if(!m_cur_vertex_prog) { ConLog.Warning("NV4097_SET_TRANSFORM_PROGRAM: m_cur_vertex_prog == NULL"); diff --git a/rpcs3/Emu/GS/RSXThread.h b/rpcs3/Emu/GS/RSXThread.h index 48bdb55bfd..7f43d589a0 100644 --- a/rpcs3/Emu/GS/RSXThread.h +++ b/rpcs3/Emu/GS/RSXThread.h @@ -226,7 +226,7 @@ class RSXThread : public ThreadBase { public: static const uint m_textures_count = 16; - static const uint m_vertex_count = 16; + static const uint m_vertex_count = 32; static const uint m_fragment_count = 16; static const uint m_tiles_count = 15; diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 4e83d11cc7..d56be02df3 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -103,6 +103,24 @@ struct Button } }; +struct AnalogStick +{ + u32 m_offset; + u32 m_keyCodeMin; + u32 m_keyCodeMax; + bool m_min_pressed; + bool m_max_pressed; + + AnalogStick(u32 offset, u32 keyCodeMin, u32 keyCodeMax) + : m_min_pressed(false) + , m_max_pressed(false) + , m_offset(offset) + , m_keyCodeMin(keyCodeMin) + , m_keyCodeMax(keyCodeMax) + { + } +}; + struct Pad { u32 m_port_status; @@ -111,6 +129,7 @@ struct Pad u32 m_device_type; Array