mirror of https://github.com/PCSX2/pcsx2.git
Refactor some Sif code.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2472 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
14ebc021ad
commit
124f91920e
601
pcsx2/Sif.cpp
601
pcsx2/Sif.cpp
|
@ -18,11 +18,9 @@
|
|||
#define _PC_ // disables MIPS opcode macros.
|
||||
|
||||
#include "IopCommon.h"
|
||||
|
||||
#include "Sif.h"
|
||||
|
||||
DMACh *sif0ch, *sif1ch, *sif2ch;
|
||||
|
||||
static _sif sif0, sif1;
|
||||
|
||||
bool eesifbusy[2] = { false, false };
|
||||
|
@ -36,9 +34,307 @@ void sifInit()
|
|||
memzero(iopsifbusy);
|
||||
}
|
||||
|
||||
__forceinline void SIF0EEDma(int &cycles, int &psxCycles, bool &done)
|
||||
{
|
||||
int size = sif0dma->qwc;
|
||||
if (dmacRegs->ctrl.STS == STS_SIF0)
|
||||
{
|
||||
SIF_LOG("SIF0 stall control");
|
||||
}
|
||||
if (size > 0) // If we're reading something continue to do so
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
int readSize = min(size, (sif0.fifo.size >> 2));
|
||||
|
||||
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
|
||||
SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2);
|
||||
|
||||
ptag = safeDmaGetAddr(sif0dma, sif0dma->madr, DMAC_SIF0);
|
||||
if (ptag == NULL) return;
|
||||
|
||||
sif0.fifo.read((u32*)ptag, readSize << 2);
|
||||
|
||||
// Clearing handled by vtlb memory protection and manual blocks.
|
||||
//Cpu->Clear(sif0dma->madr, readSize*4);
|
||||
|
||||
cycles += readSize; // fixme : BIAS is factored in below
|
||||
sif0dma->qwc -= readSize;
|
||||
sif0dma->madr += readSize << 4;
|
||||
}
|
||||
|
||||
if (sif0dma->qwc == 0)
|
||||
{
|
||||
// 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 && DMA_TAG(sif0dma->chcr._u32).IRQ) || sif0.end)
|
||||
{
|
||||
if (sif0.end)
|
||||
SIF_LOG(" EE SIF end");
|
||||
else
|
||||
SIF_LOG(" EE SIF interrupt");
|
||||
|
||||
CPU_INT(5, cycles*BIAS);
|
||||
eesifbusy[0] = false;
|
||||
done = true;
|
||||
}
|
||||
else if (sif0.fifo.size >= 4) // Read a tag
|
||||
{
|
||||
static __aligned16 u32 tag[4];
|
||||
|
||||
sif0.fifo.read((u32*)&tag[0], 4); // Tag
|
||||
SIF_LOG(" EE SIF read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
|
||||
|
||||
sif0dma->unsafeTransfer(((tDMA_TAG*)(tag)));
|
||||
sif0dma->madr = tag[1];
|
||||
|
||||
SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", sif0dma->madr, sif0dma->qwc, (tag[0] >> 28)&3, (tag[0] >> 31)&1, tag[1], tag[0]);
|
||||
|
||||
switch (DMA_TAG(tag[0]).ID)
|
||||
{
|
||||
case TAG_REFE:
|
||||
sif0.end = 1;
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_REFS:
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_END:
|
||||
sif0.end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void SIF1EEDma(int &cycles, int &psxCycles, bool &done)
|
||||
{
|
||||
if (dmacRegs->ctrl.STD == STD_SIF1)
|
||||
{
|
||||
SIF_LOG("SIF1 stall control"); // STD == fromSIF1
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Stop & signal interrupts on EE
|
||||
SIF_LOG("EE SIF1 End %x", sif1.end);
|
||||
eesifbusy[1] = false;
|
||||
done = true;
|
||||
|
||||
// Voodoocycles : 4 cycles always, stops games from throwing double interrupts.
|
||||
// Edit: Ok, one game (Okami) wants bad timing aparently, so revert this until I know which values it likes.
|
||||
//CPU_INT(6, 4);
|
||||
CPU_INT(6, cycles*BIAS);
|
||||
sif1.end = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Chain mode
|
||||
tDMA_TAG *ptag;
|
||||
|
||||
// Process DMA tag at sif1dma->tadr
|
||||
done = false;
|
||||
ptag = safeDmaGetAddr(sif1dma, sif1dma->tadr, DMAC_SIF1);
|
||||
if (ptag == NULL) return;
|
||||
|
||||
sif1dma->unsafeTransfer(ptag);
|
||||
|
||||
if (sif1dma->chcr.TTE)
|
||||
{
|
||||
Console.WriteLn("SIF1 TTE");
|
||||
sif1.fifo.write((u32*)ptag + 2, 2);
|
||||
}
|
||||
|
||||
if (sif1dma->chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
Console.WriteLn("SIF1 TIE");
|
||||
sif1.end = 1;
|
||||
}
|
||||
|
||||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_REFE: // refe
|
||||
SIF_LOG(" REFE %08X", ptag[1]._u32);
|
||||
sif1.end = 1;
|
||||
sif1dma->madr = ptag[1]._u32;
|
||||
sif1dma->tadr += 16;
|
||||
break;
|
||||
|
||||
case TAG_CNT: // cnt
|
||||
SIF_LOG(" CNT");
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
|
||||
break;
|
||||
|
||||
case TAG_NEXT: // next
|
||||
SIF_LOG(" NEXT %08X", ptag[1]._u32);
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = ptag[1]._u32;
|
||||
break;
|
||||
|
||||
case TAG_REF: // ref
|
||||
case TAG_REFS: // refs
|
||||
SIF_LOG(" REF %08X", ptag[1]._u32);
|
||||
sif1dma->madr = ptag[1]._u32;
|
||||
sif1dma->tadr += 16;
|
||||
break;
|
||||
|
||||
case TAG_END: // end
|
||||
SIF_LOG(" END");
|
||||
sif1.end = 1;
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.WriteLn("Bad addr1 source chain");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There's some data ready to transfer into the fifo..
|
||||
int qwTransfer = sif1dma->qwc;
|
||||
tDMA_TAG *pTag;
|
||||
|
||||
pTag = safeDmaGetAddr(sif1dma, sif1dma->madr, DMAC_SIF1);
|
||||
if (pTag == NULL) return;
|
||||
|
||||
if (qwTransfer > (FIFO_SIF_W - sif1.fifo.size) / 4) // Copy part of sif1dma into FIFO
|
||||
qwTransfer = (FIFO_SIF_W - sif1.fifo.size) / 4;
|
||||
|
||||
sif1.fifo.write((u32*)pTag, qwTransfer << 2);
|
||||
|
||||
sif1dma->madr += qwTransfer << 4;
|
||||
cycles += qwTransfer; // fixme : BIAS is factored in above
|
||||
sif1dma->qwc -= qwTransfer;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void SIF0IOPDma(int &cycles, int &psxCycles, bool &done)
|
||||
{
|
||||
if (sif0.counter == 0) // If there's no more to transfer
|
||||
{
|
||||
// What this is supposed to do is stop DMA if it is the end of a chain, an interrupt is called, or in normal mode.
|
||||
// It currently doesn't check for normal mode.
|
||||
//
|
||||
// The old code for this was:
|
||||
// if (sif0.sifData.data & 0xC0000000)
|
||||
// which checks if the tag type is refe or end, or if the irq flag is set.
|
||||
// If the tag is refe or end, sif0.end gets set, so I'm replacing it with something easier to read: --arcum42
|
||||
if (/*(sif0dma->chcr.MOD == NORMAL_MODE) ||*/ sif0.end || DMA_TAG(sif0.data.data).IRQ)
|
||||
{
|
||||
SIF_LOG(" IOP SIF Stopped");
|
||||
|
||||
// Stop & signal interrupts on IOP
|
||||
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);
|
||||
PSX_INT(IopEvt_SIF0, psxCycles);
|
||||
|
||||
sif0.data.data = 0;
|
||||
done = true;
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
else // There's some data ready to transfer into the fifo..
|
||||
{
|
||||
int wTransfer = min(sif0.counter, FIFO_SIF_W - sif0.fifo.size); // HW_DMA9_BCR >> 16;
|
||||
|
||||
SIF_LOG("+++++++++++ %lX of %lX", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/);
|
||||
|
||||
sif0.fifo.write((u32*)iopPhysMem(HW_DMA9_MADR), wTransfer);
|
||||
HW_DMA9_MADR += wTransfer << 2;
|
||||
psxCycles += (wTransfer / 4) * BIAS; // fixme : should be / 16
|
||||
sif0.counter -= wTransfer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__forceinline void SIF1IOPDma(int &cycles, int &psxCycles, bool &done)
|
||||
{
|
||||
int size = sif1.counter;
|
||||
|
||||
if (size > 0) // If we're reading something, continue to do so.
|
||||
{
|
||||
int readSize = size;
|
||||
|
||||
if (readSize > sif1.fifo.size) readSize = sif1.fifo.size;
|
||||
|
||||
SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
|
||||
|
||||
sif1.fifo.read((u32*)iopPhysMem(HW_DMA10_MADR), readSize);
|
||||
psxCpu->Clear(HW_DMA10_MADR, readSize);
|
||||
psxCycles += readSize / 4; // fixme: should be / 16
|
||||
sif1.counter = size - readSize;
|
||||
HW_DMA10_MADR += readSize << 2;
|
||||
}
|
||||
|
||||
if (sif1.counter <= 0)
|
||||
{
|
||||
if ((sif1.tagMode & 0x80) || (sif1.tagMode & 0x40)) // Stop on tag IRQ or END
|
||||
{
|
||||
if (sif1.tagMode & 0x40)
|
||||
SIF_LOG(" IOP SIF end");
|
||||
else
|
||||
SIF_LOG(" IOP SIF interrupt");
|
||||
|
||||
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...
|
||||
PSX_INT(IopEvt_SIF1, min ( (psxCycles * 24), 1024) );
|
||||
sif1.tagMode = 0;
|
||||
done = true;
|
||||
}
|
||||
else if (sif1.fifo.size >= 4) // Read a tag
|
||||
{
|
||||
struct sifData d;
|
||||
sif1.fifo.read((u32*)&d, 4);
|
||||
SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d", d.data & 0xffffff, d.words, DMA_TAG(d.data).ID, DMA_TAG(d.data).IRQ);
|
||||
HW_DMA10_MADR = d.data & 0xffffff;
|
||||
sif1.counter = d.words;
|
||||
sif1.tagMode = (d.data >> 24) & 0xFF;
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void SIF0Dma()
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
bool done = false;
|
||||
int cycles = 0, psxCycles = 0;
|
||||
|
||||
|
@ -46,146 +342,16 @@ __forceinline void SIF0Dma()
|
|||
|
||||
do
|
||||
{
|
||||
if (iopsifbusy[0]) // If EE SIF0 is enabled
|
||||
if (iopsifbusy[0])
|
||||
{
|
||||
if (sif0.counter == 0) // If there's no more to transfer
|
||||
{
|
||||
// What this is supposed to do is stop DMA if it is the end of a chain, an interrupt is called, or in normal mode.
|
||||
// It currently doesn't check for normal mode.
|
||||
//
|
||||
// The old code for this was:
|
||||
// if (sif0.sifData.data & 0xC0000000)
|
||||
// which checks if the tag type is refe or end, or if the irq flag is set.
|
||||
// If the tag is refe or end, sif0.end gets set, so I'm replacing it with something easier to read: --arcum42
|
||||
if (/*(sif0dma->chcr.MOD == NORMAL_MODE) ||*/ sif0.end || DMA_TAG(sif0.sifData.data).IRQ)
|
||||
{
|
||||
SIF_LOG(" IOP SIF Stopped");
|
||||
|
||||
// Stop & signal interrupts on IOP
|
||||
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);
|
||||
PSX_INT(IopEvt_SIF0, psxCycles);
|
||||
|
||||
sif0.sifData.data = 0;
|
||||
done = true;
|
||||
}
|
||||
else // Chain mode
|
||||
{
|
||||
// Process DMA tag at HW_DMA9_TADR
|
||||
sif0.sifData = *(sifData *)iopPhysMem(HW_DMA9_TADR);
|
||||
|
||||
sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4.
|
||||
|
||||
//SIF0write((u32*)iopPhysMem(HW_DMA9_TADR + 8), 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.sifData.data & 0xFFFFFF;
|
||||
sif0.counter = sif0.sifData.words & 0xFFFFFF;
|
||||
|
||||
SIF_LOG(" SIF0 Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", HW_DMA9_MADR, HW_DMA9_TADR, sif0.counter, sif0.sifData.words, sif0.sifData.data);
|
||||
|
||||
u32 tagId = DMA_TAG(sif0.sifData.data).ID;
|
||||
if ((tagId == TAG_REFE) || (tagId == TAG_END))
|
||||
SIF_LOG(" END");
|
||||
else
|
||||
SIF_LOG(" CNT %08X, %08X", sif0.sifData.data, sif0.sifData.words);
|
||||
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
else // There's some data ready to transfer into the fifo..
|
||||
{
|
||||
int wTransfer = min(sif0.counter, FIFO_SIF_W - sif0.fifo.size); // HW_DMA9_BCR >> 16;
|
||||
|
||||
SIF_LOG("+++++++++++ %lX of %lX", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/);
|
||||
|
||||
sif0.fifo.write((u32*)iopPhysMem(HW_DMA9_MADR), wTransfer);
|
||||
HW_DMA9_MADR += wTransfer << 2;
|
||||
psxCycles += (wTransfer / 4) * BIAS; // fixme : should be / 16
|
||||
sif0.counter -= wTransfer;
|
||||
}
|
||||
// If EE SIF0 is enabled.
|
||||
SIF0IOPDma(cycles, psxCycles, done);
|
||||
}
|
||||
|
||||
if (eesifbusy[0]) // If EE SIF enabled and there's something to transfer
|
||||
if (eesifbusy[0])
|
||||
{
|
||||
int size = sif0dma->qwc;
|
||||
if (dmacRegs->ctrl.STS == STS_SIF0)
|
||||
{
|
||||
SIF_LOG("SIF0 stall control");
|
||||
}
|
||||
if (size > 0) // If we're reading something continue to do so
|
||||
{
|
||||
int readSize = min(size, (sif0.fifo.size >> 2));
|
||||
|
||||
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
|
||||
SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2);
|
||||
|
||||
ptag = safeDmaGetAddr(sif0dma, sif0dma->madr, DMAC_SIF0);
|
||||
if (ptag == NULL) return;
|
||||
|
||||
sif0.fifo.read((u32*)ptag, readSize << 2);
|
||||
|
||||
// Clearing handled by vtlb memory protection and manual blocks.
|
||||
//Cpu->Clear(sif0dma->madr, readSize*4);
|
||||
|
||||
cycles += readSize; // fixme : BIAS is factored in below
|
||||
sif0dma->qwc -= readSize;
|
||||
sif0dma->madr += readSize << 4;
|
||||
}
|
||||
|
||||
if (sif0dma->qwc == 0)
|
||||
{
|
||||
// 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 && DMA_TAG(sif0dma->chcr._u32).IRQ) || sif0.end)
|
||||
{
|
||||
if (sif0.end)
|
||||
SIF_LOG(" EE SIF end");
|
||||
else
|
||||
SIF_LOG(" EE SIF interrupt");
|
||||
|
||||
CPU_INT(5, cycles*BIAS);
|
||||
eesifbusy[0] = false;
|
||||
done = true;
|
||||
}
|
||||
else if (sif0.fifo.size >= 4) // Read a tag
|
||||
{
|
||||
static __aligned16 u32 tag[4];
|
||||
|
||||
sif0.fifo.read((u32*)&tag[0], 4); // Tag
|
||||
SIF_LOG(" EE SIF read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
|
||||
|
||||
sif0dma->unsafeTransfer(((tDMA_TAG*)(tag)));
|
||||
sif0dma->madr = tag[1];
|
||||
|
||||
SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)", sif0dma->madr, sif0dma->qwc, (tag[0] >> 28)&3, (tag[0] >> 31)&1, tag[1], tag[0]);
|
||||
|
||||
switch (DMA_TAG(tag[0]).ID)
|
||||
{
|
||||
case TAG_REFE:
|
||||
sif0.end = 1;
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_REFS:
|
||||
if (dmacRegs->ctrl.STS != NO_STS)
|
||||
dmacRegs->stadr.ADDR = sif0dma->madr + (sif0dma->qwc * 16);
|
||||
break;
|
||||
|
||||
case TAG_END:
|
||||
sif0.end = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
//sif0.chain = 1;
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
// If EE SIF enabled and there's something to transfer.
|
||||
SIF0EEDma(cycles, psxCycles, done);
|
||||
}
|
||||
}
|
||||
while (!done);
|
||||
|
@ -193,163 +359,20 @@ __forceinline void SIF0Dma()
|
|||
|
||||
__forceinline void SIF1Dma()
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
bool done = FALSE;
|
||||
bool done = false;
|
||||
int cycles = 0, psxCycles = 0;
|
||||
do
|
||||
{
|
||||
if (eesifbusy[1]) // If EE SIF1 is enabled
|
||||
if (eesifbusy[1])
|
||||
{
|
||||
if (dmacRegs->ctrl.STD == STD_SIF1)
|
||||
{
|
||||
SIF_LOG("SIF1 stall control"); // STD == fromSIF1
|
||||
}
|
||||
|
||||
if (sif1dma->qwc == 0) // If there's no more to transfer
|
||||
{
|
||||
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA
|
||||
{
|
||||
// Stop & signal interrupts on EE
|
||||
SIF_LOG("EE SIF1 End %x", sif1.end);
|
||||
eesifbusy[1] = false;
|
||||
done = true;
|
||||
// Voodoocycles : 4 cycles always, stops games from throwing double interrupts.
|
||||
// Edit: Ok, one game (Okami) wants bad timing aparently, so revert this until I know which values it likes.
|
||||
//CPU_INT(6, 4);
|
||||
CPU_INT(6, cycles*BIAS);
|
||||
//sif1.chain = 0;
|
||||
sif1.end = 0;
|
||||
}
|
||||
else // Chain mode
|
||||
{
|
||||
// Process DMA tag at sif1dma->tadr
|
||||
done = false;
|
||||
ptag = safeDmaGetAddr(sif1dma, sif1dma->tadr, DMAC_SIF1);
|
||||
if (ptag == NULL) return;
|
||||
|
||||
sif1dma->unsafeTransfer(ptag);
|
||||
|
||||
if (sif1dma->chcr.TTE)
|
||||
{
|
||||
Console.WriteLn("SIF1 TTE");
|
||||
sif1.fifo.write((u32*)ptag + 2, 2);
|
||||
}
|
||||
|
||||
if (sif1dma->chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
Console.WriteLn("SIF1 TIE");
|
||||
sif1.end = 1;
|
||||
}
|
||||
//sif1.chain = 1;
|
||||
|
||||
switch (ptag->ID)
|
||||
{
|
||||
case TAG_REFE: // refe
|
||||
SIF_LOG(" REFE %08X", ptag[1]._u32);
|
||||
sif1.end = 1;
|
||||
sif1dma->madr = ptag[1]._u32;
|
||||
sif1dma->tadr += 16;
|
||||
break;
|
||||
|
||||
case TAG_CNT: // cnt
|
||||
SIF_LOG(" CNT");
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
|
||||
break;
|
||||
|
||||
case TAG_NEXT: // next
|
||||
SIF_LOG(" NEXT %08X", ptag[1]._u32);
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = ptag[1]._u32;
|
||||
break;
|
||||
|
||||
case TAG_REF: // ref
|
||||
case TAG_REFS: // refs
|
||||
SIF_LOG(" REF %08X", ptag[1]._u32);
|
||||
sif1dma->madr = ptag[1]._u32;
|
||||
sif1dma->tadr += 16;
|
||||
break;
|
||||
|
||||
case TAG_END: // end
|
||||
SIF_LOG(" END");
|
||||
sif1.end = 1;
|
||||
sif1dma->madr = sif1dma->tadr + 16;
|
||||
sif1dma->tadr = sif1dma->madr + (sif1dma->qwc << 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
Console.WriteLn("Bad addr1 source chain");
|
||||
}
|
||||
}
|
||||
}
|
||||
else // There's some data ready to transfer into the fifo..
|
||||
{
|
||||
int qwTransfer = sif1dma->qwc;
|
||||
tDMA_TAG *data;
|
||||
|
||||
data = safeDmaGetAddr(sif1dma, sif1dma->madr, DMAC_SIF1);
|
||||
if (data == NULL) return;
|
||||
|
||||
if (qwTransfer > (FIFO_SIF_W - sif1.fifo.size) / 4) // Copy part of sif1dma into FIFO
|
||||
qwTransfer = (FIFO_SIF_W - sif1.fifo.size) / 4;
|
||||
|
||||
sif1.fifo.write((u32*)data, qwTransfer << 2);
|
||||
|
||||
sif1dma->madr += qwTransfer << 4;
|
||||
cycles += qwTransfer; // fixme : BIAS is factored in above
|
||||
sif1dma->qwc -= qwTransfer;
|
||||
}
|
||||
// If EE SIF1 is enabled.
|
||||
SIF1EEDma(cycles, psxCycles, done);
|
||||
}
|
||||
|
||||
if (iopsifbusy[1]) // If IOP SIF enabled and there's something to transfer
|
||||
if (iopsifbusy[1])
|
||||
{
|
||||
int size = sif1.counter;
|
||||
|
||||
if (size > 0) // If we're reading something, continue to do so.
|
||||
{
|
||||
int readSize = size;
|
||||
|
||||
if (readSize > sif1.fifo.size) readSize = sif1.fifo.size;
|
||||
|
||||
SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
|
||||
|
||||
sif1.fifo.read((u32*)iopPhysMem(HW_DMA10_MADR), readSize);
|
||||
psxCpu->Clear(HW_DMA10_MADR, readSize);
|
||||
psxCycles += readSize / 4; // fixme: should be / 16
|
||||
sif1.counter = size - readSize;
|
||||
HW_DMA10_MADR += readSize << 2;
|
||||
}
|
||||
|
||||
if (sif1.counter <= 0)
|
||||
{
|
||||
if ((sif1.tagMode & 0x80) || (sif1.tagMode & 0x40)) // Stop on tag IRQ or END
|
||||
{
|
||||
if (sif1.tagMode & 0x40)
|
||||
SIF_LOG(" IOP SIF end");
|
||||
else
|
||||
SIF_LOG(" IOP SIF interrupt");
|
||||
|
||||
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...
|
||||
PSX_INT(IopEvt_SIF1, min ( (psxCycles * 24), 1024) );
|
||||
sif1.tagMode = 0;
|
||||
done = true;
|
||||
}
|
||||
else if (sif1.fifo.size >= 4) // Read a tag
|
||||
{
|
||||
struct sifData d;
|
||||
sif1.fifo.read((u32*)&d, 4);
|
||||
SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d", d.data & 0xffffff, d.words, DMA_TAG(d.data).ID, DMA_TAG(d.data).IRQ);
|
||||
HW_DMA10_MADR = d.data & 0xffffff;
|
||||
sif1.counter = d.words;
|
||||
sif1.tagMode = (d.data >> 24) & 0xFF;
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
// If IOP SIF enabled and there's something to transfer.
|
||||
SIF1IOPDma(cycles, psxCycles, done);
|
||||
}
|
||||
}
|
||||
while (!done);
|
||||
|
|
|
@ -67,7 +67,7 @@ struct _sif
|
|||
s32 end;
|
||||
s32 tagMode;
|
||||
s32 counter;
|
||||
struct sifData sifData;
|
||||
struct sifData data;
|
||||
};
|
||||
extern DMACh *sif0ch, *sif1ch, *sif2ch;
|
||||
|
||||
|
|
Loading…
Reference in New Issue