mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X: Fixed some more major bugs and typos; most sound *should* be working again now. Added a hackfix for a crash in the BIOS cased by what *should* be correct handling of IRQAs.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1947 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
d386ce0ac6
commit
910669f937
|
@ -128,15 +128,15 @@ void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
|||
if(MsgAutoDMA()) ConLog(" * SPU2: DMA%c AutoDMA Transfer of %d bytes to %x (%02x %x %04x).\n",
|
||||
GetDmaIndexChar(), size<<1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR)&0x7fff);
|
||||
|
||||
InputDataProgress=0;
|
||||
InputDataProgress = 0;
|
||||
if((AutoDMACtrl&(Index+1))==0)
|
||||
{
|
||||
TSA=0x2000+(Index<<10);
|
||||
DMAICounter=size;
|
||||
TSA = 0x2000 + (Index<<10);
|
||||
DMAICounter = size;
|
||||
}
|
||||
else if(size>=512)
|
||||
{
|
||||
InputDataLeft=size;
|
||||
InputDataLeft = size;
|
||||
if(AdmaInProgress==0)
|
||||
{
|
||||
#ifdef PCM24_S1_INTERLEAVE
|
||||
|
@ -149,26 +149,43 @@ void V_Core::StartADMAWrite(u16 *pMem, u32 sz)
|
|||
AutoDMAReadBuffer(Index,0);
|
||||
}
|
||||
#else
|
||||
if(((PlayMode&4)==4)&&(Index==0))
|
||||
if( ((PlayMode&4)==4) && (Index==0) )
|
||||
Cores[0].InputPos=0;
|
||||
|
||||
AutoDMAReadBuffer(0);
|
||||
#endif
|
||||
|
||||
if(size==512)
|
||||
DMAICounter=size;
|
||||
DMAICounter = size;
|
||||
}
|
||||
|
||||
AdmaInProgress=1;
|
||||
AdmaInProgress = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
InputDataLeft=0;
|
||||
DMAICounter=1;
|
||||
InputDataLeft = 0;
|
||||
DMAICounter = 1;
|
||||
}
|
||||
TADR=MADR+(size<<1);
|
||||
TADR = MADR + (size<<1);
|
||||
}
|
||||
|
||||
// HACKFIX: The BIOS breaks if we check the IRQA for both cores when issuing DMA writes. The
|
||||
// breakage is a null psxRegs.pc being loaded form some memory address (haven't traced it deeper
|
||||
// yet). We get around it by only checking the current core's IRQA, instead of doing the
|
||||
// *correct* thing and checking both. This might break some games, but having a working BIOS
|
||||
// is more important for now, until a proper fix can be uncovered.
|
||||
//
|
||||
// This problem might be caused by bad DMA timings in the IOP or a lack of proper IRQ
|
||||
// handling by the Effects Processor. After those are implemented, let's hope it gets
|
||||
// magically fixed?
|
||||
//
|
||||
// Note: This appears to affect DMA Writes only, so DMA Read DMAs are left intact (both core
|
||||
// IRQAs are tested). Very few games use DMA reads tho, so it could just be a case of "works
|
||||
// by the grace of not being used."
|
||||
//
|
||||
#define NO_BIOS_HACKFIX 0 // set to 1 to disable the hackfix
|
||||
|
||||
|
||||
void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
||||
{
|
||||
// Perform an alignment check.
|
||||
|
@ -239,10 +256,33 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
|||
//memset( pcm_cache_flags, 0, endpt2 );
|
||||
|
||||
// Emulation Grayarea: Should addresses wrap around to zero, or wrap around to
|
||||
// 0x2800? Hard to know for usre (almost no games depend on this)
|
||||
// 0x2800? Hard to know for sure (almost no games depend on this)
|
||||
|
||||
memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 );
|
||||
TDA = (buff2end+1) & 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 &&
|
||||
|
||||
#if NO_BIOS_HACKFIX
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
// Note: (start is inclusive, dest exclusive -- fixes DMC1 FMVs)
|
||||
|
||||
if( Cores[i].IRQEnable && (Cores[i].IRQA >= TSA) || (Cores[i].IRQA < TDA) )
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
#else
|
||||
if( IRQEnable && (IRQA >= TSA) || (IRQA < TDA) )
|
||||
{
|
||||
Spdif.Info = 4 << Index;
|
||||
SetIrqCall();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -250,30 +290,28 @@ void V_Core::PlainDMAWrite(u16 *pMem, u32 size)
|
|||
// Just set the TDA and check for an IRQ...
|
||||
|
||||
TDA = buff1end;
|
||||
}
|
||||
|
||||
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||
// Important: Test both core IRQ settings for either DMA!
|
||||
// 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++ )
|
||||
{
|
||||
// Note: (start is inclusive, dest exclusive -- fixes DMC1 FMVs)
|
||||
|
||||
if( Cores[i].IRQEnable && (Cores[i].IRQA >= Cores[i].TSA) && (Cores[i].IRQA < Cores[i].TDA) )
|
||||
#if NO_BIOS_HACKFIX
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
// Note: (start is inclusive, dest exclusive -- fixes DMC1 FMVs)
|
||||
|
||||
if( Cores[i].IRQEnable && (Cores[i].IRQA >= TSA) && (Cores[i].IRQA < TDA) )
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(IRQEnable)
|
||||
{
|
||||
|
||||
if( ( IRQA >= TSA ) && ( IRQA < TDA ) )
|
||||
#else
|
||||
if( IRQEnable && (IRQA >= TSA) && (IRQA < TDA) )
|
||||
{
|
||||
Spdif.Info = 4 << Index;
|
||||
SetIrqCall();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TSA = TDA & 0xFFFF0;
|
||||
|
@ -308,6 +346,19 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
|
|||
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
|
||||
{
|
||||
|
@ -315,17 +366,17 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
|
|||
// 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!
|
||||
// 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 >= Cores[i].TSA) && (Cores[i].IRQA < Cores[i].TDA) )
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
if( Cores[i].IRQEnable && (Cores[i].IRQA >= TSA) && (Cores[i].IRQA < TDA) )
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -177,8 +177,6 @@ EXPORT_C_(void) CALLBACK SPU2writeDMA4Mem(u16* pMem, u32 size) // size now in 16
|
|||
|
||||
EXPORT_C_(void) CALLBACK SPU2interruptDMA4()
|
||||
{
|
||||
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
||||
|
||||
FileLog("[%10d] SPU2 interruptDMA4\n",Cycles);
|
||||
Cores[0].Regs.STATX |= 0x80;
|
||||
//Cores[0].Regs.ATTR &= ~0x30;
|
||||
|
@ -206,8 +204,6 @@ EXPORT_C_(void) CALLBACK SPU2writeDMA7Mem(u16* pMem, u32 size)
|
|||
|
||||
EXPORT_C_(void) CALLBACK SPU2interruptDMA7()
|
||||
{
|
||||
if( cyclePtr != NULL ) TimeUpdate( *cyclePtr );
|
||||
|
||||
FileLog("[%10d] SPU2 interruptDMA7\n",Cycles);
|
||||
Cores[1].Regs.STATX |= 0x80;
|
||||
//Cores[1].Regs.ATTR &= ~0x30;
|
||||
|
@ -266,10 +262,8 @@ EXPORT_C_(s32) SPU2init()
|
|||
|
||||
memset(spu2regs, 0, 0x010000);
|
||||
memset(_spu2mem, 0, 0x200000);
|
||||
Cores[0].Index = 0;
|
||||
Cores[1].Index = 1;
|
||||
Cores[0].Reset();
|
||||
Cores[1].Reset();
|
||||
Cores[0].Reset(0);
|
||||
Cores[1].Reset(1);
|
||||
|
||||
DMALogOpen();
|
||||
|
||||
|
|
|
@ -18,6 +18,177 @@
|
|||
#include "Global.h"
|
||||
#include "dma.h"
|
||||
|
||||
#if 0
|
||||
static void __fastcall __ReadInput( uint core, StereoOut32& PData )
|
||||
{
|
||||
V_Core& thiscore( Cores[core] );
|
||||
|
||||
if((thiscore.AutoDMACtrl&(core+1))==(core+1))
|
||||
{
|
||||
s32 tl,tr;
|
||||
|
||||
if((core==1)&&((PlayMode&8)==8))
|
||||
{
|
||||
thiscore.InputPos&=~1;
|
||||
|
||||
// CDDA mode
|
||||
// Source audio data is 32 bits.
|
||||
// We don't yet have the capability to handle this high res input data
|
||||
// so we just downgrade it to 16 bits for now.
|
||||
|
||||
#ifdef PCM24_S1_INTERLEAVE
|
||||
*PData.Left=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1))));
|
||||
*PData.Right=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)+2)));
|
||||
#else
|
||||
s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]);
|
||||
s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]);
|
||||
PData.Left = *pl;
|
||||
PData.Right = *pr;
|
||||
#endif
|
||||
|
||||
PData.Left >>= 2; //give 30 bit data (SndOut downsamples the rest of the way)
|
||||
PData.Right >>= 2;
|
||||
|
||||
thiscore.InputPos+=2;
|
||||
if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) {
|
||||
thiscore.AdmaInProgress=0;
|
||||
if(thiscore.InputDataLeft>=0x200)
|
||||
{
|
||||
u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress;
|
||||
|
||||
#ifdef PCM24_S1_INTERLEAVE
|
||||
thiscore.AutoDMAReadBuffer(1);
|
||||
#else
|
||||
thiscore.AutoDMAReadBuffer(0);
|
||||
#endif
|
||||
thiscore.AdmaInProgress=1;
|
||||
|
||||
thiscore.TSA=(core<<10)+thiscore.InputPos;
|
||||
|
||||
if (thiscore.InputDataLeft<0x200)
|
||||
{
|
||||
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
||||
|
||||
if( IsDevBuild )
|
||||
{
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
thiscore.InputDataLeft=0;
|
||||
thiscore.DMAICounter=1;
|
||||
}
|
||||
}
|
||||
thiscore.InputPos&=0x1ff;
|
||||
}
|
||||
|
||||
}
|
||||
else if((core==0)&&((PlayMode&4)==4))
|
||||
{
|
||||
thiscore.InputPos&=~1;
|
||||
|
||||
s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]);
|
||||
s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]);
|
||||
PData.Left = *pl;
|
||||
PData.Right = *pr;
|
||||
|
||||
thiscore.InputPos+=2;
|
||||
if(thiscore.InputPos>=0x200) {
|
||||
thiscore.AdmaInProgress=0;
|
||||
if(thiscore.InputDataLeft>=0x200)
|
||||
{
|
||||
u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress;
|
||||
|
||||
thiscore.AutoDMAReadBuffer(0);
|
||||
|
||||
thiscore.AdmaInProgress=1;
|
||||
|
||||
thiscore.TSA=(core<<10)+thiscore.InputPos;
|
||||
|
||||
if (thiscore.InputDataLeft<0x200)
|
||||
{
|
||||
FileLog("[%10d] Spdif AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
||||
|
||||
if( IsDevBuild )
|
||||
{
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
thiscore.InputDataLeft=0;
|
||||
thiscore.DMAICounter=1;
|
||||
}
|
||||
}
|
||||
thiscore.InputPos&=0x1ff;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if((core==1)&&((PlayMode&2)!=0))
|
||||
{
|
||||
tl=0;
|
||||
tr=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using the temporary buffer because this area gets overwritten by some other code.
|
||||
//*PData.Left = (s32)*(s16*)(spu2mem+0x2000+(core<<10)+thiscore.InputPos);
|
||||
//*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+thiscore.InputPos);
|
||||
|
||||
tl = (s32)thiscore.ADMATempBuffer[thiscore.InputPos];
|
||||
tr = (s32)thiscore.ADMATempBuffer[thiscore.InputPos+0x200];
|
||||
|
||||
}
|
||||
|
||||
PData.Left = tl;
|
||||
PData.Right = tr;
|
||||
|
||||
thiscore.InputPos++;
|
||||
if((thiscore.InputPos==0x100)||(thiscore.InputPos>=0x200)) {
|
||||
thiscore.AdmaInProgress=0;
|
||||
if(thiscore.InputDataLeft>=0x200)
|
||||
{
|
||||
u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress;
|
||||
|
||||
thiscore.AutoDMAReadBuffer(0);
|
||||
|
||||
thiscore.AdmaInProgress=1;
|
||||
|
||||
thiscore.TSA=(core<<10)+thiscore.InputPos;
|
||||
|
||||
if (thiscore.InputDataLeft<0x200)
|
||||
{
|
||||
thiscore.AutoDMACtrl |= ~3;
|
||||
|
||||
if( IsDevBuild )
|
||||
{
|
||||
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, (core==0)?'4':'7');
|
||||
if(thiscore.InputDataLeft>0)
|
||||
{
|
||||
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
thiscore.InputDataLeft = 0;
|
||||
thiscore.DMAICounter = 1;
|
||||
}
|
||||
}
|
||||
thiscore.InputPos&=0x1ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PData.Left = 0;
|
||||
PData.Right = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// CDDA mode - Source audio data is 32 bits.
|
||||
// PS2 note: Very! few PS2 games use this mode. Some PSX games used it, however no
|
||||
// *known* PS2 game does since it was likely only available if the game was recorded to CD
|
||||
|
@ -49,8 +220,8 @@ __forceinline StereoOut32 V_Core::ReadInput_HiFi( bool isCDDA )
|
|||
}
|
||||
|
||||
InputPos += 2;
|
||||
//if( (InputPos==0x100) || (InputPos>=0x200) ) // CDDA mode?
|
||||
if( InputPos >= 0x200 )
|
||||
if( (InputPos==0x100) || (InputPos>=0x200) ) // CDDA mode?
|
||||
//if( InputPos >= 0x200 )
|
||||
{
|
||||
AdmaInProgress = 0;
|
||||
if(InputDataLeft >= 0x200)
|
||||
|
@ -88,6 +259,10 @@ __forceinline StereoOut32 V_Core::ReadInput_HiFi( bool isCDDA )
|
|||
|
||||
StereoOut32 V_Core::ReadInput()
|
||||
{
|
||||
/*StereoOut32 retval2;
|
||||
__ReadInput( Index, retval2 );
|
||||
return retval2;*/
|
||||
|
||||
if((AutoDMACtrl&(Index+1)) != (Index+1))
|
||||
return StereoOut32();
|
||||
|
||||
|
|
|
@ -432,11 +432,12 @@ struct V_Core
|
|||
// V_Core Methods
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
V_Core() : Index( -1 ) {} // uninitialized constructor
|
||||
// uninitialized constructor
|
||||
V_Core() : Index( -1 ), DMAPtr( NULL ) {}
|
||||
V_Core( int idx ); // our badass constructor
|
||||
virtual ~V_Core() throw();
|
||||
|
||||
void Reset();
|
||||
void Reset( int index );
|
||||
void UpdateEffectsBufferSize();
|
||||
|
||||
s32 EffectsBufferIndexer( s32 offset ) const;
|
||||
|
|
|
@ -107,11 +107,11 @@ V_Core::~V_Core() throw()
|
|||
}*/
|
||||
}
|
||||
|
||||
void V_Core::Reset()
|
||||
void V_Core::Reset( int index )
|
||||
{
|
||||
memset( this, 0, sizeof(V_Core) );
|
||||
|
||||
const int c = Index;
|
||||
const int c = Index = index;
|
||||
|
||||
Regs.STATX = 0;
|
||||
Regs.ATTR = 0;
|
||||
|
@ -276,7 +276,7 @@ u32 TicksThread = 0;
|
|||
|
||||
__forceinline void TimeUpdate(u32 cClocks)
|
||||
{
|
||||
u32 dClocks = cClocks-lClocks;
|
||||
s32 dClocks = cClocks-lClocks;
|
||||
|
||||
// [Air]: Sanity Check
|
||||
// If for some reason our clock value seems way off base, just mix
|
||||
|
@ -306,7 +306,7 @@ __forceinline void TimeUpdate(u32 cClocks)
|
|||
Cores[0].InitDelay--;
|
||||
if(Cores[0].InitDelay==0)
|
||||
{
|
||||
Cores[0].Reset();
|
||||
Cores[0].Reset(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ __forceinline void TimeUpdate(u32 cClocks)
|
|||
Cores[1].InitDelay--;
|
||||
if(Cores[1].InitDelay==0)
|
||||
{
|
||||
Cores[1].Reset();
|
||||
Cores[1].Reset(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,7 +824,7 @@ static void __fastcall RegWrite_Core( u16 value )
|
|||
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
if(Cores[i].IRQEnable && (Cores[i].IRQA == Cores[i].TSA))
|
||||
if(Cores[i].IRQEnable && (Cores[i].IRQA == thiscore.TSA))
|
||||
{
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
|
@ -851,7 +851,7 @@ static void __fastcall RegWrite_Core( u16 value )
|
|||
}
|
||||
else
|
||||
{
|
||||
thiscore.Reset();
|
||||
thiscore.Reset(thiscore.Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue