2010-04-24 21:37:39 +00:00
/* PCSX2 - PS2 Emulator for PCs
2010-05-03 14:08:02 +00:00
* Copyright ( C ) 2002 - 2010 PCSX2 Dev Team
2010-04-24 21:37:39 +00:00
*
* PCSX2 is free software : you can redistribute it and / or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found -
* ation , either version 3 of the License , or ( at your option ) any later version .
*
* PCSX2 is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along with PCSX2 .
* If not , see < http : //www.gnu.org/licenses/>.
*/
# include "PrecompiledHeader.h"
# include "Common.h"
# include "Vif.h"
2011-07-24 13:02:50 +00:00
# include "Gif_Unit.h"
2010-04-24 21:37:39 +00:00
# include "Vif_Dma.h"
2010-06-22 23:10:40 +00:00
static u32 qwctag ( u32 mask )
{
2010-08-31 05:22:26 +00:00
return ( dmacRegs . rbor . ADDR + ( mask & dmacRegs . rbsr . RMSK ) ) ;
2010-06-22 23:10:40 +00:00
}
2010-04-24 21:37:39 +00:00
2020-11-29 01:29:57 +00:00
static u32 QWCinVIFMFIFO ( u32 DrainADDR , u32 qwc )
2010-11-19 16:29:28 +00:00
{
u32 ret ;
2022-07-30 08:29:27 +00:00
2010-11-19 16:29:28 +00:00
//Calculate what we have in the fifo.
2022-07-30 08:29:27 +00:00
if ( DrainADDR < = spr0ch . madr )
2010-11-19 16:29:28 +00:00
{
//Drain is below the tadr, calculate the difference between them
ret = ( spr0ch . madr - DrainADDR ) > > 4 ;
}
else
{
u32 limit = dmacRegs . rbor . ADDR + dmacRegs . rbsr . RMSK + 16 ;
2022-07-30 08:29:27 +00:00
//Drain is higher than SPR so it has looped round,
2010-11-19 16:29:28 +00:00
//calculate from base to the SPR tag addr and what is left in the top of the ring
ret = ( ( spr0ch . madr - dmacRegs . rbor . ADDR ) + ( limit - DrainADDR ) ) > > 4 ;
}
2018-06-20 21:01:10 +00:00
2018-07-14 13:32:02 +00:00
VIF_LOG ( " VIF MFIFO Requesting %x QWC of %x Available from the MFIFO Base %x MFIFO Top %x, SPR MADR %x Drain %x " , qwc , ret , dmacRegs . rbor . ADDR , dmacRegs . rbor . ADDR + dmacRegs . rbsr . RMSK + 16 , spr0ch . madr , DrainADDR ) ;
2018-05-30 00:29:23 +00:00
2010-11-19 16:29:28 +00:00
return ret ;
}
2010-08-09 04:10:38 +00:00
static __fi bool mfifoVIF1rbTransfer ( )
2010-04-24 21:37:39 +00:00
{
2010-08-31 05:22:26 +00:00
u32 msize = dmacRegs . rbor . ADDR + dmacRegs . rbsr . RMSK + 16 ;
2020-11-29 01:29:57 +00:00
u32 mfifoqwc = std : : min ( QWCinVIFMFIFO ( vif1ch . madr , vif1ch . qwc ) , vif1ch . qwc ) ;
2022-07-30 08:29:27 +00:00
u32 * src ;
2010-04-24 21:37:39 +00:00
bool ret ;
2022-07-30 08:29:27 +00:00
if ( mfifoqwc = = 0 )
{
2018-05-30 00:29:23 +00:00
DevCon . Warning ( " VIF MFIFO no QWC before transfer (in transfer function, bit late really) " ) ;
2022-07-30 08:29:27 +00:00
return true ; //Cant do anything, lets forget it
2018-05-30 00:29:23 +00:00
}
2010-11-19 16:29:28 +00:00
2010-04-24 21:37:39 +00:00
/* Check if the transfer should wrap around the ring buffer */
2010-08-31 05:22:26 +00:00
if ( ( vif1ch . madr + ( mfifoqwc < < 4 ) ) > ( msize ) )
2010-04-24 21:37:39 +00:00
{
2022-07-30 08:29:27 +00:00
int s1 = ( ( msize ) - vif1ch . madr ) > > 2 ;
2010-04-24 21:37:39 +00:00
2018-07-14 13:32:02 +00:00
VIF_LOG ( " Split MFIFO " ) ;
2010-04-24 21:37:39 +00:00
/* it does, so first copy 's1' bytes from 'addr' to 'data' */
2010-11-19 16:29:28 +00:00
vif1ch . madr = qwctag ( vif1ch . madr ) ;
2010-08-31 05:22:26 +00:00
src = ( u32 * ) PSM ( vif1ch . madr ) ;
2022-07-30 08:29:27 +00:00
if ( src = = NULL )
return false ;
2010-04-24 21:37:39 +00:00
2012-08-16 23:03:27 +00:00
if ( vif1 . irqoffset . enabled )
ret = VIF1transfer ( src + vif1 . irqoffset . value , s1 - vif1 . irqoffset . value ) ;
2010-04-24 21:37:39 +00:00
else
2010-06-22 23:10:40 +00:00
ret = VIF1transfer ( src , s1 ) ;
2010-04-24 21:37:39 +00:00
if ( ret )
{
2022-07-30 08:29:27 +00:00
if ( vif1 . irqoffset . value ! = 0 )
DevCon . Warning ( " VIF1 MFIFO Offest != 0! vifoffset=%x " , vif1 . irqoffset . value ) ;
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
2018-05-30 00:29:23 +00:00
//DevCon.Warning("Loopyloop");
vif1ch . tadr = qwctag ( vif1ch . tadr ) ;
vif1ch . madr = qwctag ( vif1ch . madr ) ;
2010-04-24 21:37:39 +00:00
2022-07-30 08:29:27 +00:00
src = ( u32 * ) PSM ( vif1ch . madr ) ;
if ( src = = NULL )
return false ;
VIF1transfer ( src , ( ( mfifoqwc < < 2 ) - s1 ) ) ;
2010-04-24 21:37:39 +00:00
}
}
else
{
2018-07-14 13:32:02 +00:00
VIF_LOG ( " Direct MFIFO " ) ;
2018-05-30 00:29:23 +00:00
2010-04-24 21:37:39 +00:00
/* it doesn't, so just transfer 'qwc*4' words */
2010-08-31 05:22:26 +00:00
src = ( u32 * ) PSM ( vif1ch . madr ) ;
2022-07-30 08:29:27 +00:00
if ( src = = NULL )
return false ;
2010-04-24 21:37:39 +00:00
2012-08-16 23:03:27 +00:00
if ( vif1 . irqoffset . enabled )
ret = VIF1transfer ( src + vif1 . irqoffset . value , mfifoqwc * 4 - vif1 . irqoffset . value ) ;
2010-04-24 21:37:39 +00:00
else
2010-06-22 23:10:40 +00:00
ret = VIF1transfer ( src , mfifoqwc < < 2 ) ;
2010-04-24 21:37:39 +00:00
}
return ret ;
}
2010-08-11 09:16:12 +00:00
static __fi void mfifo_VIF1chain ( )
2010-04-24 21:37:39 +00:00
{
/* Is QWC = 0? if so there is nothing to transfer */
2022-12-25 05:59:04 +00:00
if ( vif1ch . qwc = = 0 )
2010-04-24 21:37:39 +00:00
{
vif1 . inprogress & = ~ 1 ;
2010-08-11 09:16:12 +00:00
return ;
2010-04-24 21:37:39 +00:00
}
2010-08-31 05:22:26 +00:00
if ( vif1ch . madr > = dmacRegs . rbor . ADDR & &
2022-07-30 08:29:27 +00:00
vif1ch . madr < ( dmacRegs . rbor . ADDR + dmacRegs . rbsr . RMSK + 16u ) )
2018-05-30 00:29:23 +00:00
{
2011-01-21 15:17:29 +00:00
//if(vif1ch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge VIF1");
2022-07-30 08:29:27 +00:00
if ( QWCinVIFMFIFO ( vif1ch . madr , vif1ch . qwc ) = = 0 )
{
2018-07-14 13:32:02 +00:00
VIF_LOG ( " VIF MFIFO Empty before transfer " ) ;
2018-05-30 00:29:23 +00:00
vif1 . inprogress | = 0x10 ;
g_vif1Cycles + = 4 ;
return ;
}
2010-08-11 09:16:12 +00:00
mfifoVIF1rbTransfer ( ) ;
2010-11-19 20:37:11 +00:00
vif1ch . madr = qwctag ( vif1ch . madr ) ;
2018-07-14 13:32:02 +00:00
//When transferring direct from the MFIFO, the TADR needs to be after the data last read
//FF7 DoC Expects the transfer to end with an Empty interrupt, so the TADR has to match SPR0_MADR
//It does an END tag (which normally doesn't increment TADR because it breaks Soul Calibur 2)
//with a QWC of 1 (rare) so we need to increment the TADR in the case of MFIFO.
vif1ch . tadr = vif1ch . madr ;
2010-04-24 21:37:39 +00:00
}
else
{
2022-07-30 08:29:27 +00:00
tDMA_TAG * pMem = dmaGetAddr ( vif1ch . madr , ! vif1ch . chcr . DIR ) ;
2018-07-14 13:32:02 +00:00
VIF_LOG ( " Non-MFIFO Location " ) ;
2010-04-24 21:37:39 +00:00
2010-08-11 09:16:12 +00:00
//No need to exit on non-mfifo as it is indirect anyway, so it can be transferring this while spr refills the mfifo
2022-07-30 08:29:27 +00:00
if ( pMem = = NULL )
return ;
2010-04-24 21:37:39 +00:00
2012-08-16 23:03:27 +00:00
if ( vif1 . irqoffset . enabled )
VIF1transfer ( ( u32 * ) pMem + vif1 . irqoffset . value , vif1ch . qwc * 4 - vif1 . irqoffset . value ) ;
2010-04-24 21:37:39 +00:00
else
2010-08-31 05:22:26 +00:00
VIF1transfer ( ( u32 * ) pMem , vif1ch . qwc < < 2 ) ;
2010-04-24 21:37:39 +00:00
}
}
2013-03-11 16:02:56 +00:00
void mfifoVifMaskMem ( int id )
{
2022-07-30 08:29:27 +00:00
switch ( id )
{
2013-03-11 16:02:56 +00:00
//These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
case TAG_CNT :
case TAG_NEXT :
2022-07-30 08:29:27 +00:00
case TAG_CALL :
2013-03-11 16:02:56 +00:00
case TAG_RET :
case TAG_END :
2022-07-30 08:29:27 +00:00
if ( vif1ch . madr < dmacRegs . rbor . ADDR ) //probably not needed but we will check anyway.
2013-03-11 16:02:56 +00:00
{
//DevCon.Warning("VIF MFIFO MADR below bottom of ring buffer, wrapping VIF MADR = %x Ring Bottom %x", vif1ch.madr, dmacRegs.rbor.ADDR);
vif1ch . madr = qwctag ( vif1ch . madr ) ;
}
2022-07-30 08:29:27 +00:00
if ( vif1ch . madr > ( dmacRegs . rbor . ADDR + ( u32 ) dmacRegs . rbsr . RMSK ) ) //Usual scenario is the tag is near the end (Front Mission 4)
2013-03-11 16:02:56 +00:00
{
//DevCon.Warning("VIF MFIFO MADR outside top of ring buffer, wrapping VIF MADR = %x Ring Top %x", vif1ch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16);
vif1ch . madr = qwctag ( vif1ch . madr ) ;
}
break ;
default :
//Do nothing as the MADR could be outside
break ;
}
}
2018-05-30 00:29:23 +00:00
void mfifoVIF1transfer ( )
2010-04-24 21:37:39 +00:00
{
2022-07-30 08:29:27 +00:00
tDMA_TAG * ptag ;
2010-04-24 21:37:39 +00:00
2011-10-15 10:45:31 +00:00
g_vif1Cycles = 0 ;
2010-04-24 21:37:39 +00:00
2018-05-30 00:29:23 +00:00
if ( vif1ch . qwc = = 0 )
2010-04-24 21:37:39 +00:00
{
2022-07-30 08:29:27 +00:00
if ( QWCinVIFMFIFO ( vif1ch . tadr , 1 ) = = 0 )
{
2018-07-14 13:32:02 +00:00
VIF_LOG ( " VIF MFIFO Empty before tag " ) ;
2018-05-30 00:29:23 +00:00
vif1 . inprogress | = 0x10 ;
g_vif1Cycles + = 4 ;
return ;
2010-04-24 21:37:39 +00:00
}
2010-11-19 16:29:28 +00:00
vif1ch . tadr = qwctag ( vif1ch . tadr ) ;
2010-08-31 05:22:26 +00:00
ptag = dmaGetAddr ( vif1ch . tadr , false ) ;
2010-04-24 21:37:39 +00:00
2014-02-26 22:34:02 +00:00
if ( dmacRegs . ctrl . STD = = STD_VIF1 & & ( ptag - > ID = = TAG_REFS ) )
{
Console . WriteLn ( " VIF MFIFO DMA Stall not implemented - Report which game to PCSX2 Team " ) ;
}
2010-08-31 05:22:26 +00:00
if ( vif1ch . chcr . TTE )
2010-04-24 21:37:39 +00:00
{
2018-05-30 00:29:23 +00:00
bool ret ;
2010-04-24 21:37:39 +00:00
2021-09-03 06:23:59 +00:00
alignas ( 16 ) static u128 masked_tag ;
2010-10-12 12:15:57 +00:00
masked_tag . _u64 [ 0 ] = 0 ;
masked_tag . _u64 [ 1 ] = * ( ( u64 * ) ptag + 1 ) ;
VIF_LOG ( " \t VIF1 SrcChain TTE=1, data = 0x%08x.%08x " , masked_tag . _u32 [ 3 ] , masked_tag . _u32 [ 2 ] ) ;
2012-08-16 23:03:27 +00:00
if ( vif1 . irqoffset . enabled )
2010-10-12 12:15:57 +00:00
{
2022-07-30 08:29:27 +00:00
ret = VIF1transfer ( ( u32 * ) & masked_tag + vif1 . irqoffset . value , 4 - vif1 . irqoffset . value , true ) ; //Transfer Tag on stall
2010-10-12 12:15:57 +00:00
//ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall
}
2010-04-24 21:37:39 +00:00
else
2010-10-12 12:15:57 +00:00
{
2012-08-16 23:03:27 +00:00
vif1 . irqoffset . value = 2 ;
vif1 . irqoffset . enabled = true ;
2022-07-30 08:29:27 +00:00
ret = VIF1transfer ( ( u32 * ) & masked_tag + 2 , 2 , true ) ; //Transfer Tag
2010-10-12 12:15:57 +00:00
}
2010-04-24 21:37:39 +00:00
2012-08-16 23:03:27 +00:00
if ( ! ret & & vif1 . irqoffset . enabled )
2010-04-24 21:37:39 +00:00
{
2010-11-19 16:29:28 +00:00
vif1 . inprogress & = ~ 1 ;
2022-07-30 08:29:27 +00:00
return ; //IRQ set by VIFTransfer
2018-05-30 00:29:23 +00:00
}
2011-10-15 10:45:31 +00:00
g_vif1Cycles + = 2 ;
2010-04-24 21:37:39 +00:00
}
2018-05-30 00:29:23 +00:00
2012-08-16 23:03:27 +00:00
vif1 . irqoffset . value = 0 ;
vif1 . irqoffset . enabled = false ;
2010-06-22 23:10:40 +00:00
2022-07-30 08:29:27 +00:00
vif1ch . unsafeTransfer ( ptag ) ;
2010-04-24 21:37:39 +00:00
2010-08-31 05:22:26 +00:00
vif1ch . madr = ptag [ 1 ] . _u32 ;
2010-11-19 16:29:28 +00:00
2018-07-14 13:32:02 +00:00
VIF_LOG ( " dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx spr0 madr = %x " ,
2022-07-30 08:29:27 +00:00
ptag [ 1 ] . _u32 , ptag [ 0 ] . _u32 , vif1ch . qwc , ptag - > ID , vif1ch . madr , vif1ch . tadr , spr0ch . madr ) ;
2010-04-24 21:37:39 +00:00
2010-11-19 16:29:28 +00:00
vif1 . done | = hwDmacSrcChainWithStack ( vif1ch , ptag - > ID ) ;
2010-04-24 21:37:39 +00:00
2013-03-11 16:02:56 +00:00
mfifoVifMaskMem ( ptag - > ID ) ;
2010-08-31 05:22:26 +00:00
if ( vif1ch . chcr . TIE & & ptag - > IRQ )
2010-04-24 21:37:39 +00:00
{
VIF_LOG ( " dmaIrq Set " ) ;
vif1 . done = true ;
}
2010-08-11 09:16:12 +00:00
2010-11-19 20:37:11 +00:00
vif1ch . tadr = qwctag ( vif1ch . tadr ) ;
2022-07-30 08:29:27 +00:00
if ( vif1ch . qwc > 0 )
vif1 . inprogress | = 1 ;
2010-11-19 16:29:28 +00:00
}
else
{
DevCon . Warning ( " Vif MFIFO QWC not 0 on tag " ) ;
2010-04-24 21:37:39 +00:00
}
2022-07-30 08:29:27 +00:00
2010-04-24 21:37:39 +00:00
2018-07-14 13:32:02 +00:00
VIF_LOG ( " mfifoVIF1transfer end %x madr %x, tadr %x " , vif1ch . chcr . _u32 , vif1ch . madr , vif1ch . tadr ) ;
2010-04-24 21:37:39 +00:00
}
void vifMFIFOInterrupt ( )
{
2011-10-15 10:45:31 +00:00
g_vif1Cycles = 0 ;
2010-04-24 21:37:39 +00:00
VIF_LOG ( " vif mfifo interrupt " ) ;
2022-07-30 08:29:27 +00:00
if ( dmacRegs . ctrl . MFD ! = MFD_VIF1 )
{
2018-05-30 00:29:23 +00:00
vif1Interrupt ( ) ;
return ;
}
2022-07-30 08:29:27 +00:00
if ( gifRegs . stat . APATH = = 2 & & gifUnit . gifPath [ 1 ] . isDone ( ) )
2013-02-08 23:41:28 +00:00
{
gifRegs . stat . APATH = 0 ;
gifRegs . stat . OPH = 0 ;
2022-07-30 08:29:27 +00:00
if ( gifUnit . checkPaths ( 1 , 0 , 1 ) )
gifUnit . Execute ( false , true ) ;
2013-02-08 23:41:28 +00:00
}
2022-07-30 08:29:27 +00:00
if ( vif1ch . chcr . DIR )
{
bool isDirect = ( vif1 . cmd & 0x7f ) = = 0x50 ;
2011-07-25 07:43:31 +00:00
bool isDirectHL = ( vif1 . cmd & 0x7f ) = = 0x51 ;
2022-07-30 08:29:27 +00:00
if ( ( isDirect & & ! gifUnit . CanDoPath2 ( ) ) | | ( isDirectHL & & ! gifUnit . CanDoPath2HL ( ) ) )
{
2011-07-25 07:43:31 +00:00
GUNIT_WARN ( " vifMFIFOInterrupt() - Waiting for Path 2 to be ready " ) ;
CPU_INT ( DMAC_MFIFO_VIF , 128 ) ;
2023-09-13 13:10:28 +00:00
CPU_SET_DMASTALL ( DMAC_MFIFO_VIF , true ) ;
2011-07-25 07:43:31 +00:00
return ;
}
2011-07-24 13:02:50 +00:00
}
2022-07-30 08:29:27 +00:00
if ( vif1 . waitforvu )
2012-04-07 01:48:34 +00:00
{
2022-07-30 08:29:27 +00:00
//DevCon.Warning("Waiting on VU1 MFIFO");
CPU_INT ( VIF_VU1_FINISH , std : : max ( 16 , cpuGetCycles ( VU_MTVU_BUSY ) ) ) ;
2023-09-13 13:10:28 +00:00
CPU_SET_DMASTALL ( DMAC_MFIFO_VIF , true ) ;
2012-04-07 01:48:34 +00:00
return ;
}
2011-07-24 13:02:50 +00:00
// We need to check the direction, if it is downloading from the GS,
// we handle that separately (KH2 for testing)
2010-06-22 23:10:40 +00:00
2011-07-24 13:02:50 +00:00
// Simulated GS transfer time done, clear the flags
2022-07-30 08:29:27 +00:00
if ( vif1 . irq & & vif1 . vifstalled . enabled & & vif1 . vifstalled . value = = VIF_IRQ_STALL )
{
2018-07-14 13:32:02 +00:00
VIF_LOG ( " VIF MFIFO Code Interrupt detected " ) ;
2010-08-31 05:22:26 +00:00
vif1Regs . stat . INT = true ;
2014-02-02 20:19:54 +00:00
2022-07-30 08:29:27 +00:00
if ( ( ( vif1Regs . code > > 24 ) & 0x7f ) ! = 0x7 )
{
2014-02-02 20:19:54 +00:00
vif1Regs . stat . VIS = true ;
}
2010-04-24 21:37:39 +00:00
hwIntcIrq ( INTC_VIF1 ) ;
- - vif1 . irq ;
2022-07-30 08:29:27 +00:00
if ( vif1Regs . stat . test ( VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS ) )
{
2011-07-25 07:43:31 +00:00
//vif1Regs.stat.FQC = 0; // FQC=0
//vif1ch.chcr.STR = false;
2020-11-29 01:29:57 +00:00
vif1Regs . stat . FQC = std : : min ( ( u32 ) 0x10 , vif1ch . qwc ) ;
2018-07-14 13:32:02 +00:00
VIF_LOG ( " VIF1 MFIFO Stalled qwc = %x done = %x inprogress = %x " , vif1ch . qwc , vif1 . done , vif1 . inprogress & 0x10 ) ;
2015-10-24 02:29:56 +00:00
//Used to check if the MFIFO was empty, there's really no need if it's finished what it needed.
2022-07-30 08:29:27 +00:00
if ( ( vif1ch . qwc > 0 | | ! vif1 . done ) )
{
2020-12-13 21:02:48 +00:00
vif1Regs . stat . VPS = VPS_DECODING ; //If there's more data you need to say it's decoding the next VIF CMD (Onimusha - Blade Warriors)
2011-01-21 15:17:29 +00:00
VIF_LOG ( " VIF1 MFIFO Stalled " ) ;
2023-09-13 13:10:28 +00:00
CPU_SET_DMASTALL ( DMAC_MFIFO_VIF , true ) ;
2011-01-21 15:17:29 +00:00
return ;
}
2010-04-24 21:37:39 +00:00
}
}
2011-01-21 15:17:29 +00:00
//Mirroring change to VIF0
2022-07-30 08:29:27 +00:00
if ( vif1 . cmd )
{
if ( vif1 . done & & vif1ch . qwc = = 0 )
vif1Regs . stat . VPS = VPS_WAITING ;
2011-01-21 15:17:29 +00:00
}
2022-07-30 08:29:27 +00:00
else
{
2011-01-21 15:17:29 +00:00
vif1Regs . stat . VPS = VPS_IDLE ;
}
2022-07-30 08:29:27 +00:00
if ( vif1 . inprogress & 0x10 )
{
2010-11-19 20:07:57 +00:00
FireMFIFOEmpty ( ) ;
2023-09-13 13:10:28 +00:00
CPU_SET_DMASTALL ( DMAC_MFIFO_VIF , true ) ;
2018-05-30 00:29:23 +00:00
return ;
2010-11-19 20:07:57 +00:00
}
2012-08-16 23:03:27 +00:00
vif1 . vifstalled . enabled = false ;
2022-07-30 08:29:27 +00:00
if ( ! vif1 . done | | vif1ch . qwc )
{
switch ( vif1 . inprogress & 1 )
{
2010-04-24 21:37:39 +00:00
case 0 : //Set up transfer
2018-05-30 00:29:23 +00:00
mfifoVIF1transfer ( ) ;
2020-11-29 01:29:57 +00:00
vif1Regs . stat . FQC = std : : min ( ( u32 ) 0x10 , vif1ch . qwc ) ;
2020-11-01 23:02:36 +00:00
[[fallthrough]] ;
2010-04-24 21:37:39 +00:00
case 1 : //Transfer data
2022-07-30 08:29:27 +00:00
if ( vif1 . inprogress & 0x1 ) //Just in case the tag breaks early (or something wierd happens)!
2012-05-30 19:19:53 +00:00
mfifo_VIF1chain ( ) ;
2010-08-11 09:16:12 +00:00
//Sanity check! making sure we always have non-zero values
2022-07-30 08:29:27 +00:00
if ( ! ( vif1Regs . stat . VGW & & gifUnit . gifPath [ GIF_PATH_3 ] . state ! = GIF_PATH_IDLE ) ) //If we're waiting on GIF, stop looping, (can be over 1000 loops!)
{
if ( vif1 . waitforvu )
{
//if (cpuGetCycles(VU_MTVU_BUSY) > static_cast<int>(g_vif1Cycles))
// DevCon.Warning("Waiting %d instead of %d", cpuGetCycles(VU_MTVU_BUSY), static_cast<int>(g_vif1Cycles));
CPU_INT ( DMAC_MFIFO_VIF , std : : max ( static_cast < int > ( ( g_vif1Cycles = = 0 ? 4 : g_vif1Cycles ) ) , cpuGetCycles ( VU_MTVU_BUSY ) ) ) ;
}
else
CPU_INT ( DMAC_MFIFO_VIF , ( g_vif1Cycles = = 0 ? 4 : g_vif1Cycles ) ) ;
}
2012-05-30 19:19:53 +00:00
2020-11-29 01:29:57 +00:00
vif1Regs . stat . FQC = std : : min ( ( u32 ) 0x10 , vif1ch . qwc ) ;
2010-04-24 21:37:39 +00:00
return ;
}
return ;
2018-07-14 13:32:02 +00:00
}
2010-04-24 21:37:39 +00:00
2012-08-16 23:03:27 +00:00
vif1 . vifstalled . enabled = false ;
vif1 . irqoffset . enabled = false ;
2010-04-24 21:37:39 +00:00
vif1 . done = 1 ;
2018-07-14 13:32:02 +00:00
2022-07-30 08:29:27 +00:00
if ( spr0ch . madr = = vif1ch . tadr )
{
2018-07-14 13:32:02 +00:00
FireMFIFOEmpty ( ) ;
}
2011-10-15 10:45:31 +00:00
g_vif1Cycles = 0 ;
2020-11-29 01:29:57 +00:00
vif1Regs . stat . FQC = std : : min ( ( u32 ) 0x10 , vif1ch . qwc ) ;
2010-08-31 05:22:26 +00:00
vif1ch . chcr . STR = false ;
2010-04-24 21:37:39 +00:00
hwDmacIrq ( DMAC_VIF1 ) ;
2011-02-24 11:07:13 +00:00
DMA_LOG ( " VIF1 MFIFO DMA End " ) ;
2023-09-13 13:10:28 +00:00
CPU_SET_DMASTALL ( DMAC_MFIFO_VIF , false ) ;
2010-08-31 05:22:26 +00:00
vif1Regs . stat . FQC = 0 ;
2010-04-24 21:37:39 +00:00
}