COP0.cpp: Updated the commented out Perf counter code to work on the newer builds, also removed the line which stopped them updating at all if the interrupt wasnt on.

Others: Fixed a couple of unpack bugs, tried to tackle an MFIFO bug with Tekken Tag. Also re-jiggled a few bits on my recent changed, please negative if it breaks anything.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1400 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2009-06-19 03:13:03 +00:00
parent d15db78baf
commit 0f30bf62b5
9 changed files with 120 additions and 52 deletions

View File

@ -217,15 +217,15 @@ void COP0_DiagnosticPCCR()
if( cpuRegs.PERF.n.pccr.b.Event1 >= 7 && cpuRegs.PERF.n.pccr.b.Event1 <= 10 ) if( cpuRegs.PERF.n.pccr.b.Event1 >= 7 && cpuRegs.PERF.n.pccr.b.Event1 <= 10 )
Console::Notice( "PERF/PCR1 Unsupported Update Event Mode = 0x%x", params cpuRegs.PERF.n.pccr.b.Event1 ); Console::Notice( "PERF/PCR1 Unsupported Update Event Mode = 0x%x", params cpuRegs.PERF.n.pccr.b.Event1 );
} }
extern int branch;
__forceinline void COP0_UpdatePCCR() __forceinline void COP0_UpdatePCCR()
{ {
if( cpuRegs.CP0.n.Status.b.ERL || !cpuRegs.PERF.n.pccr.b.CTE ) return; //if( cpuRegs.CP0.n.Status.b.ERL || !cpuRegs.PERF.n.pccr.b.CTE ) return;
// TODO : Implement memory mode checks here (kernel/super/user) // TODO : Implement memory mode checks here (kernel/super/user)
// For now we just assume user mode. // For now we just assume user mode.
if( cpuRegs.PERF.n.pccr.b.U0 ) if( cpuRegs.PERF.n.pccr.val & 0xf )
{ {
// ---------------------------------- // ----------------------------------
// Update Performance Counter 0 // Update Performance Counter 0
@ -243,24 +243,25 @@ __forceinline void COP0_UpdatePCCR()
//prev ^= (1UL<<31); // XOR is fun! //prev ^= (1UL<<31); // XOR is fun!
//if( (prev & cpuRegs.PERF.n.pcr0) & (1UL<<31) ) //if( (prev & cpuRegs.PERF.n.pcr0) & (1UL<<31) )
if( cpuRegs.PERF.n.pcr0 & 0x80000000 ) if( (cpuRegs.PERF.n.pcr0 & 0x80000000) && (cpuRegs.CP0.n.Status.b.ERL == 1) && cpuRegs.PERF.n.pccr.b.CTE)
{ {
// TODO: Vector to the appropriate exception here. // TODO: Vector to the appropriate exception here.
// This code *should* be correct, but is untested (and other parts of the emu are // This code *should* be correct, but is untested (and other parts of the emu are
// not prepared to handle proper Level 2 exception vectors yet) // not prepared to handle proper Level 2 exception vectors yet)
/*if( delay_slot ) //branch == 1 is probably not the best way to check for the delay slot, but it beats nothing! (Refraction)
/* if( branch == 1 )
{ {
cpuRegs.CP0.ErrorEPC = cpuRegs.pc - 4; cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc - 4;
cpuRegs.CP0.Cause.BD2 = 1; cpuRegs.CP0.n.Cause |= 0x40000000;
} }
else else
{ {
cpuRegs.CP0.ErrorEPC = cpuRegs.pc; cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc;
cpuRegs.CP0.Cause.BD2 = 0; cpuRegs.CP0.n.Cause &= ~0x40000000;
} }
if( cpuRegs.CP0.Status.DEV ) if( cpuRegs.CP0.n.Status.b.DEV )
{ {
// Bootstrap vector // Bootstrap vector
cpuRegs.pc = 0xbfc00280; cpuRegs.pc = 0xbfc00280;
@ -269,8 +270,8 @@ __forceinline void COP0_UpdatePCCR()
{ {
cpuRegs.pc = 0x80000080; cpuRegs.pc = 0x80000080;
} }
cpuRegs.CP0.Status.ERL = 1; cpuRegs.CP0.n.Status.b.ERL = 1;
cpuRegs.CP0.Cause.EXC2 = 2;*/ cpuRegs.CP0.n.Cause |= 0x20000;*/
} }
} }
} }
@ -289,9 +290,36 @@ __forceinline void COP0_UpdatePCCR()
cpuRegs.PERF.n.pcr1 += incr; cpuRegs.PERF.n.pcr1 += incr;
s_iLastPERFCycle[1] = cpuRegs.cycle; s_iLastPERFCycle[1] = cpuRegs.cycle;
if( cpuRegs.PERF.n.pcr1 & 0x80000000 ) if( (cpuRegs.PERF.n.pcr1 & 0x80000000) && (cpuRegs.CP0.n.Status.b.ERL == 1) && cpuRegs.PERF.n.pccr.b.CTE)
{ {
// See PCR0 comments for notes on exceptions // TODO: Vector to the appropriate exception here.
// This code *should* be correct, but is untested (and other parts of the emu are
// not prepared to handle proper Level 2 exception vectors yet)
//branch == 1 is probably not the best way to check for the delay slot, but it beats nothing! (Refraction)
/*if( branch == 1 )
{
cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc - 4;
cpuRegs.CP0.n.Cause |= 0x40000000;
}
else
{
cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc;
cpuRegs.CP0.n.Cause &= ~0x40000000;
}
if( cpuRegs.CP0.n.Status.b.DEV )
{
// Bootstrap vector
cpuRegs.pc = 0xbfc00280;
}
else
{
cpuRegs.pc = 0x80000080;
}
cpuRegs.CP0.n.Status.b.ERL = 1;
cpuRegs.CP0.n.Cause |= 0x20000;*/
} }
} }
} }

View File

@ -336,8 +336,16 @@ static __forceinline void VSyncStart(u32 sCycle)
EECNT_LOG( "///////// EE COUNTER VSYNC START \\\\\\\\\\\\\\\\\\\\ (frame: %d)", iFrame ); EECNT_LOG( "///////// EE COUNTER VSYNC START \\\\\\\\\\\\\\\\\\\\ (frame: %d)", iFrame );
vSyncDebugStuff( iFrame ); // EE Profiling and Debug code vSyncDebugStuff( iFrame ); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8; if ((CSRw & 0x8))
if (!(GSIMR&0x800)) gsIrq(); {
GSCSRr|= 0x8;
if (!(GSIMR&0x800))
{
gsIrq();
}
CSRw &= ~0x8; //Disable the interrupt from triggering twice
}
hwIntcIrq(INTC_VBLANK_S); hwIntcIrq(INTC_VBLANK_S);
psxVBlankStart(); psxVBlankStart();
@ -404,8 +412,16 @@ __forceinline void rcntUpdate_hScanline()
hsyncCounter.Mode = MODE_HRENDER; hsyncCounter.Mode = MODE_HRENDER;
} }
else { //HBLANK END / HRENDER Begin else { //HBLANK END / HRENDER Begin
if (CSRw & 0x4) GSCSRr |= 4; // signal if (CSRw & 0x4)
if (!(GSIMR&0x400)) gsIrq(); {
GSCSRr |= 4; // signal
if (!(GSIMR&0x400))
{
gsIrq();
}
CSRw &= ~0x4; //Disable the interrupt from triggering twice
}
if (gates) rcntEndGate(false, hsyncCounter.sCycle); if (gates) rcntEndGate(false, hsyncCounter.sCycle);
if (psxhblankgate) psxCheckEndGate16(0); if (psxhblankgate) psxCheckEndGate16(0);

View File

@ -290,14 +290,7 @@ void gsGIFReset()
void gsCSRwrite(u32 value) void gsCSRwrite(u32 value)
{ {
CSRw |= value & ~0x60;
if( mtgsThread != NULL )
mtgsThread->SendSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 );
else
GSwriteCSR(CSRw);
GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
// Our emulated GS has no FIFO... // Our emulated GS has no FIFO...
/*if( value & 0x100 ) { // FLUSH /*if( value & 0x100 ) { // FLUSH
@ -317,17 +310,36 @@ void gsCSRwrite(u32 value)
GSreset(); GSreset();
} }
CSRw = 0x1f; CSRw |= 0x1f;
GSCSRr = 0x551B4000; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) GSCSRr = 0x551B4000; // 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
} }
else if( value & 0x100 ) // FLUSH
{
//Console::WriteLn("GS_CSR FLUSH GS fifo: %x (CSRr=%x)", params value, GSCSRr);
}
else
{
CSRw |= value & 0x1f;
if( mtgsThread != NULL )
mtgsThread->SendSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 );
else
GSwriteCSR(CSRw);
GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f);
}
} }
static void IMRwrite(u32 value) static void IMRwrite(u32 value)
{ {
GSIMR = (value & 0x1f00)|0x6000; GSIMR = (value & 0x1f00)|0x6000;
if((GSCSRr & 0x1f) & (~(GSIMR >> 8) & 0x1f)) gsIrq(); if((GSCSRr & 0x1f) & (~(GSIMR >> 8) & 0x1f))
{
gsIrq();
}
// don't update mtgs mem // don't update mtgs mem
} }

View File

@ -949,7 +949,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
if (value & 0x100) if (value & 0x100)
{ {
vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO
} } else cpuRegs.interrupt &= ~(1<<10) | ~(1<<1); //Tekken tag seems to stop vif and start it again in normal, so we will cancel the mfifo loop
DmaExec(dmaVIF1, mem, value); DmaExec(dmaVIF1, mem, value);
return; return;

View File

@ -138,22 +138,29 @@ static void RegHandlerSIGNAL(const u32* data)
GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]);
if ((CSRw & 0x1)) if ((CSRw & 0x1))
{
GSCSRr |= 1; // signal GSCSRr |= 1; // signal
if (!(GSIMR&0x100) ) if (!(GSIMR&0x100) )
gsIrq(); {
gsIrq();
}
CSRw &= ~0x1; //Disable the interrupt from triggering twice
}
} }
static void RegHandlerFINISH(const u32* data) static void RegHandlerFINISH(const u32* data)
{ {
MTGS_LOG("MTGS FINISH data %x_%x CSRw %x\n",data[0], data[1], CSRw); DevCon::Notice("MTGS FINISH data %x_%x CSRw %x\n", params data[0], data[1], CSRw);
if ((CSRw & 0x2)) if ((CSRw & 0x2))
{
GSCSRr |= 2; // finish GSCSRr |= 2; // finish
if (!(GSIMR&0x200) ) if (!(GSIMR&0x200) )
gsIrq(); gsIrq();
CSRw &= ~0x2; //Disable the interrupt from triggering twice
}
} }
static void RegHandlerLABEL(const u32* data) static void RegHandlerLABEL(const u32* data)

View File

@ -533,6 +533,8 @@ void vifMFIFOInterrupt()
{ {
g_vifCycles = 0; g_vifCycles = 0;
if(schedulepath3msk) Vif1MskPath3();
if((vif1Regs->stat & VIF1_STAT_VGW)) if((vif1Regs->stat & VIF1_STAT_VGW))
{ {
if(gif->chcr & 0x100) if(gif->chcr & 0x100)
@ -596,14 +598,6 @@ void vifMFIFOInterrupt()
CPU_INT(10, 0); CPU_INT(10, 0);
return; return;
} }
if (!(vif1.inprogress & 0x1)) mfifoVIF1transfer(0);
if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR)))
CPU_INT(10, 0);
else
CPU_INT(10, vif1ch->qwc * BIAS);
return; return;
} }

View File

@ -92,16 +92,16 @@ static __forceinline u32 setVifRowRegs(u32 reg, u32 data)
switch (reg) switch (reg)
{ {
case 0: case 0:
vifRegs->r0 += data; vifRegs->r0 = data;
break; break;
case 1: case 1:
vifRegs->r1 += data; vifRegs->r1 = data;
break; break;
case 2: case 2:
vifRegs->r2 += data; vifRegs->r2 = data;
break; break;
case 3: case 3:
vifRegs->r3 += data; vifRegs->r3 = data;
break; break;
jNO_DEFAULT; jNO_DEFAULT;
} }

View File

@ -328,6 +328,10 @@ static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int
VIFUNPACK_LOG("addr aligned to %x", vif->tag.addr); VIFUNPACK_LOG("addr aligned to %x", vif->tag.addr);
vif->tag.addr = (vif->tag.addr & ~0xf) + (vifRegs->offset * 4); vif->tag.addr = (vif->tag.addr & ~0xf) + (vifRegs->offset * 4);
} }
if(vif->tag.addr >= (u32)(VIFdmanum ? 0x4000 : 0x1000))
{
vif->tag.addr &= (u32)(VIFdmanum ? 0x3fff : 0xfff);
}
} }
@ -634,14 +638,16 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
} }
else else
{ {
//DevCon::Notice("VIF%x Unpack ending %x > %x", params VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000); DevCon::Notice("VIF%x Unpack ending %x > %x", params VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000);
tempsize = size; tempsize = size;
size = 0; size = 0;
} }
} }
else else
{ {
tempsize = 0; tempsize = 0; //Commenting out this then
//tempsize = size; // -\_uncommenting these Two enables non-SSE unpacks
//size = 0; // -/
} }
if (size >= ft->gsize) if (size >= ft->gsize)
@ -745,6 +751,7 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
{ {
int incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + 4; int incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + 4;
size = 0; size = 0;
int addrstart = v->addr;
if((tempsize >> 2) != vif->tag.size) DevCon::Notice("split when size != tagsize"); if((tempsize >> 2) != vif->tag.size) DevCon::Notice("split when size != tagsize");
VIFUNPACK_LOG("sorting tempsize :p, size %d, vifnum %d, addr %x", tempsize, vifRegs->num, vif->tag.addr); VIFUNPACK_LOG("sorting tempsize :p, size %d, vifnum %d, addr %x", tempsize, vifRegs->num, vif->tag.addr);
@ -753,6 +760,7 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
{ {
if(v->addr >= memlimit) if(v->addr >= memlimit)
{ {
DevCon::Notice("Mem limit ovf");
v->addr &= (memlimit - 1); v->addr &= (memlimit - 1);
dest = (u32*)(VU->Mem + v->addr); dest = (u32*)(VU->Mem + v->addr);
} }
@ -789,6 +797,7 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
v->addr &= (memlimit - 1); v->addr &= (memlimit - 1);
dest = (u32*)(VU->Mem + v->addr); dest = (u32*)(VU->Mem + v->addr);
} }
v->addr = addrstart;
if(tempsize > 0) size = tempsize; if(tempsize > 0) size = tempsize;
} }
@ -2057,7 +2066,7 @@ static void Vif1CMDSTMod() // STMOD
u8 schedulepath3msk = 0; u8 schedulepath3msk = 0;
static void Vif1MskPath3() // MSKPATH3 void Vif1MskPath3() // MSKPATH3
{ {
vif1Regs->mskpath3 = schedulepath3msk & 0x1; vif1Regs->mskpath3 = schedulepath3msk & 0x1;
//Console::WriteLn("VIF MSKPATH3 %x", params vif1Regs->mskpath3); //Console::WriteLn("VIF MSKPATH3 %x", params vif1Regs->mskpath3);

View File

@ -55,6 +55,7 @@ struct vifStruct {
extern vifStruct vif0, vif1; extern vifStruct vif0, vif1;
extern int Path3progress; extern int Path3progress;
extern u8 schedulepath3msk;
void __fastcall UNPACK_S_32( u32 *dest, u32 *data, int size ); void __fastcall UNPACK_S_32( u32 *dest, u32 *data, int size );
@ -95,6 +96,7 @@ void vif0Init();
void vif1Init(); void vif1Init();
extern void vif0Interrupt(); extern void vif0Interrupt();
extern void vif1Interrupt(); extern void vif1Interrupt();
extern void Vif1MskPath3();
void vif0Write32(u32 mem, u32 value); void vif0Write32(u32 mem, u32 value);
void vif1Write32(u32 mem, u32 value); void vif1Write32(u32 mem, u32 value);