So.. I got an "unlazy" day, and coded a bit more of my iop dma handler.

It's disabled in the code, so that it wont' affect normal users.

The code isn't working properly yet. Only handlers for cdvd and spu2 are in it:
 - the cdvd one doesn't work because of the way pcsx2 handles cdvd currently
 - the spu2 one seems to work, but it's not implemented in the plugin interface, so ATM it's just "faking" it using the old functions.

So really nothing worth testing, just commiting to let people know I'm actually working on it... with long pauses in between. xD

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1052 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gigaherz 2009-04-24 01:14:25 +00:00
parent 2ac355eb03
commit e22a50a7c8
8 changed files with 250 additions and 48 deletions

View File

@ -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;

View File

@ -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"

View File

@ -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 );
}

View File

@ -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;

View File

@ -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->Target<MinDelay) MinDelay = TTarget;
ch->Target += 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;
}

View File

@ -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);

View File

@ -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;
//------------------------------------------------------------------

View File

@ -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))