From cc33a016f0e6ec479912a5daaca4de4135bc49d5 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Mon, 14 Sep 2009 04:37:59 +0000 Subject: [PATCH] Rewrote _gifTransferDummy for Path1 transfers (VU's xgkick), now it properly supports wrapping around VU memory without any hacks (hopefully fixes some games). Path2 and Path3 still use the old function since I need to do more research on them and how pcsx2 is emulating them... If this commit breaks anything let me know. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1820 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/GS.h | 5 +- pcsx2/MTGS.cpp | 104 ++++++++++++++++++++++++++---------- pcsx2/VUops.cpp | 44 +++++---------- pcsx2/x86/microVU_Lower.inl | 28 +++++----- pcsx2/x86/sVU_Lower.cpp | 33 ++++++------ 5 files changed, 121 insertions(+), 93 deletions(-) diff --git a/pcsx2/GS.h b/pcsx2/GS.h index a1ac413bc4..62ab53047c 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -94,7 +94,7 @@ struct GIFPath u8 regs[16]; __forceinline void PrepRegs(); - void SetTag(const void* mem); + void SetTag(const void* mem, bool doPrepRegs); u32 GetReg(); __forceinline bool StepReg() @@ -257,7 +257,8 @@ protected: // Processes a GIFtag & packet, and throws out some gsIRQs as needed. // Used to keep interrupts in sync with the EE, while the GS itself // runs potentially several frames behind. - int _gifTransferDummy( GIF_PATH pathidx, const u8 *pMem, u32 size ); + int _gifTransferDummy ( GIF_PATH pathidx, const u8 *pMem, u32 size ); + int _gifTransferDummy2( GIF_PATH pathidx, const u8 *pMem, u32 size ); // Used internally by SendSimplePacket type functions uint _PrepForSimplePacket(); diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index d75008b13e..00c8f50ff4 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -61,33 +61,22 @@ using namespace std; // them into an 8 bit array. __forceinline void GIFPath::PrepRegs() { - if( tag.nreg == 0 ) - { - u32 tempreg = tag.regs[0]; - for(u32 i=0; i<16; ++i, tempreg >>= 4) - { - if( i == 8 ) tempreg = tag.regs[1]; - assert( (tempreg&0xf) < 0x64 ); - regs[i] = tempreg & 0xf; - } - } - else - { - u32 tempreg = tag.regs[0]; - for(u32 i=0; i>= 4) - { - assert( (tempreg&0xf) < 0x64 ); - regs[i] = tempreg & 0xf; - } + int loopEnd = ((tag.nreg-1)&0xf) + 1; + u32 tempreg = tag.regs[0]; + + for (int i = 0; i < loopEnd; i++) { + if (i == 8) tempreg = tag.regs[1]; + regs[i] = tempreg & 0xf; + tempreg >>= 4; } } -void GIFPath::SetTag(const void* mem) +void GIFPath::SetTag(const void* mem, bool doPrepRegs = 1) { tag = *((GIFTAG*)mem); curreg = 0; - PrepRegs(); + if (doPrepRegs) PrepRegs(); } u32 GIFPath::GetReg() @@ -246,6 +235,59 @@ void mtgsThreadObject::Reset() memzero_obj( m_path ); } +#define incPmem(x) { \ + if ((pMem + x) >= ptrEnd) pMem = (pMem + x) - 0x4000; \ + else pMem += x; \ + size += x; \ +} + +__forceinline int mtgsThreadObject::_gifTransferDummy2(GIF_PATH pathidx, const u8* pMem, u32 size) +{ + GIFPath& path = m_path[pathidx]; + u8* ptrEnd = (u8*)pMem + (size<<4); // End of VU Mem + bool EOP = 0; + bool hasRegAD = 0; + size = 0; + + while(!EOP && size < 0x4000) { + path.SetTag(pMem, !path.tag.flg); + EOP = path.tag.eop; + int numRegs = ((path.tag.nreg-1)&0xf)+1; + incPmem(16); + if (!path.tag.nloop) continue; + switch(path.tag.flg) { + case GIF_FLG_PACKED: + for (u32 i = 0; i < path.tag.nloop; i++) { + for (int j = 0; j < numRegs; j++) { + if (path.regs[j] == 0x0e) { + const int handler = pMem[8]; + if (handler >= 0x60 && handler < 0x63) { + //DevCon::Status("GIF Tag Signal"); + s_GSHandlers[handler&0x3]((const u32*)pMem); + } + hasRegAD = 1; + } + incPmem(16); + } + if (!hasRegAD) { // Optimization: No Need to Loop + incPmem((16 * numRegs * (path.tag.nloop-1))); + break; + } + } + break; + case GIF_FLG_REGLIST: + numRegs = (numRegs + 1) / 2; + incPmem((16 * numRegs * path.tag.nloop)); + break; + case GIF_FLG_IMAGE: + case GIF_FLG_IMAGE2: + incPmem((16 * path.tag.nloop)); + break; + } + } + return (size / 16); +} + // Processes a GIFtag & packet, and throws out some gsIRQs as needed. // Used to keep interrupts in sync with the EE, while the GS itself // runs potentially several frames behind. @@ -905,17 +947,21 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s size = (size+15)&(~15); }*/ - // retval has the amount of data *not* processed, so we only need to reserve - // enough room for size - retval: - int retval = _gifTransferDummy( pathidx, srcdata, size ); + if (pathidx != GIF_PATH_1) { + // retval has the amount of data *not* processed, so we only need to reserve + // enough room for size - retval: + int retval = _gifTransferDummy( pathidx, srcdata, size ); - if(pathidx == 2) - { - gif->madr += (size - retval) * 16; - gif->qwc -= size - retval; + if(pathidx == GIF_PATH_3) + { + gif->madr += (size - retval) * 16; + gif->qwc -= size - retval; + } + //if(retval < 0) DevCon::Notice("Increasing size from %x to %x path %x", size, size-retval, pathidx+1); + size = size - retval; } - //if(retval < 0) DevCon::Notice("Increasing size from %x to %x path %x", size, size-retval, pathidx+1); - size = size - retval; + else size = _gifTransferDummy2(pathidx, srcdata, size); + m_packet_size = size; size++; // takes into account our command qword. diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index a757356c06..aaf742cc0c 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -2046,43 +2046,27 @@ void _vuXITOP(VURegs * VU) { void _vuXGKICK(VURegs * VU) { -// u32* ptr = (u32*)GET_VU_MEM(VU, (VU->VI[_Is_].US[0]*16) & (VU == &VU1 ? 0x3fff : 0xfff)); -// int temp = 0x4000 - ((VU->VI[_Is_].US[0]*16) & 0x3fff); -// u32 tempmem[0x8000]; - // flush all pipelines first (in the right order) _vuFlushAll(VU); - //Gonna be slow but reshuffles the memory so overflows wont occur - /* memset(tempmem, 0, sizeof(tempmem)); - memcpy(tempmem, ptr, temp); - ptr = (u32*)GET_VU_MEM(VU, 0); - memcpy(&tempmem[temp], ptr, ((VU->VI[_Is_].US[0]*16) & 0x3fff)); - GSGIFTRANSFER1((u32*)&tempmem[0], 0); - } else*/ - //DevCon::Notice("Addr %x", VU->VI[_Is_].US[0] & 0x3fff); - - u32* data = (u32*)((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff)); + u8* data = ((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff)); u32 size; size = mtgsThread->PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4); + u8* pmem = mtgsThread->GetDataPacketPtr(); + + if((size << 4) > (u32)(0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff))) { - u8* pmem = mtgsThread->GetDataPacketPtr(); - - /* if((size << 4) > (u32)(0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff))) - { - //DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", ((VU->VI[_Is_].US[0]*16) & 0x3fff) + (size << 4), (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4, size - (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff) >> 4)); - memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)); - size -= (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4; - //DevCon::Notice("Size left %x", size); - pmem += 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff); - memcpy_aligned(pmem, (u8*)VU->Mem, size<<4); - } - else - {*/ - memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), size<<4); - //} - mtgsThread->SendDataPacket(); + //DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", ((VU->VI[_Is_].US[0]*16) & 0x3fff) + (size << 4), (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4, size - (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff) >> 4)); + memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)); + size -= (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4; + //DevCon::Notice("Size left %x", size); + pmem += 0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff); + memcpy_aligned(pmem, (u8*)VU->Mem, size<<4); } + else { + memcpy_aligned(pmem, (u8*)VU->Mem+((VU->VI[_Is_].US[0]*16) & 0x3fff), size<<4); + } + mtgsThread->SendDataPacket(); } void _vuXTOP(VURegs * VU) { diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 923f8f01c7..c373eddff5 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1104,28 +1104,28 @@ mVUop(mVU_XITOP) { void __fastcall mVU_XGKICK_(u32 addr) { addr = (addr<<4) & 0x3fff; // Multiply addr by 16 to get real address - u32 *data = (u32*)(microVU1.regs->Mem + addr); - u32 size = mtgsThread->PrepDataPacket(GIF_PATH_1, data, (0x4000-addr) >> 4); - u8 *pDest = mtgsThread->GetDataPacketPtr(); -/* if((size << 4) > (0x4000-(addr&0x3fff))) { - //DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4)); - memcpy_aligned(pDest, microVU1.regs->Mem + addr, 0x4000-(addr&0x3fff)); - size -= (0x4000-(addr&0x3fff)) >> 4; - //DevCon::Notice("Size left %x", size); - pDest += 0x4000-(addr&0x3fff); + u8* data = (u8*)(microVU1.regs->Mem + addr); + u32 diff = 0x4000 - addr; + u32 size = mtgsThread->PrepDataPacket(GIF_PATH_1, data, diff >> 4); + u8* pDest = mtgsThread->GetDataPacketPtr(); + + if((size << 4) > diff) { + //DevCon::Status("XGkick Wrap!"); + memcpy_aligned(pDest, microVU1.regs->Mem + addr, diff); + size -= diff >> 4; + pDest += diff; memcpy_aligned(pDest, microVU1.regs->Mem, size<<4); } - else { */ + else { memcpy_aligned(pDest, microVU1.regs->Mem + addr, size<<4); -// } + } mtgsThread->SendDataPacket(); } microVUt(void) mVU_XGKICK_DELAY(mV, bool memVI) { mVUbackupRegs(mVU); - if (memVI) MOV32MtoR(gprT2, (uptr)&mVU->VIxgkick); - else mVUallocVIa(mVU, gprT2, _Is_); - + if (memVI) MOV32MtoR(gprT2, (uptr)&mVU->VIxgkick); + else mVUallocVIa(mVU, gprT2, _Is_); CALLFunc((uptr)mVU_XGKICK_); mVUrestoreRegs(mVU); } diff --git a/pcsx2/x86/sVU_Lower.cpp b/pcsx2/x86/sVU_Lower.cpp index 6c3c62c5a1..45d5ed2378 100644 --- a/pcsx2/x86/sVU_Lower.cpp +++ b/pcsx2/x86/sVU_Lower.cpp @@ -1973,7 +1973,7 @@ void recVUMI_XTOP( VURegs *VU, int info ) void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) { u32 size; - u32* data = (u32*)((u8*)pMem + (addr&0x3fff)); + u8* data = ((u8*)pMem + (addr&0x3fff)); // fixme: The gifTagDummy function in the MTGS (called by PrepDataPacket) has a // hack that aborts the packet if it goes past the end of VU1 memory. @@ -1983,24 +1983,21 @@ void VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) size = mtgsThread->PrepDataPacket(GIF_PATH_1, data, (0x4000-(addr&0x3fff)) >> 4); jASSUME( size > 0 ); - //if( size > 0 ) + u8* pmem = mtgsThread->GetDataPacketPtr(); + + if((size << 4) > (0x4000-(addr&0x3fff))) { - u8* pmem = mtgsThread->GetDataPacketPtr(); - - /* if((size << 4) > (0x4000-(addr&0x3fff))) - { - //DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4)); - memcpy_aligned(pmem, (u8*)pMem+addr, 0x4000-(addr&0x3fff)); - size -= (0x4000-(addr&0x3fff)) >> 4; - //DevCon::Notice("Size left %x", size); - pmem += 0x4000-(addr&0x3fff); - memcpy_aligned(pmem, (u8*)pMem, size<<4); - } - else - {*/ - memcpy_aligned(pmem, (u8*)pMem+addr, size<<4); - // } - mtgsThread->SendDataPacket(); + //DevCon::Notice("addr + Size = 0x%x, transferring %x then doing %x", (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4)); + memcpy_aligned(pmem, (u8*)pMem+addr, 0x4000-(addr&0x3fff)); + size -= (0x4000-(addr&0x3fff)) >> 4; + //DevCon::Notice("Size left %x", size); + pmem += 0x4000-(addr&0x3fff); + memcpy_aligned(pmem, (u8*)pMem, size<<4); } + else { + memcpy_aligned(pmem, (u8*)pMem+addr, size<<4); + } + + mtgsThread->SendDataPacket(); } //------------------------------------------------------------------