mirror of https://github.com/PCSX2/pcsx2.git
Sif: Pull some functions to pieces. Fix issue 549 while I'm at it.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2510 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
3c132690f5
commit
2c013c9126
323
pcsx2/Sif.cpp
323
pcsx2/Sif.cpp
|
@ -112,58 +112,8 @@ static __forceinline void SifIOPRead(int &psxCycles)
|
||||||
sif1.counter -= readSize;
|
sif1.counter -= readSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
//General format of all the SIF#(EE/IOP)Dma functions is this:
|
static __forceinline bool SIF0EEReadTag()
|
||||||
//First, SIF#Dma does a while loop, calling SIF#EEDma if EE is active,
|
|
||||||
//and then calling SIF#IOPDma if IOP is active.
|
|
||||||
//
|
|
||||||
//What the EE function does is the following:
|
|
||||||
//Check if qwc <= 0. If it is, check if we have any data left to pull.
|
|
||||||
//If we don't, set EE not to be active, call CPU_INT, and get out of the loop.
|
|
||||||
//If we do, pass data from fifo to ee if sif 0, and to ee from fifo if sif 1.
|
|
||||||
//And if qwc > 0, we do much the same thing.
|
|
||||||
//
|
|
||||||
//The IOP function is similar:
|
|
||||||
//We check if counter <= 0. If it is, check if we have data left to pull.
|
|
||||||
//If we don't, set IOP not to be active, call PSX_INT, and get out of the loop.
|
|
||||||
//If we do, pass data from fifo to iop if sif 0, and to iop from fifo if sif 1.
|
|
||||||
//And if qwc > 0, we do much the same thing.
|
|
||||||
//
|
|
||||||
// And with the IOP function, counter would be 0 initially, so the initialization
|
|
||||||
// is done in the same section of code as the exit, which is odd.
|
|
||||||
//
|
|
||||||
// This is, of course, simplified, and more study of these functions is needed.
|
|
||||||
|
|
||||||
static __forceinline void SIF0EEDma(int &cycles, bool &done)
|
|
||||||
{
|
{
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
if (dmacRegs->ctrl.STS == STS_SIF0)
|
|
||||||
{
|
|
||||||
SIF_LOG("SIF0 stall control");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sif0dma->qwc <= 0)
|
|
||||||
{
|
|
||||||
tDMA_TAG sTag(sif0dma->chcr._u32);
|
|
||||||
|
|
||||||
// Stop if TIE & the IRQ are set, or at the end.
|
|
||||||
// Remind me to look closer at this. (the IRQ tag of a chcr?)
|
|
||||||
if ((sif0dma->chcr.TIE && sTag.IRQ) || sif0.end)
|
|
||||||
{
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
if (sif0.end)
|
|
||||||
SIF_LOG(" EE SIF end");
|
|
||||||
else
|
|
||||||
SIF_LOG(" EE SIF interrupt");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
eesifbusy[0] = false;
|
|
||||||
done = true;
|
|
||||||
if (cycles == 0) DevCon.Warning("EESIF0cycles = 0");
|
|
||||||
CPU_INT(5, cycles*BIAS);
|
|
||||||
}
|
|
||||||
else if (sif0.fifo.size >= 4) // Read a tag
|
|
||||||
{
|
|
||||||
static __aligned16 u32 tag[4];
|
static __aligned16 u32 tag[4];
|
||||||
|
|
||||||
sif0.fifo.read((u32*)&tag[0], 4); // Tag
|
sif0.fifo.read((u32*)&tag[0], 4); // Tag
|
||||||
|
@ -193,57 +143,20 @@ static __forceinline void SIF0EEDma(int &cycles, bool &done)
|
||||||
sif0.end = 1;
|
sif0.end = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
done = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sif0dma->qwc > 0) // If we're reading something continue to do so
|
|
||||||
{
|
|
||||||
SifEERead(cycles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __forceinline void SIF1EEDma(int &cycles, bool &done)
|
static __forceinline bool SIF1EEWriteTag()
|
||||||
{
|
{
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
if (dmacRegs->ctrl.STD == STD_SIF1)
|
|
||||||
{
|
|
||||||
SIF_LOG("SIF1 stall control"); // STD == fromSIF1
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If there's no more to transfer.
|
|
||||||
if (sif1dma->qwc <= 0)
|
|
||||||
{
|
|
||||||
// If NORMAL mode or end of CHAIN then stop DMA.
|
|
||||||
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.end)
|
|
||||||
{
|
|
||||||
SIF_LOG("EE SIF1 End %x", sif1.end);
|
|
||||||
|
|
||||||
// Stop & signal interrupts on EE
|
|
||||||
sif1.end = 0;
|
|
||||||
eesifbusy[1] = false;
|
|
||||||
done = true;
|
|
||||||
|
|
||||||
// Voodoocycles : Okami wants around 100 cycles when booting up
|
|
||||||
// Other games reach like 50k cycles here, but the EE will long have given up by then and just retry.
|
|
||||||
// (Cause of double interrupts on the EE)
|
|
||||||
if (cycles == 0) DevCon.Warning("EESIF1cycles = 0");
|
|
||||||
CPU_INT(6, min( (int)(cycles*BIAS), 384 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Chain mode
|
// Chain mode
|
||||||
tDMA_TAG *ptag;
|
tDMA_TAG *ptag;
|
||||||
|
|
||||||
// Process DMA tag at sif1dma->tadr
|
// Process DMA tag at sif1dma->tadr
|
||||||
done = false;
|
|
||||||
ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1);
|
ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1);
|
||||||
if (ptag == NULL)
|
if (ptag == NULL)
|
||||||
{
|
{
|
||||||
DevCon.Warning("SIF1EEDma: ptag == NULL");
|
Console.WriteLn("SIF1EEDma: ptag = NULL");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sif1dma->chcr.TTE)
|
if (sif1dma->chcr.TTE)
|
||||||
|
@ -296,12 +209,183 @@ static __forceinline void SIF1EEDma(int &cycles, bool &done)
|
||||||
default:
|
default:
|
||||||
Console.WriteLn("Bad addr1 source chain");
|
Console.WriteLn("Bad addr1 source chain");
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline bool SIF0IOPWriteTag()
|
||||||
|
{
|
||||||
|
// Process DMA tag at HW_DMA9_TADR
|
||||||
|
sif0.data = *(sifData *)iopPhysMem(HW_DMA9_TADR);
|
||||||
|
sif0.data.words = (sif0.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
|
||||||
|
sif0.fifo.write((u32*)iopPhysMem(HW_DMA9_TADR + 8), 4);
|
||||||
|
|
||||||
|
HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2;
|
||||||
|
HW_DMA9_MADR = sif0.data.data & 0xFFFFFF;
|
||||||
|
sif0.counter = sif0.data.words & 0xFFFFFF;
|
||||||
|
|
||||||
|
SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.data.words, sif0.data.data);
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
u32 tagId = DMA_TAG(sif0.data.data).ID;
|
||||||
|
if ((tagId == TAG_REFE) || (tagId == TAG_END))
|
||||||
|
SIF_LOG(" END");
|
||||||
|
else
|
||||||
|
SIF_LOG(" CNT %08X, %08X", sif0.data.data, sif0.data.words);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline bool SIF1IOPWriteTag()
|
||||||
|
{
|
||||||
|
// Read a tag.
|
||||||
|
sif1.fifo.read((u32*)&sif1.data, 4);
|
||||||
|
SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d",
|
||||||
|
sif1.data.data & 0xffffff, sif1.data.words, DMA_TAG(sif1.data.data).ID,
|
||||||
|
DMA_TAG(sif1.data.data).IRQ);
|
||||||
|
|
||||||
|
HW_DMA10_MADR = sif1.data.data & 0xffffff;
|
||||||
|
sif1.counter = sif1.data.words;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void SIF0EEend(int &cycles)
|
||||||
|
{
|
||||||
|
eesifbusy[0] = false;
|
||||||
|
if (cycles == 0) DevCon.Warning("EESIF0cycles = 0");
|
||||||
|
CPU_INT(5, cycles*BIAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void SIF1EEend(int &cycles)
|
||||||
|
{
|
||||||
|
// Stop & signal interrupts on EE
|
||||||
|
sif1.end = 0;
|
||||||
|
eesifbusy[1] = false;
|
||||||
|
|
||||||
|
// Voodoocycles : Okami wants around 100 cycles when booting up
|
||||||
|
// Other games reach like 50k cycles here, but the EE will long have given up by then and just retry.
|
||||||
|
// (Cause of double interrupts on the EE)
|
||||||
|
if (cycles == 0) DevCon.Warning("EESIF1cycles = 0");
|
||||||
|
CPU_INT(6, min((int)(cycles*BIAS), 384));
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void SIF0IOPend(int &psxCycles)
|
||||||
|
{
|
||||||
|
// Stop & signal interrupts on IOP
|
||||||
|
sif0.data.data = 0;
|
||||||
|
iopsifbusy[0] = false;
|
||||||
|
|
||||||
|
// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
|
||||||
|
// So when we're all done, the equation looks like thus:
|
||||||
|
//PSX_INT(IopEvt_SIF0, ( ( psxCycles*BIAS ) / 4 ) / 8);
|
||||||
|
if (psxCycles == 0) DevCon.Warning("IOPSIF0cycles = 0");
|
||||||
|
PSX_INT(IopEvt_SIF0, psxCycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void SIF1IOPend(int &psxCycles)
|
||||||
|
{
|
||||||
|
// Stop & signal interrupts on IOP
|
||||||
|
sif1.data.data = 0;
|
||||||
|
iopsifbusy[1] = false;
|
||||||
|
|
||||||
|
//Fixme ( voodoocycles ):
|
||||||
|
//The *24 are needed for ecco the dolphin (CDVD hangs) and silver surfer (Pad not detected)
|
||||||
|
//Greater than *35 break rebooting when trying to play Tekken5 arcade history
|
||||||
|
//Total cycles over 1024 makes SIF too slow to keep up the sound stream in so3...
|
||||||
|
if (psxCycles == 0) DevCon.Warning("IOPSIF1cycles = 0");
|
||||||
|
PSX_INT(IopEvt_SIF1, min((psxCycles * 24), 1024));
|
||||||
|
}
|
||||||
|
|
||||||
|
//General format of all the SIF#(EE/IOP)Dma functions is this:
|
||||||
|
//First, SIF#Dma does a while loop, calling SIF#EEDma if EE is active,
|
||||||
|
//and then calling SIF#IOPDma if IOP is active.
|
||||||
|
//
|
||||||
|
//What the EE function does is the following:
|
||||||
|
//Check if qwc <= 0. If it is, check if we have any data left to pull.
|
||||||
|
//If we don't, set EE not to be active, call CPU_INT, and get out of the loop.
|
||||||
|
//If we do, pass data from fifo to ee if sif 0, and to ee from fifo if sif 1.
|
||||||
|
//And if qwc > 0, we do much the same thing.
|
||||||
|
//
|
||||||
|
//The IOP function is similar:
|
||||||
|
//We check if counter <= 0. If it is, check if we have data left to pull.
|
||||||
|
//If we don't, set IOP not to be active, call PSX_INT, and get out of the loop.
|
||||||
|
//If we do, pass data from fifo to iop if sif 0, and to iop from fifo if sif 1.
|
||||||
|
//And if qwc > 0, we do much the same thing.
|
||||||
|
//
|
||||||
|
// And with the IOP function, counter would be 0 initially, so the initialization
|
||||||
|
// is done in the same section of code as the exit, which is odd.
|
||||||
|
//
|
||||||
|
// This is, of course, simplified, and more study of these functions is needed.
|
||||||
|
|
||||||
|
static __forceinline void SIF0EEDma(int &cycles, bool &done)
|
||||||
|
{
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
if (dmacRegs->ctrl.STS == STS_SIF0)
|
||||||
|
{
|
||||||
|
SIF_LOG("SIF0 stall control");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sif0dma->qwc <= 0)
|
||||||
|
{
|
||||||
|
tDMA_TAG sTag(sif0dma->chcr._u32);
|
||||||
|
|
||||||
|
// Stop if TIE & the IRQ are set, or at the end.
|
||||||
|
// Remind me to look closer at this. (the IRQ tag of a chcr?)
|
||||||
|
if ((sif0dma->chcr.TIE && sTag.IRQ) || sif0.end)
|
||||||
|
{
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
if (sif0.end)
|
||||||
|
SIF_LOG(" EE SIF end");
|
||||||
|
else
|
||||||
|
SIF_LOG(" EE SIF interrupt");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
SIF0EEend(cycles);
|
||||||
|
}
|
||||||
|
else if (sif0.fifo.size >= 4) // Read a tag
|
||||||
|
{
|
||||||
|
done = false;
|
||||||
|
SIF0EEReadTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sif1dma->qwc > 0)
|
|
||||||
|
if (sif0dma->qwc > 0) // If we're reading something continue to do so
|
||||||
|
{
|
||||||
|
SifEERead(cycles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static __forceinline void SIF1EEDma(int &cycles, bool &done)
|
||||||
|
{
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
if (dmacRegs->ctrl.STD == STD_SIF1)
|
||||||
|
{
|
||||||
|
SIF_LOG("SIF1 stall control"); // STD == fromSIF1
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// If there's no more to transfer.
|
||||||
|
if (sif1dma->qwc <= 0)
|
||||||
|
{
|
||||||
|
// If NORMAL mode or end of CHAIN then stop DMA.
|
||||||
|
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.end)
|
||||||
|
{
|
||||||
|
SIF_LOG("EE SIF1 End %x", sif1.end);
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
SIF1EEend(cycles);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done = false;
|
||||||
|
if (!SIF1EEWriteTag()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
SifEEWrite(cycles);
|
SifEEWrite(cycles);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,42 +406,15 @@ static __forceinline void SIF0IOPDma(int &psxCycles, bool &done)
|
||||||
{
|
{
|
||||||
SIF_LOG(" IOP SIF Stopped");
|
SIF_LOG(" IOP SIF Stopped");
|
||||||
|
|
||||||
// Stop & signal interrupts on IOP
|
|
||||||
sif0.data.data = 0;
|
|
||||||
iopsifbusy[0] = false;
|
|
||||||
done = true;
|
done = true;
|
||||||
|
SIF0IOPend(psxCycles);
|
||||||
// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords)
|
|
||||||
// So when we're all done, the equation looks like thus:
|
|
||||||
//PSX_INT(IopEvt_SIF0, ( ( psxCycles*BIAS ) / 4 ) / 8);
|
|
||||||
if (psxCycles == 0) DevCon.Warning("IOPSIF0cycles = 0");
|
|
||||||
PSX_INT(IopEvt_SIF0, psxCycles);
|
|
||||||
}
|
}
|
||||||
else // Chain mode
|
else // Chain mode
|
||||||
{
|
{
|
||||||
// Process DMA tag at HW_DMA9_TADR
|
|
||||||
sif0.data = *(sifData *)iopPhysMem(HW_DMA9_TADR);
|
|
||||||
sif0.data.words = (sif0.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
|
|
||||||
sif0.fifo.write((u32*)iopPhysMem(HW_DMA9_TADR + 8), 4);
|
|
||||||
|
|
||||||
HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2;
|
|
||||||
HW_DMA9_MADR = sif0.data.data & 0xFFFFFF;
|
|
||||||
sif0.counter = sif0.data.words & 0xFFFFFF;
|
|
||||||
|
|
||||||
SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.data.words, sif0.data.data);
|
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
u32 tagId = DMA_TAG(sif0.data.data).ID;
|
|
||||||
if ((tagId == TAG_REFE) || (tagId == TAG_END))
|
|
||||||
SIF_LOG(" END");
|
|
||||||
else
|
|
||||||
SIF_LOG(" CNT %08X, %08X", sif0.data.data, sif0.data.words);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
done = false;
|
done = false;
|
||||||
|
SIF0IOPWriteTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (sif0.counter > 0)
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SifIOPWrite(psxCycles);
|
SifIOPWrite(psxCycles);
|
||||||
|
@ -376,7 +433,6 @@ static __forceinline void SIF1IOPDma(int &psxCycles, bool &done)
|
||||||
tDMA_TAG sTag(sif1.data.data);
|
tDMA_TAG sTag(sif1.data.data);
|
||||||
// Stop on tag IRQ or END
|
// Stop on tag IRQ or END
|
||||||
|
|
||||||
//if ((sif1.tagMode & 0x80) || (sif1.tagMode & 0x40))
|
|
||||||
if (/*sif1.end ||*/ sTag.IRQ || (sTag.ID & 4))
|
if (/*sif1.end ||*/ sTag.IRQ || (sTag.ID & 4))
|
||||||
{
|
{
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
@ -385,29 +441,14 @@ static __forceinline void SIF1IOPDma(int &psxCycles, bool &done)
|
||||||
else
|
else
|
||||||
SIF_LOG(" IOP SIF interrupt");
|
SIF_LOG(" IOP SIF interrupt");
|
||||||
#endif
|
#endif
|
||||||
// Stop & signal interrupts on IOP
|
|
||||||
sif1.data.data = 0;
|
|
||||||
iopsifbusy[1] = false;
|
|
||||||
done = true;
|
done = true;
|
||||||
|
SIF1IOPend(psxCycles);
|
||||||
//Fixme ( voodoocycles ):
|
|
||||||
//The *24 are needed for ecco the dolphin (CDVD hangs) and silver surfer (Pad not detected)
|
|
||||||
//Greater than *35 break rebooting when trying to play Tekken5 arcade history
|
|
||||||
//Total cycles over 1024 makes SIF too slow to keep up the sound stream in so3...
|
|
||||||
if (psxCycles == 0) DevCon.Warning("IOPSIF1cycles = 0");
|
|
||||||
PSX_INT(IopEvt_SIF1, min ( (psxCycles * 24), 1024) );
|
|
||||||
}
|
}
|
||||||
else if (sif1.fifo.size >= 4)
|
else if (sif1.fifo.size >= 4)
|
||||||
{
|
{
|
||||||
// Read a tag.
|
|
||||||
sif1.fifo.read((u32*)&sif1.data, 4);
|
|
||||||
SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d",
|
|
||||||
sif1.data.data & 0xffffff, sif1.data.words, DMA_TAG(sif1.data.data).ID,
|
|
||||||
DMA_TAG(sif1.data.data).IRQ);
|
|
||||||
|
|
||||||
HW_DMA10_MADR = sif1.data.data & 0xffffff;
|
|
||||||
sif1.counter = sif1.data.words;
|
|
||||||
done = false;
|
done = false;
|
||||||
|
SIF1IOPWriteTag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue