SPU2ghz: Improved "on exit" stability of the XA2 driver on WinXP machines, by covering up for things the driver is *supposed* to do itself (but apparently does not, in WinXp at least).

Also fixed a Pcsx2 compilation error when trying to enable the experimental IPU speedhack.

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@383 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-12-03 19:22:10 +00:00 committed by Gregory Hainaut
parent 1c8203a3af
commit bc08e7397b
2 changed files with 24 additions and 28 deletions

View File

@ -32,7 +32,7 @@
#ifdef USE_IPU_SPEEDHACK #ifdef USE_IPU_SPEEDHACK
# define IPU_TO_INT( val ) ipu1Interrupt() # define IPU_TO_INT( val ) ipu1Interrupt()
# define IPU_FROM_INT( val ) ipu0Interrupt() # define IPU_FROM_INT( val ) ipu0Interrupt()
# define IPU_FASTCALL # define IPU_FORCEINLINE
#else #else
# define IPU_TO_INT( val ) CPU_INT( DMAC_TO_IPU, val ) # define IPU_TO_INT( val ) CPU_INT( DMAC_TO_IPU, val )
# define IPU_FROM_INT( val ) CPU_INT( DMAC_FROM_IPU, val ) # define IPU_FROM_INT( val ) CPU_INT( DMAC_FROM_IPU, val )
@ -946,7 +946,7 @@ static void ipuSETTH(u32 val) {
/////////////////////// ///////////////////////
// IPU Worker Thread // // IPU Worker Thread //
/////////////////////// ///////////////////////
#define IPU_TO_INTERRUPT(dma) { \ #define IPU_INTERRUPT(dma) { \
hwIntcIrq(INTC_IPU); \ hwIntcIrq(INTC_IPU); \
} }
@ -966,7 +966,7 @@ void IPUCMD_WRITE(u32 val) {
switch (ipuRegs->cmd.CMD) { switch (ipuRegs->cmd.CMD) {
case SCE_IPU_BCLR: case SCE_IPU_BCLR:
ipuBCLR(val); ipuBCLR(val);
IPU_TO_INTERRUPT(DMAC_TO_IPU); IPU_INTERRUPT(DMAC_TO_IPU);
return; return;
case SCE_IPU_VDEC: case SCE_IPU_VDEC:

View File

@ -44,6 +44,7 @@ private:
public: public:
SndBuffer* sndout; SndBuffer* sndout;
IXAudio2SourceVoice* pSourceVoice; IXAudio2SourceVoice* pSourceVoice;
CRITICAL_SECTION cs;
protected: protected:
STDMETHOD_(void, OnVoiceProcessingPassStart) () {} STDMETHOD_(void, OnVoiceProcessingPassStart) () {}
@ -53,8 +54,10 @@ private:
STDMETHOD_(void, OnBufferStart) ( void* ) {} STDMETHOD_(void, OnBufferStart) ( void* ) {}
STDMETHOD_(void, OnBufferEnd) ( void* context ) STDMETHOD_(void, OnBufferEnd) ( void* context )
{ {
EnterCriticalSection( &cs );
// All of these checks are necessary because XAudio2 is wonky shizat. // All of these checks are necessary because XAudio2 is wonky shizat.
if( pSourceVoice == NULL || context == NULL || sndout == NULL ) return; if( pSourceVoice == NULL || context == NULL ) return;
s16* qb = (s16*)context; s16* qb = (s16*)context;
@ -67,6 +70,7 @@ private:
buf.pContext=context; buf.pContext=context;
pSourceVoice->SubmitSourceBuffer( &buf ); pSourceVoice->SubmitSourceBuffer( &buf );
LeaveCriticalSection( &cs );
} }
STDMETHOD_(void, OnLoopEnd) ( void* ) {} STDMETHOD_(void, OnLoopEnd) ( void* ) {}
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) { }; STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) { };
@ -121,9 +125,8 @@ public:
wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign; wfx.nAvgBytesPerSec = SampleRate * wfx.nBlockAlign;
wfx.cbSize=0; wfx.cbSize=0;
// Egh.. not sure if the initializer for these values should be before InitializeCriticalSection( &voiceContext.cs );
// or after CreateSourceVoice. Some drivers could do evil things to EnterCriticalSection( &voiceContext.cs );
// our structure whn we create the voice.
// //
// Create an XAudio2 voice to stream this wave // Create an XAudio2 voice to stream this wave
@ -136,9 +139,8 @@ public:
return -1; return -1;
} }
// See comment above. Leave this redundant code in to protect against
// potentially stupid drivers.
voiceContext.pSourceVoice = pSourceVoice; voiceContext.pSourceVoice = pSourceVoice;
voiceContext.sndout = sb;
pSourceVoice->FlushSourceBuffers(); pSourceVoice->FlushSourceBuffers();
pSourceVoice->Start( 0, 0 ); pSourceVoice->Start( 0, 0 );
@ -164,34 +166,27 @@ public:
buf.pAudioData=(BYTE*)buf.pContext; buf.pAudioData=(BYTE*)buf.pContext;
pSourceVoice->SubmitSourceBuffer( &buf ); pSourceVoice->SubmitSourceBuffer( &buf );
} }
voiceContext.sndout = sb; LeaveCriticalSection( &voiceContext.cs );
return 0; return 0;
} }
void Close() void Close()
{ {
// EnterCriticalSection( &voiceContext.cs );
// Clean up? // Clean up?
// Apparently XA2 would just rather we NOT clean up...
/*if( pSourceVoice != NULL )
{
//pSourceVoice->FlushSourceBuffers();
//pSourceVoice->Stop( 0 );
//Sleep(10); // give the engine some time to flush voices
//pSourceVoice->DestroyVoice();
}*/
//Sleep(10); // give the engine some more time, because I don't trust it.
//
// Cleanup XAudio2
//
// All XAudio2 interfaces are released when the engine is destroyed, // All XAudio2 interfaces are released when the engine is destroyed,
// but being tidy never hurt. // but being tidy never hurt.
// Actually it can hurt. As of DXSDK Aug 2008, doing a full cleanup causes
// XA2 on Vista to crash. Even if you copy/paste code directly from Microsoft.
// But doing no cleanup at all causes XA2 under XP to crash. So after much trial
// and error we found a happy comprimise as follows:
if( pSourceVoice != NULL )
pSourceVoice->DestroyVoice();
if( pMasteringVoice != NULL ) if( pMasteringVoice != NULL )
pMasteringVoice->DestroyVoice(); pMasteringVoice->DestroyVoice();
@ -202,7 +197,8 @@ public:
voiceContext.sndout = NULL; voiceContext.sndout = NULL;
voiceContext.pSourceVoice = NULL; voiceContext.pSourceVoice = NULL;
pSourceVoice = NULL; pSourceVoice = NULL;
LeaveCriticalSection( &voiceContext.cs );
DeleteCriticalSection( &voiceContext.cs );
CoUninitialize(); CoUninitialize();
} }