Refactor some Sif code.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2472 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2010-01-22 13:00:04 +00:00
parent 14ebc021ad
commit 124f91920e
2 changed files with 313 additions and 290 deletions

View File

@ -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,81 +34,7 @@ void sifInit()
memzero(iopsifbusy);
}
__forceinline void SIF0Dma()
{
tDMA_TAG *ptag;
bool done = false;
int cycles = 0, psxCycles = 0;
SIF_LOG("SIF0 DMA start...");
do
{
if (iopsifbusy[0]) // If EE SIF0 is enabled
{
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 (eesifbusy[0]) // If EE SIF enabled and there's something to transfer
__forceinline void SIF0EEDma(int &cycles, int &psxCycles, bool &done)
{
int size = sif0dma->qwc;
if (dmacRegs->ctrl.STS == STS_SIF0)
@ -119,6 +43,7 @@ __forceinline void SIF0Dma()
}
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);
@ -182,46 +107,40 @@ __forceinline void SIF0Dma()
break;
}
//sif0.chain = 1;
done = false;
}
}
}
}
while (!done);
}
__forceinline void SIF1Dma()
{
tDMA_TAG *ptag;
bool done = FALSE;
int cycles = 0, psxCycles = 0;
do
{
if (eesifbusy[1]) // If EE SIF1 is enabled
__forceinline void SIF1EEDma(int &cycles, int &psxCycles, bool &done)
{
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 there's no more to transfer.
if (sif1dma->qwc == 0)
{
if ((sif1dma->chcr.MOD == NORMAL_MODE) || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA
// 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.chain = 0;
sif1.end = 0;
}
else // Chain mode
else
{
// Chain mode
tDMA_TAG *ptag;
// Process DMA tag at sif1dma->tadr
done = false;
ptag = safeDmaGetAddr(sif1dma, sif1dma->tadr, DMAC_SIF1);
@ -240,7 +159,6 @@ __forceinline void SIF1Dma()
Console.WriteLn("SIF1 TIE");
sif1.end = 1;
}
//sif1.chain = 1;
switch (ptag->ID)
{
@ -282,18 +200,19 @@ __forceinline void SIF1Dma()
}
}
}
else // There's some data ready to transfer into the fifo..
else
{
// There's some data ready to transfer into the fifo..
int qwTransfer = sif1dma->qwc;
tDMA_TAG *data;
tDMA_TAG *pTag;
data = safeDmaGetAddr(sif1dma, sif1dma->madr, DMAC_SIF1);
if (data == NULL) return;
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*)data, qwTransfer << 2);
sif1.fifo.write((u32*)pTag, qwTransfer << 2);
sif1dma->madr += qwTransfer << 4;
cycles += qwTransfer; // fixme : BIAS is factored in above
@ -301,7 +220,69 @@ __forceinline void SIF1Dma()
}
}
if (iopsifbusy[1]) // If IOP SIF enabled and there's something to transfer
__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;
@ -351,6 +332,48 @@ __forceinline void SIF1Dma()
}
}
}
__forceinline void SIF0Dma()
{
bool done = false;
int cycles = 0, psxCycles = 0;
SIF_LOG("SIF0 DMA start...");
do
{
if (iopsifbusy[0])
{
// If EE SIF0 is enabled.
SIF0IOPDma(cycles, psxCycles, done);
}
if (eesifbusy[0])
{
// If EE SIF enabled and there's something to transfer.
SIF0EEDma(cycles, psxCycles, done);
}
}
while (!done);
}
__forceinline void SIF1Dma()
{
bool done = false;
int cycles = 0, psxCycles = 0;
do
{
if (eesifbusy[1])
{
// If EE SIF1 is enabled.
SIF1EEDma(cycles, psxCycles, done);
}
if (iopsifbusy[1])
{
// If IOP SIF enabled and there's something to transfer.
SIF1IOPDma(cycles, psxCycles, done);
}
}
while (!done);
}

View File

@ -67,7 +67,7 @@ struct _sif
s32 end;
s32 tagMode;
s32 counter;
struct sifData sifData;
struct sifData data;
};
extern DMACh *sif0ch, *sif1ch, *sif2ch;