diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt
index cdd6361b55..9f4b3cdf72 100644
--- a/pcsx2/CMakeLists.txt
+++ b/pcsx2/CMakeLists.txt
@@ -159,6 +159,8 @@ set(pcsx2Sources
SaveState.cpp
ShiftJisToUnicode.cpp
Sif.cpp
+ Sif0.cpp
+ Sif1.cpp
Sio.cpp
SourceLog.cpp
SPR.cpp
diff --git a/pcsx2/Linux/pcsx2.cbp b/pcsx2/Linux/pcsx2.cbp
index 5487cce122..5b4f680f78 100644
--- a/pcsx2/Linux/pcsx2.cbp
+++ b/pcsx2/Linux/pcsx2.cbp
@@ -295,6 +295,8 @@
+
+
diff --git a/pcsx2/Sif.cpp b/pcsx2/Sif.cpp
index 8e1092095a..6da6f154ba 100644
--- a/pcsx2/Sif.cpp
+++ b/pcsx2/Sif.cpp
@@ -20,7 +20,7 @@
#include "IopCommon.h"
#include "Sif.h"
-static _sif sif0, sif1;
+_sif sif0, sif1;
bool eesifbusy[2] = { false, false };
extern bool iopsifbusy[2];
@@ -33,579 +33,6 @@ void sifInit()
memzero(iopsifbusy);
}
-// Various read/write functions. Could probably be reduced.
-static __forceinline bool SifEERead(int &cycles)
-{
- const int readSize = min((s32)sif0dma->qwc, sif0.fifo.size >> 2);
- //if (readSize <= 0)
- //{
- tDMA_TAG *ptag;
-
- //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
- SIF_LOG("----------- %lX of %lX", readSize << 2, sif0dma->qwc << 2);
-
- ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0);
- if (ptag == NULL)
- {
- DevCon.Warning("SIFEERead: ptag == NULL");
- return false;
- }
-
- sif0.fifo.read((u32*)ptag, readSize << 2);
-
- // Clearing handled by vtlb memory protection and manual blocks.
- //Cpu->Clear(sif0dma->madr, readSize*4);
-
- sif0dma->madr += readSize << 4;
- cycles += readSize; // fixme : BIAS is factored in above
- sif0dma->qwc -= readSize;
- //}
- //else
- //{
- //DevCon.Warning("SifEERead readSize is 0");
- // return false;
- //}
- return true;
-}
-
-static __forceinline bool SifEEWrite(int &cycles)
-{
- // There's some data ready to transfer into the fifo..
-
- const int writeSize = min((s32)sif1dma->qwc, sif1.fifo.free() >> 2);
- //if (writeSize <= 0)
- //{
- //DevCon.Warning("SifEEWrite writeSize is 0");
- // return false;
- //}
- //else
- //{
- tDMA_TAG *ptag;
-
- ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1);
- if (ptag == NULL)
- {
- DevCon.Warning("SIFEEWrite: ptag == NULL");
- return false;
- }
-
- sif1.fifo.write((u32*)ptag, writeSize << 2);
-
- sif1dma->madr += writeSize << 4;
- cycles += writeSize; // fixme : BIAS is factored in above
- sif1dma->qwc -= writeSize;
- //}
- return true;
-}
-
-static __forceinline bool SifIOPWrite(int &psxCycles)
-{
- // There's some data ready to transfer into the fifo..
- const int writeSize = min(sif0.counter, sif0.fifo.free());
-
- //if (writeSize <= 0)
- //{
- //DevCon.Warning("SifIOPWrite writeSize is 0");
- // return false;
- //}
- //else
- //{
- SIF_LOG("+++++++++++ %lX of %lX", writeSize, sif0.counter);
-
- sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).madr), writeSize);
- hw_dma(9).madr += writeSize << 2;
- psxCycles += (writeSize >> 2) * BIAS; // fixme : should be >> 4
- sif0.counter -= writeSize;
- //}
- return true;
-}
-
-static __forceinline bool SifIOPRead(int &psxCycles)
-{
- // If we're reading something, continue to do so.
- const int readSize = min (sif1.counter, sif1.fifo.size);
- //if (readSize <= 0)
- //{
- //DevCon.Warning("SifIOPRead readSize is 0");
- // return false;
- //}
- //else
- //{
- SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
-
- sif1.fifo.read((u32*)iopPhysMem(hw_dma(10).madr), readSize);
- psxCpu->Clear(hw_dma(10).madr, readSize);
- hw_dma(10).madr += readSize << 2;
- psxCycles += readSize >> 2; // fixme: should be / 16
- sif1.counter -= readSize;
- //}
- return true;
-}
-
-static __forceinline bool SIFEEReadTag()
-{
- 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];
- tDMA_TAG ptag(tag[0]);
-
- SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
- sif0dma->madr, sif0dma->qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
-
- if (sif0dma->chcr.TIE && ptag.IRQ)
- {
- //Console.WriteLn("SIF0 TIE");
- sif0.end = 1;
- }
-
- switch (ptag.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;
- }
- return true;
-}
-
-static __forceinline bool SIFEEWriteTag()
-{
- // Chain mode
- tDMA_TAG *ptag;
-
- // Process DMA tag at sif1dma->tadr
- ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1);
- if (ptag == NULL)
- {
- Console.WriteLn("SIF1EEDma: ptag = NULL");
- return false;
- }
-
- 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");
- }
- return true;
-}
-
-static __forceinline bool SIFIOPWriteTag()
-{
- // Process DMA tag at HW_DMA9_TADR
- sif0.data = *(sifData *)iopPhysMem(hw_dma(9).tadr);
- sif0.data.words = (sif0.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
- sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).tadr + 8), 4);
-
- hw_dma(9).tadr += 16; ///hw_dma(9).madr + 16 + sif0.sifData.words << 2;
- hw_dma(9).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);
-
- return true;
-}
-
-static __forceinline bool SIFIOPReadTag()
-{
- // 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_dma(10).madr = sif1.data.data & 0xffffff;
- sif1.counter = sif1.data.words;
- return true;
-}
-
-static __forceinline void SIF0EEend(int &cycles)
-{
- // Stop & signal interrupts on EE
- sif0.end = 0;
- eesifbusy[0] = false;
- if (cycles == 0) DevCon.Warning("EESIF0cycles = 0"); // No transfer happened
- else CPU_INT(DMAC_SIF0, cycles*BIAS); // Hence no Interrupt
-}
-
-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"); // No transfer happened
- else CPU_INT(DMAC_SIF1, min((int)(cycles*BIAS), 384)); // Hence no Interrupt (fixes Eternal Poison reboot when selecting new game)
-}
-
-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"); // No transfer happened
- else PSX_INT(IopEvt_SIF0, psxCycles); // Hence no Interrupt
-}
-
-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"); // No transfer happened
- else PSX_INT(IopEvt_SIF1, min((psxCycles * 26), 1024)); // Hence no Interrupt
-}
-
-//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)
- {
- if ((sif0dma->chcr.MOD == NORMAL_MODE) || sif0.end)
- {
- done = true;
- SIF0EEend(cycles);
- }
- else if (sif0.fifo.size >= 4) // Read a tag
- {
- done = false;
- SIFEEReadTag();
- }
- }
-
- 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)
- {
- done = true;
- SIF1EEend(cycles);
- }
- else
- {
- done = false;
- if (!SIFEEWriteTag()) return;
- }
- }
- else
- {
- SifEEWrite(cycles);
- }
-}
-
-// Note: Test any changes in this function against Grandia III.
-static __forceinline void SIF0IOPDma(int &psxCycles, bool &done)
-{
- if (sif0.counter <= 0) // If there's no more to transfer
- {
- if (sif0_tag.IRQ || (sif0_tag.ID & 4))
- {
- done = true;
- SIF0IOPend(psxCycles);
- }
- else // Chain mode
- {
- done = false;
- SIFIOPWriteTag();
- }
- }
- else
- {
- SifIOPWrite(psxCycles);
- }
-}
-
-static __forceinline void SIF1IOPDma(int &psxCycles, bool &done)
-{
- if (sif1.counter > 0)
- {
- SifIOPRead(psxCycles);
- }
-
- if (sif1.counter <= 0)
- {
- if (sif1_tag.IRQ || (sif1_tag.ID & 4))
- {
- done = true;
- SIF1IOPend(psxCycles);
- }
- else if (sif1.fifo.size >= 4)
- {
-
- done = false;
- SIFIOPReadTag();
- }
- }
-}
-
-// Tests if iop & ee are busy before the while statement,
-// instead of during it, on the premise that anything that
-// changes the busy state in here also ends the while statement.
-//
-// Mostly works, but breaks the Mana Khemia opening movie.
-// Not sure if it's worth keeping yet.
-//#define NO_BUSY_TEST
-__forceinline void SIF0Dma()
-{
- bool done = false;
- int cycles = 0, psxCycles = 0;
-
- SIF_LOG("SIF0 DMA start...");
-
-#ifdef NO_BUSY_TEST
- if ((iopsifbusy[0]) && (eesifbusy[0]))
- {
- do
- {
- SIF0IOPDma(psxCycles, done);
- SIF0EEDma(cycles, done);
- } while (!done);
- }
- else if (iopsifbusy[0])
- {
- do
- {
- SIF0IOPDma(psxCycles, done);
- } while (!done);
- }
- else
- {
- do
- {
- SIF0EEDma(cycles, done);
- } while (!done);
- }
-#else
- do
- {
- if (iopsifbusy[0]) SIF0IOPDma(psxCycles, done);
- if (eesifbusy[0]) SIF0EEDma(cycles, done);
- } while (!done);
-#endif
-}
-
-__forceinline void SIF1Dma()
-{
- bool done = false;
- int cycles = 0, psxCycles = 0;
-
-#ifdef NO_BUSY_TEST
- if ((iopsifbusy[1]) && (eesifbusy[1]))
- {
- do
- {
- SIF1EEDma(cycles, done);
- SIF1IOPDma(psxCycles, done);
- } while (!done);
- }
- else if (iopsifbusy[1])
- {
- do
- {
- SIF1IOPDma(psxCycles, done);
- } while (!done);
- }
- else
- {
- do
- {
- SIF1EEDma(cycles, done);
- } while (!done);
- }
-#else
- do
- {
- if (eesifbusy[1]) SIF1EEDma(cycles, done);
- if (iopsifbusy[1]) SIF1IOPDma(psxCycles, done);
-
- } while (!done);
-#endif
-}
-
-__forceinline void sif0Interrupt()
-{
- HW_DMA9_CHCR &= ~0x01000000;
- psxDmaInterrupt2(2);
-}
-
-__forceinline void sif1Interrupt()
-{
- HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
- psxDmaInterrupt2(3);
-}
-
-__forceinline void EEsif0Interrupt()
-{
- hwDmacIrq(DMAC_SIF0);
- sif0dma->chcr.STR = false;
-}
-
-__forceinline void EEsif1Interrupt()
-{
- hwDmacIrq(DMAC_SIF1);
- sif1dma->chcr.STR = false;
-}
-
-__forceinline void dmaSIF0()
-{
- SIF_LOG(wxString(L"dmaSIF0" + sif0dma->cmqt_to_str()).To8BitData());
-
- if (sif0.fifo.readPos != sif0.fifo.writePos)
- {
- SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
- }
-
- psHu32(SBUS_F240) |= 0x2000;
- eesifbusy[0] = true;
-
- if (iopsifbusy[0])
- {
- XMMRegisters::Freeze();
- hwIntcIrq(INTC_SBUS);
- SIF0Dma();
- psHu32(SBUS_F240) &= ~0x20;
- psHu32(SBUS_F240) &= ~0x2000;
- XMMRegisters::Thaw();
- }
-}
-
-__forceinline void dmaSIF1()
-{
- SIF_LOG(wxString(L"dmaSIF1" + sif1dma->cmqt_to_str()).To8BitData());
-
- if (sif1.fifo.readPos != sif1.fifo.writePos)
- {
- SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
- }
-
- psHu32(SBUS_F240) |= 0x4000;
- eesifbusy[1] = true;
-
- if (iopsifbusy[1])
- {
- XMMRegisters::Freeze();
- SIF1Dma();
- psHu32(SBUS_F240) &= ~0x40;
- psHu32(SBUS_F240) &= ~0x100;
- psHu32(SBUS_F240) &= ~0x4000;
- XMMRegisters::Thaw();
- }
-
-}
-
__forceinline void dmaSIF2()
{
SIF_LOG(wxString(L"dmaSIF2" + sif2dma->cmq_to_str()).To8BitData());
diff --git a/pcsx2/Sif.h b/pcsx2/Sif.h
index 6487d43fb9..cfbde7c392 100644
--- a/pcsx2/Sif.h
+++ b/pcsx2/Sif.h
@@ -80,6 +80,10 @@ struct _sif
s32 counter;
struct sifData data;
};
+extern _sif sif0, sif1;
+
+extern bool eesifbusy[2];
+extern bool iopsifbusy[2];
extern void sifInit();
diff --git a/pcsx2/Sif0.cpp b/pcsx2/Sif0.cpp
new file mode 100644
index 0000000000..324736ba5e
--- /dev/null
+++ b/pcsx2/Sif0.cpp
@@ -0,0 +1,255 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * 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 .
+ */
+
+#include "PrecompiledHeader.h"
+
+#define _PC_ // disables MIPS opcode macros.
+
+#include "IopCommon.h"
+#include "Sif.h"
+
+static __forceinline bool SifEERead(int &cycles)
+{
+ const int readSize = min((s32)sif0dma->qwc, sif0.fifo.size >> 2);
+ //if (readSize <= 0)
+ //{
+ tDMA_TAG *ptag;
+
+ //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
+ SIF_LOG("----------- %lX of %lX", readSize << 2, sif0dma->qwc << 2);
+
+ ptag = sif0dma->getAddr(sif0dma->madr, DMAC_SIF0);
+ if (ptag == NULL)
+ {
+ DevCon.Warning("SIFEERead: ptag == NULL");
+ return false;
+ }
+
+ sif0.fifo.read((u32*)ptag, readSize << 2);
+
+ // Clearing handled by vtlb memory protection and manual blocks.
+ //Cpu->Clear(sif0dma->madr, readSize*4);
+
+ sif0dma->madr += readSize << 4;
+ cycles += readSize; // fixme : BIAS is factored in above
+ sif0dma->qwc -= readSize;
+ //}
+ //else
+ //{
+ //DevCon.Warning("SifEERead readSize is 0");
+ // return false;
+ //}
+ return true;
+}
+
+static __forceinline bool SifIOPWrite(int &psxCycles)
+{
+ // There's some data ready to transfer into the fifo..
+ const int writeSize = min(sif0.counter, sif0.fifo.free());
+
+ //if (writeSize <= 0)
+ //{
+ //DevCon.Warning("SifIOPWrite writeSize is 0");
+ // return false;
+ //}
+ //else
+ //{
+ SIF_LOG("+++++++++++ %lX of %lX", writeSize, sif0.counter);
+
+ sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).madr), writeSize);
+ hw_dma(9).madr += writeSize << 2;
+ psxCycles += (writeSize >> 2) * BIAS; // fixme : should be >> 4
+ sif0.counter -= writeSize;
+ //}
+ return true;
+}
+
+static __forceinline bool SIFEEReadTag()
+{
+ 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];
+ tDMA_TAG ptag(tag[0]);
+
+ SIF_LOG(" EE SIF dest chain tag madr:%08X qwc:%04X id:%X irq:%d(%08X_%08X)",
+ sif0dma->madr, sif0dma->qwc, ptag.ID, ptag.IRQ, tag[1], tag[0]);
+
+ if (sif0dma->chcr.TIE && ptag.IRQ)
+ {
+ //Console.WriteLn("SIF0 TIE");
+ sif0.end = 1;
+ }
+
+ switch (ptag.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;
+ }
+ return true;
+}
+
+static __forceinline bool SIFIOPWriteTag()
+{
+ // Process DMA tag at HW_DMA9_TADR
+ sif0.data = *(sifData *)iopPhysMem(hw_dma(9).tadr);
+ sif0.data.words = (sif0.data.words + 3) & 0xfffffffc; // Round up to nearest 4.
+ sif0.fifo.write((u32*)iopPhysMem(hw_dma(9).tadr + 8), 4);
+
+ hw_dma(9).tadr += 16; ///hw_dma(9).madr + 16 + sif0.sifData.words << 2;
+ hw_dma(9).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);
+
+ return true;
+}
+
+static __forceinline void SIF0EEend(int &cycles)
+{
+ // Stop & signal interrupts on EE
+ sif0.end = 0;
+ eesifbusy[0] = false;
+ if (cycles == 0) DevCon.Warning("EESIF0cycles = 0"); // No transfer happened
+ else CPU_INT(DMAC_SIF0, cycles*BIAS); // Hence no Interrupt
+}
+
+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"); // No transfer happened
+ else PSX_INT(IopEvt_SIF0, psxCycles); // Hence no Interrupt
+}
+
+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)
+ {
+ if ((sif0dma->chcr.MOD == NORMAL_MODE) || sif0.end)
+ {
+ done = true;
+ SIF0EEend(cycles);
+ }
+ else if (sif0.fifo.size >= 4) // Read a tag
+ {
+ done = false;
+ SIFEEReadTag();
+ }
+ }
+
+ if (sif0dma->qwc > 0) // If we're reading something continue to do so
+ {
+ SifEERead(cycles);
+ }
+}
+
+// Note: Test any changes in this function against Grandia III.
+static __forceinline void SIF0IOPDma(int &psxCycles, bool &done)
+{
+ if (sif0.counter <= 0) // If there's no more to transfer
+ {
+ if (sif0_tag.IRQ || (sif0_tag.ID & 4))
+ {
+ done = true;
+ SIF0IOPend(psxCycles);
+ }
+ else // Chain mode
+ {
+ done = false;
+ SIFIOPWriteTag();
+ }
+ }
+ else
+ {
+ SifIOPWrite(psxCycles);
+ }
+}
+
+__forceinline void SIF0Dma()
+{
+ bool done = false;
+ int cycles = 0, psxCycles = 0;
+
+ SIF_LOG("SIF0 DMA start...");
+
+ do
+ {
+ if (iopsifbusy[0]) SIF0IOPDma(psxCycles, done);
+ if (eesifbusy[0]) SIF0EEDma(cycles, done);
+ } while (!done);
+}
+
+__forceinline void sif0Interrupt()
+{
+ HW_DMA9_CHCR &= ~0x01000000;
+ psxDmaInterrupt2(2);
+}
+
+__forceinline void EEsif0Interrupt()
+{
+ hwDmacIrq(DMAC_SIF0);
+ sif0dma->chcr.STR = false;
+}
+
+__forceinline void dmaSIF0()
+{
+ SIF_LOG(wxString(L"dmaSIF0" + sif0dma->cmqt_to_str()).To8BitData());
+
+ if (sif0.fifo.readPos != sif0.fifo.writePos)
+ {
+ SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
+ }
+
+ psHu32(SBUS_F240) |= 0x2000;
+ eesifbusy[0] = true;
+
+ if (iopsifbusy[0])
+ {
+ XMMRegisters::Freeze();
+ hwIntcIrq(INTC_SBUS);
+ SIF0Dma();
+ psHu32(SBUS_F240) &= ~0x20;
+ psHu32(SBUS_F240) &= ~0x2000;
+ XMMRegisters::Thaw();
+ }
+}
diff --git a/pcsx2/Sif1.cpp b/pcsx2/Sif1.cpp
new file mode 100644
index 0000000000..a41e9f1e11
--- /dev/null
+++ b/pcsx2/Sif1.cpp
@@ -0,0 +1,280 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2009 PCSX2 Dev Team
+ *
+ * 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 .
+ */
+
+#include "PrecompiledHeader.h"
+
+#define _PC_ // disables MIPS opcode macros.
+
+#include "IopCommon.h"
+#include "Sif.h"
+
+static __forceinline bool SifEEWrite(int &cycles)
+{
+ // There's some data ready to transfer into the fifo..
+
+ const int writeSize = min((s32)sif1dma->qwc, sif1.fifo.free() >> 2);
+ //if (writeSize <= 0)
+ //{
+ //DevCon.Warning("SifEEWrite writeSize is 0");
+ // return false;
+ //}
+ //else
+ //{
+ tDMA_TAG *ptag;
+
+ ptag = sif1dma->getAddr(sif1dma->madr, DMAC_SIF1);
+ if (ptag == NULL)
+ {
+ DevCon.Warning("SIFEEWrite: ptag == NULL");
+ return false;
+ }
+
+ sif1.fifo.write((u32*)ptag, writeSize << 2);
+
+ sif1dma->madr += writeSize << 4;
+ cycles += writeSize; // fixme : BIAS is factored in above
+ sif1dma->qwc -= writeSize;
+ //}
+ return true;
+}
+
+static __forceinline bool SifIOPRead(int &psxCycles)
+{
+ // If we're reading something, continue to do so.
+ const int readSize = min (sif1.counter, sif1.fifo.size);
+ //if (readSize <= 0)
+ //{
+ //DevCon.Warning("SifIOPRead readSize is 0");
+ // return false;
+ //}
+ //else
+ //{
+ SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
+
+ sif1.fifo.read((u32*)iopPhysMem(hw_dma(10).madr), readSize);
+ psxCpu->Clear(hw_dma(10).madr, readSize);
+ hw_dma(10).madr += readSize << 2;
+ psxCycles += readSize >> 2; // fixme: should be / 16
+ sif1.counter -= readSize;
+ //}
+ return true;
+}
+
+static __forceinline bool SIFEEWriteTag()
+{
+ // Chain mode
+ tDMA_TAG *ptag;
+
+ // Process DMA tag at sif1dma->tadr
+ ptag = sif1dma->DMAtransfer(sif1dma->tadr, DMAC_SIF1);
+ if (ptag == NULL)
+ {
+ Console.WriteLn("SIF1EEDma: ptag = NULL");
+ return false;
+ }
+
+ 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");
+ }
+ return true;
+}
+
+static __forceinline bool SIFIOPReadTag()
+{
+ // 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_dma(10).madr = sif1.data.data & 0xffffff;
+ sif1.counter = sif1.data.words;
+ return true;
+}
+
+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"); // No transfer happened
+ else CPU_INT(DMAC_SIF1, min((int)(cycles*BIAS), 384)); // Hence no Interrupt (fixes Eternal Poison reboot when selecting new game)
+}
+
+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"); // No transfer happened
+ else PSX_INT(IopEvt_SIF1, min((psxCycles * 26), 1024)); // Hence no Interrupt
+}
+
+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)
+ {
+ done = true;
+ SIF1EEend(cycles);
+ }
+ else
+ {
+ done = false;
+ if (!SIFEEWriteTag()) return;
+ }
+ }
+ else
+ {
+ SifEEWrite(cycles);
+ }
+}
+
+static __forceinline void SIF1IOPDma(int &psxCycles, bool &done)
+{
+ if (sif1.counter > 0)
+ {
+ SifIOPRead(psxCycles);
+ }
+
+ if (sif1.counter <= 0)
+ {
+ if (sif1_tag.IRQ || (sif1_tag.ID & 4))
+ {
+ done = true;
+ SIF1IOPend(psxCycles);
+ }
+ else if (sif1.fifo.size >= 4)
+ {
+
+ done = false;
+ SIFIOPReadTag();
+ }
+ }
+}
+
+__forceinline void SIF1Dma()
+{
+ bool done = false;
+ int cycles = 0, psxCycles = 0;
+
+ do
+ {
+ if (eesifbusy[1]) SIF1EEDma(cycles, done);
+ if (iopsifbusy[1]) SIF1IOPDma(psxCycles, done);
+
+ } while (!done);
+}
+
+__forceinline void sif1Interrupt()
+{
+ HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
+ psxDmaInterrupt2(3);
+}
+
+__forceinline void EEsif1Interrupt()
+{
+ hwDmacIrq(DMAC_SIF1);
+ sif1dma->chcr.STR = false;
+}
+
+__forceinline void dmaSIF1()
+{
+ SIF_LOG(wxString(L"dmaSIF1" + sif1dma->cmqt_to_str()).To8BitData());
+
+ if (sif1.fifo.readPos != sif1.fifo.writePos)
+ {
+ SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
+ }
+
+ psHu32(SBUS_F240) |= 0x4000;
+ eesifbusy[1] = true;
+
+ if (iopsifbusy[1])
+ {
+ XMMRegisters::Freeze();
+ SIF1Dma();
+ psHu32(SBUS_F240) &= ~0x40;
+ psHu32(SBUS_F240) &= ~0x100;
+ psHu32(SBUS_F240) &= ~0x4000;
+ XMMRegisters::Thaw();
+ }
+}
diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj b/pcsx2/windows/VCprojects/pcsx2.vcxproj
index 7614c0303c..2fcaa671fb 100644
--- a/pcsx2/windows/VCprojects/pcsx2.vcxproj
+++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj
@@ -222,6 +222,8 @@
+
+
diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index ef69ec5528..ce09808e7e 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -784,6 +784,14 @@
RelativePath="..\..\Sif.cpp"
>
+
+
+
+