mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
de0442321f
commit
cc33a016f0
|
@ -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();
|
||||
|
|
104
pcsx2/MTGS.cpp
104
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<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.
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue