From bba1b6a6e0d72d73e03a4b8f202cc430c61bb3a2 Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 8 Dec 2013 00:52:41 +0200 Subject: [PATCH] SPU improvements - Implemented more SPU Channels. - Improved interpreter. Minor improvements. --- rpcs3/Emu/Cell/RawSPUThread.cpp | 55 +++------- rpcs3/Emu/Cell/SPUDisAsm.h | 2 +- rpcs3/Emu/Cell/SPUInterpreter.h | 38 ++++--- rpcs3/Emu/Cell/SPUOpcodes.h | 2 +- rpcs3/Emu/Cell/SPUThread.h | 123 ++++++++++++++-------- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 46 ++++++-- rpcs3/Emu/SysCalls/Modules/cellResc.cpp | 1 + rpcs3/Emu/SysCalls/SysCalls.h | 3 - 8 files changed, 158 insertions(+), 112 deletions(-) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 36848ab401..ee0cf6c4b3 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -67,10 +67,10 @@ bool RawSPUThread::Read32(const u64 addr, u32* value) case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_QueryMask)", m_index); *value = Prxy.QueryMask.GetValue(); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Read32(Prxy_TagStatus)", m_index); *value = Prxy.TagStatus.GetValue(); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_Out_MBox)", m_index); while(!SPU.Out_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break; - case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); *value = SPU.In_MBox.GetValue(); break; + case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_In_MBox)", m_index); while(!SPU.In_MBox.Pop(*value) && !Emu.IsStopped()) Sleep(1); break; case SPU_MBox_Status_offs: //ConLog.Warning("RawSPUThread[%d]: Read32(SPU_MBox_Status)", m_index); - SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1); - SPU.MBox_Status.SetValue((SPU.MBox_Status.GetValue() & ~0xff00) | (SPU.In_MBox.GetCount() << 8)); + //SPU.MBox_Status.SetValue(SPU.Out_MBox.GetCount() ? SPU.MBox_Status.GetValue() | 1 : SPU.MBox_Status.GetValue() & ~1); + SPU.MBox_Status.SetValue((SPU.Out_MBox.GetCount() & 0xff) | (SPU.In_MBox.GetFreeCount() << 8)); *value = SPU.MBox_Status.GetValue(); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Read32(SPU_RunCntl)", m_index); *value = SPU.RunCntl.GetValue(); break; @@ -156,38 +156,9 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) case MFC_EAL_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_EAL, 0x%x)", m_index, value); MFC.EAL.SetValue(value); break; case MFC_Size_Tag_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_Size_Tag, 0x%x)", m_index, value); MFC.Size_Tag.SetValue(value); break; case MFC_CMDStatus_offs: - { ConLog.Warning("RawSPUThread[%d]: Write32(MFC_CMDStatus, 0x%x)", m_index, value); MFC.CMDStatus.SetValue(value); - u16 op = value & MFC_MASK_CMD; - - switch(op) - { - case MFC_PUT_CMD: - case MFC_GET_CMD: - { - u32 lsa = MFC.LSA.GetValue(); - u64 ea = (u64)MFC.EAL.GetValue() | ((u64)MFC.EAH.GetValue() << 32); - u32 size_tag = MFC.Size_Tag.GetValue(); - u16 tag = (u16)size_tag; - u16 size = size_tag >> 16; - - ConLog.Warning("RawSPUThread[%d]: DMA %s:", m_index, op == MFC_PUT_CMD ? "PUT" : "GET"); - ConLog.Warning("*** lsa = 0x%x", lsa); - ConLog.Warning("*** ea = 0x%llx", ea); - ConLog.Warning("*** tag = 0x%x", tag); - ConLog.Warning("*** size = 0x%x", size); - ConLog.SkipLn(); - - MFC.CMDStatus.SetValue(dmac.Cmd(value, tag, lsa, ea, size)); - } - break; - - default: - ConLog.Error("RawSPUThread[%d]: Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", m_index, op, value); - break; - } - } + DoMfcCmd(); break; case MFC_QStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(MFC_QStatus, 0x%x)", m_index, value); MFC.QStatus.SetValue(value); break; case Prxy_QueryType_offs: @@ -213,7 +184,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value) case Prxy_QueryMask_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_QueryMask, 0x%x)", m_index, value); Prxy.QueryMask.SetValue(value); break; case Prxy_TagStatus_offs: ConLog.Warning("RawSPUThread[%d]: Write32(Prxy_TagStatus, 0x%x)", m_index, value); Prxy.TagStatus.SetValue(value); break; case SPU_Out_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Out_MBox, 0x%x)", m_index, value); while(!SPU.Out_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break; - case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); SPU.In_MBox.SetValue(value); break; + case SPU_In_MBox_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_In_MBox, 0x%x)", m_index, value); while(!SPU.In_MBox.Push(value) && !Emu.IsStopped()) Sleep(1); break; case SPU_MBox_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_MBox_Status, 0x%x)", m_index, value); SPU.MBox_Status.SetValue(value); break; case SPU_RunCntl_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_RunCntl, 0x%x)", m_index, value); SPU.RunCntl.SetValue(value); break; case SPU_Status_offs: ConLog.Warning("RawSPUThread[%d]: Write32(SPU_Status, 0x%x)", m_index, value); SPU.Status.SetValue(value); break; @@ -284,7 +255,8 @@ void RawSPUThread::Task() } } - bool is_last_paused = SPU.RunCntl.GetValue() == SPU_RUNCNTL_STOP; + bool is_last_paused = true; + while(true) { int status = ThreadStatus(); @@ -306,11 +278,9 @@ void RawSPUThread::Task() { if(!is_last_paused) { - if(is_last_paused = SPU.RunCntl.GetValue() != SPU_RUNCNTL_RUNNABLE) - { - SPU.NPC.SetValue(PC); - SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); - } + is_last_paused = true; + SPU.NPC.SetValue(PC); + SPU.Status.SetValue(SPU_STATUS_WAITING_FOR_CHANNEL); } Sleep(1); @@ -322,6 +292,7 @@ void RawSPUThread::Task() is_last_paused = false; PC = SPU.NPC.GetValue(); SPU.Status.SetValue(SPU_STATUS_RUNNING); + ConLog.Warning("Starting RawSPU..."); } Step(); @@ -330,7 +301,7 @@ void RawSPUThread::Task() if(status == CPUThread_Step) { m_is_step = false; - break; + continue; } for(uint i=0; i> 16; + + ConLog.Warning("DMA %s:", op & MFC_PUT_CMD ? "PUT" : "GET"); + ConLog.Warning("*** lsa = 0x%x", lsa); + ConLog.Warning("*** ea = 0x%llx", ea); + ConLog.Warning("*** tag = 0x%x", tag); + ConLog.Warning("*** size = 0x%x", size); + ConLog.Warning("*** cmd = 0x%x", cmd); + ConLog.SkipLn(); + + MFC.CMDStatus.SetValue(dmac.Cmd(cmd, tag, lsa, ea, size)); + } + break; + + default: + ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x)", op, cmd); + break; + } + } + u32 GetChannelCount(u32 ch) { switch(ch) @@ -395,7 +429,7 @@ public: return 0;//return SPU.OutIntr_Mbox.GetFreeCount(); default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } @@ -406,28 +440,11 @@ public: { const u32 v = r._u32[3]; + ConLog.Warning("%s: %s = 0x%x", __FUNCTION__, spu_ch_name[ch], v); + switch(ch) { - case SPU_WrEventMask: //Write event mask - case SPU_WrEventAck: //Write end of event processing - case SPU_WrDec: //Write decrementer count - case SPU_WrSRR0: //Write SPU machine state save/restore register 0 (SRR0) - case MFC_WrMSSyncReq: //Write multisource synchronization request - case MFC_LSA: //Write local memory address command parameter - case MFC_EAH: //Write high order DMA effective address command parameter - case MFC_EAL: //Write low order DMA effective address command parameter - case MFC_Size: //Write DMA transfer size command parameter - case MFC_TagID: //Write tag identifier command parameter - case MFC_Cmd: //Write and enqueue DMA command with associated class ID - case MFC_WrTagMask: //Write tag mask - case MFC_WrTagUpdate: //Write request for conditional or unconditional tag status update - case MFC_WrListStallAck: //Write DMA list stall-and-notify acknowledge - ConLog.Error("%s error: unimplemented channel (%s).", __FUNCTION__, spu_ch_name[ch]); - break; - case SPU_WrOutIntrMbox: - ConLog.Warning("SPU_WrOutIntrMbox = 0x%x", v); - while(!SPU.OutIntr_Mbox.Push(v) && !Emu.IsStopped()) { Sleep(1); @@ -435,16 +452,47 @@ public: break; case SPU_WrOutMbox: - ConLog.Warning("SPU_WrOutMbox = 0x%x", v); - while(!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) { Sleep(1); } break; + case MFC_WrTagMask: + Prxy.QueryMask.SetValue(v); + break; + + case MFC_WrTagUpdate: + Prxy.TagStatus.SetValue(Prxy.QueryMask.GetValue()); + break; + + case MFC_LSA: + MFC.LSA.SetValue(v); + break; + + case MFC_EAH: + MFC.EAH.SetValue(v); + break; + + case MFC_EAL: + MFC.EAL.SetValue(v); + break; + + case MFC_Size: + MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & 0xffff) | (v << 16)); + break; + + case MFC_TagID: + MFC.Size_Tag.SetValue((MFC.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff)); + break; + + case MFC_Cmd: + MFC.CMDStatus.SetValue(v); + DoMfcCmd(); + break; + default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } } @@ -456,29 +504,20 @@ public: switch(ch) { - case SPU_RdEventStat: //Read event status with mask applied - case SPU_RdSigNotify1: //Signal notification 1 - case SPU_RdSigNotify2: //Signal notification 2 - case SPU_RdDec: //Read decrementer count - case SPU_RdEventMask: //Read event mask - case SPU_RdMachStat: //Read SPU run status - case SPU_RdSRR0: //Read SPU machine state save/restore register 0 (SRR0) - case MFC_RdTagMask: //Read tag mask - case MFC_RdTagStat: //Read tag status with mask applied - case MFC_RdListStallStat: //Read DMA list stall-and-notify status - case MFC_RdAtomicStat: //Read completion status of last completed immediate MFC atomic update command - ConLog.Error("%s error: unimplemented channel (%s).", __FUNCTION__, spu_ch_name[ch]); - break; - case SPU_RdInMbox: if(!SPU.In_MBox.Pop(v)) v = 0; - ConLog.Warning("%s: SPU_RdInMbox(0x%x).", __FUNCTION__, v); + break; + + case MFC_RdTagStat: + v = Prxy.TagStatus.GetValue(); break; default: - ConLog.Error("%s error: unknown/illegal channel (%d).", __FUNCTION__, ch); + ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]); break; } + + ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]); } bool IsGoodLSA(const u32 lsa) const { return Memory.IsGoodAddr(lsa + m_offset) && lsa < 0x40000; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index bfef39781b..b7ac55744d 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -39,9 +39,18 @@ int cellGcmMapMainMemory(u32 address, u32 size, mem32_t offset) return CELL_OK; } +int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) +{ + cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); + //Memory.Map(io, ea, size); + //Emu.GetGSManager().GetRender().m_ioAddress = io; + Emu.GetGSManager().GetRender().m_report_main_addr = ea; + return CELL_OK; +} + int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) { - cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); + cellGcmSys.Warning("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); const u32 local_size = 0xf900000; //TODO const u32 local_addr = Memory.RSXFBMem.GetStartAddr(); @@ -144,6 +153,7 @@ int cellGcmAddressToOffset(u32 address, mem32_t offset) } offset = address - sa; + //ConLog.Warning("Address To Offset: 0x%x -> 0x%x", address, address - sa); //Memory.Write16(map_offset_addr + map_offset_pos + 0, ea); //Memory.Write16(map_offset_addr + map_offset_pos + 2, offset); //map_offset_pos += 4; @@ -153,7 +163,7 @@ int cellGcmAddressToOffset(u32 address, mem32_t offset) int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height) { - cellGcmSys.Log("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", + cellGcmSys.Warning("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", id, offset, width ? pitch/width : pitch, width, height); if(id > 7) return CELL_EINVAL; @@ -308,14 +318,6 @@ int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize) return CELL_OK; } -int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) -{ - cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); - Memory.Map(io, ea, size); - Emu.GetGSManager().GetRender().m_report_main_addr = ea; - return CELL_OK; -} - int cellGcmUnbindZcull(u8 index) { cellGcmSys.Warning("cellGcmUnbindZcull(index=%d)", index); @@ -353,7 +355,23 @@ int cellGcmSetFlipCommandWithWaitLabel(u32 ctx, u32 id, u32 label_index, u32 lab { int res = cellGcmSetPrepareFlip(ctx, id); Memory.Write32(Memory.RSXCMDMem.GetStartAddr() + 0x10 * label_index, label_value); - return res == CELL_GCM_ERROR_FAILURE ? CELL_GCM_ERROR_FAILURE : CELL_OK; + return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; +} + +int cellGcmSetFlip(mem_ptr_t ctxt, u32 id) +{ + cellGcmSys.Warning("cellGcmSetFlip(ctx=0x%x, id=0x%x)", ctxt.GetAddr(), id); + + int res = cellGcmSetPrepareFlip(ctxt, id); + return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; +} + +int cellGcmSetWaitFlip(mem_ptr_t ctxt) +{ + cellGcmSys.Warning("cellGcmSetWaitFlip(ctx=0x%x)", ctxt.GetAddr()); + + //GSLockCurrent lock(GS_LOCK_WAIT_FLIP); + return CELL_OK; } int cellGcmInitCursor() @@ -531,6 +549,8 @@ int cellGcmSetDebugOutputLevel (int level) default: return CELL_EINVAL; } + + return CELL_OK; } int cellGcmSetSecondVFrequency (u32 freq) @@ -547,6 +567,8 @@ int cellGcmSetSecondVFrequency (u32 freq) default: return CELL_EINVAL; } + + return CELL_OK; } void cellGcmSys_init() @@ -596,4 +618,6 @@ void cellGcmSys_init() cellGcmSys.AddFunc(0x8572bce2, cellGcmGetReportDataAddressLocation); cellGcmSys.AddFunc(0x51c9d62b, cellGcmSetDebugOutputLevel); cellGcmSys.AddFunc(0x4d7ce993, cellGcmSetSecondVFrequency); + cellGcmSys.AddFunc(0xdc09357e, cellGcmSetFlip); + cellGcmSys.AddFunc(0x983fb9aa, cellGcmSetWaitFlip); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp index 700f51ef03..55700fd4fc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellResc.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellResc.cpp @@ -600,6 +600,7 @@ int cellRescGetBufferSize(mem32_t colorBuffers, mem32_t vertexArray, mem32_t fra colorBuffersSize = s_rescInternalInstance->m_dstBufInterval * GetNumColorBuffers(); vertexArraySize = 0x180; //sizeof(RescVertex_t) * VERTEX_NUMBER_RESERVED; //fragmentUcodeSize = m_pCFragmentShader->GetUcodeSize(); + fragmentUcodeSize = 0x300; } else //CELL_RESC_CONSTANT_VRAM { diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 8e9b151099..b779f0b68e 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -233,9 +233,6 @@ extern int cellVideoOutGetConfiguration(u32 videoOut, u32 config_addr, u32 optio extern int cellVideoOutGetNumberOfDevice(u32 videoOut); extern int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option); -//cellMsgDialog -extern int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 userData, u32 extParam); - //cellPad extern int cellPadInit(u32 max_connect); extern int cellPadEnd();