diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 37679de3c..77002ab55 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -36,7 +36,7 @@ static u32 gifqwc = 0; static bool gifmfifoirq = false; //Just some temporary bits to store Path1 transfers if another is in progress. -u8 Path1Buffer[0x1000000]; +__aligned16 u8 Path1Buffer[0x1000000]; u32 Path1WritePos = 0; u32 Path1ReadPos = 0; @@ -65,7 +65,6 @@ void gsPath1Interrupt() uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size); GetMTGS().SendDataPacket(); - pxAssume( count == size ); Path1ReadPos += count; if(GSTransferStatus.PTH1 == STOPPED_MODE) diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index 8533cdc98..097cb0353 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -290,7 +290,7 @@ extern void gifMFIFOInterrupt(); //Just some temporary bits to store Path1 transfers if another is in progress. extern void gsPath1Interrupt(); -extern u8 Path1Buffer[0x1000000]; +extern __aligned16 u8 Path1Buffer[0x1000000]; extern u32 Path1WritePos; extern u32 Path1ReadPos; #endif diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index f7af60450..5de48fb8d 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -134,7 +134,8 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { } pass2 { vif1Only(); - + nVifStruct& v = nVif[1]; + if (GSTransferStatus.PTH3 < IDLE_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) @@ -167,79 +168,34 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { return 0; } - - + // HACK ATTACK! + // we shouldn't be clearing the queue flag here at all. Ideally, the queue statuses + // should be checked, handled, and cleared from the EOP check in GIFPath only. --air gifRegs->stat.clear_flags(GIF_STAT_P2Q); - nVifStruct& v = nVif[1]; - const int ret = aMin(vif1.vifpacketsize, vif1.tag.size); - u32 size = ret << 2; + // the tag size should ALWAYS be 128 bits (qwc). If it isn't, it means there's a serious bug + // somewhere in the VIF (likely relating to +/-'ing the tag.size during processing). + pxAssumeMsg( (vif1.tag.size & 1) == 0, "Invalid Vif1 DIRECT packet size detected!" ); - //gifRegs->stat.APATH = GIF_APATH2; //Flag is cleared in vif1interrupt to simulate it being in progress. - - //In the original code we were saving this data, it seems if it does happen, its just blank, so we ignore it. - - if (!size) { DevCon.WriteLn("Path2: No Data Transfer?"); } - + const int minSize = aMin(vif1.vifpacketsize, vif1.tag.size)/4; + uint ret; - if(vif1.vifpacketsize < 4 && v.bSize < 16) - { - nVifStruct& v = nVif[idx]; + if (!minSize) + DevCon.Warning("VIF DIRECT (PATH2): No Data Transfer?"); - memcpy(&v.buffer[v.bPtr], data, vif1.vifpacketsize << 2); - v.bSize += vif1.vifpacketsize << 2; - v.bPtr += vif1.vifpacketsize << 2; - vif1.tag.size -= vif1.vifpacketsize; - if(vif1.tag.size == 0) - { - DevCon.Warning("Missaligned packet on DIRECT end!"); - vif1.cmd = 0; - } - return vif1.vifpacketsize; - } - else - { - nVifStruct& v = nVif[idx]; - if(v.bSize) - { - int ret = 0; + GetMTGS().PrepDataPacket(GIF_PATH_2, minSize); + ret = GIFPath_CopyTag(GIF_PATH_2, (u128*)data, minSize)*4; + GetMTGS().SendDataPacket(); - if(v.bSize < 16) - { - if(((16 - v.bSize) >> 2) > vif1.vifpacketsize) DevCon.Warning("Not Enough Data!"); - ret = (16 - v.bSize) >> 2; - memcpy(&v.buffer[v.bPtr], data, ret << 2); - vif1.tag.size -= ret; - v.bSize = 0; - v.bPtr = 0; - } - GetMTGS().PrepDataPacket(GIF_PATH_2, 1); - GIFPath_CopyTag(GIF_PATH_2, (u128*)v.buffer, 1); - GetMTGS().SendDataPacket(); + vif1.tag.size -= ret; - if(vif1.tag.size == 0) - { - vif1.cmd = 0; - } - vif1.vifstalled = true; - return ret; - } - else - { - GetMTGS().PrepDataPacket(GIF_PATH_2, size/16); - uint count = GIFPath_CopyTag(GIF_PATH_2, (u128*)data, size/16) * 4; - GetMTGS().SendDataPacket(); - - vif1.tag.size -= count; - if(vif1.tag.size == 0) - { - vif1.cmd = 0; - } - vif1.vifstalled = true; - return count; - } - } - + if(vif1.tag.size == 0) + { + vif1.cmd = 0; + gifRegs->stat.clear_flags(GIF_STAT_APATH2 | GIF_STAT_OPH); + } + vif1.vifstalled = true; + return ret; } return 0; } diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index a0e8ac58a..859f4db46 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -817,6 +817,9 @@ __forceinline int GIFPath::CopyTag(const u128* pMem128, u32 size) gsIrq(); } } + + // [TODO] : DMAC Arbitration rights should select the next queued GIF transfer here. + break; } if(SIGNAL_IMR_Pending == true) @@ -873,9 +876,18 @@ __forceinline int GIFPath_CopyTag(GIF_PATH pathidx, const u128* pMem, u32 size) { switch( pathidx ) { - case GIF_PATH_1: return s_gifPath[GIF_PATH_1].CopyTag(pMem, size); - case GIF_PATH_2: return s_gifPath[GIF_PATH_2].CopyTag(pMem, size); - case GIF_PATH_3: return s_gifPath[GIF_PATH_3].CopyTag(pMem, size); + case GIF_PATH_1: + pxAssertMsg(!s_gifPath[GIF_PATH_2].IsActive(), "GIFpath conflict: Attempted to start PATH1 while PATH2 is already active."); + pxAssertMsg(!s_gifPath[GIF_PATH_3].IsActive(), "GIFpath conflict: Attempted to start PATH1 while PATH3 is already active."); + return s_gifPath[GIF_PATH_1].CopyTag(pMem, size); + case GIF_PATH_2: + pxAssertMsg(!s_gifPath[GIF_PATH_1].IsActive(), "GIFpath conflict: Attempted to start PATH2 while PATH1 is already active."); + pxAssertMsg(!s_gifPath[GIF_PATH_3].IsActive(), "GIFpath conflict: Attempted to start PATH2 while PATH3 is already active."); + return s_gifPath[GIF_PATH_2].CopyTag(pMem, size); + case GIF_PATH_3: + pxAssertMsg(!s_gifPath[GIF_PATH_1].IsActive(), "GIFpath conflict: Attempted to start PATH3 while PATH1 is already active."); + pxAssertMsg(!s_gifPath[GIF_PATH_2].IsActive(), "GIFpath conflict: Attempted to start PATH3 while PATH2 is already active."); + return s_gifPath[GIF_PATH_3].CopyTag(pMem, size); jNO_DEFAULT; }