mirror of https://github.com/PCSX2/pcsx2.git
Experimental implementation of spu2 interface for the new iop dmac.
It's implemented only on SPU2-X and disabled by default. FF12 and Atelier iris had working FMVs and bgm, other games might not Try at your own risk. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2554 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
3ab89904e4
commit
9ae807134e
|
@ -344,17 +344,30 @@ const DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] =
|
||||||
{"Ps1 Mdec", _D__}, //1
|
{"Ps1 Mdec", _D__}, //1
|
||||||
{"Ps1 Gpu", _D__}, //2
|
{"Ps1 Gpu", _D__}, //2
|
||||||
{"CDVD", _DR_, CHANNEL_BASE1(3), cdvdDmaRead, errDmaWrite, cdvdDmaInterrupt}, //3: CDVD
|
{"CDVD", _DR_, CHANNEL_BASE1(3), cdvdDmaRead, errDmaWrite, cdvdDmaInterrupt}, //3: CDVD
|
||||||
{"SPU2 Core0", _DRW, CHANNEL_BASE1(4), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //4: Spu Core0
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
{"SPU2 Core0", _ERW, CHANNEL_BASE1(4), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //4: Spu/Spu2 Core0
|
||||||
|
#else
|
||||||
|
{"SPU2 Core0", _D__}, //4: Spu/Spu2 Core0
|
||||||
|
#endif
|
||||||
{"?", _D__}, //5
|
{"?", _D__}, //5
|
||||||
{"OT", _D__}, //6: OT?
|
{"OT", _D__}, //6: OT?
|
||||||
|
|
||||||
// Second DMAC, new in PS2 IOP
|
// Second DMAC, new in PS2 IOP
|
||||||
{"SPU2 Core1", _DRW, CHANNEL_BASE2(0), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu Core1
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
{"SPU2 Core1", _ERW, CHANNEL_BASE2(0), spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu2 Core1
|
||||||
|
#else
|
||||||
|
{"SPU2 Core1", _D__}, //7: Spu2 Core1
|
||||||
|
#endif
|
||||||
{"Dev9", _DRW},// CHANNEL_BASE2(1), dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9
|
{"Dev9", _DRW},// CHANNEL_BASE2(1), dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9
|
||||||
{"Sif0", _DRW},// CHANNEL_BASE2(2), sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0
|
{"Sif0", _DRW},// CHANNEL_BASE2(2), sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0
|
||||||
{"Sif1", _DRW},// CHANNEL_BASE2(3), sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1
|
{"Sif1", _DRW},// CHANNEL_BASE2(3), sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SIO
|
||||||
{"Sio2 (writes)", _E_W, CHANNEL_BASE2(4), errDmaRead, sio2DmaWrite, sio2DmaInterrupt}, //11: Sio2
|
{"Sio2 (writes)", _E_W, CHANNEL_BASE2(4), errDmaRead, sio2DmaWrite, sio2DmaInterrupt}, //11: Sio2
|
||||||
{"Sio2 (reads)", _ER_, CHANNEL_BASE2(5), sio2DmaRead, errDmaWrite, sio2DmaInterrupt}, //12: Sio2
|
{"Sio2 (reads)", _ER_, CHANNEL_BASE2(5), sio2DmaRead, errDmaWrite, sio2DmaInterrupt}, //12: Sio2
|
||||||
|
#else
|
||||||
|
{"Sio2 (writes)", _D__}, //11: Sio2
|
||||||
|
{"Sio2 (reads)", _D__}, //12: Sio2
|
||||||
|
#endif
|
||||||
{"?", _D__}, //13
|
{"?", _D__}, //13
|
||||||
// if each dmac has 7 channels, the list would end here, but I'm not sure :p
|
// if each dmac has 7 channels, the list would end here, but I'm not sure :p
|
||||||
};
|
};
|
||||||
|
@ -486,8 +499,8 @@ static void __releaseinline IopDmaProcessChannel(int elapsed, int& MinDelay)
|
||||||
|
|
||||||
NextUpdateDelay = ProcessedBytes/2; // / ch->Width;
|
NextUpdateDelay = ProcessedBytes/2; // / ch->Width;
|
||||||
}
|
}
|
||||||
else
|
else if(RequestedDelay==0)
|
||||||
DevCon.Warning("What now? :p");
|
DevCon.Warning("What now? :p"); // its ok as long as there's a delay requeste, autodma requires this.
|
||||||
|
|
||||||
if (RequestedDelay != 0) NextUpdateDelay = RequestedDelay;
|
if (RequestedDelay != 0) NextUpdateDelay = RequestedDelay;
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,8 @@ void V_Core::LogAutoDMA( FILE* fp )
|
||||||
|
|
||||||
void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo
|
void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo
|
||||||
{
|
{
|
||||||
int spos = ((InputPos+0xff)&0x100); //starting position of the free buffer
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
int spos = ((InputPosRead+0xff)&0x100); //starting position of the free buffer
|
||||||
|
|
||||||
LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile );
|
LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile );
|
||||||
|
|
||||||
|
@ -119,10 +120,12 @@ void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not spl
|
||||||
}
|
}
|
||||||
// See ReadInput at mixer.cpp for explanation on the commented out lines
|
// See ReadInput at mixer.cpp for explanation on the commented out lines
|
||||||
//
|
//
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
int size = (sz)&(~511);
|
int size = (sz)&(~511);
|
||||||
|
|
||||||
if(MsgAutoDMA()) ConLog(" * SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
|
if(MsgAutoDMA()) ConLog(" * SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
|
||||||
|
@ -150,7 +153,7 @@ void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if( ((PlayMode&4)==4) && (Index==0) )
|
if( ((PlayMode&4)==4) && (Index==0) )
|
||||||
Cores[0].InputPos=0;
|
Cores[0].InputPosRead=0;
|
||||||
|
|
||||||
AutoDMAReadBuffer(0);
|
AutoDMAReadBuffer(0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -167,6 +170,7 @@ void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
||||||
DMAICounter = 1;
|
DMAICounter = 1;
|
||||||
}
|
}
|
||||||
TADR = MADR + (size<<1);
|
TADR = MADR + (size<<1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACKFIX: The BIOS breaks if we check the IRQA for both cores when issuing DMA writes. The
|
// HACKFIX: The BIOS breaks if we check the IRQA for both cores when issuing DMA writes. The
|
||||||
|
@ -186,7 +190,6 @@ void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
||||||
// Update: This hack is no longer needed when we don't do a core reset. Guess the null pc was in spu2 memory?
|
// Update: This hack is no longer needed when we don't do a core reset. Guess the null pc was in spu2 memory?
|
||||||
#define NO_BIOS_HACKFIX 1 // set to 1 to disable the hackfix
|
#define NO_BIOS_HACKFIX 1 // set to 1 to disable the hackfix
|
||||||
|
|
||||||
|
|
||||||
void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
||||||
{
|
{
|
||||||
// Perform an alignment check.
|
// Perform an alignment check.
|
||||||
|
@ -322,6 +325,7 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
||||||
|
|
||||||
void V_Core::DoDMAread(u16* pMem, u32 size)
|
void V_Core::DoDMAread(u16* pMem, u32 size)
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
TSA &= 0xffff8;
|
TSA &= 0xffff8;
|
||||||
|
|
||||||
u32 buff1end = TSA + size;
|
u32 buff1end = TSA + size;
|
||||||
|
@ -387,10 +391,12 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
|
||||||
Regs.STATX &= ~0x80;
|
Regs.STATX &= ~0x80;
|
||||||
//Regs.ATTR |= 0x30;
|
//Regs.ATTR |= 0x30;
|
||||||
TADR = MADR + (size<<1);
|
TADR = MADR + (size<<1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
DMAPtr = pMem;
|
DMAPtr = pMem;
|
||||||
|
|
||||||
if(size<2) {
|
if(size<2) {
|
||||||
|
@ -420,4 +426,184 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
||||||
}
|
}
|
||||||
Regs.STATX &= ~0x80;
|
Regs.STATX &= ~0x80;
|
||||||
//Regs.ATTR |= 0x30;
|
//Regs.ATTR |= 0x30;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 V_Core::NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
bool DmaStarting = !DmaStarted;
|
||||||
|
DmaStarted = true;
|
||||||
|
|
||||||
|
TSA &= 0xffff8;
|
||||||
|
|
||||||
|
u16* pMem = (u16*)data;
|
||||||
|
|
||||||
|
u32 buff1end = TSA + bytesLeft;
|
||||||
|
u32 buff2end = 0;
|
||||||
|
if( buff1end > 0x100000 )
|
||||||
|
{
|
||||||
|
buff2end = buff1end - 0x100000;
|
||||||
|
buff1end = 0x100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 buff1size = (buff1end-TSA);
|
||||||
|
memcpy( pMem, GetMemPtr( TSA ), buff1size*2 );
|
||||||
|
|
||||||
|
// Note on TSA's position after our copy finishes:
|
||||||
|
// IRQA should be measured by the end of the writepos+0x20. But the TDA
|
||||||
|
// should be written back at the precise endpoint of the xfer.
|
||||||
|
|
||||||
|
if( buff2end > 0 )
|
||||||
|
{
|
||||||
|
// second branch needs cleared:
|
||||||
|
// It starts at the beginning of memory and moves forward to buff2end
|
||||||
|
|
||||||
|
memcpy( &pMem[buff1size], GetMemPtr( 0 ), buff2end*2 );
|
||||||
|
|
||||||
|
TDA = (buff2end+0x20) & 0xfffff;
|
||||||
|
|
||||||
|
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||||
|
// Important: Test both core IRQ settings for either DMA!
|
||||||
|
// Note: Because this buffer wraps, we use || instead of &&
|
||||||
|
|
||||||
|
for( int i=0; i<2; i++ )
|
||||||
|
{
|
||||||
|
if( Cores[i].IRQEnable && (Cores[i].IRQA >= TSA) || (Cores[i].IRQA < TDA) )
|
||||||
|
{
|
||||||
|
Spdif.Info = 4 << i;
|
||||||
|
SetIrqCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Buffer doesn't wrap/overflow!
|
||||||
|
// Just set the TDA and check for an IRQ...
|
||||||
|
|
||||||
|
TDA = (buff1end + 0x20) & 0xfffff;
|
||||||
|
|
||||||
|
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||||
|
// Important: Test both core IRQ settings for either DMA!
|
||||||
|
|
||||||
|
for( int i=0; i<2; i++ )
|
||||||
|
{
|
||||||
|
if( Cores[i].IRQEnable && (Cores[i].IRQA >= TSA) && (Cores[i].IRQA < TDA) )
|
||||||
|
{
|
||||||
|
Spdif.Info = 4 << i;
|
||||||
|
SetIrqCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TSA = TDA & 0xFFFFF;
|
||||||
|
|
||||||
|
Regs.STATX &= ~0x80;
|
||||||
|
//Regs.ATTR |= 0x30;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
*bytesProcessed = bytesLeft;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 V_Core::NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
bool DmaStarting = !DmaStarted;
|
||||||
|
DmaStarted = true;
|
||||||
|
|
||||||
|
if(bytesLeft<2)
|
||||||
|
{
|
||||||
|
// execute interrupt code early
|
||||||
|
NewDmaInterrupt();
|
||||||
|
|
||||||
|
*bytesProcessed = bytesLeft;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IsDevBuild )
|
||||||
|
DebugCores[Index].lastsize = bytesLeft;
|
||||||
|
|
||||||
|
TSA &= ~7;
|
||||||
|
|
||||||
|
bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1));
|
||||||
|
|
||||||
|
if(adma_enable)
|
||||||
|
{
|
||||||
|
TSA&=0x1fff;
|
||||||
|
//Console.Error(" * SPU2: AutoDMA transfers not supported yet! (core %d)\n", Index);
|
||||||
|
|
||||||
|
if(DmaStarting)
|
||||||
|
{
|
||||||
|
ConLog(" * SPU2: AutoDMA transfer starting on core %d: %d bytes\n", Index, bytesLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 processed = 0;
|
||||||
|
while((AutoDmaFree>0)&&(bytesLeft>=0x400))
|
||||||
|
{
|
||||||
|
// copy block
|
||||||
|
|
||||||
|
LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile );
|
||||||
|
|
||||||
|
// HACKFIX!! DMAPtr can be invalid after a savestate load, so the savestate just forces it
|
||||||
|
// to NULL and we ignore it here. (used to work in old VM editions of PCSX2 with fixed
|
||||||
|
// addressing, but new PCSX2s have dynamic memory addressing).
|
||||||
|
|
||||||
|
s16* mptr = (s16*)data;
|
||||||
|
|
||||||
|
if(false)//(mode)
|
||||||
|
{
|
||||||
|
memcpy((ADMATempBuffer+(InputPosWrite<<1)),mptr,0x400);
|
||||||
|
mptr+=0x200;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy((ADMATempBuffer+InputPosWrite),mptr,0x200);
|
||||||
|
//memcpy((spu2mem+0x2000+(core<<10)+InputPosWrite),mptr,0x200);
|
||||||
|
mptr+=0x100;
|
||||||
|
|
||||||
|
memcpy((ADMATempBuffer+InputPosWrite+0x200),mptr,0x200);
|
||||||
|
//memcpy((spu2mem+0x2200+(core<<10)+InputPosWrite),mptr,0x200);
|
||||||
|
mptr+=0x100;
|
||||||
|
}
|
||||||
|
// See ReadInput at mixer.cpp for explanation on the commented out lines
|
||||||
|
//
|
||||||
|
|
||||||
|
InputPosWrite = (InputPosWrite + 0x100) & 0x1ff;
|
||||||
|
AutoDmaFree -= 0x200;
|
||||||
|
processed += 0x400;
|
||||||
|
bytesLeft -= 0x400;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(processed==0)
|
||||||
|
{
|
||||||
|
*bytesProcessed = 0;
|
||||||
|
return 768*15; // pause a bit
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*bytesProcessed = processed;
|
||||||
|
return 0; // auto pause
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Sliced transfers?
|
||||||
|
PlainDMAWrite((u16*)data,bytesLeft);
|
||||||
|
}
|
||||||
|
Regs.STATX &= ~0x80;
|
||||||
|
//Regs.ATTR |= 0x30;
|
||||||
|
#endif
|
||||||
|
*bytesProcessed = bytesLeft;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void V_Core::NewDmaInterrupt()
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
FileLog("[%10d] SPU2 interruptDMA4\n",Cycles);
|
||||||
|
Regs.STATX |= 0x80;
|
||||||
|
//Regs.ATTR &= ~0x30;
|
||||||
|
DmaStarted = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
|
@ -195,6 +195,44 @@ EXPORT_C_(void) CALLBACK SPU2setSettingsDir(const char* dir)
|
||||||
CfgSetSettingsDir( dir );
|
CfgSetSettingsDir( dir );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_C_(s32) SPU2dmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
|
||||||
|
{
|
||||||
|
if(channel==4)
|
||||||
|
return Cores[0].NewDmaRead(data,bytesLeft, bytesProcessed);
|
||||||
|
else
|
||||||
|
return Cores[1].NewDmaRead(data,bytesLeft, bytesProcessed);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_C_(s32) SPU2dmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed)
|
||||||
|
{
|
||||||
|
if(channel==4)
|
||||||
|
return Cores[0].NewDmaWrite(data,bytesLeft, bytesProcessed);
|
||||||
|
else
|
||||||
|
return Cores[1].NewDmaWrite(data,bytesLeft, bytesProcessed);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_C_(void) SPU2dmaInterrupt(s32 channel)
|
||||||
|
{
|
||||||
|
if(channel==4)
|
||||||
|
return Cores[0].NewDmaInterrupt();
|
||||||
|
else
|
||||||
|
return Cores[1].NewDmaInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)())
|
||||||
|
{
|
||||||
|
_irqcallback = SPU2callback;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)())
|
||||||
|
{
|
||||||
|
_irqcallback = SPU2callback;
|
||||||
|
dma4callback = DMA4callback;
|
||||||
|
dma7callback = DMA7callback;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EXPORT_C_(void) CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units
|
EXPORT_C_(void) CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units
|
||||||
{
|
{
|
||||||
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
||||||
|
@ -222,6 +260,13 @@ EXPORT_C_(void) CALLBACK SPU2interruptDMA4()
|
||||||
//Cores[0].Regs.ATTR &= ~0x30;
|
//Cores[0].Regs.ATTR &= ~0x30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_C_(void) CALLBACK SPU2interruptDMA7()
|
||||||
|
{
|
||||||
|
FileLog("[%10d] SPU2 interruptDMA7\n",Cycles);
|
||||||
|
Cores[1].Regs.STATX |= 0x80;
|
||||||
|
//Cores[1].Regs.ATTR &= ~0x30;
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT_C_(void) CALLBACK SPU2readDMA7Mem(u16* pMem, u32 size)
|
EXPORT_C_(void) CALLBACK SPU2readDMA7Mem(u16* pMem, u32 size)
|
||||||
{
|
{
|
||||||
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
||||||
|
@ -242,13 +287,6 @@ EXPORT_C_(void) CALLBACK SPU2writeDMA7Mem(u16* pMem, u32 size)
|
||||||
Cores[1].DoDMAwrite(pMem,size);
|
Cores[1].DoDMAwrite(pMem,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(void) CALLBACK SPU2interruptDMA7()
|
|
||||||
{
|
|
||||||
FileLog("[%10d] SPU2 interruptDMA7\n",Cycles);
|
|
||||||
Cores[1].Regs.STATX |= 0x80;
|
|
||||||
//Cores[1].Regs.ATTR &= ~0x30;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(s32) SPU2init()
|
EXPORT_C_(s32) SPU2init()
|
||||||
{
|
{
|
||||||
assert( regtable[0x400] == NULL );
|
assert( regtable[0x400] == NULL );
|
||||||
|
@ -452,13 +490,6 @@ EXPORT_C_(void) SPU2async(u32 cycles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)())
|
|
||||||
{
|
|
||||||
_irqcallback = SPU2callback;
|
|
||||||
dma4callback = DMA4callback;
|
|
||||||
dma7callback = DMA7callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT_C_(u16) SPU2read(u32 rmem)
|
EXPORT_C_(u16) SPU2read(u32 rmem)
|
||||||
{
|
{
|
||||||
// if(!replay_mode)
|
// if(!replay_mode)
|
||||||
|
|
|
@ -37,20 +37,28 @@ EXPORT_C_(void) SPU2close();
|
||||||
EXPORT_C_(void) SPU2shutdown();
|
EXPORT_C_(void) SPU2shutdown();
|
||||||
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
|
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
|
||||||
EXPORT_C_(u16) SPU2read(u32 mem);
|
EXPORT_C_(u16) SPU2read(u32 mem);
|
||||||
|
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
EXPORT_C_(s32) SPU2dmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||||
|
EXPORT_C_(s32) SPU2dmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||||
|
EXPORT_C_(void) SPU2dmaInterrupt(s32 channel);
|
||||||
|
|
||||||
|
// dma irq callbacks not needed anymore, they are handled by the dmac
|
||||||
|
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)());
|
||||||
|
#else
|
||||||
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
|
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
|
||||||
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
||||||
EXPORT_C_(void) SPU2interruptDMA4();
|
EXPORT_C_(void) SPU2interruptDMA4();
|
||||||
EXPORT_C_(void) SPU2readDMA7Mem(u16* pMem, u32 size);
|
EXPORT_C_(void) SPU2readDMA7Mem(u16* pMem, u32 size);
|
||||||
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
||||||
|
EXPORT_C_(void) SPU2interruptDMA7();
|
||||||
|
|
||||||
// all addresses passed by dma will be pointers to the array starting at baseaddr
|
// all addresses passed by dma will be pointers to the array starting at baseaddr
|
||||||
// This function is necessary to successfully save and reload the spu2 state
|
// This function is necessary to successfully save and reload the spu2 state
|
||||||
EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr);
|
|
||||||
|
|
||||||
EXPORT_C_(void) SPU2interruptDMA7();
|
|
||||||
EXPORT_C_(u32) SPU2ReadMemAddr(int core);
|
EXPORT_C_(u32) SPU2ReadMemAddr(int core);
|
||||||
EXPORT_C_(void) SPU2WriteMemAddr(int core,u32 value);
|
EXPORT_C_(void) SPU2WriteMemAddr(int core,u32 value);
|
||||||
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
|
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
|
||||||
|
#endif
|
||||||
|
|
||||||
// extended funcs
|
// extended funcs
|
||||||
// if start is 1, starts recording spu2 data, else stops
|
// if start is 1, starts recording spu2 data, else stops
|
||||||
|
@ -71,13 +79,16 @@ EXPORT_C_(s32) SPU2test();
|
||||||
extern u8 callirq;
|
extern u8 callirq;
|
||||||
|
|
||||||
extern void (* _irqcallback)();
|
extern void (* _irqcallback)();
|
||||||
|
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
extern void (* dma4callback)();
|
extern void (* dma4callback)();
|
||||||
extern void (* dma7callback)();
|
extern void (* dma7callback)();
|
||||||
|
|
||||||
extern double srate_pv;
|
|
||||||
|
|
||||||
extern s16 *input_data;
|
extern s16 *input_data;
|
||||||
extern u32 input_data_ptr;
|
extern u32 input_data_ptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern double srate_pv;
|
||||||
|
|
||||||
extern int recording;
|
extern int recording;
|
||||||
extern u32 lClocks;
|
extern u32 lClocks;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include "Global.h"
|
#include "Global.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
|
||||||
|
#include "PS2E-spu2.h" // required for ENABLE_NEW_IOPDMA_SPU2 define
|
||||||
|
|
||||||
// Core 0 Input is "SPDIF mode" - Source audio is AC3 compressed.
|
// Core 0 Input is "SPDIF mode" - Source audio is AC3 compressed.
|
||||||
|
|
||||||
// Core 1 Input is "CDDA mode" - Source audio data is 32 bits.
|
// Core 1 Input is "CDDA mode" - Source audio data is 32 bits.
|
||||||
|
@ -29,17 +31,17 @@
|
||||||
//
|
//
|
||||||
StereoOut32 V_Core::ReadInput_HiFi()
|
StereoOut32 V_Core::ReadInput_HiFi()
|
||||||
{
|
{
|
||||||
InputPos &= ~1;
|
InputPosRead &= ~1;
|
||||||
|
|
||||||
#ifdef PCM24_S1_INTERLEAVE
|
#ifdef PCM24_S1_INTERLEAVE
|
||||||
StereoOut32 retval(
|
StereoOut32 retval(
|
||||||
*((s32*)(ADMATempBuffer+(InputPos<<1))),
|
*((s32*)(ADMATempBuffer+(InputPosRead<<1))),
|
||||||
*((s32*)(ADMATempBuffer+(InputPos<<1)+2))
|
*((s32*)(ADMATempBuffer+(InputPosRead<<1)+2))
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
StereoOut32 retval(
|
StereoOut32 retval(
|
||||||
(s32&)(ADMATempBuffer[InputPos]),
|
(s32&)(ADMATempBuffer[InputPosRead]),
|
||||||
(s32&)(ADMATempBuffer[InputPos+0x200])
|
(s32&)(ADMATempBuffer[InputPosRead+0x200])
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -53,13 +55,17 @@ StereoOut32 V_Core::ReadInput_HiFi()
|
||||||
retval.Right >>= 4;
|
retval.Right >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputPos += 2;
|
InputPosRead += 2;
|
||||||
|
|
||||||
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
|
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
|
||||||
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
|
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
|
||||||
|
|
||||||
if( (InputPos==0x100) || (InputPos>=0x200) )
|
if( (InputPosRead==0x100) || (InputPosRead>=0x200) )
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
// WARNING: Assumes this to be in the same thread as the dmas
|
||||||
|
AutoDmaFree += 0x200;
|
||||||
|
#else
|
||||||
AdmaInProgress = 0;
|
AdmaInProgress = 0;
|
||||||
if(InputDataLeft >= 0x200)
|
if(InputDataLeft >= 0x200)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +76,7 @@ StereoOut32 V_Core::ReadInput_HiFi()
|
||||||
#endif
|
#endif
|
||||||
AdmaInProgress = 1;
|
AdmaInProgress = 1;
|
||||||
|
|
||||||
TSA = (Index<<10) + InputPos;
|
TSA = (Index<<10) + InputPosRead;
|
||||||
|
|
||||||
if (InputDataLeft < 0x200)
|
if (InputDataLeft < 0x200)
|
||||||
{
|
{
|
||||||
|
@ -87,7 +93,8 @@ StereoOut32 V_Core::ReadInput_HiFi()
|
||||||
DMAICounter = 1;
|
DMAICounter = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputPos &= 0x1ff;
|
#endif
|
||||||
|
InputPosRead &= 0x1ff;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -106,14 +113,18 @@ StereoOut32 V_Core::ReadInput()
|
||||||
//*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+InputPos);
|
//*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+InputPos);
|
||||||
|
|
||||||
retval = StereoOut32(
|
retval = StereoOut32(
|
||||||
(s32)ADMATempBuffer[InputPos],
|
(s32)ADMATempBuffer[InputPosRead],
|
||||||
(s32)ADMATempBuffer[InputPos+0x200]
|
(s32)ADMATempBuffer[InputPosRead+0x200]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
InputPos++;
|
InputPosRead++;
|
||||||
if( (InputPos==0x100) || (InputPos>=0x200) )
|
if( (InputPosRead==0x100) || (InputPosRead>=0x200) )
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||||
|
// WARNING: Assumes this to be in the same thread as the dmas
|
||||||
|
AutoDmaFree += 0x200;
|
||||||
|
#else
|
||||||
AdmaInProgress = 0;
|
AdmaInProgress = 0;
|
||||||
if(InputDataLeft >= 0x200)
|
if(InputDataLeft >= 0x200)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +133,7 @@ StereoOut32 V_Core::ReadInput()
|
||||||
AutoDMAReadBuffer(0);
|
AutoDMAReadBuffer(0);
|
||||||
|
|
||||||
AdmaInProgress = 1;
|
AdmaInProgress = 1;
|
||||||
TSA = (Index<<10) + InputPos;
|
TSA = (Index<<10) + InputPosRead;
|
||||||
|
|
||||||
if (InputDataLeft < 0x200)
|
if (InputDataLeft < 0x200)
|
||||||
{
|
{
|
||||||
|
@ -141,7 +152,8 @@ StereoOut32 V_Core::ReadInput()
|
||||||
DMAICounter = 1;
|
DMAICounter = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputPos&=0x1ff;
|
#endif
|
||||||
|
InputPosRead&=0x1ff;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,12 +103,16 @@ void dummy1()
|
||||||
|
|
||||||
void dummy4()
|
void dummy4()
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
SPU2interruptDMA4();
|
SPU2interruptDMA4();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void dummy7()
|
void dummy7()
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
SPU2interruptDMA7();
|
SPU2interruptDMA7();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Cread(a,b,c,d) if(fread(a,b,c,d)<b) break;
|
#define Cread(a,b,c,d) if(fread(a,b,c,d)<b) break;
|
||||||
|
@ -117,6 +121,7 @@ void dummy7()
|
||||||
#include "Windows/Dialogs.h"
|
#include "Windows/Dialogs.h"
|
||||||
EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow)
|
EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow)
|
||||||
{
|
{
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
// load file
|
// load file
|
||||||
FILE *file=fopen(filename,"rb");
|
FILE *file=fopen(filename,"rb");
|
||||||
|
|
||||||
|
@ -190,5 +195,6 @@ EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdS
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
replay_mode=false;
|
replay_mode=false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,13 +29,18 @@ EXPORTS
|
||||||
SPU2close @8
|
SPU2close @8
|
||||||
SPU2write @9
|
SPU2write @9
|
||||||
SPU2read @10
|
SPU2read @10
|
||||||
SPU2readDMA4Mem @11
|
SPU2async @11
|
||||||
SPU2writeDMA4Mem @12
|
|
||||||
SPU2readDMA7Mem @13
|
SPU2readDMA4Mem @12
|
||||||
SPU2writeDMA7Mem @14
|
SPU2writeDMA4Mem @13
|
||||||
SPU2async @15
|
SPU2readDMA7Mem @14
|
||||||
|
SPU2writeDMA7Mem @15
|
||||||
SPU2interruptDMA4 @16
|
SPU2interruptDMA4 @16
|
||||||
SPU2interruptDMA7 @17
|
SPU2interruptDMA7 @17
|
||||||
|
SPU2dmaRead
|
||||||
|
SPU2dmaWrite
|
||||||
|
SPU2dmaInterrupt
|
||||||
|
|
||||||
SPU2irqCallback @18
|
SPU2irqCallback @18
|
||||||
|
|
||||||
SPU2setupRecording @19
|
SPU2setupRecording @19
|
||||||
|
|
|
@ -391,7 +391,8 @@ struct V_Core
|
||||||
u16 AutoDMACtrl; // AutoDMA Status
|
u16 AutoDMACtrl; // AutoDMA Status
|
||||||
s32 DMAICounter; // DMA Interrupt Counter
|
s32 DMAICounter; // DMA Interrupt Counter
|
||||||
u32 InputDataLeft; // Input Buffer
|
u32 InputDataLeft; // Input Buffer
|
||||||
u32 InputPos;
|
u32 InputPosRead;
|
||||||
|
u32 InputPosWrite;
|
||||||
u32 InputDataProgress;
|
u32 InputDataProgress;
|
||||||
|
|
||||||
V_Reverb Revb; // Reverb Registers
|
V_Reverb Revb; // Reverb Registers
|
||||||
|
@ -419,6 +420,11 @@ struct V_Core
|
||||||
u8 AttrBit4;
|
u8 AttrBit4;
|
||||||
u8 AttrBit5;
|
u8 AttrBit5;
|
||||||
|
|
||||||
|
// new dma only
|
||||||
|
bool DmaStarted;
|
||||||
|
u32 AutoDmaFree;
|
||||||
|
|
||||||
|
// old dma only
|
||||||
u16* DMAPtr;
|
u16* DMAPtr;
|
||||||
u32 MADR;
|
u32 MADR;
|
||||||
u32 TADR;
|
u32 TADR;
|
||||||
|
@ -494,6 +500,11 @@ struct V_Core
|
||||||
|
|
||||||
void LogAutoDMA( FILE* fp );
|
void LogAutoDMA( FILE* fp );
|
||||||
|
|
||||||
|
s32 NewDmaRead(u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||||
|
s32 NewDmaWrite(u32* data, u32 bytesLeft, u32* bytesProcessed);
|
||||||
|
void NewDmaInterrupt();
|
||||||
|
|
||||||
|
// old dma only
|
||||||
void DoDMAwrite(u16* pMem, u32 size);
|
void DoDMAwrite(u16* pMem, u32 size);
|
||||||
void DoDMAread(u16* pMem, u32 size);
|
void DoDMAread(u16* pMem, u32 size);
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,7 @@ __forceinline void TimeUpdate(u32 cClocks)
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifndef ENABLE_NEW_IOPDMA_SPU2
|
||||||
//Update DMA4 interrupt delay counter
|
//Update DMA4 interrupt delay counter
|
||||||
if(Cores[0].DMAICounter>0)
|
if(Cores[0].DMAICounter>0)
|
||||||
{
|
{
|
||||||
|
@ -357,6 +358,7 @@ __forceinline void TimeUpdate(u32 cClocks)
|
||||||
Cores[1].MADR+=TickInterval<<1;
|
Cores[1].MADR+=TickInterval<<1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
dClocks -= TickInterval;
|
dClocks -= TickInterval;
|
||||||
lClocks += TickInterval;
|
lClocks += TickInterval;
|
||||||
|
|
Loading…
Reference in New Issue