PATH3 Masking: Tweaks mainly for Path3Masking to fix TOCA3, This is the best Path3 masking is ever going to get, there might be an occasional glitch, but nothing major *fingers crossed*, Now have the ability to log Path3 stuff seperately which will help if problems do arise.

Cleaned up Gifdma a little, removing duplicate code. Disabled a few console writes we dont nee really.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4278 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2011-02-01 01:24:37 +00:00
parent dd66d3ac5f
commit 3fb753d463
11 changed files with 202 additions and 203 deletions

View File

@ -275,6 +275,7 @@ struct SysTraceLogPack
SysTraceLog_EE Memory;
SysTraceLog_EE GIFtag;
SysTraceLog_VIFcode VIFcode;
SysTraceLog_EE MSKPATH3;
SysTraceLog_EE_Disasm R5900;
SysTraceLog_EE_Disasm COP0;
@ -371,6 +372,7 @@ extern void __Log( const char* fmt, ... );
#define VIF_LOG macTrace(EE.VIF)
#define SPR_LOG macTrace(EE.SPR)
#define GIF_LOG macTrace(EE.GIF)
#define MSKPATH3_LOG macTrace(EE.MSKPATH3)
#define EECNT_LOG macTrace(EE.Counters)
#define VifCodeLog macTrace(EE.VIFcode)
#define GifTagLog macTrace(EE.GIFtag)

View File

