More cleanup. Ran Artistic Vision on a few of the files rama had suggested, and did a few changes that make things easier to read. Still more work to be done here...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@862 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2009-03-30 13:21:15 +00:00
parent fa134fb61b
commit 8a99bf1d63
5 changed files with 2041 additions and 1864 deletions

View File

@ -17,7 +17,6 @@
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "IopCommon.h" #include "IopCommon.h"
using namespace R3000A; using namespace R3000A;
@ -27,21 +26,22 @@ using namespace R3000A;
// Dma8 in PsxSpd.c // Dma8 in PsxSpd.c
// Dma11/12 in PsxSio2.c // Dma11/12 in PsxSio2.c
// Should be a bool, and will be next time I break savestate. --arcum42
int iopsifbusy[2] = { 0, 0 }; int iopsifbusy[2] = { 0, 0 };
static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc, _SPU2readDMA4Mem spu2ReadFunc ) static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc, _SPU2readDMA4Mem spu2ReadFunc)
{ {
const char dmaNum = spuCore ? '7' : '4'; const char dmaNum = spuCore ? '7' : '4';
/*if (chcr & 0x400) DevCon::Status("SPU 2 DMA %c linked list chain mode! chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr); /*if (chcr & 0x400) DevCon::Status("SPU 2 DMA %c linked list chain mode! chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
if (chcr & 0x40000000) DevCon::Notice("SPU 2 DMA %c Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr); if (chcr & 0x40000000) DevCon::Notice("SPU 2 DMA %c Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
if ((chcr & 0x1) == 0) DevCon::Status("SPU 2 DMA %c loading from spu2 memory chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);*/ if ((chcr & 0x1) == 0) DevCon::Status("SPU 2 DMA %c loading from spu2 memory chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);*/
const int size = (bcr >> 16) * (bcr & 0xFFFF); const int size = (bcr >> 16) * (bcr & 0xFFFF);
// Update the spu2 to the current cycle before initiating the DMA // Update the spu2 to the current cycle before initiating the DMA
if(SPU2async) if (SPU2async)
{ {
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
//Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
@ -49,9 +49,9 @@ static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _
psxCounters[6].sCycleT = psxRegs.cycle; psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = size * 3; psxCounters[6].CycleT = size * 3;
psxNextCounter -= (psxRegs.cycle-psxNextsCounter); psxNextCounter -= (psxRegs.cycle - psxNextsCounter);
psxNextsCounter = psxRegs.cycle; psxNextsCounter = psxRegs.cycle;
if(psxCounters[6].CycleT < psxNextCounter) if (psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT; psxNextCounter = psxCounters[6].CycleT;
} }
@ -60,30 +60,30 @@ static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _
case 0x01000201: //cpu to spu2 transfer case 0x01000201: //cpu to spu2 transfer
PSXDMA_LOG("*** DMA %c - mem2spu *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr); PSXDMA_LOG("*** DMA %c - mem2spu *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr);
spu2WriteFunc((u16 *)iopPhysMem(madr), size*2); spu2WriteFunc((u16 *)iopPhysMem(madr), size*2);
break; break;
case 0x01000200: //spu2 to cpu transfer case 0x01000200: //spu2 to cpu transfer
PSXDMA_LOG("*** DMA %c - spu2mem *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr); PSXDMA_LOG("*** DMA %c - spu2mem *** %x addr = %x size = %x", dmaNum, chcr, madr, bcr);
spu2ReadFunc((u16 *)iopPhysMem(madr), size*2); spu2ReadFunc((u16 *)iopPhysMem(madr), size*2);
psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size); psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size);
break; break;
default: default:
Console::Error("*** DMA %c - SPU unknown *** %x addr = %x size = %x", params dmaNum, chcr, madr, bcr); Console::Error("*** DMA %c - SPU unknown *** %x addr = %x size = %x", params dmaNum, chcr, madr, bcr);
break; break;
} }
} }
void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0 void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0
{ {
psxDmaGeneric( madr, bcr, chcr, 0, SPU2writeDMA4Mem, SPU2readDMA4Mem ); psxDmaGeneric(madr, bcr, chcr, 0, SPU2writeDMA4Mem, SPU2readDMA4Mem);
} }
int psxDma4Interrupt() int psxDma4Interrupt()
{ {
HW_DMA4_CHCR &= ~0x01000000; HW_DMA4_CHCR &= ~0x01000000;
psxDmaInterrupt(4); psxDmaInterrupt(4);
iopIntcIrq( 9 ); iopIntcIrq(9);
return 1; return 1;
} }
@ -99,13 +99,18 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr)
PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx", chcr, madr, bcr); PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx", chcr, madr, bcr);
if (chcr == 0x11000002) { if (chcr == 0x11000002)
while (bcr--) { {
while (bcr--)
{
*mem-- = (madr - 4) & 0xffffff; *mem-- = (madr - 4) & 0xffffff;
madr -= 4; madr -= 4;
} }
mem++; *mem = 0xffffff; mem++;
} else { *mem = 0xffffff;
}
else
{
// Unknown option // Unknown option
PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr); PSXDMA_LOG("*** DMA 6 - OT unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
} }
@ -115,14 +120,13 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr)
void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1 void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1
{ {
psxDmaGeneric( madr, bcr, chcr, 1, SPU2writeDMA7Mem, SPU2readDMA7Mem ); psxDmaGeneric(madr, bcr, chcr, 1, SPU2writeDMA7Mem, SPU2readDMA7Mem);
} }
int psxDma7Interrupt() int psxDma7Interrupt()
{ {
HW_DMA7_CHCR &= ~0x01000000; HW_DMA7_CHCR &= ~0x01000000;
psxDmaInterrupt2(0); psxDmaInterrupt2(0);
//iopIntcIrq( 9 );
return 1; return 1;
} }
@ -134,20 +138,23 @@ void psxDma9(u32 madr, u32 bcr, u32 chcr)
iopsifbusy[0] = 1; iopsifbusy[0] = 1;
psHu32(0x1000F240) |= 0x2000; psHu32(0x1000F240) |= 0x2000;
if (eesifbusy[0] == 1) { if (eesifbusy[0] == 1)
{
SIF0Dma(); SIF0Dma();
psHu32(0x1000F240) &= ~0x20; psHu32(0x1000F240) &= ~0x20;
psHu32(0x1000F240) &= ~0x2000; psHu32(0x1000F240) &= ~0x2000;
} }
} }
void psxDma10(u32 madr, u32 bcr, u32 chcr) { void psxDma10(u32 madr, u32 bcr, u32 chcr)
{
SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx", chcr, madr, bcr); SIF_LOG("IOP: dmaSIF1 chcr = %lx, madr = %lx, bcr = %lx", chcr, madr, bcr);
iopsifbusy[1] = 1; iopsifbusy[1] = 1;
psHu32(0x1000F240) |= 0x4000; psHu32(0x1000F240) |= 0x4000;
if (eesifbusy[1] == 1) { if (eesifbusy[1] == 1)
{
FreezeXMMRegs(1); FreezeXMMRegs(1);
SIF1Dma(); SIF1Dma();
psHu32(0x1000F240) &= ~0x40; psHu32(0x1000F240) &= ~0x40;
@ -157,80 +164,86 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) {
} }
} }
void psxDma8(u32 madr, u32 bcr, u32 chcr) { void psxDma8(u32 madr, u32 bcr, u32 chcr)
{
const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8; const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
switch (chcr & 0x01000201) { switch (chcr & 0x01000201)
{
case 0x01000201: //cpu to dev9 transfer case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr); PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size); DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size);
break; break;
case 0x01000200: //dev9 to cpu transfer case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr); PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9readDMA8Mem((u32*)iopPhysMem(madr), size); DEV9readDMA8Mem((u32*)iopPhysMem(madr), size);
break; break;
default: default:
PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr); PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr);
break; break;
} }
HW_DMA8_CHCR &= ~0x01000000; HW_DMA8_CHCR &= ~0x01000000;
psxDmaInterrupt2(1); psxDmaInterrupt2(1);
} }
void dev9Interrupt() { void dev9Interrupt()
if( (dev9Handler != NULL) && (dev9Handler() != 1) ) {
return; if ((dev9Handler != NULL) && (dev9Handler() != 1)) return;
iopIntcIrq( 13 ); iopIntcIrq(13);
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
void dev9Irq(int cycles) { void dev9Irq(int cycles)
{
PSX_INT(IopEvt_DEV9, cycles); PSX_INT(IopEvt_DEV9, cycles);
} }
void usbInterrupt() { void usbInterrupt()
if( usbHandler != NULL && (usbHandler() != 1) ) {
return; if (usbHandler != NULL && (usbHandler() != 1)) return;
iopIntcIrq( 22 ); iopIntcIrq(22);
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
void usbIrq(int cycles) { void usbIrq(int cycles)
{
PSX_INT(IopEvt_USB, cycles); PSX_INT(IopEvt_USB, cycles);
} }
void fwIrq() { void fwIrq()
iopIntcIrq( 24 ); {
iopIntcIrq(24);
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
void spu2DMA4Irq() { void spu2DMA4Irq()
{
SPU2interruptDMA4(); SPU2interruptDMA4();
//HW_DMA4_BCR = 0;
HW_DMA4_CHCR &= ~0x01000000; HW_DMA4_CHCR &= ~0x01000000;
psxDmaInterrupt(4); psxDmaInterrupt(4);
} }
void spu2DMA7Irq() { void spu2DMA7Irq()
{
SPU2interruptDMA7(); SPU2interruptDMA7();
//HW_DMA7_BCR = 0;
HW_DMA7_CHCR &= ~0x01000000; HW_DMA7_CHCR &= ~0x01000000;
psxDmaInterrupt2(0); psxDmaInterrupt2(0);
} }
void spu2Irq() { void spu2Irq()
iopIntcIrq( 9 ); {
iopIntcIrq(9);
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
} }
void iopIntcIrq( uint irqType ) void iopIntcIrq(uint irqType)
{ {
psxHu32(0x1070)|= 1<<irqType; psxHu32(0x1070) |= 1 << irqType;
iopTestIntc(); iopTestIntc();
} }
@ -238,21 +251,25 @@ void iopIntcIrq( uint irqType )
// //
// Gigaherz's "Improved DMA Handling" Engine WIP... // Gigaherz's "Improved DMA Handling" Engine WIP...
// //
// fixme: Is this in progress?
#if FALSE #if FALSE
typedef s32 (* DmaHandler) (s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); typedef s32(* DmaHandler)(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
typedef void (* DmaIHandler)(s32 channel); typedef void (* DmaIHandler)(s32 channel);
s32 errDmaWrite (s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
s32 errDmaRead (s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed);
struct DmaHandlerInfo { struct DmaHandlerInfo
{
DmaHandler Read; DmaHandler Read;
DmaHandler Write; DmaHandler Write;
DmaIHandler Interrupt; DmaIHandler Interrupt;
}; };
struct DmaStatusInfo { struct DmaStatusInfo
{
u32 Control; u32 Control;
u32 Width; // bytes/word, for timing purposes u32 Width; // bytes/word, for timing purposes
u32 MemAddr; u32 MemAddr;
@ -268,7 +285,8 @@ struct DmaStatusInfo {
DmaStatusInfo IopChannels[DMA_CHANNEL_MAX]; // I dont' knwo how many there are, 10? DmaStatusInfo IopChannels[DMA_CHANNEL_MAX]; // I dont' knwo how many there are, 10?
DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] = { DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] =
{
{0}, //0 {0}, //0
{0}, //1 {0}, //1
{0}, //2 {0}, //2
@ -284,7 +302,8 @@ DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] = {
{0}, // Sio2 {0}, // Sio2
}; };
const char* IopDmaNames[DMA_CHANNEL_MAX] = { const char* IopDmaNames[DMA_CHANNEL_MAX] =
{
"Ps1 Mdec", "Ps1 Mdec",
"Ps1 Mdec", "Ps1 Mdec",
"Ps1 Gpu", "Ps1 Gpu",
@ -298,7 +317,8 @@ const char* IopDmaNames[DMA_CHANNEL_MAX] = {
"Sif1", //10: SIF1 "Sif1", //10: SIF1
"Sio2",//... "Sio2",//...
"Sio2", "Sio2",
"?","?","?"}; "?", "?", "?"
};
}; };
// Prototypes. To be implemented later (or in other parts of the emulator) // Prototypes. To be implemented later (or in other parts of the emulator)
@ -320,16 +340,16 @@ void IopDmaUpdate(u32 elapsed)
{ {
u32 MinDelay = 0xFFFFFFFF; u32 MinDelay = 0xFFFFFFFF;
for(int i=0;i<DMA_CHANNEL_MAX;i++) for (int i = 0;i < DMA_CHANNEL_MAX;i++)
{ {
DmaStatusInfo *ch = IopChannels+i; DmaStatusInfo *ch = IopChannels + i;
if(ch->Control&DMA_CTRL_ACTIVE) if (ch->Control&DMA_CTRL_ACTIVE)
{ {
ch->Target-=elapsed; ch->Target -= elapsed;
if(ch->Target<=0) if (ch->Target <= 0)
{ {
if(ch->ByteCount<=0) if (ch->ByteCount <= 0)
{ {
ch->Control &= ~DMA_CTRL_ACTIVE; ch->Control &= ~DMA_CTRL_ACTIVE;
RaiseDmaIrq(i); RaiseDmaIrq(i);
@ -338,17 +358,17 @@ void IopDmaUpdate(u32 elapsed)
else else
{ {
// TODO: Make sure it's the right order // TODO: Make sure it's the right order
DmaHandler handler = (ch->Control&DMA_CTRL_DIRECTION)?IopDmaHandlers[i].Read:IopDmaHandlers[i].Write; DmaHandler handler = (ch->Control & DMA_CTRL_DIRECTION) ? IopDmaHandlers[i].Read : IopDmaHandlers[i].Write;
u32 BCount = 0; u32 BCount = 0;
s32 Target = (handler)?handler(i,(u32*)PSXM(ch->MemAddr),ch->ByteCount,&BCount):0; s32 Target = (handler) ? handler(i, (u32*)PSXM(ch->MemAddr), ch->ByteCount, &BCount) : 0;
ch->Target = 100; ch->Target = 100;
if(Target<0) if (Target < 0)
{ {
// TODO: ... What to do if the plugin errors? :P // TODO: ... What to do if the plugin errors? :P
} }
else if(BCount!=0) else if (BCount != 0)
{ {
ch->MemAddr += BCount; ch->MemAddr += BCount;
ch->ByteCount -= BCount; ch->ByteCount -= BCount;
@ -356,24 +376,24 @@ void IopDmaUpdate(u32 elapsed)
ch->Target = BCount / ch->Width; ch->Target = BCount / ch->Width;
} }
if (Target!=0) ch->Target=Target; if (Target != 0) ch->Target = Target;
} }
} }
} }
} }
} }
s32 errDmaRead (s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed)
{ {
Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.",0,channel,IopDmaNames[channel]); Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]);
*wordsProcessed = wordsLeft; *wordsProcessed = wordsLeft;
return 0; return 0;
} }
s32 errDmaWrite (s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed)
{ {
Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.",0,channel,IopDmaNames[channel]); Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]);
*wordsProcessed = wordsLeft; *wordsProcessed = wordsLeft;
return 0; return 0;

View File

@ -25,63 +25,58 @@
#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) #define spr0 ((DMACh*)&PS2MEM_HW[0xD000])
#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) #define spr1 ((DMACh*)&PS2MEM_HW[0xD400])
#define gif ((DMACh*)&PS2MEM_HW[0xA000])
extern void mfifoGIFtransfer(int);
/* Both of these should be bools. Again, next savestate break. --arcum42 */
static int spr0finished = 0; static int spr0finished = 0;
static int spr1finished = 0; static int spr1finished = 0;
static u32 mfifotransferred = 0; static u32 mfifotransferred = 0;
void sprInit() { void sprInit()
{
} }
//__forceinline static void SPR0transfer(u32 *data, int size) {
///* while (size > 0) {
// SPR_LOG("SPR1transfer: %x", *data);
// data++; size--;
// }*/
// size <<= 2;
// if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO
// (psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO
// hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size);
// } else {
// u32 * p = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff];
// //WriteCodeSSE2(p,data,size >> 4);
// memcpy_fast((u8*)data, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], size);
// }
// spr0->sadr+= size;
//}
static void TestClearVUs(u32 madr, u32 size) static void TestClearVUs(u32 madr, u32 size)
{ {
if( madr >= 0x11000000 ) { if (madr >= 0x11000000)
if( madr < 0x11004000 ) { {
if (madr < 0x11004000)
{
DbgCon::Notice("scratch pad clearing vu0"); DbgCon::Notice("scratch pad clearing vu0");
CpuVU0.Clear(madr&0xfff, size); CpuVU0.Clear(madr&0xfff, size);
} }
else if( madr >= 0x11008000 && madr < 0x1100c000 ) { else if (madr >= 0x11008000 && madr < 0x1100c000)
{
DbgCon::Notice("scratch pad clearing vu1"); DbgCon::Notice("scratch pad clearing vu1");
CpuVU1.Clear(madr&0x3fff, size); CpuVU1.Clear(madr&0x3fff, size);
} }
} }
} }
int _SPR0chain() { int _SPR0chain()
{
u32 *pMem; u32 *pMem;
if (spr0->qwc == 0) return 0; if (spr0->qwc == 0) return 0;
pMem = (u32*)dmaGetAddr(spr0->madr); pMem = (u32*)dmaGetAddr(spr0->madr);
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
//SPR0transfer(pMem, qwc << 2); if ((psHu32(DMAC_CTRL) & 0xC) >= 0x8) // 0x8 VIF1 MFIFO, 0xC GIF MFIFO
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("SPR MFIFO Write outside MFIFO area");
if ((psHu32(DMAC_CTRL) & 0xC) >= 0x8) { // 0x8 VIF1 MFIFO, 0xC GIF MFIFO
if((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("SPR MFIFO Write outside MFIFO area");
hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4); hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
spr0->madr += spr0->qwc << 4; spr0->madr += spr0->qwc << 4;
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
mfifotransferred += spr0->qwc; mfifotransferred += spr0->qwc;
} else { }
else
{
memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4); memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
//Cpu->Clear(spr0->madr, spr0->qwc<<2);
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes) TestClearVUs(spr0->madr, spr0->qwc << 2); // Wtf is going on here? AFAIK, only VIF should affect VU micromem (cottonvibes)
@ -90,7 +85,7 @@ int _SPR0chain() {
spr0->sadr += spr0->qwc << 4; spr0->sadr += spr0->qwc << 4;
return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed
} }
#define SPR0chain() \ #define SPR0chain() \
@ -98,91 +93,98 @@ int _SPR0chain() {
spr0->qwc = 0; spr0->qwc = 0;
void _SPR0interleave() { void _SPR0interleave()
{
int qwc = spr0->qwc; int qwc = spr0->qwc;
int sqwc = psHu32(DMAC_SQWC) & 0xff; int sqwc = psHu32(DMAC_SQWC) & 0xff;
int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff;
int cycles = 0; int cycles = 0;
u32 *pMem; u32 *pMem;
if(tqwc == 0) tqwc = qwc;
//Console::WriteLn("dmaSPR0 interleave");
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr);
while (qwc > 0) { if (tqwc == 0) tqwc = qwc;
spr0->qwc = std::min(tqwc, qwc); qwc-= spr0->qwc; //Console::WriteLn("dmaSPR0 interleave");
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr);
while (qwc > 0)
{
spr0->qwc = std::min(tqwc, qwc);
qwc -= spr0->qwc;
pMem = (u32*)dmaGetAddr(spr0->madr); pMem = (u32*)dmaGetAddr(spr0->madr);
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO if ((psHu32(DMAC_CTRL) & 0xC) == 0xC || // GIF MFIFO
(psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO (psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); {
hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
mfifotransferred += spr0->qwc; mfifotransferred += spr0->qwc;
} else { }
//Cpu->Clear(spr0->madr, spr0->qwc<<2); else
{
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0->madr, spr0->qwc<<2); TestClearVUs(spr0->madr, spr0->qwc << 2);
memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc<<4); memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4);
} }
cycles += tqwc * BIAS; cycles += tqwc * BIAS;
spr0->sadr+= spr0->qwc * 16; spr0->sadr += spr0->qwc * 16;
spr0->madr+= (sqwc+spr0->qwc)*16; //qwc-= sqwc; spr0->madr += (sqwc + spr0->qwc) * 16; //qwc-= sqwc;
} }
spr0->qwc = 0; spr0->qwc = 0;
spr0finished = 1; spr0finished = 1;
//CPU_INT(8, cycles);
} }
static __forceinline void _dmaSPR0() { static __forceinline void _dmaSPR0()
{
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) // STS == fromSPR
Console::WriteLn("SPR0 stall %d", params (psHu32(DMAC_CTRL)>>6)&3); {
Console::WriteLn("SPR0 stall %d", params(psHu32(DMAC_CTRL) >> 6)&3);
} }
// Transfer Dn_QWC from SPR to Dn_MADR // Transfer Dn_QWC from SPR to Dn_MADR
if ((spr0->chcr & 0xc) == 0x0) { // Normal Mode if ((spr0->chcr & 0xc) == 0x0) // Normal Mode
{
int cycles = 0; int cycles = 0;
SPR0chain(); SPR0chain();
//CPU_INT(8, cycles);
spr0finished = 1; spr0finished = 1;
return; return;
} else if ((spr0->chcr & 0xc) == 0x4) { }
int cycles = 0; else if ((spr0->chcr & 0xc) == 0x4)
u32 *ptag; {
int id; int cycles = 0;
int done = 0; u32 *ptag;
int id;
int done = 0;
if(spr0->qwc > 0){ if (spr0->qwc > 0)
SPR0chain(); {
//CPU_INT(8, cycles); SPR0chain();
spr0finished = 1; spr0finished = 1;
return; return;
} }
// Destination Chain Mode // Destination Chain Mode
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff];
//while (done == 0) { // Loop while Dn_CHCR.STR is 1 spr0->sadr += 16;
ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff];
spr0->sadr+= 16;
// Transfer dma tag if tte is set // Transfer dma tag if tte is set
// if (spr0->chcr & 0x40) SPR0transfer(ptag, 4);
spr0->chcr = ( spr0->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 spr0->chcr = (spr0->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
spr0->madr = ptag[1]; //MADR = ADDR field spr0->madr = ptag[1]; //MADR = ADDR field
SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", SPR_LOG("spr0 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
ptag[1], ptag[0], spr0->qwc, id, spr0->madr, spr0->sadr); ptag[1], ptag[0], spr0->qwc, id, spr0->madr, spr0->sadr);
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) // STS == fromSPR
{
Console::WriteLn("SPR stall control"); Console::WriteLn("SPR stall control");
} }
switch (id) { switch (id)
{
case 0: // CNTS - Transfer QWC following the tag (Stall Control) case 0: // CNTS - Transfer QWC following the tag (Stall Control)
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20 ) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) psHu32(DMAC_STADR) = spr0->madr + (spr0->qwc * 16); //Copy MADR to DMAC_STADR stall addr register
break; break;
case 1: // CNT - Transfer QWC following the tag. case 1: // CNT - Transfer QWC following the tag.
@ -194,33 +196,27 @@ static __forceinline void _dmaSPR0() {
break; break;
} }
SPR0chain(); SPR0chain();
if (spr0->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag if (spr0->chcr & 0x80 && ptag[0] >> 31) //Check TIE bit of CHCR and IRQ bit of tag
{
//Console::WriteLn("SPR0 TIE"); //Console::WriteLn("SPR0 TIE");
done = 1; done = 1;
spr0->qwc = 0; spr0->qwc = 0;
//break;
} }
/* if (spr0->chcr & 0x80 && ptag[0] >> 31) {
SPR_LOG("dmaIrq Set\n");
spr0->chcr&= ~0x100;
hwDmacIrq(8);
return;
}*/
//}
spr0finished = done; spr0finished = done;
if(done == 0) { if (done == 0)
ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR {
ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
CPU_INT(8, spr0->qwc / BIAS); CPU_INT(8, spr0->qwc / BIAS);
spr0->qwc = 0; spr0->qwc = 0;
return; return;
} }
SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx",
ptag[1], ptag[0], spr0->qwc, id, spr0->madr); ptag[1], ptag[0], spr0->qwc, id, spr0->madr);
//CPU_INT(8, cycles); }
} else { // Interleave Mode else // Interleave Mode
{
_SPR0interleave(); _SPR0interleave();
} }
@ -228,69 +224,62 @@ static __forceinline void _dmaSPR0() {
} }
extern void mfifoGIFtransfer(int);
#define gif ((DMACh*)&PS2MEM_HW[0xA000])
void SPRFROMinterrupt() void SPRFROMinterrupt()
{ {
//int qwc = spr0->qwc;
_dmaSPR0(); _dmaSPR0();
if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) { // GIF MFIFO if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) // GIF MFIFO
if((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area"); {
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr); //Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr);
mfifoGIFtransfer(mfifotransferred); mfifoGIFtransfer(mfifotransferred);
mfifotransferred = 0; mfifotransferred = 0;
} else
if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) { // VIF1 MFIFO
if((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr);
//vifqwc+= qwc;
mfifoVIF1transfer(mfifotransferred);
mfifotransferred = 0;
} }
if(spr0finished == 0) return; else
spr0->chcr&= ~0x100; if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO
{
if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area");
spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR));
//Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr);
mfifoVIF1transfer(mfifotransferred);
mfifotransferred = 0;
}
if (spr0finished == 0) return;
spr0->chcr &= ~0x100;
hwDmacIrq(8); hwDmacIrq(8);
} }
void dmaSPR0() { // fromSPR void dmaSPR0() // fromSPR
{
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr); spr0->chcr, spr0->madr, spr0->qwc, spr0->sadr);
if ((spr0->chcr & 0xc) == 0x4 && spr0->qwc == 0){ if ((spr0->chcr & 0xc) == 0x4 && spr0->qwc == 0)
u32 *ptag; {
ptag = (u32*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR u32 *ptag;
CPU_INT(8, (ptag[0] & 0xffff) / BIAS); ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR
// spr0->qwc = 0; CPU_INT(8, (ptag[0] & 0xffff) / BIAS);
return; return;
} }
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values // COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix) // It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction) // This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
CPU_INT(8, spr0->qwc / BIAS); CPU_INT(8, spr0->qwc / BIAS);
} }
__forceinline static void SPR1transfer(u32 *data, int size) { __forceinline static void SPR1transfer(u32 *data, int size)
/* { {
int i;
for (i=0; i<size; i++) {
SPR_LOG( "SPR1transfer[0x%x]: 0x%x\n", (spr1->sadr+i*4) & 0x3fff, data[i] );
}
}*/
//Cpu->Clear(spr1->sadr, size); // why?
memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2); memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)data, size << 2);
spr1->sadr+= size << 2; spr1->sadr += size << 2;
} }
int _SPR1chain() { int _SPR1chain()
{
u32 *pMem; u32 *pMem;
if (spr1->qwc == 0) return 0; if (spr1->qwc == 0) return 0;
@ -299,7 +288,7 @@ int _SPR1chain() {
if (pMem == NULL) return -1; if (pMem == NULL) return -1;
SPR1transfer(pMem, spr1->qwc << 2); SPR1transfer(pMem, spr1->qwc << 2);
spr1->madr+= spr1->qwc << 4; spr1->madr += spr1->qwc << 4;
return (spr1->qwc) * BIAS; return (spr1->qwc) * BIAS;
} }
@ -309,118 +298,127 @@ int _SPR1chain() {
spr1->qwc = 0; spr1->qwc = 0;
void _SPR1interleave() { void _SPR1interleave()
{
int qwc = spr1->qwc; int qwc = spr1->qwc;
int sqwc = psHu32(DMAC_SQWC) & 0xff; int sqwc = psHu32(DMAC_SQWC) & 0xff;
int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff;
int cycles = 0; int cycles = 0;
u32 *pMem; u32 *pMem;
if(tqwc == 0) tqwc = qwc;
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr);
while (qwc > 0) { if (tqwc == 0) tqwc = qwc;
spr1->qwc = std::min(tqwc, qwc); qwc-= spr1->qwc; SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr);
while (qwc > 0)
{
spr1->qwc = std::min(tqwc, qwc);
qwc -= spr1->qwc;
pMem = (u32*)dmaGetAddr(spr1->madr); pMem = (u32*)dmaGetAddr(spr1->madr);
memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc <<4); memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc << 4);
spr1->sadr += spr1->qwc * 16; spr1->sadr += spr1->qwc * 16;
cycles += spr1->qwc * BIAS; cycles += spr1->qwc * BIAS;
spr1->madr+= (sqwc + spr1->qwc) * 16; //qwc-= sqwc; spr1->madr += (sqwc + spr1->qwc) * 16; //qwc-= sqwc;
} }
spr1->qwc = 0; spr1->qwc = 0;
spr1finished = 1; spr1finished = 1;
//CPU_INT(9, cycles);
} }
void _dmaSPR1() { // toSPR work function void _dmaSPR1() // toSPR work function
if ((spr1->chcr & 0xc) == 0) { // Normal Mode {
if ((spr1->chcr & 0xc) == 0) // Normal Mode
{
int cycles = 0; int cycles = 0;
//if(spr1->qwc == 0 && (spr1->chcr & 0xc) == 1) spr1->qwc = 0xffff;
// Transfer Dn_QWC from Dn_MADR to SPR1 // Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain(); SPR1chain();
spr1finished = 1; spr1finished = 1;
//CPU_INT(9, cycles);
return; return;
} }
else if ((spr1->chcr & 0xc) == 0x4){ else if ((spr1->chcr & 0xc) == 0x4)
{
int cycles = 0; int cycles = 0;
u32 *ptag; u32 *ptag;
int id, done=0; int id, done = 0;
if(spr1->qwc > 0){ if (spr1->qwc > 0)
//if(spr1->qwc == 0 && (spr1->chcr & 0xc) == 1) spr1->qwc = 0xffff; {
// Transfer Dn_QWC from Dn_MADR to SPR1 // Transfer Dn_QWC from Dn_MADR to SPR1
SPR1chain(); SPR1chain();
spr1finished = 1; spr1finished = 1;
//CPU_INT(9, cycles);
return; return;
} }
// Chain Mode // Chain Mode
// while (done == 0) { // Loop while Dn_CHCR.STR is 1
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
if (ptag == NULL) { //Is ptag empty? if (ptag == NULL) //Is ptag empty?
{
Console::WriteLn("SPR1 Tag BUSERR"); Console::WriteLn("SPR1 Tag BUSERR");
spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register psHu32(DMAC_STAT) |= 1 << 15; //If yes, set BEIS (BUSERR) in DMAC_STAT register
done = 1; done = 1;
spr1finished = done; spr1finished = done;
return; return;
} }
spr1->chcr = ( spr1->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15
id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag
spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
spr1->madr = ptag[1]; //MADR = ADDR field spr1->madr = ptag[1]; //MADR = ADDR field
// Transfer dma tag if tte is set // Transfer dma tag if tte is set
if (spr1->chcr & 0x40) { if (spr1->chcr & 0x40)
{
SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]); SPR_LOG("SPR TTE: %x_%x\n", ptag[3], ptag[2]);
SPR1transfer(ptag, 4); //Transfer Tag SPR1transfer(ptag, 4); //Transfer Tag
} }
SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx",
ptag[1], ptag[0], spr1->qwc, id, spr1->madr); ptag[1], ptag[0], spr1->qwc, id, spr1->madr);
done = hwDmacSrcChain(spr1, id); done = hwDmacSrcChain(spr1, id);
SPR1chain(); //Transfers the data set by the switch SPR1chain(); //Transfers the data set by the switch
if (spr1->chcr & 0x80 && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag if (spr1->chcr & 0x80 && ptag[0] >> 31) //Check TIE bit of CHCR and IRQ bit of tag
{
SPR_LOG("dmaIrq Set"); SPR_LOG("dmaIrq Set");
//Console::WriteLn("SPR1 TIE"); //Console::WriteLn("SPR1 TIE");
spr1->qwc = 0; spr1->qwc = 0;
done = 1; done = 1;
// break;
} }
//}
spr1finished = done; spr1finished = done;
if(done == 0) { if (done == 0)
{
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag
CPU_INT(9, spr1->qwc / BIAS); CPU_INT(9, spr1->qwc / BIAS);
spr1->qwc = 0; spr1->qwc = 0;
} }
} else { // Interleave Mode }
else // Interleave Mode
{
_SPR1interleave(); _SPR1interleave();
} }
} }
void dmaSPR1() { // toSPR void dmaSPR1() // toSPR
{
SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n" SPR_LOG("dmaSPR1 chcr = 0x%x, madr = 0x%x, qwc = 0x%x\n"
" tadr = 0x%x, sadr = 0x%x", " tadr = 0x%x, sadr = 0x%x",
spr1->chcr, spr1->madr, spr1->qwc, spr1->chcr, spr1->madr, spr1->qwc,
spr1->tadr, spr1->sadr); spr1->tadr, spr1->sadr);
if ((spr1->chcr & 0xc) == 0x4 && spr1->qwc == 0){ if ((spr1->chcr & 0xc) == 0x4 && spr1->qwc == 0)
u32 *ptag; {
ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR u32 *ptag;
CPU_INT(9, (ptag[0] & 0xffff) / BIAS); ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR
//spr1->qwc = 0; CPU_INT(9, (ptag[0] & 0xffff) / BIAS);
return; //spr1->qwc = 0;
} return;
}
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values // COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix) // It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction) // This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
@ -430,14 +428,14 @@ void dmaSPR1() { // toSPR
void SPRTOinterrupt() void SPRTOinterrupt()
{ {
_dmaSPR1(); _dmaSPR1();
if( spr1finished == 0 ) return; if (spr1finished == 0) return;
spr1->chcr &= ~0x100; spr1->chcr &= ~0x100;
hwDmacIrq(9); hwDmacIrq(9);
} }
void SaveState::sprFreeze() void SaveState::sprFreeze()
{ {
FreezeTag( "SPRdma" ); FreezeTag("SPRdma");
Freeze(spr0finished); Freeze(spr0finished);
Freeze(spr1finished); Freeze(spr1finished);

View File

@ -37,7 +37,8 @@ DMACh *sif2ch;
#define FIFO_SIF0_W 128 #define FIFO_SIF0_W 128
#define FIFO_SIF1_W 128 #define FIFO_SIF1_W 128
struct _sif0{ struct _sif0
{
u32 fifoData[FIFO_SIF0_W]; u32 fifoData[FIFO_SIF0_W];
int fifoReadPos; int fifoReadPos;
int fifoWritePos; int fifoWritePos;
@ -49,7 +50,8 @@ struct _sif0{
struct sifData sifData; struct sifData sifData;
}; };
struct _sif1 { struct _sif1
{
u32 fifoData[FIFO_SIF1_W]; u32 fifoData[FIFO_SIF1_W];
int fifoReadPos; int fifoReadPos;
int fifoWritePos; int fifoWritePos;
@ -76,21 +78,13 @@ void sifInit()
static __forceinline void SIF0write(u32 *from, int words) static __forceinline void SIF0write(u32 *from, int words)
{ {
/*if(FIFO_SIF0_W < (words+sif0.fifoWritePos)) {*/ const int wP0 = min((FIFO_SIF0_W - sif0.fifoWritePos), words);
const int wP1 = words - wP0;
const int wP0 = min((FIFO_SIF0_W-sif0.fifoWritePos),words); memcpy(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2);
const int wP1 = words - wP0; memcpy(&sif0.fifoData[0], &from[wP0], wP1 << 2);
memcpy(&sif0.fifoData[sif0.fifoWritePos], from, wP0 << 2); sif0.fifoWritePos = (sif0.fifoWritePos + words) & (FIFO_SIF0_W - 1);
memcpy(&sif0.fifoData[0], &from[wP0], wP1 << 2);
sif0.fifoWritePos = (sif0.fifoWritePos + words) & (FIFO_SIF0_W-1);
/*}
else
{
memcpy_fast(&sif0.fifoData[sif0.fifoWritePos], from, words << 2);
sif0.fifoWritePos += words;
}*/
sif0.fifoSize += words; sif0.fifoSize += words;
SIF_LOG(" SIF0 + %d = %d (pos=%d)", words, sif0.fifoSize, sif0.fifoWritePos); SIF_LOG(" SIF0 + %d = %d (pos=%d)", words, sif0.fifoSize, sif0.fifoWritePos);
@ -98,66 +92,39 @@ static __forceinline void SIF0write(u32 *from, int words)
static __forceinline void SIF0read(u32 *to, int words) static __forceinline void SIF0read(u32 *to, int words)
{ {
/*if(FIFO_SIF0_W < (words+sif0.fifoReadPos)) const int wP0 = min((FIFO_SIF0_W - sif0.fifoReadPos), words);
{*/ const int wP1 = words - wP0;
const int wP0 = min((FIFO_SIF0_W-sif0.fifoReadPos),words);
const int wP1 = words - wP0;
memcpy(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2); memcpy(to, &sif0.fifoData[sif0.fifoReadPos], wP0 << 2);
memcpy(&to[wP0], &sif0.fifoData[0], wP1 << 2); memcpy(&to[wP0], &sif0.fifoData[0], wP1 << 2);
sif0.fifoReadPos = (sif0.fifoReadPos + words) & (FIFO_SIF0_W-1);
/*}
else
{
memcpy_fast(to, &sif0.fifoData[sif0.fifoReadPos], words << 2);
sif0.fifoReadPos += words;
}*/
sif0.fifoReadPos = (sif0.fifoReadPos + words) & (FIFO_SIF0_W - 1);
sif0.fifoSize -= words; sif0.fifoSize -= words;
SIF_LOG(" SIF0 - %d = %d (pos=%d)", words, sif0.fifoSize, sif0.fifoReadPos); SIF_LOG(" SIF0 - %d = %d (pos=%d)", words, sif0.fifoSize, sif0.fifoReadPos);
} }
__forceinline void SIF1write(u32 *from, int words) __forceinline void SIF1write(u32 *from, int words)
{ {
/*if(FIFO_SIF1_W < (words+sif1.fifoWritePos)) const int wP0 = min((FIFO_SIF1_W - sif1.fifoWritePos), words);
{*/ const int wP1 = words - wP0;
const int wP0 = min((FIFO_SIF1_W-sif1.fifoWritePos),words);
const int wP1 = words - wP0;
memcpy(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2); memcpy(&sif1.fifoData[sif1.fifoWritePos], from, wP0 << 2);
memcpy(&sif1.fifoData[0], &from[wP0], wP1 << 2); memcpy(&sif1.fifoData[0], &from[wP0], wP1 << 2);
sif1.fifoWritePos = (sif1.fifoWritePos + words) & (FIFO_SIF1_W-1);
/*}
else
{
memcpy_fast(&sif1.fifoData[sif1.fifoWritePos], from, words << 2);
sif1.fifoWritePos += words;
}*/
sif1.fifoWritePos = (sif1.fifoWritePos + words) & (FIFO_SIF1_W - 1);
sif1.fifoSize += words; sif1.fifoSize += words;
SIF_LOG(" SIF1 + %d = %d (pos=%d)", words, sif1.fifoSize, sif1.fifoWritePos); SIF_LOG(" SIF1 + %d = %d (pos=%d)", words, sif1.fifoSize, sif1.fifoWritePos);
} }
static __forceinline void SIF1read(u32 *to, int words) static __forceinline void SIF1read(u32 *to, int words)
{ {
/*if(FIFO_SIF1_W < (words+sif1.fifoReadPos)) const int wP0 = min((FIFO_SIF1_W - sif1.fifoReadPos), words);
{*/ const int wP1 = words - wP0;
const int wP0 = min((FIFO_SIF1_W-sif1.fifoReadPos),words);
const int wP1 = words - wP0;
memcpy(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2); memcpy(to, &sif1.fifoData[sif1.fifoReadPos], wP0 << 2);
memcpy(&to[wP0], &sif1.fifoData[0], wP1 << 2); memcpy(&to[wP0], &sif1.fifoData[0], wP1 << 2);
sif1.fifoReadPos = (sif1.fifoReadPos + words) & (FIFO_SIF1_W-1);
/*}
else
{
memcpy_fast(to, &sif1.fifoData[sif1.fifoReadPos], words << 2);
sif1.fifoReadPos += words;
}*/
sif1.fifoReadPos = (sif1.fifoReadPos + words) & (FIFO_SIF1_W - 1);
sif1.fifoSize -= words; sif1.fifoSize -= words;
SIF_LOG(" SIF1 - %d = %d (pos=%d)", words, sif1.fifoSize, sif1.fifoReadPos); SIF_LOG(" SIF1 - %d = %d (pos=%d)", words, sif1.fifoSize, sif1.fifoReadPos);
} }
@ -165,22 +132,16 @@ static __forceinline void SIF1read(u32 *to, int words)
__forceinline void SIF0Dma() __forceinline void SIF0Dma()
{ {
u32 *ptag; u32 *ptag;
int notDone = 1; int notDone = TRUE;
int cycles = 0, psxCycles = 0; int cycles = 0, psxCycles = 0;
SIF_LOG("SIF0 DMA start..."); SIF_LOG("SIF0 DMA start...");
do do
{ {
if (iopsifbusy[0] == 1) // If EE SIF0 is enabled
/*if ((psHu32(DMAC_CTRL) & 0xC0)) {
Console::WriteLn("DMA Stall Control %x", params (psHu32(DMAC_CTRL) & 0xC0));
}*/
if(iopsifbusy[0] == 1) // If EE SIF0 is enabled
{ {
//int size = sif0.counter; //HW_DMA9_BCR >> 16; if (sif0.counter == 0) // If there's no more to transfer
if(sif0.counter == 0) // If there's no more to transfer
{ {
// Note.. add normal mode here // Note.. add normal mode here
if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA if (sif0.sifData.data & 0xC0000000) // If NORMAL mode or end of CHAIN, or interrupt then stop DMA
@ -188,37 +149,32 @@ __forceinline void SIF0Dma()
SIF_LOG(" IOP SIF Stopped"); SIF_LOG(" IOP SIF Stopped");
// Stop & signal interrupts on IOP // Stop & signal interrupts on IOP
//HW_DMA9_CHCR &= ~0x01000000; //reset TR flag
//psxDmaInterrupt2(2);
iopsifbusy[0] = 0; iopsifbusy[0] = 0;
PSX_INT(IopEvt_SIF0, psxCycles);
// iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords) // 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: // So when we're all done, the equation looks like thus:
//PSX_INT(IopEvt_SIF0, ( ( psxCycles*BIAS ) / 4 ) / 8); //PSX_INT(IopEvt_SIF0, ( ( psxCycles*BIAS ) / 4 ) / 8);
PSX_INT(IopEvt_SIF0, psxCycles);
//hwIntcIrq(INTC_SBUS);
sif0.sifData.data = 0; sif0.sifData.data = 0;
notDone = 0; notDone = FALSE;
} }
else // Chain mode else // Chain mode
{ {
// Process DMA tag at HW_DMA9_TADR // Process DMA tag at HW_DMA9_TADR
sif0.sifData = *(sifData *)iopPhysMem( HW_DMA9_TADR ); sif0.sifData = *(sifData *)iopPhysMem(HW_DMA9_TADR);
sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4. sif0.sifData.words = (sif0.sifData.words + 3) & 0xfffffffc; // Round up to nearest 4.
SIF0write((u32*)iopPhysMem(HW_DMA9_TADR+8), 4); SIF0write((u32*)iopPhysMem(HW_DMA9_TADR + 8), 4);
//psxCycles += 2; HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF;
HW_DMA9_MADR = sif0.sifData.data & 0xFFFFFF;
HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2; HW_DMA9_TADR += 16; ///HW_DMA9_MADR + 16 + sif0.sifData.words << 2;
//HW_DMA9_BCR = (sif0.sifData.words << 16) | 1;
sif0.counter = sif0.sifData.words & 0xFFFFFF; sif0.counter = sif0.sifData.words & 0xFFFFFF;
notDone = 1; notDone = TRUE;
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); 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);
if(sif0.sifData.data & 0x40000000) if (sif0.sifData.data & 0x40000000)
SIF_LOG(" END"); SIF_LOG(" END");
else else
SIF_LOG(" CNT %08X, %08X", sif0.sifData.data, sif0.sifData.words); SIF_LOG(" CNT %08X, %08X", sif0.sifData.data, sif0.sifData.words);
@ -226,82 +182,63 @@ __forceinline void SIF0Dma()
} }
else // There's some data ready to transfer into the fifo.. else // There's some data ready to transfer into the fifo..
{ {
int wTransfer = min(sif0.counter, FIFO_SIF0_W-sif0.fifoSize); // HW_DMA9_BCR >> 16; int wTransfer = min(sif0.counter, FIFO_SIF0_W - sif0.fifoSize); // HW_DMA9_BCR >> 16;
SIF_LOG("+++++++++++ %lX of %lX", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/ ); SIF_LOG("+++++++++++ %lX of %lX", wTransfer, sif0.counter /*(HW_DMA9_BCR >> 16)*/);
SIF0write((u32*)iopPhysMem(HW_DMA9_MADR), wTransfer); SIF0write((u32*)iopPhysMem(HW_DMA9_MADR), wTransfer);
HW_DMA9_MADR += wTransfer << 2; HW_DMA9_MADR += wTransfer << 2;
//HW_DMA9_BCR = (HW_DMA9_BCR & 0xFFFF) | (((HW_DMA9_BCR >> 16) - wTransfer)<<16);
psxCycles += (wTransfer / 4) * BIAS; // fixme : should be / 16 psxCycles += (wTransfer / 4) * BIAS; // fixme : should be / 16
//psxCycles += wTransfer;
sif0.counter -= wTransfer; sif0.counter -= wTransfer;
//notDone = 1;
} }
} }
if(eesifbusy[0] == 1) // If EE SIF enabled and there's something to transfer if (eesifbusy[0] == 1) // If EE SIF enabled and there's something to transfer
{ {
int size = sif0dma->qwc; int size = sif0dma->qwc;
if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) { // STS == fromSIF0 if ((psHu32(DMAC_CTRL) & 0x30) == 0x10) // STS == fromSIF0
{
SIF_LOG("SIF0 stall control"); SIF_LOG("SIF0 stall control");
} }
if(size > 0) // If we're reading something continue to do so if (size > 0) // If we're reading something continue to do so
{ {
/*if(sif0.fifoSize > 0) int readSize = min(size, (sif0.fifoSize >> 2));
{*/
int readSize = min(size, (sif0.fifoSize>>2));
//SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr); //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr);
SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2 ); SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2);
_dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5);
SIF0read((u32*)ptag, readSize<<2); SIF0read((u32*)ptag, readSize << 2);
// {
// int i;
// for(i = 0; i < readSize; ++i) {
// SIF_LOG("EE SIF0 read madr: %x %x %x %x", ((u32*)ptag)[4*i+0], ((u32*)ptag)[4*i+1], ((u32*)ptag)[4*i+2], ((u32*)ptag)[4*i+3]);
// }
// }
Cpu->Clear(sif0dma->madr, readSize*4); Cpu->Clear(sif0dma->madr, readSize*4);
cycles += readSize * BIAS; // fixme : BIAS is factored in below cycles += readSize * BIAS; // fixme : BIAS is factored in below
//cycles += readSize; sif0dma->qwc -= readSize;
sif0dma->qwc -= readSize; sif0dma->madr += readSize << 4;
sif0dma->madr += readSize << 4;
//notDone = 1;
//}
} }
if(sif0dma->qwc == 0) if (sif0dma->qwc == 0)
{ {
if((sif0dma->chcr & 0x80000080) == 0x80000080) // Stop on tag IRQ if ((sif0dma->chcr & 0x80000080) == 0x80000080) // Stop on tag IRQ
{ {
// Tag interrupt // Tag interrupt
SIF_LOG(" EE SIF interrupt"); SIF_LOG(" EE SIF interrupt");
//sif0dma->chcr &= ~0x100;
eesifbusy[0] = 0; eesifbusy[0] = 0;
CPU_INT(5, cycles*BIAS); CPU_INT(5, cycles*BIAS);
//hwDmacIrq(5); notDone = FALSE;
notDone = 0;
} }
else if(sif0.end) // Stop on tag END else if (sif0.end) // Stop on tag END
{ {
// End tag. // End tag.
SIF_LOG(" EE SIF end"); SIF_LOG(" EE SIF end");
//sif0dma->chcr &= ~0x100;
//hwDmacIrq(5);
eesifbusy[0] = 0; eesifbusy[0] = 0;
CPU_INT(5, cycles*BIAS); CPU_INT(5, cycles*BIAS);
notDone = 0; notDone = FALSE;
} }
else if(sif0.fifoSize >= 4) // Read a tag else if (sif0.fifoSize >= 4) // Read a tag
{ {
static PCSX2_ALIGNED16(u32 tag[4]); static PCSX2_ALIGNED16(u32 tag[4]);
SIF0read((u32*)&tag[0], 4); // Tag SIF0read((u32*)&tag[0], 4); // Tag
@ -311,49 +248,43 @@ __forceinline void SIF0Dma()
sif0dma->madr = tag[1]; sif0dma->madr = tag[1];
sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000); sif0dma->chcr = (sif0dma->chcr & 0xffff) | (tag[0] & 0xffff0000);
/*if ((sif0dma->chcr & 0x80) && (tag[0] >> 31)) { 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]);
Console::WriteLn("SIF0 TIE");
}*/
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]);
if ((psHu32(DMAC_CTRL) & 0x30) != 0 && ((tag[0]>>28)&3) == 0) if ((psHu32(DMAC_CTRL) & 0x30) != 0 && ((tag[0] >> 28)&3) == 0)
psHu32(DMAC_STADR) = sif0dma->madr + (sif0dma->qwc * 16); psHu32(DMAC_STADR) = sif0dma->madr + (sif0dma->qwc * 16);
notDone = 1; notDone = TRUE;
sif0.chain = 1; sif0.chain = 1;
if(tag[0] & 0x40000000) if (tag[0] & 0x40000000) sif0.end = 1;
sif0.end = 1;
} }
} }
} }
}while(notDone); }
while (notDone);
} }
__forceinline void SIF1Dma() __forceinline void SIF1Dma()
{ {
int id; int id;
u32 *ptag; u32 *ptag;
int notDone; bool notDone = true;
int cycles = 0, psxCycles = 0; int cycles = 0, psxCycles = 0;
notDone = 1;
do do
{ {
if(eesifbusy[1] == 1) // If EE SIF1 is enabled if (eesifbusy[1] == 1) // If EE SIF1 is enabled
{ {
if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0) if ((psHu32(DMAC_CTRL) & 0xC0) == 0xC0)
SIF_LOG("SIF1 stall control"); // STS == fromSIF1 SIF_LOG("SIF1 stall control"); // STS == fromSIF1
if(sif1dma->qwc == 0) // If there's no more to transfer if (sif1dma->qwc == 0) // If there's no more to transfer
{ {
if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA if ((sif1dma->chcr & 0xc) == 0 || sif1.end) // If NORMAL mode or end of CHAIN then stop DMA
{ {
// Stop & signal interrupts on EE // Stop & signal interrupts on EE
//sif1dma->chcr &= ~0x100;
//hwDmacIrq(6);
SIF_LOG("EE SIF1 End %x", sif1.end); SIF_LOG("EE SIF1 End %x", sif1.end);
eesifbusy[1] = 0; eesifbusy[1] = 0;
notDone = 0; notDone = FALSE;
CPU_INT(6, cycles*BIAS); CPU_INT(6, cycles*BIAS);
sif1.chain = 0; sif1.chain = 0;
sif1.end = 0; sif1.end = 0;
@ -361,20 +292,21 @@ __forceinline void SIF1Dma()
else // Chain mode else // Chain mode
{ {
// Process DMA tag at sif1dma->tadr // Process DMA tag at sif1dma->tadr
notDone = 1; notDone = TRUE;
_dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6);
sif1dma->chcr = ( sif1dma->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); // Copy the tag sif1dma->chcr = (sif1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Copy the tag
sif1dma->qwc = (u16)ptag[0]; sif1dma->qwc = (u16)ptag[0];
if (sif1dma->chcr & 0x40) { if (sif1dma->chcr & 0x40)
{
Console::WriteLn("SIF1 TTE"); Console::WriteLn("SIF1 TTE");
SIF1write(ptag+2, 2); SIF1write(ptag + 2, 2);
} }
sif1.chain = 1; sif1.chain = 1;
id = (ptag[0] >> 28) & 0x7; id = (ptag[0] >> 28) & 0x7;
switch(id) switch (id)
{ {
case 0: // refe case 0: // refe
SIF_LOG(" REFE %08X", ptag[1]); SIF_LOG(" REFE %08X", ptag[1]);
@ -412,7 +344,8 @@ __forceinline void SIF1Dma()
default: default:
Console::WriteLn("Bad addr1 source chain"); Console::WriteLn("Bad addr1 source chain");
} }
if ((sif1dma->chcr & 0x80) && (ptag[0] >> 31)) { if ((sif1dma->chcr & 0x80) && (ptag[0] >> 31))
{
Console::WriteLn("SIF1 TIE"); Console::WriteLn("SIF1 TIE");
sif1.end = 1; sif1.end = 1;
} }
@ -423,124 +356,112 @@ __forceinline void SIF1Dma()
int qwTransfer = sif1dma->qwc; int qwTransfer = sif1dma->qwc;
u32 *data; u32 *data;
//notDone = 1;
_dmaGetAddr(sif1dma, data, sif1dma->madr, 6); _dmaGetAddr(sif1dma, data, sif1dma->madr, 6);
if(qwTransfer > (FIFO_SIF1_W-sif1.fifoSize)/4) // Copy part of sif1dma into FIFO if (qwTransfer > (FIFO_SIF1_W - sif1.fifoSize) / 4) // Copy part of sif1dma into FIFO
qwTransfer = (FIFO_SIF1_W-sif1.fifoSize)/4; qwTransfer = (FIFO_SIF1_W - sif1.fifoSize) / 4;
SIF1write(data, qwTransfer << 2); SIF1write(data, qwTransfer << 2);
sif1dma->madr += qwTransfer << 4; sif1dma->madr += qwTransfer << 4;
cycles += qwTransfer * BIAS; // fixme : BIAS is factored in above cycles += qwTransfer * BIAS; // fixme : BIAS is factored in above
//cycles += qwTransfer; // 1 cycle per quadword (BIAS is factored later)
sif1dma->qwc -= qwTransfer; sif1dma->qwc -= qwTransfer;
} }
} }
if(iopsifbusy[1] == 1) // If IOP SIF enabled and there's something to transfer if (iopsifbusy[1] == 1) // If IOP SIF enabled and there's something to transfer
{ {
int size = sif1.counter; int size = sif1.counter;
if(size > 0) // If we're reading something continue to do so if (size > 0) // If we're reading something continue to do so
{ {
/*if(sif1.fifoSize > 0) int readSize = size;
{*/
int readSize = size;
if(readSize > sif1.fifoSize) readSize = sif1.fifoSize; if (readSize > sif1.fifoSize) readSize = sif1.fifoSize;
SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR); SIF_LOG(" IOP SIF doing transfer %04X to %08X", readSize, HW_DMA10_MADR);
SIF1read((u32*)iopPhysMem(HW_DMA10_MADR), readSize); SIF1read((u32*)iopPhysMem(HW_DMA10_MADR), readSize);
psxCpu->Clear(HW_DMA10_MADR, readSize); psxCpu->Clear(HW_DMA10_MADR, readSize);
psxCycles += readSize / 4; // fixme: should be / 16 psxCycles += readSize / 4; // fixme: should be / 16
sif1.counter = size-readSize; sif1.counter = size - readSize;
HW_DMA10_MADR += readSize << 2; HW_DMA10_MADR += readSize << 2;
//notDone = 1;
//}
} }
if(sif1.counter <= 0) if (sif1.counter <= 0)
{ {
if(sif1.tagMode & 0x80) // Stop on tag IRQ if (sif1.tagMode & 0x80) // Stop on tag IRQ
{ {
// Tag interrupt // Tag interrupt
SIF_LOG(" IOP SIF interrupt"); SIF_LOG(" IOP SIF interrupt");
//HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
//psxDmaInterrupt2(3);
iopsifbusy[1] = 0; iopsifbusy[1] = 0;
PSX_INT(IopEvt_SIF1, psxCycles); PSX_INT(IopEvt_SIF1, psxCycles);
//hwIntcIrq(INTC_SBUS);
sif1.tagMode = 0; sif1.tagMode = 0;
notDone = 0; notDone = FALSE;
} }
else if(sif1.tagMode & 0x40) // Stop on tag END else if (sif1.tagMode & 0x40) // Stop on tag END
{ {
// End tag. // End tag.
SIF_LOG(" IOP SIF end"); SIF_LOG(" IOP SIF end");
//HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
//psxDmaInterrupt2(3);
iopsifbusy[1] = 0; iopsifbusy[1] = 0;
PSX_INT(IopEvt_SIF1, psxCycles); PSX_INT(IopEvt_SIF1, psxCycles);
//hwIntcIrq(INTC_SBUS);
sif1.tagMode = 0; sif1.tagMode = 0;
notDone = 0; notDone = FALSE;
} }
else if(sif1.fifoSize >= 4) // Read a tag else if (sif1.fifoSize >= 4) // Read a tag
{ {
struct sifData d; struct sifData d;
SIF1read((u32*)&d, 4); SIF1read((u32*)&d, 4);
SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d", d.data & 0xffffff, d.words, (d.data>>28)&7, (d.data>>31)&1); SIF_LOG(" IOP SIF dest chain tag madr:%08X wc:%04X id:%X irq:%d", d.data & 0xffffff, d.words, (d.data >> 28)&7, (d.data >> 31)&1);
HW_DMA10_MADR = d.data & 0xffffff; HW_DMA10_MADR = d.data & 0xffffff;
sif1.counter = d.words; sif1.counter = d.words;
sif1.tagMode = (d.data >> 24) & 0xFF; sif1.tagMode = (d.data >> 24) & 0xFF;
notDone = 1; notDone = TRUE;
} }
} }
} }
} while (notDone); }
while (notDone);
} }
__forceinline void sif0Interrupt() { __forceinline void sif0Interrupt()
{
HW_DMA9_CHCR &= ~0x01000000; HW_DMA9_CHCR &= ~0x01000000;
psxDmaInterrupt2(2); psxDmaInterrupt2(2);
//hwIntcIrq(INTC_SBUS);
} }
__forceinline void sif1Interrupt() { __forceinline void sif1Interrupt()
{
HW_DMA10_CHCR &= ~0x01000000; //reset TR flag HW_DMA10_CHCR &= ~0x01000000; //reset TR flag
psxDmaInterrupt2(3); psxDmaInterrupt2(3);
//hwIntcIrq(INTC_SBUS);
} }
__forceinline void EEsif0Interrupt() { __forceinline void EEsif0Interrupt()
{
sif0dma->chcr &= ~0x100; sif0dma->chcr &= ~0x100;
hwDmacIrq(DMAC_SIF0); hwDmacIrq(DMAC_SIF0);
} }
__forceinline void EEsif1Interrupt() { __forceinline void EEsif1Interrupt()
{
hwDmacIrq(DMAC_SIF1); hwDmacIrq(DMAC_SIF1);
sif1dma->chcr &= ~0x100; sif1dma->chcr &= ~0x100;
} }
__forceinline void dmaSIF0() { __forceinline void dmaSIF0()
{
SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx", SIF_LOG("EE: dmaSIF0 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr); sif0dma->chcr, sif0dma->madr, sif0dma->qwc, sif0dma->tadr);
if (sif0.fifoReadPos != sif0.fifoWritePos) { if (sif0.fifoReadPos != sif0.fifoWritePos)
{
SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos"); SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
} }
// if(sif0dma->qwc > 0 & (sif0dma->chcr & 0x4) == 0x4) {
// sif0dma->chcr &= ~4; //Halflife sets a QWC amount in chain mode, no tadr set.
// Console::WriteLn("yo");
// }
psHu32(0x1000F240) |= 0x2000; psHu32(0x1000F240) |= 0x2000;
eesifbusy[0] = 1; eesifbusy[0] = 1;
if(eesifbusy[0] == 1 && iopsifbusy[0] == 1) { if (eesifbusy[0] == 1 && iopsifbusy[0] == 1)
{
FreezeXMMRegs(1); FreezeXMMRegs(1);
hwIntcIrq(INTC_SBUS); hwIntcIrq(INTC_SBUS);
SIF0Dma(); SIF0Dma();
@ -550,22 +471,20 @@ __forceinline void dmaSIF0() {
} }
} }
__forceinline void dmaSIF1() { __forceinline void dmaSIF1()
{
SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx", SIF_LOG("EE: dmaSIF1 chcr = %lx, madr = %lx, qwc = %lx, tadr = %lx",
sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr); sif1dma->chcr, sif1dma->madr, sif1dma->qwc, sif1dma->tadr);
if (sif1.fifoReadPos != sif1.fifoWritePos) { if (sif1.fifoReadPos != sif1.fifoWritePos)
{
SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos"); SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
} }
// if(sif1dma->qwc > 0 & (sif1dma->chcr & 0x4) == 0x4) {
// sif1dma->chcr &= ~4; //Halflife sets a QWC amount in chain mode, no tadr set.
// Console::WriteLn("yo2");
// }
psHu32(0x1000F240) |= 0x4000; psHu32(0x1000F240) |= 0x4000;
eesifbusy[1] = 1; eesifbusy[1] = 1;
if(eesifbusy[1] == 1 && iopsifbusy[1] == 1) { if (eesifbusy[1] == 1 && iopsifbusy[1] == 1)
{
FreezeXMMRegs(1); FreezeXMMRegs(1);
SIF1Dma(); SIF1Dma();
psHu32(0x1000F240) &= ~0x40; psHu32(0x1000F240) &= ~0x40;
@ -576,11 +495,12 @@ __forceinline void dmaSIF1() {
} }
__forceinline void dmaSIF2() { __forceinline void dmaSIF2()
{
SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx", SIF_LOG("dmaSIF2 chcr = %lx, madr = %lx, qwc = %lx",
sif2dma->chcr, sif2dma->madr, sif2dma->qwc); sif2dma->chcr, sif2dma->madr, sif2dma->qwc);
sif2dma->chcr&= ~0x100; sif2dma->chcr &= ~0x100;
hwDmacIrq(7); hwDmacIrq(7);
Console::WriteLn("*PCSX2*: dmaSIF2"); Console::WriteLn("*PCSX2*: dmaSIF2");
} }
@ -588,7 +508,7 @@ __forceinline void dmaSIF2() {
void SaveState::sifFreeze() void SaveState::sifFreeze()
{ {
FreezeTag( "SIFdma" ); FreezeTag("SIFdma");
Freeze(sif0); Freeze(sif0);
Freeze(sif1); Freeze(sif1);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff