mirror of https://github.com/PCSX2/pcsx2.git
Another MTGS fix. This one was a known bug that I was saving for last, and in fixing it I was able to roll back the hack-fix for in-game stalls from r375.
git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@376 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
parent
6043dd643a
commit
b585641029
124
pcsx2/GS.cpp
124
pcsx2/GS.cpp
|
@ -65,7 +65,7 @@ static void thread_close( thread_t& thread )
|
||||||
if( status != STILL_ACTIVE ) break;
|
if( status != STILL_ACTIVE ) break;
|
||||||
Sleep( 3 );
|
Sleep( 3 );
|
||||||
}
|
}
|
||||||
CloseHandle( &thread );
|
CloseHandle( thread );
|
||||||
thread = NULL;
|
thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ struct wait_event_t
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
wait_event_t() : cond( NULL ), mutex( NULL ) {}
|
wait_event_t() : cond( PTHREAD_COND_INITIALIZER ), mutex( PTHREAD_MUTEX_INITIALIZER ) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pthread_mutex_t mutex_t;
|
typedef pthread_mutex_t mutex_t;
|
||||||
|
@ -141,9 +141,7 @@ static bool thread_create( thread_t& thread )
|
||||||
|
|
||||||
static void thread_close( thread_t& thread )
|
static void thread_close( thread_t& thread )
|
||||||
{
|
{
|
||||||
if( thread.p == NULL ) return;
|
|
||||||
pthread_join( thread, NULL );
|
pthread_join( thread, NULL );
|
||||||
thread.p = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void event_init( wait_event_t& evt )
|
static void event_init( wait_event_t& evt )
|
||||||
|
@ -360,17 +358,6 @@ s32 gsOpen()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep instead of timeslice. This function is for use in cases where longer
|
|
||||||
// delays are merited.
|
|
||||||
__forceinline void _Sleep( int ms )
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(ms);
|
|
||||||
#else
|
|
||||||
usleep(ms * 1000);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GS_SETEVENT()
|
void GS_SETEVENT()
|
||||||
{
|
{
|
||||||
event_set(g_hGsEvent);
|
event_set(g_hGsEvent);
|
||||||
|
@ -383,7 +370,7 @@ __forceinline void gsWaitGS()
|
||||||
|
|
||||||
GS_SETEVENT();
|
GS_SETEVENT();
|
||||||
while( *(volatile PU8*)&g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos )
|
while( *(volatile PU8*)&g_pGSRingPos != *(volatile PU8*)&g_pGSWritePos )
|
||||||
_Sleep(2);
|
_TIMESLICE();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the gsEvent flag and releases a timeslice.
|
// Sets the gsEvent flag and releases a timeslice.
|
||||||
|
@ -618,7 +605,7 @@ void GSRingBufSimplePacket(int type, int data0, int data1, int data2)
|
||||||
assert( future_writepos != *(volatile PU8*)&g_pGSRingPos );
|
assert( future_writepos != *(volatile PU8*)&g_pGSRingPos );
|
||||||
InterlockedExchangePointer(&g_pGSWritePos, future_writepos);
|
InterlockedExchangePointer(&g_pGSWritePos, future_writepos);
|
||||||
|
|
||||||
GS_SETEVENT();
|
//GS_SETEVENT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void gsReset()
|
void gsReset()
|
||||||
|
@ -636,6 +623,7 @@ void gsReset()
|
||||||
#endif
|
#endif
|
||||||
MTGS_LOG( "MTGS > Sending Reset...\n" );
|
MTGS_LOG( "MTGS > Sending Reset...\n" );
|
||||||
GSRingBufSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
|
GSRingBufSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
|
||||||
|
//GS_SETEVENT();
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
g_mtgsCopyLock = 0;
|
g_mtgsCopyLock = 0;
|
||||||
|
@ -704,18 +692,22 @@ void gsGIFReset()
|
||||||
|
|
||||||
void CSRwrite(u32 value)
|
void CSRwrite(u32 value)
|
||||||
{
|
{
|
||||||
// [TODO] Ideally GSwriteCSR should be run through the MTGS ringbuffer also, but it doesn't
|
|
||||||
// make much of a difference since the GS plugin only uses it for re-enabling gsInts, which
|
|
||||||
// are handled by Pcsx2's GIFtagTransferDummy function instead of the GA in MTGS mode anyway.
|
|
||||||
// (in other words the gs copy of CSRw is effectively ignored in MTGS mode)
|
|
||||||
|
|
||||||
CSRw |= value & ~0x60;
|
CSRw |= value & ~0x60;
|
||||||
GSwriteCSR(CSRw);
|
|
||||||
|
if( CHECK_MULTIGS )
|
||||||
|
{
|
||||||
|
GSRingBufSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 );
|
||||||
|
GS_SETEVENT();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GSwriteCSR(CSRw);
|
||||||
|
|
||||||
GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
|
GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
|
||||||
if( value & 0x100 ) { // FLUSH
|
|
||||||
|
// Our emulated GS has no FIFO...
|
||||||
|
/*if( value & 0x100 ) { // FLUSH
|
||||||
//SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr);
|
//SysPrintf("GS_CSR FLUSH GS fifo: %x (CSRr=%x)\n", value, GSCSRr);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (value & 0x200) { // resetGS
|
if (value & 0x200) { // resetGS
|
||||||
|
|
||||||
|
@ -725,20 +717,13 @@ void CSRwrite(u32 value)
|
||||||
if( !_gsGIFSoftReset( 7 ) )
|
if( !_gsGIFSoftReset( 7 ) )
|
||||||
{
|
{
|
||||||
if( CHECK_MULTIGS )
|
if( CHECK_MULTIGS )
|
||||||
{
|
|
||||||
GSRingBufSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
|
GSRingBufSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 );
|
||||||
}
|
|
||||||
else
|
else
|
||||||
GSreset();
|
GSreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
GSCSRr = 0x551B400F; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib)
|
GSCSRr = 0x551B400F; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib)
|
||||||
GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
|
GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1
|
||||||
|
|
||||||
// and this too (fixed megaman ac)
|
|
||||||
//CSRw = (u32)GSCSRr;
|
|
||||||
// Since the line above was commented out, I don't think this was needed anymore (Air)
|
|
||||||
//GSwriteCSR(CSRw);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,14 +763,12 @@ void gsWrite16(u32 mem, u16 value) {
|
||||||
case 0x12000010: // GS_SMODE1
|
case 0x12000010: // GS_SMODE1
|
||||||
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
||||||
else Config.PsxType &= ~1; // NTSC
|
else Config.PsxType &= ~1; // NTSC
|
||||||
|
|
||||||
UpdateVSyncRate();
|
UpdateVSyncRate();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12000020: // GS_SMODE2
|
case 0x12000020: // GS_SMODE2
|
||||||
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
||||||
else Config.PsxType &= ~2; // Non-Interlaced
|
else Config.PsxType &= ~2; // Non-Interlaced
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12001000: // GS_CSR
|
case 0x12001000: // GS_CSR
|
||||||
|
@ -816,15 +799,12 @@ void gsWrite32(u32 mem, u32 value)
|
||||||
case 0x12000010: // GS_SMODE1
|
case 0x12000010: // GS_SMODE1
|
||||||
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
||||||
else Config.PsxType &= ~1; // NTSC
|
else Config.PsxType &= ~1; // NTSC
|
||||||
*(u32*)PS2GS_BASE(mem) = value;
|
|
||||||
|
|
||||||
UpdateVSyncRate();
|
UpdateVSyncRate();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12000020: // GS_SMODE2
|
case 0x12000020: // GS_SMODE2
|
||||||
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
||||||
else Config.PsxType &= ~2; // Non-Interlaced
|
else Config.PsxType &= ~2; // Non-Interlaced
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12001000: // GS_CSR
|
case 0x12001000: // GS_CSR
|
||||||
|
@ -852,14 +832,13 @@ void gsWrite64(u32 mem, u64 value) {
|
||||||
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
if((value & 0x6000) == 0x6000) Config.PsxType |= 1; // PAL
|
||||||
else Config.PsxType &= ~1; // NTSC
|
else Config.PsxType &= ~1; // NTSC
|
||||||
UpdateVSyncRate();
|
UpdateVSyncRate();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12000020: // GS_SMODE2
|
case 0x12000020: // GS_SMODE2
|
||||||
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
if(value & 0x1) Config.PsxType |= 2; // Interlaced
|
||||||
else Config.PsxType &= ~2; // Non-Interlaced
|
else Config.PsxType &= ~2; // Non-Interlaced
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x12001000: // GS_CSR
|
case 0x12001000: // GS_CSR
|
||||||
CSRwrite((u32)value);
|
CSRwrite((u32)value);
|
||||||
return;
|
return;
|
||||||
|
@ -878,27 +857,27 @@ void gsWrite64(u32 mem, u64 value) {
|
||||||
|
|
||||||
u8 gsRead8(u32 mem)
|
u8 gsRead8(u32 mem)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS read 8 %8.8lx, at %8.8lx\n", *(u8*)PS2GS_BASE(mem), mem);
|
GIF_LOG("GS read 8 from %8.8lx value: %8.8lx\n", mem, *(u8*)PS2GS_BASE(mem));
|
||||||
|
|
||||||
return *(u8*)PS2GS_BASE(mem);
|
return *(u8*)PS2GS_BASE(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 gsRead16(u32 mem)
|
u16 gsRead16(u32 mem)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS read 16 %8.8lx, at %8.8lx\n", *(u16*)PS2GS_BASE(mem), mem);
|
GIF_LOG("GS read 16 from %8.8lx value: %8.8lx\n", mem, *(u16*)PS2GS_BASE(mem));
|
||||||
|
|
||||||
return *(u16*)PS2GS_BASE(mem);
|
return *(u16*)PS2GS_BASE(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 gsRead32(u32 mem)
|
u32 gsRead32(u32 mem)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS read 32 %8.8lx, at %8.8lx\n", *(u32*)PS2GS_BASE(mem), mem);
|
GIF_LOG("GS read 32 from %8.8lx value: %8.8lx\n", mem, *(u32*)PS2GS_BASE(mem));
|
||||||
return *(u32*)PS2GS_BASE(mem);
|
return *(u32*)PS2GS_BASE(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 gsRead64(u32 mem)
|
u64 gsRead64(u32 mem)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS read 64 %8.8lx, at %8.8lx\n", *(u32*)PS2GS_BASE(mem), mem);
|
GIF_LOG("GS read 64 from %8.8lx value: %8.8lx_%8.8lx\n", mem, *(u32*)PS2GS_BASE(mem+4), *(u32*)PS2GS_BASE(mem) );
|
||||||
return *(u64*)PS2GS_BASE(mem);
|
return *(u64*)PS2GS_BASE(mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,7 +887,7 @@ void gsIrq() {
|
||||||
|
|
||||||
static void GSRegHandlerSIGNAL(u32* data)
|
static void GSRegHandlerSIGNAL(u32* data)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS SIGNAL data %x_%x CSRw %x\n",data[0], data[1], CSRw);
|
MTGS_LOG("MTGS SIGNAL data %x_%x CSRw %x\n",data[0], data[1], CSRw);
|
||||||
|
|
||||||
GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]);
|
GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]);
|
||||||
|
|
||||||
|
@ -924,7 +903,7 @@ static void GSRegHandlerSIGNAL(u32* data)
|
||||||
|
|
||||||
static void GSRegHandlerFINISH(u32* data)
|
static void GSRegHandlerFINISH(u32* data)
|
||||||
{
|
{
|
||||||
GIF_LOG("GS FINISH data %x_%x CSRw %x\n",data[0], data[1], CSRw);
|
MTGS_LOG("MTGS FINISH data %x_%x CSRw %x\n",data[0], data[1], CSRw);
|
||||||
|
|
||||||
if ((CSRw & 0x2))
|
if ((CSRw & 0x2))
|
||||||
GSCSRr |= 2; // finish
|
GSCSRr |= 2; // finish
|
||||||
|
@ -1626,6 +1605,7 @@ extern "C" void GSPostVsyncEnd()
|
||||||
//SysPrintf( " Sending VSync : %d \n", g_pGSvSyncCount );
|
//SysPrintf( " Sending VSync : %d \n", g_pGSvSyncCount );
|
||||||
#endif
|
#endif
|
||||||
GSRingBufSimplePacket(GS_RINGTYPE_VSYNC, (*(u32*)(PS2MEM_GS+0x1000)&0x2000), 0, 0);
|
GSRingBufSimplePacket(GS_RINGTYPE_VSYNC, (*(u32*)(PS2MEM_GS+0x1000)&0x2000), 0, 0);
|
||||||
|
GS_SETEVENT();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000));
|
GSvsync((*(u32*)(PS2MEM_GS+0x1000)&0x2000));
|
||||||
|
@ -1737,53 +1717,6 @@ GS_THREADPROC
|
||||||
*(u64*)(g_MTGSMem+*(u32*)(g_pGSRingPos+4)) = *(u64*)(g_pGSRingPos+8);
|
*(u64*)(g_MTGSMem+*(u32*)(g_pGSRingPos+4)) = *(u64*)(g_pGSRingPos+8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GS_RINGTYPE_VIFFIFO:
|
|
||||||
{
|
|
||||||
u64* pMem;
|
|
||||||
assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) );
|
|
||||||
assert( vif1ch->qwc == (tag>>16) );
|
|
||||||
|
|
||||||
assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) );
|
|
||||||
pMem = (u64*)dmaGetAddr(vif1ch->madr);
|
|
||||||
|
|
||||||
if (pMem == NULL) {
|
|
||||||
psHu32(DMAC_STAT)|= 1<<15;
|
|
||||||
continue; // don't increment gsRingPos
|
|
||||||
}
|
|
||||||
|
|
||||||
if( GSreadFIFO2 == NULL ) {
|
|
||||||
int size;
|
|
||||||
for (size=(tag>>16); size>0; size--) {
|
|
||||||
GSreadFIFO((u64*)&PS2MEM_HW[0x5000]);
|
|
||||||
pMem[0] = psHu64(0x5000);
|
|
||||||
pMem[1] = psHu64(0x5008); pMem+= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GSreadFIFO2(pMem, tag>>16);
|
|
||||||
|
|
||||||
// set incase read
|
|
||||||
psHu64(0x5000) = pMem[2*(tag>>16)-2];
|
|
||||||
psHu64(0x5008) = pMem[2*(tag>>16)-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( vif1ch->madr == *(u32*)(g_pGSRingPos+4) );
|
|
||||||
assert( vif1ch->qwc == (tag>>16) );
|
|
||||||
|
|
||||||
// tag = (tag>>16) + (cpuRegs.cycle- *(u32*)(g_pGSRingPos+8));
|
|
||||||
// if( tag & 0x80000000 ) tag = 0;
|
|
||||||
vif1ch->madr += vif1ch->qwc * 16;
|
|
||||||
if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000;
|
|
||||||
|
|
||||||
// fixme : calling CPU_INT could create a race condition if it runs parallel
|
|
||||||
// with the EE/IOP code also calling CPU_INT.
|
|
||||||
|
|
||||||
CPU_INT(1, 0); // since gs thread always lags real thread
|
|
||||||
vif1ch->qwc = 0;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GS_RINGTYPE_SAVE:
|
case GS_RINGTYPE_SAVE:
|
||||||
{
|
{
|
||||||
gzFile f = *(gzFile*)(g_pGSRingPos+4);
|
gzFile f = *(gzFile*)(g_pGSRingPos+4);
|
||||||
|
@ -1852,6 +1785,11 @@ GS_THREADPROC
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case GS_RINGTYPE_WRITECSR:
|
||||||
|
GSwriteCSR( *(u32*)(g_pGSRingPos+4) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
SysPrintf("GSThreadProc, bad packet (%x) at g_pGSRingPos: %x, g_pGSWritePos: %x\n", tag, g_pGSRingPos, g_pGSWritePos);
|
SysPrintf("GSThreadProc, bad packet (%x) at g_pGSRingPos: %x, g_pGSWritePos: %x\n", tag, g_pGSRingPos, g_pGSWritePos);
|
||||||
|
|
|
@ -54,7 +54,6 @@ enum GS_RINGTYPE
|
||||||
, GS_RINGTYPE_P2
|
, GS_RINGTYPE_P2
|
||||||
, GS_RINGTYPE_P3
|
, GS_RINGTYPE_P3
|
||||||
, GS_RINGTYPE_VSYNC
|
, GS_RINGTYPE_VSYNC
|
||||||
, GS_RINGTYPE_VIFFIFO // GSreadFIFO2
|
|
||||||
, GS_RINGTYPE_FRAMESKIP
|
, GS_RINGTYPE_FRAMESKIP
|
||||||
, GS_RINGTYPE_MEMWRITE8
|
, GS_RINGTYPE_MEMWRITE8
|
||||||
, GS_RINGTYPE_MEMWRITE16
|
, GS_RINGTYPE_MEMWRITE16
|
||||||
|
@ -65,6 +64,7 @@ enum GS_RINGTYPE
|
||||||
, GS_RINGTYPE_RECORD
|
, GS_RINGTYPE_RECORD
|
||||||
, GS_RINGTYPE_RESET // issues a GSreset() command.
|
, GS_RINGTYPE_RESET // issues a GSreset() command.
|
||||||
, GS_RINGTYPE_SOFTRESET // issues a soft reset for the GIF
|
, GS_RINGTYPE_SOFTRESET // issues a soft reset for the GIF
|
||||||
|
, GS_RINGTYPE_WRITECSR
|
||||||
};
|
};
|
||||||
|
|
||||||
// if returns NULL, don't copy (memory is preserved)
|
// if returns NULL, don't copy (memory is preserved)
|
||||||
|
|
|
@ -438,7 +438,7 @@ static __forceinline void _cpuTestPERF()
|
||||||
|
|
||||||
// Maximum wait between branches. Lower values provide a tighter synchronization between
|
// Maximum wait between branches. Lower values provide a tighter synchronization between
|
||||||
// the EE and the IOP, but incur more execution overhead.
|
// the EE and the IOP, but incur more execution overhead.
|
||||||
#define EE_WAIT_CYCLE 512 // 2048 is still unstable due to COP0
|
#define EE_WAIT_CYCLE 2048 // 2048 is still unstable due to COP0
|
||||||
|
|
||||||
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
|
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
|
||||||
u32 g_nextBranchCycle = 0;
|
u32 g_nextBranchCycle = 0;
|
||||||
|
@ -517,8 +517,6 @@ X86_32CODE(extern u8 g_globalMMXSaved;)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u32 g_MTGSVifStart = 0, g_MTGSVifCount=0;
|
|
||||||
|
|
||||||
void cpuBranchTest()
|
void cpuBranchTest()
|
||||||
{
|
{
|
||||||
#ifndef PCSX2_NORECBUILD
|
#ifndef PCSX2_NORECBUILD
|
||||||
|
@ -534,16 +532,6 @@ void cpuBranchTest()
|
||||||
// Perform counters, ints, and IOP updates:
|
// Perform counters, ints, and IOP updates:
|
||||||
_cpuBranchTest_Shared();
|
_cpuBranchTest_Shared();
|
||||||
|
|
||||||
// ---- MTGS -------------
|
|
||||||
// stall mtgs if it is taking too long
|
|
||||||
|
|
||||||
if( g_MTGSVifCount > 0 ) {
|
|
||||||
if( (int)(cpuRegs.cycle-g_MTGSVifStart) > g_MTGSVifCount ) {
|
|
||||||
gsWaitGS();
|
|
||||||
g_MTGSVifCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---- VU0 -------------
|
// ---- VU0 -------------
|
||||||
|
|
||||||
if (VU0.VI[REG_VPU_STAT].UL & 0x1)
|
if (VU0.VI[REG_VPU_STAT].UL & 0x1)
|
||||||
|
|
105
pcsx2/VifDma.c
105
pcsx2/VifDma.c
|
@ -2234,7 +2234,6 @@ __forceinline void vif1Interrupt() {
|
||||||
cpuRegs.interrupt &= ~(1 << 1);
|
cpuRegs.interrupt &= ~(1 << 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern u32 g_MTGSVifStart, g_MTGSVifCount;
|
|
||||||
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
|
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
|
||||||
void dmaVIF1()
|
void dmaVIF1()
|
||||||
{
|
{
|
||||||
|
@ -2309,76 +2308,54 @@ void dmaVIF1()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CPU_INT(1, g_vifCycles);
|
CPU_INT(1, g_vifCycles);
|
||||||
} else { // from Memory
|
} else {
|
||||||
|
|
||||||
|
int size;
|
||||||
|
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
|
||||||
if( CHECK_MULTIGS ) {
|
|
||||||
u8* pTempMem, *pEndMem;
|
|
||||||
|
|
||||||
u8* pMem = GSRingBufCopy(0, GS_RINGTYPE_VIFFIFO);
|
// VIF from gsMemory
|
||||||
*(u32*)(pMem-16) = GS_RINGTYPE_VIFFIFO|(vif1ch->qwc<<16); // hack
|
|
||||||
*(u32*)(pMem-12) = vif1ch->madr;
|
|
||||||
*(u32*)(pMem-8) = cpuRegs.cycle;
|
|
||||||
|
|
||||||
// touch all the pages to make sure they are in memory
|
|
||||||
pTempMem = dmaGetAddr(vif1ch->madr);
|
|
||||||
pEndMem = (u8*)((uptr)(pTempMem + vif1ch->qwc*16 + 0xfff)&~0xfff);
|
|
||||||
pTempMem = (u8*)((uptr)pTempMem&~0xfff);
|
|
||||||
while(pTempMem < pEndMem ) {
|
|
||||||
pTempMem[0]++;
|
|
||||||
pTempMem[0]--;
|
|
||||||
pTempMem += 0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
GSRINGBUF_DONECOPY(pMem, 0);
|
if (pMem == NULL) { //Is ptag empty?
|
||||||
|
SysPrintf("Vif1 Tag BUSERR\n");
|
||||||
g_MTGSVifStart = cpuRegs.cycle;
|
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
|
||||||
g_MTGSVifCount = 4000000; // a little less than 1/60th of a second
|
vif1.done = 1;
|
||||||
|
vif1Regs->stat&= ~0x1f000000;
|
||||||
// wait is, the safest option
|
|
||||||
//gsWaitGS();
|
|
||||||
//SysPrintf("waiting for gs\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
int size;
|
|
||||||
u64* pMem = (u64*)dmaGetAddr(vif1ch->madr);
|
|
||||||
if (pMem == NULL) { //Is ptag empty?
|
|
||||||
SysPrintf("Vif1 Tag BUSERR\n");
|
|
||||||
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
|
|
||||||
vif1.done = 1;
|
|
||||||
vif1Regs->stat&= ~0x1f000000;
|
|
||||||
vif1ch->qwc = 0;
|
|
||||||
CPU_INT(1, g_vifCycles);
|
|
||||||
|
|
||||||
return; //Return -1 as an error has occurred
|
|
||||||
}
|
|
||||||
FreezeXMMRegs(1);
|
|
||||||
if( GSreadFIFO2 == NULL ) {
|
|
||||||
for (size=vif1ch->qwc; size>0; --size) {
|
|
||||||
if (size > 1) GSreadFIFO((u64*)&PS2MEM_HW[0x5000]);
|
|
||||||
pMem[0] = psHu64(0x5000);
|
|
||||||
pMem[1] = psHu64(0x5008); pMem+= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
GSreadFIFO2(pMem, vif1ch->qwc);
|
|
||||||
|
|
||||||
// set incase read
|
|
||||||
psHu64(0x5000) = pMem[2*vif1ch->qwc-2];
|
|
||||||
psHu64(0x5008) = pMem[2*vif1ch->qwc-1];
|
|
||||||
}
|
|
||||||
FreezeXMMRegs(0);
|
|
||||||
|
|
||||||
|
|
||||||
if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000;
|
|
||||||
g_vifCycles += vif1ch->qwc * 2;
|
|
||||||
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
|
|
||||||
vif1ch->qwc = 0;
|
vif1ch->qwc = 0;
|
||||||
CPU_INT(1, g_vifCycles);
|
CPU_INT(1, g_vifCycles);
|
||||||
|
|
||||||
|
return; //Return -1 as an error has occurred
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading
|
||||||
|
// stuff from the GS. The *only* way to handle this case safely is to flush the GS
|
||||||
|
// completely and execute the transfer there-after.
|
||||||
|
|
||||||
|
FreezeXMMRegs(1);
|
||||||
|
if( GSreadFIFO2 == NULL ) {
|
||||||
|
for (size=vif1ch->qwc; size>0; --size) {
|
||||||
|
if (size > 1 ) {
|
||||||
|
gsWaitGS();
|
||||||
|
GSreadFIFO((u64*)&PS2MEM_HW[0x5000]);
|
||||||
|
}
|
||||||
|
pMem[0] = psHu64(0x5000);
|
||||||
|
pMem[1] = psHu64(0x5008); pMem+= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gsWaitGS();
|
||||||
|
GSreadFIFO2(pMem, vif1ch->qwc);
|
||||||
|
|
||||||
|
// set incase read
|
||||||
|
psHu64(0x5000) = pMem[2*vif1ch->qwc-2];
|
||||||
|
psHu64(0x5008) = pMem[2*vif1ch->qwc-1];
|
||||||
|
}
|
||||||
|
FreezeXMMRegs(0);
|
||||||
|
|
||||||
|
if(vif1Regs->mskpath3 == 0)vif1Regs->stat&= ~0x1f000000;
|
||||||
|
g_vifCycles += vif1ch->qwc * 2;
|
||||||
|
vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes
|
||||||
|
vif1ch->qwc = 0;
|
||||||
|
CPU_INT(1, g_vifCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
vif1.done = 1;
|
vif1.done = 1;
|
||||||
|
|
Loading…
Reference in New Issue