diff --git a/pcsx2/CdRom.cpp b/pcsx2/CdRom.cpp index e22160be77..e9b4e6eb00 100644 --- a/pcsx2/CdRom.cpp +++ b/pcsx2/CdRom.cpp @@ -937,6 +937,34 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { psxDmaInterrupt(3); } +#ifdef ENABLE_NEW_IOPDMA +s32 cdvdDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +{ + // hacked up from the code above + + if (cdr.Readed == 0) + { + //CDR_LOG("*** DMA 3 *** NOT READY"); + wordsProcessed = 0; + return 10000; + } + + memcpy_fast(data, cdr.pTransfer, wordsLeft); + //psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=wordsLeft; + *wordsProcessed = wordsLeft; + + Console::Status("New IOP DMA handled CDVD DMA: channel %d, data %p, remaining %08x, processed %08x.", params channel,data,wordsLeft, *wordsProcessed); + return 0; +} + +void cdvdDmaInterrupt(s32 channel) +{ + cdrInterrupt(); +} + +#endif + void cdrReset() { memzero_obj(cdr); cdr.CurTrack=1; diff --git a/pcsx2/IopCommon.h b/pcsx2/IopCommon.h index 27b8341f4d..18b2161e32 100644 --- a/pcsx2/IopCommon.h +++ b/pcsx2/IopCommon.h @@ -29,10 +29,10 @@ #include "Sio.h" #include "Sif.h" +#include "IopDma.h" #include "IopMem.h" #include "IopHw.h" #include "IopBios.h" -#include "IopDma.h" #include "IopCounters.h" #include "IopSio2.h" diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index 1152854a19..664dceb228 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -38,8 +38,7 @@ #define PSXPIXEL ((int)(PSXCLK / 13500000)) #define PSXSOUNDCLK ((int)(48000)) - -psxCounter psxCounters[8]; +psxCounter psxCounters[NUM_COUNTERS]; s32 psxNextCounter; u32 psxNextsCounter; u8 psxhblankgate = 0; @@ -141,6 +140,12 @@ void psxRcntInit() { psxCounters[7].mode = 0x8; } +#ifdef ENABLE_NEW_IOPDMA + psxCounters[8].rate = 2000; + psxCounters[8].CycleT = psxCounters[7].rate; + psxCounters[8].mode = 0x8; +#endif + for (i=0; i<8; i++) psxCounters[i].sCycleT = psxRegs.cycle; @@ -453,6 +458,24 @@ void psxRcntUpdate() if (c < psxNextCounter) psxNextCounter = c; } +#ifdef ENABLE_NEW_IOPDMA + + // New Iop DMA handler WIP + { + const s32 difference = psxRegs.cycle - psxCounters[8].sCycleT; + s32 c = psxCounters[8].CycleT; + + if(difference >= psxCounters[8].CycleT) + { + psxCounters[8].sCycleT = psxRegs.cycle; + psxCounters[8].CycleT = psxCounters[8].rate; + IopDmaUpdate(difference); + } + else c -= difference; + if (c < psxNextCounter) psxNextCounter = c; + } +#endif + for (i=0; i<6; i++) _rcntSet( i ); } diff --git a/pcsx2/IopCounters.h b/pcsx2/IopCounters.h index 69c56acd74..8a743408f0 100644 --- a/pcsx2/IopCounters.h +++ b/pcsx2/IopCounters.h @@ -27,7 +27,13 @@ struct psxCounter { s32 CycleT; }; -extern psxCounter psxCounters[8]; +#ifdef ENABLE_NEW_IOPDMA +# define NUM_COUNTERS 9 +#else +# define NUM_COUNTERS 8 +#endif + +extern psxCounter psxCounters[NUM_COUNTERS]; extern s32 psxNextCounter; extern u32 psxNextsCounter; diff --git a/pcsx2/IopDma.cpp b/pcsx2/IopDma.cpp index 697b0acb9e..1af6cef622 100644 --- a/pcsx2/IopDma.cpp +++ b/pcsx2/IopDma.cpp @@ -258,35 +258,96 @@ void iopIntcIrq(uint irqType) // // fixme: Is this in progress? -#if FALSE +#ifdef ENABLE_NEW_IOPDMA -typedef s32(* DmaHandler)(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); -typedef void (* DmaIHandler)(s32 channel); - -s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); -s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); - -struct DmaHandlerInfo +s32 spu2DmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - DmaHandler Read; - DmaHandler Write; - DmaIHandler Interrupt; -}; + // FIXME: change the plugin interfaces so that they are aware of this new dma handler -struct DmaStatusInfo + /* + u32 bytes = 1024; + if(bytesLeft<1024) + bytes=bytesLeft; + */ + u32 bytes=bytesLeft; + + // Update the spu2 to the current cycle before initiating the DMA + if (SPU2async) + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); + + psxCounters[6].sCycleT = psxRegs.cycle; + psxCounters[6].CycleT = bytes * 3; + + psxNextCounter -= (psxRegs.cycle - psxNextsCounter); + psxNextsCounter = psxRegs.cycle; + if (psxCounters[6].CycleT < psxNextCounter) + psxNextCounter = psxCounters[6].CycleT; + } + + if(channel==7) + SPU2readDMA7Mem((u16 *)data, bytes/2); + else + SPU2readDMA4Mem((u16 *)data, bytes/2); + + *bytesProcessed = bytes; + + return 0; +} + +s32 spu2DmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - u32 Control; - u32 Width; // bytes/word, for timing purposes - u32 MemAddr; - u32 ByteCount; - u32 Target; -}; + // FIXME: change the plugin interfaces so that they are aware of this new dma handler -// FIXME: Dummy constants, to be "filled in" with proper values later -#define DMA_CTRL_ACTIVE 0x80000000 -#define DMA_CTRL_DIRECTION 0x00000001 -#define DMA_CHANNEL_MAX 16 /* ? */ + /* + u32 bytes = 1024; + if(bytesLeft<1024) + bytes=bytesLeft; + */ + u32 bytes=bytesLeft; + + + // Update the spu2 to the current cycle before initiating the DMA + if (SPU2async) + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); + + psxCounters[6].sCycleT = psxRegs.cycle; + psxCounters[6].CycleT = bytes * 3; + + psxNextCounter -= (psxRegs.cycle - psxNextsCounter); + psxNextsCounter = psxRegs.cycle; + if (psxCounters[6].CycleT < psxNextCounter) + psxNextCounter = psxCounters[6].CycleT; + } + + if(channel==7) + SPU2writeDMA7Mem((u16 *)data, bytes/2); + else + SPU2writeDMA4Mem((u16 *)data, bytes/2); + + + *bytesProcessed = bytes; + + return 0; +} + +void spu2DmaInterrupt(s32 channel) +{ + if(channel==7) + SPU2interruptDMA7(); + else + SPU2interruptDMA4(); +} + +//typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +//typedef void (* DmaIHandler)(s32 channel); + +s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); DmaStatusInfo IopChannels[DMA_CHANNEL_MAX]; // I dont' knwo how many there are, 10? @@ -300,9 +361,9 @@ DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] = {0}, //5 {0}, //6: OT? {spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu Core1 - {dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9 - {sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0 - {sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1 + {0},//{dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9 + {0},//{sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0 + {0},//{sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1 {0}, // Sio2 {0}, // Sio2 }; @@ -324,26 +385,37 @@ const char* IopDmaNames[DMA_CHANNEL_MAX] = "Sio2", "?", "?", "?" }; -}; // Prototypes. To be implemented later (or in other parts of the emulator) -void SetDmaUpdateTarget(u32 delay); -void RaiseDmaIrq(u32 channel); +void SetDmaUpdateTarget(u32 delay) +{ + psxCounters[8].CycleT = delay; +} + +void RaiseDmaIrq(u32 channel) +{ + if(channel<7) + psxDmaInterrupt(channel); + else + psxDmaInterrupt2(channel-7); +} // WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS! void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr) { // I dont' really understand this, but it's used above. Is this BYTES OR WHAT? - int size = (bcr >> 16) * (bcr & 0xFFFF); + int size = 4* (bcr >> 16) * (bcr & 0xFFFF); IopChannels[channel].Control = chcr | DMA_CTRL_ACTIVE; IopChannels[channel].MemAddr = madr; IopChannels[channel].ByteCount = size; + + SetDmaUpdateTarget(0); } void IopDmaUpdate(u32 elapsed) { - u32 MinDelay = 0xFFFFFFFF; + s32 MinDelay = 0x7FFFFFFF; for (int i = 0;i < DMA_CHANNEL_MAX;i++) { @@ -363,12 +435,17 @@ void IopDmaUpdate(u32 elapsed) else { // 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].Write : IopDmaHandlers[i].Read; u32 BCount = 0; - s32 Target = (handler) ? handler(i, (u32*)PSXM(ch->MemAddr), ch->ByteCount, &BCount) : 0; + s32 Target = (handler) ? handler(i, (u32*)iopPhysMem(ch->MemAddr), ch->ByteCount, &BCount) : 0; - ch->Target = 100; + if(BCount>0) + { + psxCpu->Clear(ch->MemAddr, BCount/4); + } + + int TTarget = 100; if (Target < 0) { // TODO: ... What to do if the plugin errors? :P @@ -378,29 +455,38 @@ void IopDmaUpdate(u32 elapsed) ch->MemAddr += BCount; ch->ByteCount -= BCount; - ch->Target = BCount / ch->Width; + TTarget = BCount; // / ch->Width; } - if (Target != 0) ch->Target = Target; + if (Target != 0) TTarget = Target; + + if (ch->TargetTarget += TTarget; } } } } + + if(MinDelay<0x7FFFFFFF) + SetDmaUpdateTarget(MinDelay); + else + SetDmaUpdateTarget(10000); } -s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - 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.", params 0, channel, IopDmaNames[channel]); - *wordsProcessed = wordsLeft; + *bytesProcessed = bytesLeft; return 0; } -s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - 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.", params 0, channel, IopDmaNames[channel]); - *wordsProcessed = wordsLeft; + *bytesProcessed = bytesLeft; return 0; } diff --git a/pcsx2/IopDma.h b/pcsx2/IopDma.h index 416d941e29..c4136fe334 100644 --- a/pcsx2/IopDma.h +++ b/pcsx2/IopDma.h @@ -21,6 +21,46 @@ #include "PS2Edefs.h" +//#define ENABLE_NEW_IOPDMA + +#ifdef ENABLE_NEW_IOPDMA + +typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +typedef void (* DmaIHandler)(s32 channel); + +struct DmaHandlerInfo +{ + DmaHandler Read; + DmaHandler Write; + DmaIHandler Interrupt; +}; + +struct DmaStatusInfo +{ + u32 Control; + u32 Width; // bytes/word, for timing purposes + u32 MemAddr; + u32 ByteCount; + s32 Target; +}; + +// FIXME: Dummy constants, to be "filled in" with proper values later +#define DMA_CTRL_ACTIVE 0x01000000 +#define DMA_CTRL_DIRECTION 0x00000001 + +#define DMA_CHANNEL_MAX 16 /* ? */ + +// WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS! +void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr); +void IopDmaUpdate(u32 elapsed); + +// external dma handlers +extern s32 cdvdDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +extern void cdvdDmaInterrupt(s32 channel); + +//#else +#endif + void psxDma2(u32 madr, u32 bcr, u32 chcr); void psxDma3(u32 madr, u32 bcr, u32 chcr); void psxDma4(u32 madr, u32 bcr, u32 chcr); diff --git a/pcsx2/IopHw.cpp b/pcsx2/IopHw.cpp index 8a486855d2..b973f43ac0 100644 --- a/pcsx2/IopHw.cpp +++ b/pcsx2/IopHw.cpp @@ -1020,7 +1020,7 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f8010c8: PSXHW_LOG("DMA4 CHCR 32bit write %lx", value); HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) - DmaExec(4); + DmaExecNew(4); return; //------------------------------------------------------------------ @@ -1053,7 +1053,7 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f801508: PSXHW_LOG("DMA7 CHCR 32bit write %lx", value); HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) - DmaExec2(7); + DmaExecNew2(7); return; //------------------------------------------------------------------ diff --git a/pcsx2/IopHw.h b/pcsx2/IopHw.h index 6fdabcc287..5579161b9c 100644 --- a/pcsx2/IopHw.h +++ b/pcsx2/IopHw.h @@ -69,6 +69,25 @@ enum IOPCountRegs } \ } +#ifdef ENABLE_NEW_IOPDMA +#define DmaExecNew(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \ + } \ +} + +#define DmaExecNew2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \ + } \ +} +#else +#define DmaExecNew(n) DmaExec(n) +#define DmaExecNew2(n) DmaExec2(n) +#endif + #define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA #define HW_DMA0_BCR (psxHu32(0x1084)) #define HW_DMA0_CHCR (psxHu32(0x1088))