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 )
Console::Notice( "PERF/PCR1 Unsupported Update Event Mode = 0x%x", params cpuRegs.PERF.n.pccr.b.Event1 );
}
extern int branch;
__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)
// 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
@ -243,24 +243,25 @@ __forceinline void COP0_UpdatePCCR()
//prev ^= (1UL<<31); // XOR is fun!
//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.
// 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)
/*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.Cause.BD2 = 1;
cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc - 4;
cpuRegs.CP0.n.Cause |= 0x40000000;
}
else
{
cpuRegs.CP0.ErrorEPC = cpuRegs.pc;
cpuRegs.CP0.Cause.BD2 = 0;
cpuRegs.CP0.n.ErrorEPC = cpuRegs.pc;
cpuRegs.CP0.n.Cause &= ~0x40000000;
}
if( cpuRegs.CP0.Status.DEV )
if( cpuRegs.CP0.n.Status.b.DEV )
{
// Bootstrap vector
cpuRegs.pc = 0xbfc00280;
@ -269,8 +270,8 @@ __forceinline void COP0_UpdatePCCR()
{
cpuRegs.pc = 0x80000080;
}
cpuRegs.CP0.Status.ERL = 1;
cpuRegs.CP0.Cause.EXC2 = 2;*/
cpuRegs.CP0.n.Status.b.ERL = 1;
cpuRegs.CP0.n.Cause |= 0x20000;*/
}
}
}
@ -289,9 +290,36 @@ __forceinline void COP0_UpdatePCCR()
cpuRegs.PERF.n.pcr1 += incr;
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 );
vSyncDebugStuff( iFrame ); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq();
if ((CSRw & 0x8))
{
GSCSRr|= 0x8;
if (!(GSIMR&0x800))
{
gsIrq();
}
CSRw &= ~0x8; //Disable the interrupt from triggering twice
}
hwIntcIrq(INTC_VBLANK_S);
psxVBlankStart();
@ -404,8 +412,16 @@ __forceinline void rcntUpdate_hScanline()
hsyncCounter.Mode = MODE_HRENDER;
}
else { //HBLANK END / HRENDER Begin
if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq();
if (CSRw & 0x4)
{
GSCSRr |= 4; // signal
if (!(GSIMR&0x400))
{
gsIrq();
}
CSRw &= ~0x4; //Disable the interrupt from triggering twice
}
if (gates) rcntEndGate(false, hsyncCounter.sCycle);
if (psxhblankgate) psxCheckEndGate16(0);

View File

@ -290,14 +290,7 @@ void gsGIFReset()
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...
/*if( value & 0x100 ) { // FLUSH
@ -317,17 +310,36 @@ void gsCSRwrite(u32 value)
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)
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)
{
GSIMR = (value & 0x1f00)|0x6000;
if((GSCSRr & 0x1f) & (~(GSIMR >> 8) & 0x1f)) gsIrq();
if((GSCSRr & 0x1f) & (~(GSIMR >> 8) & 0x1f))
{
gsIrq();
}
// don't update mtgs mem
}

View File

@ -949,7 +949,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value )
if (value & 0x100)
{
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);
return;

View File

@ -138,22 +138,29 @@ static void RegHandlerSIGNAL(const u32* data)
GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]);
if ((CSRw & 0x1))
{
GSCSRr |= 1; // signal
if (!(GSIMR&0x100) )
gsIrq();
if (!(GSIMR&0x100) )
{
gsIrq();
}
CSRw &= ~0x1; //Disable the interrupt from triggering twice
}
}
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))
{
GSCSRr |= 2; // finish
if (!(GSIMR&0x200) )
gsIrq();
if (!(GSIMR&0x200) )
gsIrq();
CSRw &= ~0x2; //Disable the interrupt from triggering twice
}
}
static void RegHandlerLABEL(const u32* data)

View File

@ -533,6 +533,8 @@ void vifMFIFOInterrupt()
{
g_vifCycles = 0;
if(schedulepath3msk) Vif1MskPath3();
if((vif1Regs->stat & VIF1_STAT_VGW))
{
if(gif->chcr & 0x100)
@ -596,14 +598,6 @@ void vifMFIFOInterrupt()
CPU_INT(10, 0);
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;
}

View File

@ -92,16 +92,16 @@ static __forceinline u32 setVifRowRegs(u32 reg, u32 data)
switch (reg)
{
case 0:
vifRegs->r0 += data;
vifRegs->r0 = data;
break;
case 1:
vifRegs->r1 += data;
vifRegs->r1 = data;
break;
case 2:
vifRegs->r2 += data;
vifRegs->r2 = data;
break;
case 3:
vifRegs->r3 += data;
vifRegs->r3 = data;
break;
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);
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
{
//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;
size = 0;
}
}
else
{
tempsize = 0;
tempsize = 0; //Commenting out this then
//tempsize = size; // -\_uncommenting these Two enables non-SSE unpacks
//size = 0; // -/
}
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;
size = 0;
int addrstart = v->addr;
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);
@ -753,6 +760,7 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
{
if(v->addr >= memlimit)
{
DevCon::Notice("Mem limit ovf");
v->addr &= (memlimit - 1);
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);
dest = (u32*)(VU->Mem + v->addr);
}
v->addr = addrstart;
if(tempsize > 0) size = tempsize;
}
@ -2057,7 +2066,7 @@ static void Vif1CMDSTMod() // STMOD
u8 schedulepath3msk = 0;
static void Vif1MskPath3() // MSKPATH3
void Vif1MskPath3() // MSKPATH3
{
vif1Regs->mskpath3 = schedulepath3msk & 0x1;
//Console::WriteLn("VIF MSKPATH3 %x", params vif1Regs->mskpath3);

View File

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