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
This commit is contained in:
cottonvibes 2009-09-14 04:37:59 +00:00
parent de0442321f
commit cc33a016f0
5 changed files with 121 additions and 93 deletions

View File

@ -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();

View File

@ -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<tag.nreg; ++i, tempreg >>= 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.

View File

@ -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) {

View File

@ -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);
}

View File

@ -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();
}
//------------------------------------------------------------------