@ -53,7 +53,7 @@ void gsPath1Interrupt()
if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false)
if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false)
{
gifRegs.stat.P1Q = false;
@ -89,6 +89,11 @@ void gsPath1Interrupt()
else
{
if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
if(gifRegs.stat.P1Q == false && Path1ReadPos != Path1WritePos)
{
DevCon.Warning("Wa's Goin on ere then?");
gifRegs.stat.P1Q = true;
}
//DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
//if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
}
@ -115,12 +120,16 @@ __fi void gsInterrupt()
return;
}
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{
gifRegs.stat.OPH = false;
if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
{
GSTransferStatus.PTH3 = STOPPED_MODE;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
if(gifRegs.stat.APATH == GIF_APATH3)
{
gifRegs.stat.APATH = GIF_APATH_IDLE;
gifRegs.stat.OPH = false;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
}
@ -239,7 +248,7 @@ static __fi tDMA_TAG* ReadTag2()
bool CheckPaths(int Channel)
{
if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.mode.IMT)
if((GSTransferStatus.PTH3 == IMAGE_MODE && gifRegs.mode.IMT) || GSTransferStatus.PTH3 == WAITING_MODE)
{
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
{
@ -253,13 +262,14 @@ bool CheckPaths(int Channel)
}
}
}
else if((GSTransferStatus.PTH3 == IDLE_MODE)|| (GSTransferStatus.PTH3 == STOPPED_MODE))
else if(GSTransferStatus.PTH3 == STOPPED_MODE)
{
//This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3) || vif1Regs.stat.VGW == true)
{
//DevCon.Warning("GIF Stall 2 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
gifRegs.stat.IP3 = true;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
CPU_INT(DMAC_GIF, 16);
return false;
}
@ -297,86 +307,9 @@ void GIFdma()
gifch.qwc = 0;
}
clearFIFOstuff(true);
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
{
if (gifch.qwc == 0)
{
if ((gifch.chcr.MOD == CHAIN_MODE) && gifch.chcr.STR)
{
//DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs.mskpath3);
ptag = ReadTag();
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (ptag == NULL) return;
GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr);
//Check TIE bit of CHCR and IRQ bit of tag
if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set");
}
}
if (GSTransferStatus.PTH3 == IDLE_MODE)
{
GIF_LOG("PTH3 MASK Paused by VIF QWC %x", gifch.qwc);
//DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs.mskpath3);
if(gifch.qwc == 0) gsInterrupt();
else gifRegs.stat.set_flags(GIF_STAT_P3Q);
return;
}
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
//Check with Path3 masking games
if (gifch.qwc > 0) {
gifRegs.stat.set_flags(GIF_STAT_P3Q);
if(CheckPaths(DMAC_GIF) == false) return;
gifRegs.stat.clear_flags(GIF_STAT_P3Q);
GIF_LOG("PTH3 MASK Transferring");
GIFchain();
/*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH_IDLE)
{
GSTransferStatus.PTH3 = STOPPED_MODE;
}*/
}//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return
CPU_INT(DMAC_GIF, gscycles);
return;
}
// Transfer Dn_QWC from Dn_MADR to GIF
if ((gifch.chcr.MOD == NORMAL_MODE) || (gifch.qwc > 0)) // Normal Mode
{
if ((dmacRegs.ctrl.STD == STD_GIF) && (gifch.chcr.MOD == NORMAL_MODE))
{
//Console.WriteLn("DMA Stall Control on GIF normal");
}
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
//Check with Path3 masking games
//DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs.mskpath3);
if (gifch.qwc > 0) {
gifRegs.stat.set_flags(GIF_STAT_P3Q);
if(CheckPaths(DMAC_GIF) == false) return;
gifRegs.stat.clear_flags(GIF_STAT_P3Q);
GIFchain(); //Transfers the data set by the switch
CPU_INT(DMAC_GIF, gscycles);
return;
} else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gifch.chcr._u32);
//else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts
}
if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done)) // Chain Mode
if ((gifch.chcr.MOD == CHAIN_MODE) && (!gspath3done) && gifch.qwc == 0) // Chain Mode
{
ptag = ReadTag();
if (ptag == NULL) return;
@ -392,12 +325,7 @@ void GIFdma()
// We really need to test this. Pay attention to prevcycles, as it used to trigger GIFchains in the code above. (rama)
//Console.WriteLn("GS Stall Control start Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gifch.madr, psHu32(DMAC_STADR));
prevcycles = gscycles;
//gifch.tadr -= 16;
// Quake III revolution wants to see tadr move.
// Simple Media System (homebrew) as well.
// -16 also seems right (it shifts the bg image right if anything else).
gifch.tadr -= 16;
// Next line also needs to be here, according to ref
gifch.qwc = 0;
hwDmacIrq(DMAC_STALL_SIS);
CPU_INT(DMAC_GIF, gscycles);
@ -407,11 +335,38 @@ void GIFdma()
}
checkTieBit(ptag);
/*if(gifch.qwc == 0)
}
clearFIFOstuff(true);
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
{
if (GSTransferStatus.PTH3 == STOPPED_MODE)
{
gsInterrupt();
MSKPATH3_LOG("Path3 Paused by VIF QWC %x", gifch.qwc);
if(gifch.qwc == 0) CPU_INT(DMAC_GIF, 4);
else gifRegs.stat.set_flags(GIF_STAT_P3Q);
return;
}*/
}
}
// Transfer Dn_QWC from Dn_MADR to GIF
if (gifch.qwc > 0) // Normal Mode
{
gifRegs.stat.FQC = min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3]
gifRegs.stat.set_flags(GIF_STAT_P3Q);
if(CheckPaths(DMAC_GIF) == false)
return;
gifRegs.stat.clear_flags(GIF_STAT_P3Q);
GIFchain(); //Transfers the data set by the switch
CPU_INT(DMAC_GIF, gscycles);
return;
}
prevcycles = 0;
@ -626,6 +581,19 @@ void mfifoGIFtransfer(int qwc)
if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY;
}
if (vif1Regs.mskpath3 || gifRegs.mode.M3R)
{
if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL;
if (GSTransferStatus.PTH3 == STOPPED_MODE)
{
DevCon.Warning("GIFMFIFO PTH3 MASK Paused by VIF QWC %x");
MSKPATH3_LOG("Path3 Paused by VIF Idling");
gifRegs.stat.set_flags(GIF_STAT_P3Q);
return;
}
}
if (!mfifoGIFchain())
{
Console.WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", gifch.qwc, gifch.madr, gifch.tadr);
@ -656,12 +624,16 @@ void gifMFIFOInterrupt()
return;
}
if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{
gifRegs.stat.OPH = false;
if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE)
{
GSTransferStatus.PTH3 = STOPPED_MODE;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
if(gifRegs.stat.APATH == GIF_APATH3)
{
gifRegs.stat.APATH = GIF_APATH_IDLE;
gifRegs.stat.OPH = false;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
}
if((gifstate & GIF_STATE_EMPTY))

View File

@ -218,6 +218,12 @@ TLD_EE_VIFcode = {
"VIF"
},
TLD_EE_MSKPATH3 = {
L"MSKPATH3", L"MSKPATH3",
pxDt("All processing involved in Path3 Masking"),
"MSKPATH3"
},
TLD_EE_SPR = {
L"MFIFO", L"Scratchpad MFIFO",
pxDt("Scratchpad's MFIFO activity."),
@ -335,6 +341,7 @@ SysTraceLogPack::EE_PACK::EE_PACK()
, Memory (&TLD_EE_Memory)
, GIFtag (&TLD_EE_GIFtag)
, VIFcode (&TLD_EE_VIFcode)
, MSKPATH3 (&TLD_EE_MSKPATH3)
, R5900 (&TLD_EE_R5900)
, COP0 (&TLD_EE_COP0)

View File

@ -151,7 +151,7 @@ __fi void vif1FBRST(u32 value) {
//DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs.mskpath3);
if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR == true)
{
//DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3);
DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3);
gsInterrupt();
vif1Regs.mskpath3 = false;
gifRegs.stat.M3P = 0;

View File

@ -258,7 +258,7 @@ bool CheckPath2GIF(EE_EventType channel)
{
if( vif1.GifWaitState == 0 ) //DIRECT/HL Check
{
if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q)
if(GSTransferStatus.PTH3 < STOPPED_MODE || gifRegs.stat.P1Q)
{
if(gifRegs.stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs.stat.P1Q == false)
{
@ -285,19 +285,18 @@ bool CheckPath2GIF(EE_EventType channel)
return false;
}
if (GSTransferStatus.PTH3 < IDLE_MODE)
if (GSTransferStatus.PTH3 < STOPPED_MODE)
{
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
//DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
//DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs.stat.P1Q, gifRegs.stat.P3Q, gifRegs.stat.IP3 );
CPU_INT(channel, 8);
CPU_INT(channel, 128);
return false;
}
else
{
vif1Regs.stat.VGW = false;
}
vif1Regs.stat.VGW = false;
}
else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish
else if( vif1.GifWaitState == 3 ) // Any futher GIF transfers are paused.
{
if (gifRegs.ctrl.PSE)
{
@ -305,10 +304,9 @@ bool CheckPath2GIF(EE_EventType channel)
CPU_INT(channel, 128);
return false;
}
else
{
vif1Regs.stat.VGW = false;
}
vif1Regs.stat.VGW = false;
}
else //Normal Flush
{
@ -318,18 +316,18 @@ bool CheckPath2GIF(EE_EventType channel)
CPU_INT(channel, 128);
return false;
}
else
{
vif1Regs.stat.VGW = false;
}
vif1Regs.stat.VGW = false;
}
}
if(SIGNAL_IMR_Pending == true && (vif1.cmd & 0x7e) == 0x50)
{
//DevCon.Warning("Path 2 Paused");
CPU_INT(channel, 128);
return false;
}
return true;
}
__fi void vif1Interrupt()
@ -338,19 +336,24 @@ __fi void vif1Interrupt()
g_vifCycles = 0;
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
{
gifRegs.stat.OPH = false;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
if (schedulepath3msk & 0x10)
{
MSKPATH3_LOG("Scheduled Path3 Mask Firing");
Vif1MskPath3();
CPU_INT(DMAC_VIF1, 8);
return;
}
if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE)
{
GSTransferStatus.PTH2 = STOPPED_MODE;
if(gifRegs.stat.APATH == GIF_APATH2)
{
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
}
//Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here.
if (dmacRegs.ctrl.MFD == MFD_VIF1)
{

View File

@ -261,17 +261,23 @@ void vifMFIFOInterrupt()
return;
}
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE)
{
GSTransferStatus.PTH2 = STOPPED_MODE;
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
/*gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;*/
if(gifRegs.stat.APATH == GIF_APATH2)
{
if(gifRegs.stat.DIR == 0)gifRegs.stat.OPH = false;
gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt();
}
}
if (schedulepath3msk & 0x10) Vif1MskPath3();
if (schedulepath3msk & 0x10)
{
MSKPATH3_LOG("Scheduled Path3 Mask Firing on MFIFO VIF");
Vif1MskPath3();
}
if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false)
{

View File

@ -90,15 +90,22 @@ void Vif1MskPath3() {
if (!vif1Regs.mskpath3)
{
MSKPATH3_LOG("Disabling Path3 Mask");
//if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE;
//DevCon.Warning("Mask off");
//if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE;
if(gifRegs.stat.P3Q)
{
MSKPATH3_LOG("Path3 Waiting to Transfer, triggering");
gsInterrupt();//gsInterrupt();
}
}// else if(!gif->chcr.STR && GSTransferStatus.PTH3 == IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;//else DevCon.Warning("Mask on");
}
else
{
MSKPATH3_LOG("Path3 Mask Enabled");
}
// else if(!gif->chcr.STR && GSTransferStatus.PTH3 == IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;//else DevCon.Warning("Mask on");
schedulepath3msk = 0;
}
@ -137,7 +144,7 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
pass2 {
vif1Only();
if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs.stat.P1Q == true)
if (GSTransferStatus.PTH3 < STOPPED_MODE || gifRegs.stat.P1Q == true)
{
if(gifRegs.stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs.stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs.stat.P1Q == false)
{
@ -264,10 +271,10 @@ vifOp(vifCode_FlushA) {
pass1 {
vifFlush(idx);
// Gif is already transferring so wait for it.
if (gifRegs.stat.P1Q || GSTransferStatus.PTH3 <= PENDINGSTOP_MODE) {
if (gifRegs.stat.P1Q || GSTransferStatus.PTH3 < STOPPED_MODE) {
//DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs.mskpath3);
//
MSKPATH3_LOG("Waiting for Path3 to Flush");
//DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR);
vif1Regs.stat.VGW = true;
vifX.GifWaitState = 1;
@ -376,17 +383,15 @@ vifOp(vifCode_MSCNT) {
// ToDo: FixMe
vifOp(vifCode_MskPath3) {
vif1Only();
pass1 {
//I Hate the timing sensitivity of this stuff
if (vif1ch.chcr.STR && vif1.lastcmd != 0x13) {
schedulepath3msk = 0x10 | ((vif1Regs.code >> 15) & 0x1);
}
else
{
schedulepath3msk = (vif1Regs.code >> 15) & 0x1;
Vif1MskPath3();
}
if(vif1ch.chcr.STR)vif1.vifstalled = true;
pass1 {
MSKPATH3_LOG("Direct MSKPATH3");
schedulepath3msk = 0x10 | (vif1Regs.code >> 15) & 0x1;
if(vif1ch.chcr.STR && vif1.lastcmd != 0x13)vif1.vifstalled = true;
else Vif1MskPath3();
vif1.cmd = 0;
}
pass3 { VifCodeLog("MskPath3"); }

View File

@ -74,14 +74,14 @@ _vifT void vifTransferLoop(u32* &data) {
u32& pSize = vifX.vifpacketsize;
int iBit = vifX.cmd >> 7;
vifXRegs.stat.VPS |= VPS_TRANSFERRING;
vifXRegs.stat.ER1 = false;
while (pSize > 0 && !vifX.vifstalled) {
if(!vifX.cmd) { // Get new VifCode
vifX.lastcmd = (vifXRegs.code >> 24) & 0x7f;
vifXRegs.code = data[0];
vifX.cmd = data[0] >> 24;
iBit = data[0] >> 31;
@ -95,6 +95,7 @@ _vifT void vifTransferLoop(u32* &data) {
vifCmdHandler[idx][vifX.cmd & 0x7f](0, data);
data++; pSize--;
vifX.lastcmd = (vifXRegs.code >> 24) & 0x7f;
if (analyzeIbit<idx>(data, iBit)) break;
continue;
}

View File

@ -138,6 +138,7 @@ static SysTraceLog * const traceLogList[] =
&SysTrace.EE.IPU,
&SysTrace.EE.GIFtag,
&SysTrace.EE.VIFcode,
&SysTrace.EE.MSKPATH3,
&SysTrace.EE.DMAC,
&SysTrace.EE.Counters,

View File

@ -631,6 +631,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
uint& ringpos = GetMTGS().m_packet_writepos;
const uint original_ringpos = ringpos;
u32 startSize = size; // Start Size
while (size > 0) {
@ -639,7 +641,7 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
SetTag<Aligned>((u8*)pMem128);
copyTag();
GifTagLog("\tSetTag: %ls", tag.ToString().c_str());
GifTagLog("\tSetTag: %ls Path %d", tag.ToString().c_str(), pathidx + 1);
if(nloop > 0)
{
@ -654,30 +656,22 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
else GSTransferStatus.PTH2 = TRANSFER_MODE;
break;
case GIF_PATH_3:
if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE)
{
GSTransferStatus.PTH3 = IDLE_MODE;
}
else
{
if(tag.FLG & 2) GSTransferStatus.PTH3 = IMAGE_MODE;
else GSTransferStatus.PTH3 = TRANSFER_MODE;
}
if(tag.FLG & 2) GSTransferStatus.PTH3 = IMAGE_MODE;
else GSTransferStatus.PTH3 = TRANSFER_MODE;
break;
}
}
if(GSTransferStatus.PTH3 < PENDINGSTOP_MODE || pathidx != 2)
{
gifRegs.stat.OPH = true;
gifRegs.stat.APATH = pathidx + 1;
}
gifRegs.stat.OPH = true;
gifRegs.stat.APATH = pathidx + 1;
if(pathidx == GIF_PATH_3)
if(nloop == 0 && tag.EOP)
{
break;
}
}
else
{
@ -694,7 +688,7 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
case GIF_PATH_3:
if(tag.FLG & 2) GSTransferStatus.PTH3 = IMAGE_MODE;
else GSTransferStatus.PTH3 = TRANSFER_MODE;
break;
}
gifRegs.stat.APATH = pathidx + 1;
@ -809,13 +803,26 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
case GIF_FLG_IMAGE2:
{
GifTagLog("IMAGE Mode EOP %x", tag.EOP);
int len = aMin(size, nloop);
if(pathidx == GIF_PATH_3 && gifRegs.stat.IMT)
{
int len = aMin((int)nloop, 8);
MemCopy_WrappedDest( pMem128, RingBuffer.m_Ring, ringpos, RingBufferSize, len );
MemCopy_WrappedDest( pMem128, RingBuffer.m_Ring, ringpos, RingBufferSize, len );
pMem128 += len;
size -= len;
nloop -= len;
break;
}
else
{
pMem128 += len;
size -= len;
nloop -= len;
int len = aMin(size, nloop);
MemCopy_WrappedDest( pMem128, RingBuffer.m_Ring, ringpos, RingBufferSize, len );
pMem128 += len;
size -= len;
nloop -= len;
}
}
break;
}
@ -852,30 +859,8 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
}
}
}
if (tag.EOP && !nloop) break;
if (tag.EOP && !nloop)
{
if (CSRreg.FINISH)
{
// IMPORTANT: only signal FINISH if ALL THREE paths are stopped (nloop is zero and EOP is set)
// FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active
// drawing *and* image transfer actions must be finished before the IRQ raises.
if(gifRegs.stat.P1Q || gifRegs.stat.P2Q || gifRegs.stat.P3Q)
{
//GH3 and possibly others have path data queued waiting for another path to finish! we need to check they are done too
//DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.P3Q);
}
else if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
{
gsIrq();
}
}
// [TODO] : DMAC Arbitration rights should select the next queued GIF transfer here.
break;
}
if(SIGNAL_IMR_Pending == true)
{
//DevCon.Warning("Path %x", pathidx + 1);
@ -895,14 +880,31 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
GSTransferStatus.PTH1 = STOPPED_MODE;
break;
case GIF_PATH_2:
GSTransferStatus.PTH2 = STOPPED_MODE;
GSTransferStatus.PTH2 = PENDINGSTOP_MODE;
break;
case GIF_PATH_3:
//For huge chunks we may have delay problems, so we need to stall it till the interrupt, else we get desync (Lemmings)
if(size > 8) GSTransferStatus.PTH3 = PENDINGSTOP_MODE;
else GSTransferStatus.PTH3 = STOPPED_MODE;
GSTransferStatus.PTH3 = PENDINGSTOP_MODE;
MSKPATH3_LOG("Path3 Finishing GIFTag packet");
break;
}
if (CSRreg.FINISH)
{
// IMPORTANT: only signal FINISH if ALL THREE paths are stopped (nloop is zero and EOP is set)
// FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active
// drawing *and* image transfer actions must be finished before the IRQ raises.
if(gifRegs.stat.P1Q || gifRegs.stat.P2Q || gifRegs.stat.P3Q)
{
//GH3 and possibly others have path data queued waiting for another path to finish! we need to check they are done too
//DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.P3Q);
}
else if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive())
{
gsIrq();
}
}
}
else if( nloop == 0)
{
@ -917,7 +919,7 @@ __fi int GIFPath::CopyTag(const u128* pMem128, u32 size)
GSTransferStatus.PTH2 = WAITING_MODE;
break;
case GIF_PATH_3:
if(GSTransferStatus.PTH3 < IDLE_MODE) GSTransferStatus.PTH3 = WAITING_MODE;
if(GSTransferStatus.PTH3 < STOPPED_MODE) GSTransferStatus.PTH3 = WAITING_MODE;
break;
}
}

View File

@ -389,7 +389,7 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
//Which causes a CPCOND0 to fail.
icase(DMAC_FAKESTAT)
{
DevCon.Warning("Midway fixup addr=%x writing %x for DMA_STAT", mem, value);
//DevCon.Warning("Midway fixup addr=%x writing %x for DMA_STAT", mem, value);
HW_LOG("Midways own DMAC_STAT Write 32bit %x", value);
// lower 16 bits: clear on 1
@ -434,7 +434,7 @@ __fi bool dmacWrite32( u32 mem, mem32_t& value )
{
if((psHu32(mem & ~0xff) & 0x100) && dmacRegs.ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
{
DevCon.Warning("Write to DMA addr %x while STR is busy! Ignoring", mem);
//DevCon.Warning("Write to DMA addr %x while STR is busy! Ignoring", mem);
return false;
}
}