diff --git a/plugins/spu2-x/src/ADSR.cpp b/plugins/spu2-x/src/ADSR.cpp index a79142fa69..903fdef4a2 100644 --- a/plugins/spu2-x/src/ADSR.cpp +++ b/plugins/spu2-x/src/ADSR.cpp @@ -15,7 +15,7 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" static const s32 ADSR_MAX_VOL = 0x7fffffff; @@ -34,7 +34,7 @@ void InitADSR() // INIT ADSR else rate <<= shift; - PsxRates[i] = (int)min( rate, 0x3fffffffLL ); + PsxRates[i] = (int)std::min( rate, 0x3fffffffLL ); } } diff --git a/plugins/spu2-x/src/BaseTypes.h b/plugins/spu2-x/src/BaseTypes.h deleted file mode 100644 index cb72ed104f..0000000000 --- a/plugins/spu2-x/src/BaseTypes.h +++ /dev/null @@ -1,119 +0,0 @@ - -#ifndef _BASETYPES_H_ -#define _BASETYPES_H_ - -#include "PS2Edefs.h" - -//system defines -#ifdef __LINUX__ -# undef __LINUX__ // supress gtk's warnings on redefinition -# include -#else -# define WINVER 0x0501 -# define _WIN32_WINNT 0x0501 -# include -# include -# include -# include "resource.h" -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include - -using std::string; -using std::wstring; - -////////////////////////////////////////////////////////////////////////// -// Override Win32 min/max macros with the STL's type safe and macro -// free varieties (much safer!) - -#undef min -#undef max - -#include - -using std::min; -using std::max; - -template< typename T > -static __forceinline void Clampify( T& src, T min, T max ) -{ - src = std::min( std::max( src, min ), max ); -} - -template< typename T > -static __forceinline T GetClamped( T src, T min, T max ) -{ - return std::min( std::max( src, min ), max ); -} - -extern void SysMessage(const char *fmt, ...); - -////////////////////////////////////////////////////////////// -// Dev / Debug conditionals -- -// Consts for using if() statements instead of uglier #ifdef macros. -// Abbreviated macros for dev/debug only consoles and msgboxes. - -#ifdef SPU2X_DEVBUILD -# define DevCon Console -# define DevMsg MsgBox -#else -# define DevCon 0&&Console -# define DevMsg -#endif - -#ifdef PCSX2_DEBUG -# define DbgCon Console -#else -# define DbgCon 0&&Console -#endif - -struct StereoOut16; -struct StereoOutFloat; - -struct StereoOut32 -{ - static StereoOut32 Empty; - - s32 Left; - s32 Right; - - StereoOut32() : - Left( 0 ), - Right( 0 ) - { - } - - StereoOut32( s32 left, s32 right ) : - Left( left ), - Right( right ) - { - } - - StereoOut32( const StereoOut16& src ); - explicit StereoOut32( const StereoOutFloat& src ); - - StereoOut16 DownSample() const; - - StereoOut32 operator+( const StereoOut32& right ) const - { - return StereoOut32( - Left + right.Left, - Right + right.Right - ); - } - - StereoOut32 operator/( int src ) const - { - return StereoOut32( Left / src, Right / src ); - } -}; - -#endif diff --git a/plugins/spu2-x/src/Config.h b/plugins/spu2-x/src/Config.h new file mode 100644 index 0000000000..190bd88891 --- /dev/null +++ b/plugins/spu2-x/src/Config.h @@ -0,0 +1,88 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ + +#pragma once + +extern bool DebugEnabled; + +extern bool _MsgToConsole; +extern bool _MsgKeyOnOff; +extern bool _MsgVoiceOff; +extern bool _MsgDMA; +extern bool _MsgAutoDMA; +extern bool _MsgOverruns; +extern bool _MsgCache; + +extern bool _AccessLog; +extern bool _DMALog; +extern bool _WaveLog; + +extern bool _CoresDump; +extern bool _MemDump; +extern bool _RegDump; + +static __forceinline bool MsgToConsole() { return _MsgToConsole & DebugEnabled; } + +static __forceinline bool MsgKeyOnOff() { return _MsgKeyOnOff & MsgToConsole(); } +static __forceinline bool MsgVoiceOff() { return _MsgVoiceOff & MsgToConsole(); } +static __forceinline bool MsgDMA() { return _MsgDMA & MsgToConsole(); } +static __forceinline bool MsgAutoDMA() { return _MsgAutoDMA & MsgDMA(); } +static __forceinline bool MsgOverruns() { return _MsgOverruns & MsgToConsole(); } +static __forceinline bool MsgCache() { return _MsgCache & MsgToConsole(); } + +static __forceinline bool AccessLog() { return _AccessLog & DebugEnabled; } +static __forceinline bool DMALog() { return _DMALog & DebugEnabled; } +static __forceinline bool WaveLog() { return _WaveLog & DebugEnabled; } + +static __forceinline bool CoresDump() { return _CoresDump & DebugEnabled; } +static __forceinline bool MemDump() { return _MemDump & DebugEnabled; } +static __forceinline bool RegDump() { return _RegDump & DebugEnabled; } + + +extern wchar_t AccessLogFileName[255]; +extern wchar_t WaveLogFileName[255]; +extern wchar_t DMA4LogFileName[255]; +extern wchar_t DMA7LogFileName[255]; +extern wchar_t CoresDumpFileName[255]; +extern wchar_t MemDumpFileName[255]; +extern wchar_t RegDumpFileName[255]; + +extern int Interpolation; + +extern bool EffectsDisabled; + +extern u32 OutputModule; +extern int SndOutLatencyMS; + +extern wchar_t dspPlugin[]; +extern int dspPluginModule; + +extern bool dspPluginEnabled; +extern bool timeStretchDisabled; +extern bool StereoExpansionEnabled; + +namespace SoundtouchCfg +{ + extern void ApplySettings( soundtouch::SoundTouch& sndtouch ); +} + +////// + +extern void ReadSettings(); +extern void WriteSettings(); +extern void configure(); +extern void AboutBox(); diff --git a/plugins/spu2-x/src/ConvertUTF.cpp b/plugins/spu2-x/src/ConvertUTF.cpp index 24679ae4fd..66d031607d 100644 --- a/plugins/spu2-x/src/ConvertUTF.cpp +++ b/plugins/spu2-x/src/ConvertUTF.cpp @@ -38,13 +38,9 @@ ------------------------------------------------------------------------ */ -#include "PS2Etypes.h" - -#include -#include +#include "Global.h" #include "ConvertUTF.h" - using std::string; using std::wstring; diff --git a/plugins/spu2-x/src/Debug.cpp b/plugins/spu2-x/src/Debug.cpp index 404db45524..114f728ff1 100644 --- a/plugins/spu2-x/src/Debug.cpp +++ b/plugins/spu2-x/src/Debug.cpp @@ -15,7 +15,7 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" int crazy_debug=0; diff --git a/plugins/spu2-x/src/Decoder.cpp b/plugins/spu2-x/src/Decoder.cpp index f2174be3ef..5f76691481 100644 --- a/plugins/spu2-x/src/Decoder.cpp +++ b/plugins/spu2-x/src/Decoder.cpp @@ -15,7 +15,8 @@ //License along with this library; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -#include "Spu2.h" + +#include "Global.h" extern "C" { #include "liba52/inttypes.h" @@ -129,12 +130,13 @@ s32 stoi(sample_t n) //input: [-1..1] void spdif_update() { - StereoOut32 Data; + for(int i=0;i. */ -#include "Spu2.h" +#include "Global.h" +#include "dma.h" + +#include "PS2E-spu2.h" // temporary until I resolve cyclePtr/TimeUpdate dependencies. extern u8 callirq; -FILE *DMA4LogFile=0; -FILE *DMA7LogFile=0; -FILE *ADMA4LogFile=0; -FILE *ADMA7LogFile=0; -FILE *ADMAOutLogFile=0; +static FILE *DMA4LogFile = NULL; +static FILE *DMA7LogFile = NULL; +static FILE *ADMA4LogFile = NULL; +static FILE *ADMA7LogFile = NULL; +static FILE *ADMAOutLogFile = NULL; -FILE *REGWRTLogFile[2]={0,0}; - -int packcount=0; - -u16* MBASE[2] = {0,0}; - -u16* DMABaseAddr; +static FILE *REGWRTLogFile[2] = {0,0}; void DMALogOpen() { @@ -56,16 +53,6 @@ void DMA7LogWrite(void *lpData, u32 ulSize) { fwrite(lpData,ulSize,1,DMA7LogFile); } -void ADMA4LogWrite(void *lpData, u32 ulSize) { - if(!DMALog()) return; - if (!ADMA4LogFile) return; - fwrite(lpData,ulSize,1,ADMA4LogFile); -} -void ADMA7LogWrite(void *lpData, u32 ulSize) { - if(!DMALog()) return; - if (!ADMA7LogFile) return; - fwrite(lpData,ulSize,1,ADMA7LogFile); -} void ADMAOutLogWrite(void *lpData, u32 ulSize) { if(!DMALog()) return; if (!ADMAOutLogFile) return; @@ -79,118 +66,110 @@ void RegWriteLog(u32 core,u16 value) fwrite(&value,2,1,REGWRTLogFile[core]); } -void DMALogClose() { - if(!DMALog()) return; - if (DMA4LogFile) fclose(DMA4LogFile); - if (DMA7LogFile) fclose(DMA7LogFile); - if (REGWRTLogFile[0]) fclose(REGWRTLogFile[0]); - if (REGWRTLogFile[1]) fclose(REGWRTLogFile[1]); - if (ADMA4LogFile) fclose(ADMA4LogFile); - if (ADMA7LogFile) fclose(ADMA7LogFile); - if (ADMAOutLogFile) fclose(ADMAOutLogFile); +void DMALogClose() +{ + safe_fclose(DMA4LogFile); + safe_fclose(DMA7LogFile); + safe_fclose(REGWRTLogFile[0]); + safe_fclose(REGWRTLogFile[1]); + safe_fclose(ADMA4LogFile); + safe_fclose(ADMA7LogFile); + safe_fclose(ADMAOutLogFile); } - -__forceinline u16 DmaRead(u32 core) +void V_Core::LogAutoDMA( FILE* fp ) { - const u16 ret = (u16)spu2M_Read(Cores[core].TDA); - Cores[core].TDA++; - Cores[core].TDA&=0xfffff; - return ret; + if( !DMALog() || !fp ) return; + fwrite( DMAPtr+InputDataProgress, 0x400, 1, fp ); } -__forceinline void DmaWrite(u32 core, u16 value) +void V_Core::AutoDMAReadBuffer(int mode) //mode: 0= split stereo; 1 = do not split stereo { - spu2M_Write( Cores[core].TSA, value ); - Cores[core].TSA++; - Cores[core].TSA&=0xfffff; -} + int spos = ((InputPos+0xff)&0x100); //starting position of the free buffer -void AutoDMAReadBuffer(int core, int mode) //mode: 0= split stereo; 1 = do not split stereo -{ - int spos=((Cores[core].InputPos+0xff)&0x100); //starting position of the free buffer + LogAutoDMA( Index ? ADMA7LogFile : ADMA4LogFile ); - if(core==0) - ADMA4LogWrite(Cores[core].DMAPtr+Cores[core].InputDataProgress,0x400); - else - ADMA7LogWrite(Cores[core].DMAPtr+Cores[core].InputDataProgress,0x400); + // 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). if(mode) - { - //hacky :p - - memcpy((Cores[core].ADMATempBuffer+(spos<<1)),Cores[core].DMAPtr+Cores[core].InputDataProgress,0x400); - Cores[core].MADR+=0x400; - Cores[core].InputDataLeft-=0x200; - Cores[core].InputDataProgress+=0x200; + { + if( DMAPtr != NULL ) + memcpy((ADMATempBuffer+(spos<<1)),DMAPtr+InputDataProgress,0x400); + MADR+=0x400; + InputDataLeft-=0x200; + InputDataProgress+=0x200; } else { - memcpy((Cores[core].ADMATempBuffer+spos),Cores[core].DMAPtr+Cores[core].InputDataProgress,0x200); - //memcpy((spu2mem+0x2000+(core<<10)+spos),Cores[core].DMAPtr+Cores[core].InputDataProgress,0x200); - Cores[core].MADR+=0x200; - Cores[core].InputDataLeft-=0x100; - Cores[core].InputDataProgress+=0x100; + if( DMAPtr != NULL ) + memcpy((ADMATempBuffer+spos),DMAPtr+InputDataProgress,0x200); + //memcpy((spu2mem+0x2000+(core<<10)+spos),DMAPtr+InputDataProgress,0x200); + MADR+=0x200; + InputDataLeft-=0x100; + InputDataProgress+=0x100; - memcpy((Cores[core].ADMATempBuffer+spos+0x200),Cores[core].DMAPtr+Cores[core].InputDataProgress,0x200); - //memcpy((spu2mem+0x2200+(core<<10)+spos),Cores[core].DMAPtr+Cores[core].InputDataProgress,0x200); - Cores[core].MADR+=0x200; - Cores[core].InputDataLeft-=0x100; - Cores[core].InputDataProgress+=0x100; + if( DMAPtr != NULL ) + memcpy((ADMATempBuffer+spos+0x200),DMAPtr+InputDataProgress,0x200); + //memcpy((spu2mem+0x2200+(core<<10)+spos),DMAPtr+InputDataProgress,0x200); + MADR+=0x200; + InputDataLeft-=0x100; + InputDataProgress+=0x100; } // See ReadInput at mixer.cpp for explanation on the commented out lines // } -void StartADMAWrite(int core,u16 *pMem, u32 sz) +void V_Core::StartADMAWrite(u16 *pMem, u32 sz) { - 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", - (core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff); + GetDmaIndexChar(), size<<1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR)&0x7fff); - Cores[core].InputDataProgress=0; - if((Cores[core].AutoDMACtrl&(core+1))==0) + InputDataProgress=0; + if((AutoDMACtrl&(Index+1))==0) { - Cores[core].TSA=0x2000+(core<<10); - Cores[core].DMAICounter=size; + TSA=0x2000+(Index<<10); + DMAICounter=size; } else if(size>=512) { - Cores[core].InputDataLeft=size; - if(Cores[core].AdmaInProgress==0) + InputDataLeft=size; + if(AdmaInProgress==0) { #ifdef PCM24_S1_INTERLEAVE - if((core==1)&&((PlayMode&8)==8)) + if((Index==1)&&((PlayMode&8)==8)) { - AutoDMAReadBuffer(core,1); + AutoDMAReadBuffer(Index,1); } else { - AutoDMAReadBuffer(core,0); + AutoDMAReadBuffer(Index,0); } #else - if(((PlayMode&4)==4)&&(core==0)) + if(((PlayMode&4)==4)&&(Index==0)) Cores[0].InputPos=0; - AutoDMAReadBuffer(core,0); + AutoDMAReadBuffer(0); #endif if(size==512) - Cores[core].DMAICounter=size; + DMAICounter=size; } - Cores[core].AdmaInProgress=1; + AdmaInProgress=1; } else { - Cores[core].InputDataLeft=0; - Cores[core].DMAICounter=1; + InputDataLeft=0; + DMAICounter=1; } - Cores[core].TADR=Cores[core].MADR+(size<<1); + TADR=MADR+(size<<1); } -void DoDMAWrite(int core,u16 *pMem,u32 size) +void V_Core::PlainDMAWrite(u16 *pMem, u32 size) { // Perform an alignment check. // Not really important. Everything should work regardless, @@ -198,29 +177,29 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) #if 0 uptr pa = ((uptr)pMem)&7; - uptr pm = Cores[core].TSA&0x7; + uptr pm = TSA&0x7; if( pa ) { - fprintf(stderr, "* SPU2 DMA Write > Missaligned SOURCE! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size); + fprintf(stderr, "* SPU2 DMA Write > Missaligned SOURCE! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, TSA, TDA, size); } if( pm ) { - fprintf(stderr, "* SPU2 DMA Write > Missaligned TARGET! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, Cores[core].TSA, Cores[core].TDA, size ); + fprintf(stderr, "* SPU2 DMA Write > Missaligned TARGET! Core: %d TSA: 0x%x TDA: 0x%x Size: 0x%x\n", core, TSA, TDA, size ); } #endif - if(core==0) + if(Index==0) DMA4LogWrite(pMem,size<<1); else DMA7LogWrite(pMem,size<<1); - if(MsgDMA()) ConLog(" * SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",(core==0)?'4':'7',size<<1,Cores[core].TSA,Cores[core].DMABits,Cores[core].AutoDMACtrl,(~Cores[core].Regs.ATTR)&0x7fff); + if(MsgDMA()) ConLog(" * SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x).\n",GetDmaIndexChar(),size<<1,TSA,DMABits,AutoDMACtrl,(~Regs.ATTR)&0x7fff); - Cores[core].TSA &= 0xfffff; + TSA &= 0xfffff; - u32 buff1end = Cores[core].TSA + size; + u32 buff1end = TSA + size; u32 buff2end=0; if( buff1end > 0x100000 ) { @@ -228,7 +207,7 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) buff1end = 0x100000; } - const int cacheIdxStart = Cores[core].TSA / pcm_WordsPerBlock; + const int cacheIdxStart = TSA / pcm_WordsPerBlock; const int cacheIdxEnd = (buff1end+pcm_WordsPerBlock-1) / pcm_WordsPerBlock; PcmCacheEntry* cacheLine = &pcm_cache_data[cacheIdxStart]; PcmCacheEntry& cacheEnd = pcm_cache_data[cacheIdxEnd]; @@ -240,14 +219,14 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) } while ( cacheLine != &cacheEnd ); //ConLog( " * SPU2 : Cache Clear Range! TSA=0x%x, TDA=0x%x (low8=0x%x, high8=0x%x, len=0x%x)\n", - // Cores[core].TSA, buff1end, flagTSA, flagTDA, clearLen ); + // TSA, buff1end, flagTSA, flagTDA, clearLen ); // First Branch needs cleared: // It starts at TSA and goes to buff1end. - const u32 buff1size = (buff1end-Cores[core].TSA); - memcpy( GetMemPtr( Cores[core].TSA ), pMem, buff1size*2 ); + const u32 buff1size = (buff1end-TSA); + memcpy( GetMemPtr( TSA ), pMem, buff1size*2 ); if( buff2end > 0 ) { @@ -263,57 +242,50 @@ void DoDMAWrite(int core,u16 *pMem,u32 size) // 0x2800? Hard to know for usre (almost no games depend on this) memcpy( GetMemPtr( 0 ), &pMem[buff1size], buff2end*2 ); - Cores[core].TDA = (buff2end+1) & 0xfffff; - - if(Cores[core].IRQEnable) - { - // Flag interrupt? - // If IRQA occurs between start and dest, flag it. - // Since the buffer wraps, the conditional might seem odd, but it works. - - if( ( Cores[core].IRQA >= Cores[core].TSA ) || - ( Cores[core].IRQA < Cores[core].TDA ) ) - { - Spdif.Info = 4 << core; - SetIrqCall(); - } - } + TDA = (buff2end+1) & 0xfffff; } else { // Buffer doesn't wrap/overflow! // Just set the TDA and check for an IRQ... - Cores[core].TDA = buff1end; + TDA = buff1end; + } - if(Cores[core].IRQEnable) + // 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) ) { - // Flag interrupt? - // If IRQA occurs between start and dest, flag it. - // (start is inclusive, dest exclusive -- fixes DMC1 and hopefully won't break - // other games. ;) - - if( ( Cores[core].IRQA >= Cores[core].TSA ) && - ( Cores[core].IRQA < Cores[core].TDA ) ) - { - Spdif.Info = 4 << core; - SetIrqCall(); - } + Spdif.Info = 4 << i; + SetIrqCall(); } } - Cores[core].TSA=Cores[core].TDA&0xFFFF0; - Cores[core].DMAICounter=size; - Cores[core].TADR=Cores[core].MADR+(size<<1); + if(IRQEnable) + { + + if( ( IRQA >= TSA ) && ( IRQA < TDA ) ) + { + Spdif.Info = 4 << Index; + SetIrqCall(); + } + } + + TSA = TDA & 0xFFFF0; + DMAICounter = size; + TADR = MADR + (size<<1); } -void SPU2readDMA(int core, u16* pMem, u32 size) +void V_Core::DoDMAread(u16* pMem, u32 size) { - if( cyclePtr != NULL ) TimeUpdate( *cyclePtr ); + TSA &= 0xffff8; - Cores[core].TSA &= 0xffff8; - - u32 buff1end = Cores[core].TSA + size; + u32 buff1end = TSA + size; u32 buff2end = 0; if( buff1end > 0x100000 ) { @@ -321,8 +293,8 @@ void SPU2readDMA(int core, u16* pMem, u32 size) buff1end = 0x100000; } - const u32 buff1size = (buff1end-Cores[core].TSA); - memcpy( pMem, GetMemPtr( Cores[core].TSA ), buff1size*2 ); + 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 @@ -335,146 +307,65 @@ void SPU2readDMA(int core, u16* pMem, u32 size) memcpy( &pMem[buff1size], GetMemPtr( 0 ), buff2end*2 ); - Cores[core].TDA = (buff2end+0x20) & 0xfffff; - - for( int i=0; i<2; i++ ) - { - if(Cores[i].IRQEnable) - { - // Flag interrupt? - // If IRQA occurs between start and dest, flag it. - // Since the buffer wraps, the conditional might seem odd, but it works. - - if( ( Cores[i].IRQA >= Cores[core].TSA ) || - ( Cores[i].IRQA <= Cores[core].TDA ) ) - { - Spdif.Info=4<= Cores[i].TSA) && (Cores[i].IRQA < Cores[i].TDA) ) { - if(Cores[i].IRQEnable) - { - // Flag interrupt? - // If IRQA occurs between start and dest, flag it: - - if( ( Cores[i].IRQA >= Cores[i].TSA ) && - ( Cores[i].IRQA < Cores[i].TDA ) ) - { - Spdif.Info=4< -// -//This library is free software; you can redistribute it and/or -//modify it under the terms of the GNU Lesser General Public -//License as published by the Free Software Foundation; either -//version 2.1 of the License, or (at your option) any later version. -// -//This library is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -//Lesser General Public License for more details. -// -//You should have received a copy of the GNU Lesser General Public -//License along with this library; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -#ifndef DMA_H_INCLUDED -#define DMA_H_INCLUDED +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ -void DMALogOpen(); -void DMA4LogWrite(void *lpData, u32 ulSize); -void DMA7LogWrite(void *lpData, u32 ulSize); -void DMALogClose(); +#pragma once -extern void DmaWrite(u32 core, u16 data); -extern u16 DmaRead(u32 core); - -extern void AutoDMAReadBuffer(int core, int mode); - -#endif // DMA_H_INCLUDED // \ No newline at end of file +extern void DMALogOpen(); +extern void DMA4LogWrite(void *lpData, u32 ulSize); +extern void DMA7LogWrite(void *lpData, u32 ulSize); +extern void DMALogClose(); diff --git a/plugins/spu2-x/src/Global.h b/plugins/spu2-x/src/Global.h new file mode 100644 index 0000000000..f0db1b915b --- /dev/null +++ b/plugins/spu2-x/src/Global.h @@ -0,0 +1,110 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ + +#ifndef _SPU2X_GLOBAL_H_ +#define _SPU2X_GLOBAL_H_ + +struct StereoOut16; +struct StereoOut32; +struct StereoOutFloat; + +struct V_Core; + +namespace soundtouch +{ + class SoundTouch; +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::wstring; + +#include "Pcsx2Types.h" + +namespace VersionInfo +{ + static const u8 Release = 1; + static const u8 Revision = 3; // increase that with each version +} + +////////////////////////////////////////////////////////////////////////// +// Override Win32 min/max macros with the STL's type safe and macro +// free varieties (much safer!) + +#undef min +#undef max + +template< typename T > +static __forceinline void Clampify( T& src, T min, T max ) +{ + src = std::min( std::max( src, min ), max ); +} + +template< typename T > +static __forceinline T GetClamped( T src, T min, T max ) +{ + return std::min( std::max( src, min ), max ); +} + +extern void SysMessage(const char *fmt, ...); + +////////////////////////////////////////////////////////////// +// Dev / Debug conditionals -- +// Consts for using if() statements instead of uglier #ifdef macros. +// Abbreviated macros for dev/debug only consoles and msgboxes. + +#ifdef PCSX2_DEVBUILD +# define DevCon Console +# define DevMsg MsgBox +#else +# define DevCon 0&&Console +# define DevMsg +#endif + +#ifdef PCSX2_DEBUG +# define DbgCon Console +#else +# define DbgCon 0&&Console +#endif + +#ifdef PCSX2_DEVBUILD +# define SPU2_LOG +#endif + +#include "Utilities/Exceptions.h" +#include "Utilities/SafeArray.h" + +#include "ConvertUTF.h" + +#include "defs.h" +#include "regs.h" + +#include "Config.h" +#include "Debug.h" +#include "SndOut.h" + +#endif \ No newline at end of file diff --git a/plugins/spu2-x/src/Linux/Config.cpp b/plugins/spu2-x/src/Linux/Config.cpp index 848ce31b27..79f14a2fb4 100644 --- a/plugins/spu2-x/src/Linux/Config.cpp +++ b/plugins/spu2-x/src/Linux/Config.cpp @@ -1,8 +1,8 @@ -/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 - * Developed and maintained by the Pcsx2 Development Team. - * - * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] - * +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * * SPU2-X is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. @@ -14,95 +14,95 @@ * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . */ - -#include "Spu2.h" -#include "Dialogs.h" - -bool DebugEnabled=false; -bool _MsgToConsole=false; -bool _MsgKeyOnOff=false; -bool _MsgVoiceOff=false; -bool _MsgDMA=false; -bool _MsgAutoDMA=false; -bool _MsgOverruns=false; -bool _MsgCache=false; - -bool _AccessLog=false; -bool _DMALog=false; -bool _WaveLog=false; - -bool _CoresDump=false; -bool _MemDump=false; -bool _RegDump=false; - - - -wchar_t AccessLogFileName[255]; -wchar_t WaveLogFileName[255]; - -wchar_t DMA4LogFileName[255]; -wchar_t DMA7LogFileName[255]; - -wchar_t CoresDumpFileName[255]; -wchar_t MemDumpFileName[255]; -wchar_t RegDumpFileName[255]; - - -#ifdef SPU2X_DEVBUILD -static const int LATENCY_MAX = 3000; -#else -static const int LATENCY_MAX = 750; -#endif - -static const int LATENCY_MIN = 40; - -int AutoDMAPlayRate[2] = {0,0}; - -// MIXING -int Interpolation = 1; -/* values: - 0: no interpolation (use nearest) - 1. linear interpolation - 2. cubic interpolation -*/ - -bool EffectsDisabled = false; - -// OUTPUT -int SndOutLatencyMS = 160; -bool timeStretchDisabled = false; - -u32 OutputModule = 0; - -CONFIG_DSOUNDOUT Config_DSoundOut; -CONFIG_WAVEOUT Config_WaveOut; -CONFIG_XAUDIO2 Config_XAudio2; - -// DSP -bool dspPluginEnabled = false; -int dspPluginModule = 0; -wchar_t dspPlugin[256]; - -bool StereoExpansionEnabled = false; - -/*****************************************************************************/ - -void ReadSettings() -{ -} - -/*****************************************************************************/ - -void WriteSettings() -{ -} - - -void configure() -{ - ReadSettings(); -} - -void MessageBox(char const*, ...) -{ -} + +#include "Spu2.h" +#include "Dialogs.h" + +bool DebugEnabled=false; +bool _MsgToConsole=false; +bool _MsgKeyOnOff=false; +bool _MsgVoiceOff=false; +bool _MsgDMA=false; +bool _MsgAutoDMA=false; +bool _MsgOverruns=false; +bool _MsgCache=false; + +bool _AccessLog=false; +bool _DMALog=false; +bool _WaveLog=false; + +bool _CoresDump=false; +bool _MemDump=false; +bool _RegDump=false; + + + +wchar_t AccessLogFileName[255]; +wchar_t WaveLogFileName[255]; + +wchar_t DMA4LogFileName[255]; +wchar_t DMA7LogFileName[255]; + +wchar_t CoresDumpFileName[255]; +wchar_t MemDumpFileName[255]; +wchar_t RegDumpFileName[255]; + + +#ifdef PCSX2_DEVBUILD +static const int LATENCY_MAX = 3000; +#else +static const int LATENCY_MAX = 750; +#endif + +static const int LATENCY_MIN = 40; + +int AutoDMAPlayRate[2] = {0,0}; + +// MIXING +int Interpolation = 1; +/* values: + 0: no interpolation (use nearest) + 1. linear interpolation + 2. cubic interpolation +*/ + +bool EffectsDisabled = false; + +// OUTPUT +int SndOutLatencyMS = 160; +bool timeStretchDisabled = false; + +u32 OutputModule = 0; + +CONFIG_DSOUNDOUT Config_DSoundOut; +CONFIG_WAVEOUT Config_WaveOut; +CONFIG_XAUDIO2 Config_XAudio2; + +// DSP +bool dspPluginEnabled = false; +int dspPluginModule = 0; +wchar_t dspPlugin[256]; + +bool StereoExpansionEnabled = false; + +/*****************************************************************************/ + +void ReadSettings() +{ +} + +/*****************************************************************************/ + +void WriteSettings() +{ +} + + +void configure() +{ + ReadSettings(); +} + +void MessageBox(char const*, ...) +{ +} diff --git a/plugins/spu2-x/src/Linux/Config.h b/plugins/spu2-x/src/Linux/Config.h index 2701950a5e..05a10b56d2 100644 --- a/plugins/spu2-x/src/Linux/Config.h +++ b/plugins/spu2-x/src/Linux/Config.h @@ -103,8 +103,6 @@ public: protected: static void ClampValues(); - //static bool CALLBACK DialogProc(uptr hWnd,u32 uMsg,WPARAM wParam,LPARAM lParam); - }; diff --git a/plugins/spu2-x/src/Linux/Linux.cpp b/plugins/spu2-x/src/Linux/Linux.cpp index 443917f845..d10b41bc15 100644 --- a/plugins/spu2-x/src/Linux/Linux.cpp +++ b/plugins/spu2-x/src/Linux/Linux.cpp @@ -1,8 +1,8 @@ -/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 - * Developed and maintained by the Pcsx2 Development Team. - * - * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] - * +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * * SPU2-X is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. @@ -14,46 +14,46 @@ * You should have received a copy of the GNU Lesser General Public License * along with SPU2-X. If not, see . */ - -#include "Linux.h" - -void SysMessage(char *fmt, ...) { - GtkWidget *Ok,*Txt; - GtkWidget *Box,*Box1; - va_list list; - char msg[512]; - - va_start(list, fmt); - vsprintf(msg, fmt, list); - va_end(list); - - if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; - - MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); - gtk_window_set_title(GTK_WINDOW(MsgDlg), "SPU2null Msg"); - gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); - - Box = gtk_vbox_new(5, 0); - gtk_container_add(GTK_CONTAINER(MsgDlg), Box); - gtk_widget_show(Box); - - Txt = gtk_label_new(msg); - - gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); - gtk_widget_show(Txt); - - Box1 = gtk_hbutton_box_new(); - gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); - gtk_widget_show(Box1); - - Ok = gtk_button_new_with_label("Ok"); - gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); - gtk_container_add(GTK_CONTAINER(Box1), Ok); - GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); - gtk_widget_show(Ok); - - gtk_widget_show(MsgDlg); - - gtk_main(); -} + +#include "Linux.h" + +void SysMessage(char *fmt, ...) { + GtkWidget *Ok,*Txt; + GtkWidget *Box,*Box1; + va_list list; + char msg[512]; + + va_start(list, fmt); + vsprintf(msg, fmt, list); + va_end(list); + + if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0; + + MsgDlg = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_position(GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); + gtk_window_set_title(GTK_WINDOW(MsgDlg), "SPU2null Msg"); + gtk_container_set_border_width(GTK_CONTAINER(MsgDlg), 5); + + Box = gtk_vbox_new(5, 0); + gtk_container_add(GTK_CONTAINER(MsgDlg), Box); + gtk_widget_show(Box); + + Txt = gtk_label_new(msg); + + gtk_box_pack_start(GTK_BOX(Box), Txt, FALSE, FALSE, 5); + gtk_widget_show(Txt); + + Box1 = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(Box), Box1, FALSE, FALSE, 0); + gtk_widget_show(Box1); + + Ok = gtk_button_new_with_label("Ok"); + gtk_signal_connect (GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnMsg_Ok), NULL); + gtk_container_add(GTK_CONTAINER(Box1), Ok); + GTK_WIDGET_SET_FLAGS(Ok, GTK_CAN_DEFAULT); + gtk_widget_show(Ok); + + gtk_widget_show(MsgDlg); + + gtk_main(); +} diff --git a/plugins/spu2-x/src/Lowpass.cpp b/plugins/spu2-x/src/Lowpass.cpp index c6d6e84fb0..1624306cd6 100644 --- a/plugins/spu2-x/src/Lowpass.cpp +++ b/plugins/spu2-x/src/Lowpass.cpp @@ -19,35 +19,39 @@ #include #include -LPF_data::LPF_data( double freq, double srate ) +template< typename FloatType > __forceinline +LowPassFilter::LowPassFilter( FloatType freq, FloatType srate ) { - double omega = 2.0 * freq / srate; - static const double g = 1.0; + typedef FloatType FT; + + FloatType omega = (FT)2.0 * freq / srate; + static const FloatType g = (FT)1.0; // calculating coefficients: - double k,p,q,a; - double a0,a1,a2,a3,a4; + FloatType k,p,q,a; + FloatType a0,a1,a2,a3,a4; - k=(4.0*g-3.0)/(g+1.0); - p=1.0-0.25*k;p*=p; + k = ((FT)4.0*g-(FT)3.0)/(g+(FT)1.0); + p = (FT)1.0-(FT)0.25*k; + p *= p; // LP: - a=1.0/(tan(0.5*omega)*(1.0+p)); - p=1.0+a; - q=1.0-a; - - a0=1.0/(k+p*p*p*p); - a1=4.0*(k+p*p*p*q); - a2=6.0*(k+p*p*q*q); - a3=4.0*(k+p*q*q*q); - a4= (k+q*q*q*q); - p=a0*(k+1.0); + a = (FT)1.0/(tan((FT)0.5*omega)*((FT)1.0+p)); + p = (FT)1.0+a; + q = (FT)1.0-a; + a0 = (FT)1.0/(k+p*p*p*p); + a1 = (FT)4.0*(k+p*p*p*q); + a2 = (FT)6.0*(k+p*p*q*q); + a3 = (FT)4.0*(k+p*q*q*q); + a4 = (k+q*q*q*q); + p = a0*(k+(FT)1.0); + coef[0] = p; - coef[1] = 4.0*p; - coef[2] = 6.0*p; - coef[3] = 4.0*p; + coef[1] = (FT)4.0*p; + coef[2] = (FT)6.0*p; + coef[3] = (FT)4.0*p; coef[4] = p; coef[5] = -a1*a0; coef[6] = -a2*a0; @@ -56,9 +60,10 @@ LPF_data::LPF_data( double freq, double srate ) } // Processes a single sample into the LPF. -double LPF_data::sample( double inval ) +template< typename FloatType > __forceinline +FloatType LowPassFilter::sample( FloatType inval ) { - const double out = (coef[0]*inval) + d[0]; + const FloatType out = (coef[0]*inval) + d[0]; d[0] = (coef[1]*inval) + (coef[5]*out) + d[1]; d[1] = (coef[2]*inval) + (coef[6]*out) + d[2]; d[2] = (coef[3]*inval) + (coef[7]*out) + d[3]; @@ -66,3 +71,23 @@ double LPF_data::sample( double inval ) return out; } + +LowPassFilter32::LowPassFilter32( float freq, float srate ) : + impl_lpf( freq, srate ) +{ +} + +LowPassFilter64::LowPassFilter64( double freq, double srate ) : + impl_lpf( freq, srate ) +{ +} + +float LowPassFilter32::sample( float inval ) +{ + return impl_lpf.sample( inval ); +} + +double LowPassFilter64::sample( double inval ) +{ + return impl_lpf.sample( inval ); +} diff --git a/plugins/spu2-x/src/Lowpass.h b/plugins/spu2-x/src/Lowpass.h index 23dc5f8380..f1876b04c0 100644 --- a/plugins/spu2-x/src/Lowpass.h +++ b/plugins/spu2-x/src/Lowpass.h @@ -1,30 +1,44 @@ /* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 -* Developed and maintained by the Pcsx2 Development Team. -* -* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] -* -* SPU2-X is free software: you can redistribute it and/or modify it under the terms -* of the GNU Lesser General Public License as published by the Free Software Found- -* ation, either version 3 of the License, or (at your option) any later version. -* -* SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -* PURPOSE. See the GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with SPU2-X. If not, see . -*/ + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ #pragma once -#include "BaseTypes.h" - -struct LPF_data +template< typename FloatType > +struct LowPassFilter { - double coef[9]; - double d[4]; + FloatType coef[9]; + FloatType d[4]; - LPF_data( double freq, double srate ); - double sample( double inval ); + LowPassFilter( FloatType freq, FloatType srate ); + FloatType sample( FloatType inval ); }; +struct LowPassFilter32 +{ + LowPassFilter impl_lpf; + + LowPassFilter32( float freq, float srate ); + float sample( float inval ); +}; + +struct LowPassFilter64 +{ + LowPassFilter impl_lpf; + + LowPassFilter64( double freq, double srate ); + double sample( double inval ); +}; diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index fb41dfb818..a9e1c1bcc7 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -15,8 +15,8 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" -#include +#include "Global.h" +//#include extern void spdif_update(); @@ -477,22 +477,9 @@ static s32 __forceinline __fastcall GetNoiseValues( V_Core& thiscore, uint voice ///////////////////////////////////////////////////////////////////////////////////////// // // -static __forceinline StereoOut32 ReadInputPV( uint core ) +__forceinline StereoOut32 V_Core::ReadInputPV() { - V_Core& thiscore( Cores[core] ); - u32 pitch = AutoDMAPlayRate[core]; - - if(pitch==0) pitch=48000; - - thiscore.ADMAPV += pitch; - while(thiscore.ADMAPV>=48000) - { - ReadInput( core, thiscore.ADMAP ); - thiscore.ADMAPV -= 48000; - } - - // Apply volumes: - return ApplyVolume( thiscore.ADMAP, thiscore.InpVol ); + return ApplyVolume( ReadInput(), InpVol ); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -547,7 +534,7 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx ) vc.OutX = Value; if( IsDevBuild ) - DebugCores[coreidx].Voices[voiceidx].displayPeak = max(DebugCores[coreidx].Voices[voiceidx].displayPeak,abs(vc.OutX)); + DebugCores[coreidx].Voices[voiceidx].displayPeak = std::max(DebugCores[coreidx].Voices[voiceidx].displayPeak,abs(vc.OutX)); // Write-back of raw voice data (post ADSR applied) @@ -567,19 +554,6 @@ static __forceinline StereoOut32 MixVoice( uint coreidx, uint voiceidx ) } } -struct VoiceMixSet -{ - static const VoiceMixSet Empty; - StereoOut32 Dry, Wet; - - VoiceMixSet() {} - VoiceMixSet( const StereoOut32& dry, const StereoOut32& wet ) : - Dry( dry ), - Wet( wet ) - { - } -}; - const VoiceMixSet VoiceMixSet::Empty( (StereoOut32()), (StereoOut32()) ); // Don't use SteroOut32::Empty because C++ doesn't make any dep/order checks on global initializers. static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx ) @@ -599,61 +573,60 @@ static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx ) } } -static StereoOut32 __fastcall MixCore( const uint coreidx, const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext ) +StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext ) { - V_Core& thiscore( Cores[coreidx] ); - thiscore.MasterVol.Update(); + MasterVol.Update(); // Saturate final result to standard 16 bit range. const VoiceMixSet Voices( clamp_mix( inVoices.Dry ), clamp_mix( inVoices.Wet ) ); // Write Mixed results To Output Area - spu2M_WriteFast( 0x1000 + (coreidx<<12) + OutPos, Voices.Dry.Left ); - spu2M_WriteFast( 0x1200 + (coreidx<<12) + OutPos, Voices.Dry.Right ); - spu2M_WriteFast( 0x1400 + (coreidx<<12) + OutPos, Voices.Wet.Left ); - spu2M_WriteFast( 0x1600 + (coreidx<<12) + OutPos, Voices.Wet.Right ); + spu2M_WriteFast( 0x1000 + (Index<<12) + OutPos, Voices.Dry.Left ); + spu2M_WriteFast( 0x1200 + (Index<<12) + OutPos, Voices.Dry.Right ); + spu2M_WriteFast( 0x1400 + (Index<<12) + OutPos, Voices.Wet.Left ); + spu2M_WriteFast( 0x1600 + (Index<<12) + OutPos, Voices.Wet.Right ); // Write mixed results to logfile (if enabled) - WaveDump::WriteCore( coreidx, CoreSrc_DryVoiceMix, Voices.Dry ); - WaveDump::WriteCore( coreidx, CoreSrc_WetVoiceMix, Voices.Wet ); + WaveDump::WriteCore( Index, CoreSrc_DryVoiceMix, Voices.Dry ); + WaveDump::WriteCore( Index, CoreSrc_WetVoiceMix, Voices.Wet ); // Mix in the Input data StereoOut32 TD( - Input.Left & thiscore.DryGate.InpL, - Input.Right & thiscore.DryGate.InpR + Input.Left & DryGate.InpL, + Input.Right & DryGate.InpR ); // Mix in the Voice data - TD.Left += Voices.Dry.Left & thiscore.DryGate.SndL; - TD.Right += Voices.Dry.Right & thiscore.DryGate.SndR; + TD.Left += Voices.Dry.Left & DryGate.SndL; + TD.Right += Voices.Dry.Right & DryGate.SndR; // Mix in the External (nothing/core0) data - TD.Left += Ext.Left & thiscore.DryGate.ExtL; - TD.Right += Ext.Right & thiscore.DryGate.ExtR; + TD.Left += Ext.Left & DryGate.ExtL; + TD.Right += Ext.Right & DryGate.ExtR; if( !EffectsDisabled ) { //Reverb pointer advances regardless of the FxEnable bit... - Reverb_AdvanceBuffer( thiscore ); + Reverb_AdvanceBuffer(); - if( thiscore.FxEnable ) + if( FxEnable ) { // Mix Input, Voice, and External data: StereoOut32 TW( - Input.Left & thiscore.WetGate.InpL, - Input.Right & thiscore.WetGate.InpR + Input.Left & WetGate.InpL, + Input.Right & WetGate.InpR ); - TW.Left += Voices.Wet.Left & thiscore.WetGate.SndL; - TW.Right += Voices.Wet.Right & thiscore.WetGate.SndR; - TW.Left += Ext.Left & thiscore.WetGate.ExtL; - TW.Right += Ext.Right & thiscore.WetGate.ExtR; + TW.Left += Voices.Wet.Left & WetGate.SndL; + TW.Right += Voices.Wet.Right & WetGate.SndR; + TW.Left += Ext.Left & WetGate.ExtL; + TW.Right += Ext.Right & WetGate.ExtR; - WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, TW ); + WaveDump::WriteCore( Index, CoreSrc_PreReverb, TW ); - StereoOut32 RV( DoReverb( thiscore, TW ) ); + StereoOut32 RV( DoReverb( TW ) ); // Volume boost after effects application. Boosting volume prior to effects // causes slight overflows in some games, and the volume boost is required. @@ -663,15 +636,15 @@ static StereoOut32 __fastcall MixCore( const uint coreidx, const VoiceMixSet& in RV.Left *= 2; RV.Right *= 2; - WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, RV ); + WaveDump::WriteCore( Index, CoreSrc_PostReverb, RV ); // Mix Dry+Wet - return TD + ApplyVolume( RV, thiscore.FxVol ); + return TD + ApplyVolume( RV, FxVol ); } else { - WaveDump::WriteCore( coreidx, CoreSrc_PreReverb, 0, 0 ); - WaveDump::WriteCore( coreidx, CoreSrc_PostReverb, 0, 0 ); + WaveDump::WriteCore( Index, CoreSrc_PreReverb, 0, 0 ); + WaveDump::WriteCore( Index, CoreSrc_PostReverb, 0, 0 ); } } return TD; @@ -685,8 +658,8 @@ __forceinline void Mix() // Note: Playmode 4 is SPDIF, which overrides other inputs. StereoOut32 InputData[2] = { - (PlayMode&4) ? StereoOut32::Empty : ReadInputPV( 0 ), - (PlayMode&8) ? StereoOut32::Empty : ReadInputPV( 1 ) + (PlayMode&4) ? StereoOut32::Empty : Cores[0].ReadInputPV(), + (PlayMode&8) ? StereoOut32::Empty : Cores[1].ReadInputPV() }; WaveDump::WriteCore( 0, CoreSrc_Input, InputData[0] ); @@ -697,7 +670,7 @@ __forceinline void Mix() MixCoreVoices( VoiceData[0], 0 ); MixCoreVoices( VoiceData[1], 1 ); - StereoOut32 Ext( MixCore( 0, VoiceData[0], InputData[0], StereoOut32::Empty ) ); + StereoOut32 Ext( Cores[0].Mix( VoiceData[0], InputData[0], StereoOut32::Empty ) ); if( (PlayMode & 4) || (Cores[0].Mute!=0) ) Ext = StereoOut32::Empty; @@ -714,14 +687,14 @@ __forceinline void Mix() WaveDump::WriteCore( 0, CoreSrc_External, Ext ); ApplyVolume( Ext, Cores[1].ExtVol ); - StereoOut32 Out( MixCore( 1, VoiceData[1], InputData[1], Ext ) ); + StereoOut32 Out( Cores[1].Mix( VoiceData[1], InputData[1], Ext ) ); if( PlayMode & 8 ) { // Experimental CDDA support // The CDDA overrides all other mixer output. It's a direct feed! - ReadInput( 1, Out ); + Out = Cores[1].ReadInput(); //WaveLog::WriteCore( 1, "CDDA-32", OutL, OutR ); } else diff --git a/plugins/spu2-x/src/Mixer.h b/plugins/spu2-x/src/Mixer.h new file mode 100644 index 0000000000..8422a17154 --- /dev/null +++ b/plugins/spu2-x/src/Mixer.h @@ -0,0 +1,62 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ + + +#pragma once + +struct StereoOut32 +{ + static StereoOut32 Empty; + + s32 Left; + s32 Right; + + StereoOut32() : + Left( 0 ), + Right( 0 ) + { + } + + StereoOut32( s32 left, s32 right ) : + Left( left ), + Right( right ) + { + } + + StereoOut32( const StereoOut16& src ); + explicit StereoOut32( const StereoOutFloat& src ); + + StereoOut16 DownSample() const; + + StereoOut32 operator+( const StereoOut32& right ) const + { + return StereoOut32( + Left + right.Left, + Right + right.Right + ); + } + + StereoOut32 operator/( int src ) const + { + return StereoOut32( Left / src, Right / src ); + } +}; + + +extern void Mix(); +extern s32 clamp_mix( s32 x, u8 bitshift=0 ); +extern s32 MulShr32( s32 srcval, s32 mulval ); + +extern StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift=0 ); diff --git a/plugins/spu2-x/src/DllInterface.cpp b/plugins/spu2-x/src/PS2E-spu2.cpp similarity index 63% rename from plugins/spu2-x/src/DllInterface.cpp rename to plugins/spu2-x/src/PS2E-spu2.cpp index 11fce3a26d..ab3f80c959 100644 --- a/plugins/spu2-x/src/DllInterface.cpp +++ b/plugins/spu2-x/src/PS2E-spu2.cpp @@ -15,33 +15,40 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" +#include "PS2E-spu2.h" +#include "dma.h" #include "Dialogs.h" #include "RegTable.h" #ifdef _MSC_VER -#include "svnrev.h" -#else -#include -#include +# include "svnrev.h" #endif -// [Air]: Adding the spu2init boolean wasn't necessary except to help me in -// debugging the spu2 suspend/resume behavior (when user hits escape). -static bool spu2open=false; // has spu2open plugin interface been called? -static bool spu2init=false; // has spu2init plugin interface been called? - -//static s32 logvolume[16384]; -static u32 pClocks=0; - -// Pcsx2 expects ASNI, not unicode, so this MUST always be char... +// PCSX2 expects ASNI, not unicode, so this MUST always be char... static char libraryName[256]; + +static bool IsOpened = false; +static bool IsInitialized = false; + +static u32 pClocks = 0; + +u32* cyclePtr = NULL; +u32 lClocks = 0; + #ifdef _MSC_VER -BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD dwReason,LPVOID lpvReserved) +HINSTANCE hInstance; +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved) { if( dwReason == DLL_PROCESS_ATTACH ) hInstance = hinstDLL; + + else if( dwReason == DLL_PROCESS_DETACH ) + { + // TODO : perform shutdown procedure, just in case PCSX2 itself failed + // to for some reason.. + } return TRUE; } #endif @@ -106,7 +113,7 @@ EXPORT_C_(char*) PS2EgetLibName() EXPORT_C_(u32) PS2EgetLibVersion2(u32 type) { - return (VersionInfo::PluginApi<<16) | (VersionInfo::Release<<8) | VersionInfo::Revision; + return (PS2E_SPU2_VERSION<<16) | (VersionInfo::Release<<8) | VersionInfo::Revision; } EXPORT_C_(void) SPU2configure() @@ -126,6 +133,87 @@ EXPORT_C_(s32) SPU2test() return SndBuffer::Test(); } +// -------------------------------------------------------------------------------------- +// DMA 4/7 Callbacks from Core Emulator +// -------------------------------------------------------------------------------------- + +u16* DMABaseAddr; +void (* _irqcallback)(); +void (* dma4callback)(); +void (* dma7callback)(); + +EXPORT_C_(u32) CALLBACK SPU2ReadMemAddr(int core) +{ + return Cores[core].MADR; +} +EXPORT_C_(void) CALLBACK SPU2WriteMemAddr(int core,u32 value) +{ + Cores[core].MADR = value; +} + +EXPORT_C_(void) CALLBACK SPU2setDMABaseAddr(uptr baseaddr) +{ + DMABaseAddr = (u16*)baseaddr; +} + +EXPORT_C_(void) CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) // size now in 16bit units +{ + if( cyclePtr != NULL ) TimeUpdate( *cyclePtr ); + + FileLog("[%10d] SPU2 readDMA4Mem size %x\n",Cycles, size<<1); + Cores[0].DoDMAread(pMem, size); +} + +EXPORT_C_(void) CALLBACK SPU2writeDMA4Mem(u16* pMem, u32 size) // size now in 16bit units +{ + if( cyclePtr != NULL ) TimeUpdate( *cyclePtr ); + + FileLog("[%10d] SPU2 writeDMA4Mem size %x at address %x\n",Cycles, size<<1, Cores[0].TSA); +#ifdef S2R_ENABLE + if(!replay_mode) + s2r_writedma4(Cycles,pMem,size); +#endif + Cores[0].DoDMAwrite(pMem,size); +} + +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; +} + +EXPORT_C_(void) CALLBACK SPU2readDMA7Mem(u16* pMem, u32 size) +{ + if( cyclePtr != NULL ) TimeUpdate( *cyclePtr ); + + FileLog("[%10d] SPU2 readDMA7Mem size %x\n",Cycles, size<<1); + Cores[1].DoDMAread(pMem,size); +} + +EXPORT_C_(void) CALLBACK SPU2writeDMA7Mem(u16* pMem, u32 size) +{ + if( cyclePtr != NULL ) TimeUpdate( *cyclePtr ); + + FileLog("[%10d] SPU2 writeDMA7Mem size %x at address %x\n",Cycles, size<<1, Cores[1].TSA); +#ifdef S2R_ENABLE + if(!replay_mode) + s2r_writedma7(Cycles,pMem,size); +#endif + Cores[1].DoDMAwrite(pMem,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; +} + EXPORT_C_(s32) SPU2init() { #define MAKESURE(a,b) \ @@ -147,13 +235,13 @@ EXPORT_C_(s32) SPU2init() #endif srand((unsigned)time(NULL)); - if (spu2init) + if (IsInitialized) { ConLog( " * SPU2: Already initialized - Ignoring SPU2init signal." ); return 0; } - spu2init=true; + IsInitialized = true; spu2regs = (short*)malloc(0x010000); _spu2mem = (short*)malloc(0x200000); @@ -181,8 +269,8 @@ EXPORT_C_(s32) SPU2init() } } - memset(spu2regs,0,0x010000); - memset(_spu2mem,0,0x200000); + memset(spu2regs, 0, 0x010000); + memset(_spu2mem, 0, 0x200000); Cores[0].Reset(); Cores[1].Reset(); @@ -217,7 +305,7 @@ EXPORT_C_(s32) SPU2init() EXPORT_C_(s32) SPU2open(void *pDsp) { - if( spu2open ) return 0; + if( IsOpened ) return 0; FileLog("[%10d] SPU2 Open\n",Cycles); @@ -229,7 +317,7 @@ EXPORT_C_(s32) SPU2open(void *pDsp) debugDialogOpen=1; }*/ - spu2open = true; + IsOpened = true; try { SndBuffer::Init(); @@ -247,7 +335,9 @@ EXPORT_C_(s32) SPU2open(void *pDsp) EXPORT_C_(void) SPU2close() { - if( !spu2open ) return; + if( !IsOpened ) return; + IsOpened = false; + FileLog("[%10d] SPU2 Close\n",Cycles); #ifndef __LINUX__ @@ -255,13 +345,12 @@ EXPORT_C_(void) SPU2close() #endif spdif_shutdown(); SndBuffer::Cleanup(); - - spu2open = false; } EXPORT_C_(void) SPU2shutdown() { - if(!spu2init) return; + if(!IsInitialized) return; + IsInitialized = false; ConLog( " * SPU2: Shutting down.\n" ); @@ -285,12 +374,9 @@ EXPORT_C_(void) SPU2shutdown() DMALogClose(); - spu2init = false; - - SAFE_FREE(spu2regs); - SAFE_FREE(_spu2mem); - - SAFE_FREE( pcm_cache_data ); + safe_free(spu2regs); + safe_free(_spu2mem); + safe_free( pcm_cache_data ); spu2regs = NULL; _spu2mem = NULL; @@ -312,32 +398,8 @@ bool numpad_plus = false, numpad_plus_old = false; EXPORT_C_(void) SPU2async(u32 cycles) { - if( IsDevBuild ) - { - u32 oldClocks = lClocks; - static u32 timer=0,time1=0,time2=0; - timer++; - if (timer == 1){ - time1=timeGetTime(); - } - if (timer == 3000){ - time2 = timeGetTime()-time1 ; - timer=0; - } - } - DspUpdate(); - if( IsDevBuild ) - { - /*numpad_plus = (GetAsyncKeyState(VK_ADD)&0x8000)!=0; - if(numpad_plus && !numpad_plus_old) - { - DoFullDump(); - } - numpad_plus_old = numpad_plus;*/ - } - if(cyclePtr != NULL) { TimeUpdate( *cyclePtr ); @@ -366,7 +428,7 @@ EXPORT_C_(u16) SPU2read(u32 rmem) if(rmem==0x1f9001AC) { - ret = DmaRead(core); + ret = Cores[core].DmaRead(); } else { @@ -375,7 +437,7 @@ EXPORT_C_(u16) SPU2read(u32 rmem) if (rmem>>16 == 0x1f80) { - ret = SPU_ps1_read(rmem); + ret = Cores[0].ReadRegPS1(rmem); } else if( (mem&0xFFFF) >= 0x800 ) { @@ -400,44 +462,19 @@ EXPORT_C_(void) SPU2write(u32 rmem, u16 value) s2r_writereg(Cycles,rmem,value); #endif - if(rmem==0x1f9001ac) - { - //RegWriteLog(0,value); - if((Cores[0].IRQEnable)&&(Cores[0].TSA==Cores[0].IRQA)) - { - Spdif.Info=4; - SetIrqCall(); - } - spu2M_Write( Cores[0].TSA++, value ); - Cores[0].TSA&=0xfffff; - } - else if(rmem==0x1f9005ac) - { - //RegWriteLog(1,value); - if((Cores[0].IRQEnable)&&(Cores[0].TSA==Cores[0].IRQA)) - { - Spdif.Info=4; - SetIrqCall(); - } - spu2M_Write( Cores[1].TSA++, value ); - Cores[1].TSA&=0xfffff; - } + // Note: Reverb/Effects are very sensitive to having precise update timings. + // If the SPU2 isn't in in sync with the IOP, samples can end up playing at rather + // incorrect pitches and loop lengths. + + if( cyclePtr != NULL ) + TimeUpdate( *cyclePtr ); + + if (rmem>>16 == 0x1f80) + Cores[0].WriteRegPS1(rmem,value); else { - // Note: Reverb/Effects are very sensitive to having precise update timings. - // If the SPU2 isn't in in sync with the IOP, samples can end up playing at rather - // incorrect pitches and loop lengths. - - if( cyclePtr != NULL ) - TimeUpdate( *cyclePtr ); - - if (rmem>>16 == 0x1f80) - SPU_ps1_write(rmem,value); - else - { - SPU2writeLog( "write", rmem, value ); - SPU2_FastWrite( rmem, value ); - } + SPU2writeLog( "write", rmem, value ); + SPU2_FastWrite( rmem, value ); } } @@ -453,3 +490,29 @@ EXPORT_C_(int) SPU2setupRecording(int start, void* pData) return 0; } + +EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data) +{ + if( mode == FREEZE_SIZE ) + { + data->size = Savestate::SizeIt(); + return 0; + } + + jASSUME( mode == FREEZE_LOAD || mode == FREEZE_SAVE ); + jASSUME( data != NULL ); + + if( data->data == NULL ) return -1; + Savestate::DataBlock& spud = (Savestate::DataBlock&)*(data->data); + + switch( mode ) + { + case FREEZE_LOAD: return Savestate::ThawIt( spud ); + case FREEZE_SAVE: return Savestate::FreezeIt( spud ); + + jNO_DEFAULT; + } + + // technically unreachable, but kills a warning: + return 0; +} diff --git a/plugins/spu2-x/src/PS2E-spu2.h b/plugins/spu2-x/src/PS2E-spu2.h new file mode 100644 index 0000000000..b04b7878f2 --- /dev/null +++ b/plugins/spu2-x/src/PS2E-spu2.h @@ -0,0 +1,92 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ + +#pragma once + +#include "Pcsx2Defs.h" +#include "PS2Edefs.h" + +#ifdef __LINUX__ +//Until I get around to putting in Linux svn code, this is an unknown svn version. +#define SVN_REV_UNKNOWN +#endif + +#ifdef _MSC_VER +#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK +#else +#define EXPORT_C_(type) extern "C" type +#endif + +// We have our own versions that have the DLLExport attribute configured: + +EXPORT_C_(s32) SPU2init(); +EXPORT_C_(s32) SPU2open(void *pDsp); +EXPORT_C_(void) SPU2close(); +EXPORT_C_(void) SPU2shutdown(); +EXPORT_C_(void) SPU2write(u32 mem, u16 value); +EXPORT_C_(u16) SPU2read(u32 mem); +EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size); +EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size); +EXPORT_C_(void) SPU2interruptDMA4(); +EXPORT_C_(void) SPU2readDMA7Mem(u16* pMem, u32 size); +EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size); + +// 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 +EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr); + +EXPORT_C_(void) SPU2interruptDMA7(); +EXPORT_C_(u32) SPU2ReadMemAddr(int core); +EXPORT_C_(void) SPU2WriteMemAddr(int core,u32 value); +EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); + +// extended funcs +// if start is 1, starts recording spu2 data, else stops +// returns a non zero value if successful +// for now, pData is not used +EXPORT_C_(int) SPU2setupRecording(int start, void* pData); + +EXPORT_C_(void) SPU2setClockPtr(u32* ptr); + +EXPORT_C_(void) SPU2async(u32 cycles); +EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data); +EXPORT_C_(void) SPU2configure(); +EXPORT_C_(void) SPU2about(); +EXPORT_C_(s32) SPU2test(); + +#include "Spu2replay.h" + +extern u8 callirq; + +extern void (* _irqcallback)(); +extern void (* dma4callback)(); +extern void (* dma7callback)(); + +extern double srate_pv; + +extern s16 *input_data; +extern u32 input_data_ptr; + +extern int recording; +extern u32 lClocks; +extern u32* cyclePtr; + +extern void SPU2writeLog( const char* action, u32 rmem, u16 value ); +extern void TimeUpdate(u32 cClocks); +extern void SPU2_FastWrite( u32 rmem, u16 value ); + +extern void LowPassFilterInit(); + +//#define PCM24_S1_INTERLEAVE diff --git a/plugins/spu2-x/src/PrecompiledHeader.cpp b/plugins/spu2-x/src/PrecompiledHeader.cpp new file mode 100644 index 0000000000..076b1eb792 --- /dev/null +++ b/plugins/spu2-x/src/PrecompiledHeader.cpp @@ -0,0 +1,2 @@ + +#include "Global.h" \ No newline at end of file diff --git a/plugins/spu2-x/src/ReadInput.cpp b/plugins/spu2-x/src/ReadInput.cpp index b6ab222c86..c63055d8c4 100644 --- a/plugins/spu2-x/src/ReadInput.cpp +++ b/plugins/spu2-x/src/ReadInput.cpp @@ -15,172 +15,138 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" +#include "dma.h" -void __fastcall ReadInput( uint core, StereoOut32& PData ) +// 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 +// media (ie, not available in DVD mode, which almost all PS2 games use). Plus PS2 games +// generally prefer to use ADPCM streaming audio since they need as much storage space as +// possible for FMVs and high-def textures. +// +__forceinline StereoOut32 V_Core::ReadInput_HiFi( bool isCDDA ) { - V_Core& thiscore( Cores[core] ); + InputPos &= ~1; - if((thiscore.AutoDMACtrl&(core+1))==(core+1)) +#ifdef PCM24_S1_INTERLEAVE + StereoOut32 retval( + *((s32*)(ADMATempBuffer+(InputPos<<1))), + *((s32*)(ADMATempBuffer+(InputPos<<1)+2)) + ); +#else + StereoOut32 retval( + (s32&)(ADMATempBuffer[InputPos]), + (s32&)(ADMATempBuffer[InputPos+0x200]) + ); +#endif + + if( isCDDA ) { - s32 tl,tr; - - if((core==1)&&((PlayMode&8)==8)) + //give 30 bit data (SndOut downsamples the rest of the way) + retval.Left >>= 2; + retval.Right >>= 2; + } + + InputPos += 2; + //if( (InputPos==0x100) || (InputPos>=0x200) ) // CDDA mode? + if( InputPos >= 0x200 ) + { + AdmaInProgress = 0; + if(InputDataLeft >= 0x200) { - 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. + u8 k = (InputDataLeft >= InputDataProgress); #ifdef PCM24_S1_INTERLEAVE - *PData.Left=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)))); - *PData.Right=*(((s32*)(thiscore.ADMATempBuffer+(thiscore.InputPos<<1)+2))); + AutoDMAReadBuffer(1); #else - s32 *pl=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos]); - s32 *pr=(s32*)&(thiscore.ADMATempBuffer[thiscore.InputPos+0x200]); - PData.Left = *pl; - PData.Right = *pr; + AutoDMAReadBuffer(0); #endif + AdmaInProgress = 1; - PData.Left >>= 2; //give 30 bit data (SndOut downsamples the rest of the way) - PData.Right >>= 2; + TSA = (Index<<10) + InputPos; - 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 - AutoDMAReadBuffer(core,1); -#else - AutoDMAReadBuffer(core,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; - - AutoDMAReadBuffer(core,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)) + if (InputDataLeft < 0x200) { - 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); + FileLog("[%10d] %s AutoDMA%c block end.\n", isCDDA ? "CDDA" : "SPDIF", Cycles, GetDmaIndexChar()); - 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) + if( IsDevBuild ) { - u8 k=thiscore.InputDataLeft>=thiscore.InputDataProgress; - - AutoDMAReadBuffer(core,0); - - thiscore.AdmaInProgress=1; - - thiscore.TSA=(core<<10)+thiscore.InputPos; - - if (thiscore.InputDataLeft<0x200) + if(InputDataLeft > 0) { - 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; + if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); } } - thiscore.InputPos&=0x1ff; + InputDataLeft = 0; + DMAICounter = 1; } } + InputPos &= 0x1ff; + } + return retval; +} + +StereoOut32 V_Core::ReadInput() +{ + if((AutoDMACtrl&(Index+1)) != (Index+1)) + return StereoOut32(); + + if( (Index==1) && ((PlayMode&8)==8) ) + { + return ReadInput_HiFi( false ); + } + else if( (Index==0) && ((PlayMode&4)==4) ) + { + return ReadInput_HiFi( true ); } else { - PData.Left = 0; - PData.Right = 0; + StereoOut32 retval; + + if( (Index!=1) || ((PlayMode&2)==0) ) + { + // Using the temporary buffer because this area gets overwritten by some other code. + //*PData.Left = (s32)*(s16*)(spu2mem+0x2000+(core<<10)+InputPos); + //*PData.Right = (s32)*(s16*)(spu2mem+0x2200+(core<<10)+InputPos); + + retval = StereoOut32( + (s32)ADMATempBuffer[InputPos], + (s32)ADMATempBuffer[InputPos+0x200] + ); + } + + InputPos++; + if( (InputPos==0x100) || (InputPos>=0x200) ) + { + AdmaInProgress = 0; + if(InputDataLeft >= 0x200) + { + u8 k=InputDataLeft>=InputDataProgress; + + AutoDMAReadBuffer(0); + + AdmaInProgress = 1; + TSA = (Index<<10) + InputPos; + + if (InputDataLeft < 0x200) + { + AutoDMACtrl |= ~3; + + if( IsDevBuild ) + { + FileLog("[%10d] AutoDMA%c block end.\n",Cycles, GetDmaIndexChar()); + if(InputDataLeft>0) + { + if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n"); + } + } + + InputDataLeft = 0; + DMAICounter = 1; + } + } + InputPos&=0x1ff; + } + return retval; } } diff --git a/plugins/spu2-x/src/RegLog.cpp b/plugins/spu2-x/src/RegLog.cpp index 7c8d58808e..26b24bdafc 100644 --- a/plugins/spu2-x/src/RegLog.cpp +++ b/plugins/spu2-x/src/RegLog.cpp @@ -15,7 +15,7 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" #include "RegTable.h" const char *ParamNames[8]={"VOLL","VOLR","PITCH","ADSR1","ADSR2","ENVX","VOLXL","VOLXR"}; diff --git a/plugins/spu2-x/src/RegTable.cpp b/plugins/spu2-x/src/RegTable.cpp index 423a9cdad8..9f01381d12 100644 --- a/plugins/spu2-x/src/RegTable.cpp +++ b/plugins/spu2-x/src/RegTable.cpp @@ -15,14 +15,13 @@ * along with SPU2-X. If not, see . */ - -#include "Spu2.h" +#include "Global.h" #include "RegTable.h" // This var is used to confirm that our lookup table is "correct" // If the assertion in DllMain fails, it means the table has too too few entries. // (it can't have too many because that would generate a compiler error). -const u16 zero=0; +const u16 zero = 0; #define PCORE(c,p) \ U16P(Cores[c].p) diff --git a/plugins/spu2-x/src/RegTable.h b/plugins/spu2-x/src/RegTable.h index c531891aef..e9a94ceccc 100644 --- a/plugins/spu2-x/src/RegTable.h +++ b/plugins/spu2-x/src/RegTable.h @@ -19,10 +19,10 @@ #ifndef _REGTABLE_H_ #define _REGTABLE_H_ -#define U16P(x) ( (u16*)&(x) ) +#define U16P(x) ( (u16*)&(x) ) // Returns the hiword of a 32 bit integer. -#define U16P_HI(x) ( ((u16*)&(x))+1 ) +#define U16P_HI(x) ( ((u16*)&(x))+1 ) // Yay! Global namespace pollution 101! extern const u16 zero; diff --git a/plugins/spu2-x/src/Reverb.cpp b/plugins/spu2-x/src/Reverb.cpp index a2d91e2727..194dfaf935 100644 --- a/plugins/spu2-x/src/Reverb.cpp +++ b/plugins/spu2-x/src/Reverb.cpp @@ -15,52 +15,56 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" +#include "Lowpass.h" -static LPF_data lowpass_left( 11000, SampleRate ); -static LPF_data lowpass_right( 11000, SampleRate ); +// Low pass filters: Change these to 32 for a speedup (benchmarks needed to see if +// the speed gain is worth the quality drop) -static __forceinline s32 RevbGetIndexer( V_Core& thiscore, s32 offset ) +static LowPassFilter64 lowpass_left( 11000, SampleRate ); +static LowPassFilter64 lowpass_right( 11000, SampleRate ); + +__forceinline s32 V_Core::RevbGetIndexer( s32 offset ) { - u32 pos = thiscore.ReverbX + offset; + u32 pos = ReverbX + offset; // Need to use modulus here, because games can and will drop the buffer size // without notice, and it leads to offsets several times past the end of the buffer. - if( pos > thiscore.EffectsEndA ) + if( pos > EffectsEndA ) { - //pos = thiscore.EffectsStartA + ((thiscore.ReverbX + offset) % (u32)thiscore.EffectsBufferSize); - pos -= thiscore.EffectsEndA+1; - pos += thiscore.EffectsStartA; + //pos = EffectsStartA + ((ReverbX + offset) % (u32)EffectsBufferSize); + pos -= EffectsEndA+1; + pos += EffectsStartA; } return pos; } -void Reverb_AdvanceBuffer( V_Core& thiscore ) +void V_Core::Reverb_AdvanceBuffer() { - if( (Cycles & 1) && (thiscore.EffectsBufferSize > 0) ) + if( (Cycles & 1) && (EffectsBufferSize > 0) ) { - //thiscore.ReverbX = RevbGetIndexer( thiscore, 1 ); - thiscore.ReverbX += 1; + //ReverbX = RevbGetIndexer( thiscore, 1 ); + ReverbX += 1; - if( thiscore.ReverbX >= (u32)thiscore.EffectsBufferSize ) thiscore.ReverbX = 0; + if( ReverbX >= (u32)EffectsBufferSize ) ReverbX = 0; - //thiscore.ReverbX += 1; - //if(thiscore.ReverbX >= (u32)thiscore.EffectsBufferSize ) - // thiscore.ReverbX %= (u32)thiscore.EffectsBufferSize; + //ReverbX += 1; + //if(ReverbX >= (u32)EffectsBufferSize ) + // ReverbX %= (u32)EffectsBufferSize; } } ///////////////////////////////////////////////////////////////////////////////////////// -StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) +StereoOut32 V_Core::DoReverb( const StereoOut32& Input ) { // Reverb processing occurs at 24khz, so we skip processing every other sample, // and use the previous calculation for this core instead. if( (Cycles&1)==0 ) { - StereoOut32 retval( thiscore.LastEffect ); + StereoOut32 retval( LastEffect ); // Make sure and pass input through the LPF. The result can be discarded. // This gives the LPF a better sampling from which to kill offending frequencies. @@ -68,15 +72,15 @@ StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) lowpass_left.sample( Input.Left / 32768.0 ); lowpass_right.sample( Input.Right / 32768.0 ); - //thiscore.LastEffect = Input; + //LastEffect = Input; return retval; } else { - if( thiscore.RevBuffers.NeedsUpdated ) - thiscore.UpdateEffectsBufferSize(); + if( RevBuffers.NeedsUpdated ) + UpdateEffectsBufferSize(); - if( thiscore.EffectsBufferSize <= 0 ) + if( EffectsBufferSize <= 0 ) { // StartA is past EndA, so effects are disabled. //ConLog( " * SPU2: Effects disabled due to leapfrogged EffectsStart." ); @@ -91,54 +95,54 @@ StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) // Advance the current reverb buffer pointer, and cache the read/write addresses we'll be // needing for this session of reverb. - const u32 src_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_SRC_A0 ); - const u32 src_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_SRC_A1 ); - const u32 src_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_SRC_B0 ); - const u32 src_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_SRC_B1 ); + const u32 src_a0 = RevbGetIndexer( RevBuffers.IIR_SRC_A0 ); + const u32 src_a1 = RevbGetIndexer( RevBuffers.IIR_SRC_A1 ); + const u32 src_b0 = RevbGetIndexer( RevBuffers.IIR_SRC_B0 ); + const u32 src_b1 = RevbGetIndexer( RevBuffers.IIR_SRC_B1 ); - const u32 dest_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_A0 ); - const u32 dest_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_A1 ); - const u32 dest_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_B0 ); - const u32 dest_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_B1 ); + const u32 dest_a0 = RevbGetIndexer( RevBuffers.IIR_DEST_A0 ); + const u32 dest_a1 = RevbGetIndexer( RevBuffers.IIR_DEST_A1 ); + const u32 dest_b0 = RevbGetIndexer( RevBuffers.IIR_DEST_B0 ); + const u32 dest_b1 = RevbGetIndexer( RevBuffers.IIR_DEST_B1 ); - const u32 dest2_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_A0 + 1 ); - const u32 dest2_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_A1 + 1 ); - const u32 dest2_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_B0 + 1 ); - const u32 dest2_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.IIR_DEST_B1 + 1 ); + const u32 dest2_a0 = RevbGetIndexer( RevBuffers.IIR_DEST_A0 + 1 ); + const u32 dest2_a1 = RevbGetIndexer( RevBuffers.IIR_DEST_A1 + 1 ); + const u32 dest2_b0 = RevbGetIndexer( RevBuffers.IIR_DEST_B0 + 1 ); + const u32 dest2_b1 = RevbGetIndexer( RevBuffers.IIR_DEST_B1 + 1 ); - const u32 acc_src_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_A0 ); - const u32 acc_src_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_B0 ); - const u32 acc_src_c0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_C0 ); - const u32 acc_src_d0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_D0 ); + const u32 acc_src_a0 = RevbGetIndexer( RevBuffers.ACC_SRC_A0 ); + const u32 acc_src_b0 = RevbGetIndexer( RevBuffers.ACC_SRC_B0 ); + const u32 acc_src_c0 = RevbGetIndexer( RevBuffers.ACC_SRC_C0 ); + const u32 acc_src_d0 = RevbGetIndexer( RevBuffers.ACC_SRC_D0 ); - const u32 acc_src_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_A1 ); - const u32 acc_src_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_B1 ); - const u32 acc_src_c1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_C1 ); - const u32 acc_src_d1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.ACC_SRC_D1 ); + const u32 acc_src_a1 = RevbGetIndexer( RevBuffers.ACC_SRC_A1 ); + const u32 acc_src_b1 = RevbGetIndexer( RevBuffers.ACC_SRC_B1 ); + const u32 acc_src_c1 = RevbGetIndexer( RevBuffers.ACC_SRC_C1 ); + const u32 acc_src_d1 = RevbGetIndexer( RevBuffers.ACC_SRC_D1 ); - const u32 fb_src_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.FB_SRC_A0 ); - const u32 fb_src_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.FB_SRC_A1 ); - const u32 fb_src_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.FB_SRC_B0 ); - const u32 fb_src_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.FB_SRC_B1 ); + const u32 fb_src_a0 = RevbGetIndexer( RevBuffers.FB_SRC_A0 ); + const u32 fb_src_a1 = RevbGetIndexer( RevBuffers.FB_SRC_A1 ); + const u32 fb_src_b0 = RevbGetIndexer( RevBuffers.FB_SRC_B0 ); + const u32 fb_src_b1 = RevbGetIndexer( RevBuffers.FB_SRC_B1 ); - const u32 mix_dest_a0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.MIX_DEST_A0 ); - const u32 mix_dest_a1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.MIX_DEST_A1 ); - const u32 mix_dest_b0 = RevbGetIndexer( thiscore, thiscore.RevBuffers.MIX_DEST_B0 ); - const u32 mix_dest_b1 = RevbGetIndexer( thiscore, thiscore.RevBuffers.MIX_DEST_B1 ); + const u32 mix_dest_a0 = RevbGetIndexer( RevBuffers.MIX_DEST_A0 ); + const u32 mix_dest_a1 = RevbGetIndexer( RevBuffers.MIX_DEST_A1 ); + const u32 mix_dest_b0 = RevbGetIndexer( RevBuffers.MIX_DEST_B0 ); + const u32 mix_dest_b1 = RevbGetIndexer( RevBuffers.MIX_DEST_B1 ); // ----------------------------------------- // End Buffer Pointers, Begin Reverb! // ----------------------------------------- - //StereoOut32 INPUT_SAMPLE( thiscore.LastEffect + Input ); + //StereoOut32 INPUT_SAMPLE( LastEffect + Input ); // Note: LowPass on the input! Very important. Some games like DDS get terrible feedback otherwise. // Decisions, Decisions! Should we mix in the 22khz sample skipped, or not? // First one mixes in the 22hkz sample. Second one does not. /*StereoOut32 INPUT_SAMPLE( - (s32)(lowpass_left.sample( (Input.Left+thiscore.LastEffect.Left) / 32768.0 ) * 32768.0), - (s32)(lowpass_right.sample( (Input.Right+thiscore.LastEffect.Right) / 32768.0 ) * 32768.0) + (s32)(lowpass_left.sample( (Input.Left+LastEffect.Left) / 32768.0 ) * 32768.0), + (s32)(lowpass_right.sample( (Input.Right+LastEffect.Right) / 32768.0 ) * 32768.0) );*/ StereoOut32 INPUT_SAMPLE( @@ -146,15 +150,15 @@ StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) (s32)(lowpass_right.sample( Input.Right / 32768.0 ) * 32768.0) ); - const s32 IIR_INPUT_A0 = ((_spu2mem[src_a0] * thiscore.Revb.IIR_COEF) + (INPUT_SAMPLE.Left * thiscore.Revb.IN_COEF_L))>>16; - const s32 IIR_INPUT_A1 = ((_spu2mem[src_a1] * thiscore.Revb.IIR_COEF) + (INPUT_SAMPLE.Right * thiscore.Revb.IN_COEF_R))>>16; - const s32 IIR_INPUT_B0 = ((_spu2mem[src_b0] * thiscore.Revb.IIR_COEF) + (INPUT_SAMPLE.Left * thiscore.Revb.IN_COEF_L))>>16; - const s32 IIR_INPUT_B1 = ((_spu2mem[src_b1] * thiscore.Revb.IIR_COEF) + (INPUT_SAMPLE.Right * thiscore.Revb.IN_COEF_R))>>16; + const s32 IIR_INPUT_A0 = ((_spu2mem[src_a0] * Revb.IIR_COEF) + (INPUT_SAMPLE.Left * Revb.IN_COEF_L))>>16; + const s32 IIR_INPUT_A1 = ((_spu2mem[src_a1] * Revb.IIR_COEF) + (INPUT_SAMPLE.Right * Revb.IN_COEF_R))>>16; + const s32 IIR_INPUT_B0 = ((_spu2mem[src_b0] * Revb.IIR_COEF) + (INPUT_SAMPLE.Left * Revb.IN_COEF_L))>>16; + const s32 IIR_INPUT_B1 = ((_spu2mem[src_b1] * Revb.IIR_COEF) + (INPUT_SAMPLE.Right * Revb.IN_COEF_R))>>16; - const s32 IIR_A0 = (IIR_INPUT_A0 * thiscore.Revb.IIR_ALPHA) + (_spu2mem[dest_a0] * (0x7fff - thiscore.Revb.IIR_ALPHA)); - const s32 IIR_A1 = (IIR_INPUT_A1 * thiscore.Revb.IIR_ALPHA) + (_spu2mem[dest_a1] * (0x7fff - thiscore.Revb.IIR_ALPHA)); - const s32 IIR_B0 = (IIR_INPUT_B0 * thiscore.Revb.IIR_ALPHA) + (_spu2mem[dest_b0] * (0x7fff - thiscore.Revb.IIR_ALPHA)); - const s32 IIR_B1 = (IIR_INPUT_B1 * thiscore.Revb.IIR_ALPHA) + (_spu2mem[dest_b1] * (0x7fff - thiscore.Revb.IIR_ALPHA)); + const s32 IIR_A0 = (IIR_INPUT_A0 * Revb.IIR_ALPHA) + (_spu2mem[dest_a0] * (0x7fff - Revb.IIR_ALPHA)); + const s32 IIR_A1 = (IIR_INPUT_A1 * Revb.IIR_ALPHA) + (_spu2mem[dest_a1] * (0x7fff - Revb.IIR_ALPHA)); + const s32 IIR_B0 = (IIR_INPUT_B0 * Revb.IIR_ALPHA) + (_spu2mem[dest_b0] * (0x7fff - Revb.IIR_ALPHA)); + const s32 IIR_B1 = (IIR_INPUT_B1 * Revb.IIR_ALPHA) + (_spu2mem[dest_b1] * (0x7fff - Revb.IIR_ALPHA)); _spu2mem[dest2_a0] = clamp_mix( IIR_A0 >> 16 ); _spu2mem[dest2_a1] = clamp_mix( IIR_A1 >> 16 ); _spu2mem[dest2_b0] = clamp_mix( IIR_B0 >> 16 ); @@ -162,10 +166,10 @@ StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) // Faster single-mul approach to interpolation: // (doesn't work yet -- breaks Digital Devil Saga badly) - /*const s32 IIR_A0 = IIR_INPUT_A0 + (((_spu2mem[dest_a0]-IIR_INPUT_A0) * thiscore.Revb.IIR_ALPHA)>>16); - const s32 IIR_A1 = IIR_INPUT_A1 + (((_spu2mem[dest_a1]-IIR_INPUT_A1) * thiscore.Revb.IIR_ALPHA)>>16); - const s32 IIR_B0 = IIR_INPUT_B0 + (((_spu2mem[dest_b0]-IIR_INPUT_B0) * thiscore.Revb.IIR_ALPHA)>>16); - const s32 IIR_B1 = IIR_INPUT_B1 + (((_spu2mem[dest_b1]-IIR_INPUT_B1) * thiscore.Revb.IIR_ALPHA)>>16); + /*const s32 IIR_A0 = IIR_INPUT_A0 + (((_spu2mem[dest_a0]-IIR_INPUT_A0) * Revb.IIR_ALPHA)>>16); + const s32 IIR_A1 = IIR_INPUT_A1 + (((_spu2mem[dest_a1]-IIR_INPUT_A1) * Revb.IIR_ALPHA)>>16); + const s32 IIR_B0 = IIR_INPUT_B0 + (((_spu2mem[dest_b0]-IIR_INPUT_B0) * Revb.IIR_ALPHA)>>16); + const s32 IIR_B1 = IIR_INPUT_B1 + (((_spu2mem[dest_b1]-IIR_INPUT_B1) * Revb.IIR_ALPHA)>>16); _spu2mem[dest2_a0] = clamp_mix( IIR_A0 ); _spu2mem[dest2_a1] = clamp_mix( IIR_A1 ); @@ -173,36 +177,36 @@ StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ) _spu2mem[dest2_b1] = clamp_mix( IIR_B1 );*/ const s32 ACC0 = - ((_spu2mem[acc_src_a0] * thiscore.Revb.ACC_COEF_A)) + - ((_spu2mem[acc_src_b0] * thiscore.Revb.ACC_COEF_B)) + - ((_spu2mem[acc_src_c0] * thiscore.Revb.ACC_COEF_C)) + - ((_spu2mem[acc_src_d0] * thiscore.Revb.ACC_COEF_D)); + ((_spu2mem[acc_src_a0] * Revb.ACC_COEF_A)) + + ((_spu2mem[acc_src_b0] * Revb.ACC_COEF_B)) + + ((_spu2mem[acc_src_c0] * Revb.ACC_COEF_C)) + + ((_spu2mem[acc_src_d0] * Revb.ACC_COEF_D)); const s32 ACC1 = - ((_spu2mem[acc_src_a1] * thiscore.Revb.ACC_COEF_A)) + - ((_spu2mem[acc_src_b1] * thiscore.Revb.ACC_COEF_B)) + - ((_spu2mem[acc_src_c1] * thiscore.Revb.ACC_COEF_C)) + - ((_spu2mem[acc_src_d1] * thiscore.Revb.ACC_COEF_D)); + ((_spu2mem[acc_src_a1] * Revb.ACC_COEF_A)) + + ((_spu2mem[acc_src_b1] * Revb.ACC_COEF_B)) + + ((_spu2mem[acc_src_c1] * Revb.ACC_COEF_C)) + + ((_spu2mem[acc_src_d1] * Revb.ACC_COEF_D)); - const s32 FB_A0 = (_spu2mem[fb_src_a0] * thiscore.Revb.FB_ALPHA); - const s32 FB_A1 = (_spu2mem[fb_src_a1] * thiscore.Revb.FB_ALPHA); + const s32 FB_A0 = (_spu2mem[fb_src_a0] * Revb.FB_ALPHA); + const s32 FB_A1 = (_spu2mem[fb_src_a1] * Revb.FB_ALPHA); - const s32 fb_xor_a0 = _spu2mem[fb_src_a0] * ( thiscore.Revb.FB_ALPHA ^ 0x8000 ); - const s32 fb_xor_a1 = _spu2mem[fb_src_a1] * ( thiscore.Revb.FB_ALPHA ^ 0x8000 ); + const s32 fb_xor_a0 = _spu2mem[fb_src_a0] * ( Revb.FB_ALPHA ^ 0x8000 ); + const s32 fb_xor_a1 = _spu2mem[fb_src_a1] * ( Revb.FB_ALPHA ^ 0x8000 ); _spu2mem[mix_dest_a0] = clamp_mix( (ACC0 - FB_A0) >> 16 ); _spu2mem[mix_dest_a1] = clamp_mix( (ACC1 - FB_A1) >> 16 ); - _spu2mem[mix_dest_b0] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<16, ACC0) - fb_xor_a0 - (_spu2mem[fb_src_b0] * thiscore.Revb.FB_X)) >> 16 ); - _spu2mem[mix_dest_b1] = clamp_mix( (MulShr32(thiscore.Revb.FB_ALPHA<<16, ACC1) - fb_xor_a1 - (_spu2mem[fb_src_b1] * thiscore.Revb.FB_X)) >> 16 ); + _spu2mem[mix_dest_b0] = clamp_mix( (MulShr32(Revb.FB_ALPHA<<16, ACC0) - fb_xor_a0 - (_spu2mem[fb_src_b0] * Revb.FB_X)) >> 16 ); + _spu2mem[mix_dest_b1] = clamp_mix( (MulShr32(Revb.FB_ALPHA<<16, ACC1) - fb_xor_a1 - (_spu2mem[fb_src_b1] * Revb.FB_X)) >> 16 ); - thiscore.LastEffect.Left = _spu2mem[mix_dest_a0] + _spu2mem[mix_dest_b0]; - thiscore.LastEffect.Right = _spu2mem[mix_dest_a1] + _spu2mem[mix_dest_b1]; + LastEffect.Left = _spu2mem[mix_dest_a0] + _spu2mem[mix_dest_b0]; + LastEffect.Right = _spu2mem[mix_dest_a1] + _spu2mem[mix_dest_b1]; - clamp_mix( thiscore.LastEffect ); + clamp_mix( LastEffect ); - //thiscore.LastEffect.Left = (s32)(lowpass_left.sample( thiscore.LastEffect.Left / 32768.0 ) * 32768.0); - //thiscore.LastEffect.Right = (s32)(lowpass_right.sample( thiscore.LastEffect.Right / 32768.0 ) * 32768.0); + //LastEffect.Left = (s32)(lowpass_left.sample( LastEffect.Left / 32768.0 ) * 32768.0); + //LastEffect.Right = (s32)(lowpass_right.sample( LastEffect.Right / 32768.0 ) * 32768.0); - return thiscore.LastEffect; + return LastEffect; } } diff --git a/plugins/spu2-x/src/SaveStateSPU.cpp b/plugins/spu2-x/src/SaveStateSPU.cpp deleted file mode 100644 index 5b19f5b59b..0000000000 --- a/plugins/spu2-x/src/SaveStateSPU.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 - * Developed and maintained by the Pcsx2 Development Team. - * - * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] - * - * SPU2-X is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with SPU2-X. If not, see . - */ - -#include "Spu2.h" - -namespace Savestate { - -struct SPU2freezeData -{ - u32 version; - u8 unkregs[0x10000]; - u8 mem[0x200000]; - - u32 id; - V_Core Cores[2]; - V_SPDIF Spdif; - s16 OutPos; - s16 InputPos; - u32 Cycles; - u32 lClocks; - int PlayMode; - - // Used as a base pointer to a series PcmCache blocks. - PcmCacheEntry cacheData; -}; - -// Arbitrary ID to identify SPU2-X saves. -static const u32 SAVE_ID = 0x1227521; - -// versioning for saves. -// Increment this when changes to the savestate system are made. - -static const u32 SAVE_VERSION = 0x0005; - -static void wipe_the_cache() -{ - memset( pcm_cache_data, 0, pcm_BlockCount * sizeof(PcmCacheEntry) ); -} - - -static s16 old_state_sBuffer[pcm_DecodedSamplesPerBlock] = {0}; - -typedef s32 __fastcall FreezeHandlerFunction( SPU2freezeData& data ); - -s32 __fastcall FreezeIt( SPU2freezeData& spud ) -{ - spud.id = SAVE_ID; - spud.version = SAVE_VERSION; - - memcpy(spud.unkregs, spu2regs, 0x010000); - memcpy(spud.mem, _spu2mem, 0x200000); - memcpy(spud.Cores, Cores, sizeof(Cores)); - memcpy(&spud.Spdif, &Spdif, sizeof(Spdif)); - spud.OutPos = OutPos; - spud.InputPos = InputPos; - spud.Cycles = Cycles; - spud.lClocks = lClocks; - spud.PlayMode = PlayMode; - - // Save our cache: - // We could just force the user to rebuild the cache when loading - // from stavestates, but for most games the cache is pretty - // small and compresses well. - // - // Potential Alternative: - // If the cache is not saved then it is necessary to save the - // decoded blocks currently in use by active voices. This allows - // voices to resume seamlessly on load. - - PcmCacheEntry* pcmDst = &spud.cacheData; - int blksSaved=0; - - for( int bidx=0; bidx FreezeSave > Saved %d cache blocks.\n", blksSaved++ ); - - return 0; -} - -s32 __fastcall ThawIt( SPU2freezeData& spud ) -{ - if( spud.id != SAVE_ID || spud.version < SAVE_VERSION ) - { - printf("\n*** SPU2-X Warning:\n"); - if( spud.id == SAVE_ID ) - printf("\tSavestate version is from an older version of this plugin.\n"); - else - printf("\tThe savestate you are trying to load was not made with this plugin.\n"); - - printf("\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n"); - printf(" and then continue from there.\n\n"); - - // Do *not* reset the cores. - // We'll need some "hints" as to how the cores should be initialized, - // and the only way to get that is to use the game's existing core settings - // and hope they kinda match the settings for the savestate (IRQ enables and such). - // - - //CoreReset( 0 ); - //CoreReset( 1 ); - - // adpcm cache : Clear all the cache flags and buffers. - - wipe_the_cache(); - } - else - { - // base stuff - memcpy(spu2regs, spud.unkregs, 0x010000); - memcpy(_spu2mem, spud.mem, 0x200000); - - memcpy(Cores, spud.Cores, sizeof(Cores)); - memcpy(&Spdif, &spud.Spdif, sizeof(Spdif)); - OutPos = spud.OutPos; - InputPos = spud.InputPos; - Cycles = spud.Cycles; - lClocks = spud.lClocks; - PlayMode = spud.PlayMode; - - // Load the ADPCM cache: - - wipe_the_cache(); - - const PcmCacheEntry* pcmSrc = &spud.cacheData; - int blksLoaded=0; - - for( int bidx=0; bidxsize = SizeIt(); - return 0; - } - - jASSUME( mode == FREEZE_LOAD || mode == FREEZE_SAVE ); - jASSUME( data != NULL ); - - if( data->data == NULL ) return -1; - SPU2freezeData& spud = (SPU2freezeData&)*(data->data); - - switch( mode ) - { - case FREEZE_LOAD: return ThawIt( spud ); - case FREEZE_SAVE: return FreezeIt( spud ); - - jNO_DEFAULT; - } - - // technically unreachable, but kills a warning: - return 0; -} diff --git a/plugins/spu2-x/src/SndOut.cpp b/plugins/spu2-x/src/SndOut.cpp index 29588ccf43..f022f212da 100644 --- a/plugins/spu2-x/src/SndOut.cpp +++ b/plugins/spu2-x/src/SndOut.cpp @@ -15,7 +15,7 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +#include "Global.h" StereoOut32 StereoOut32::Empty( 0, 0 ); @@ -56,11 +56,7 @@ public: s32 Init() { return 0; } void Close() { } s32 Test() const { return 0; } -#ifdef _MSC_VER - void Configure(HWND parent) { } -#else void Configure(uptr parent) { } -#endif bool Is51Out() const { return false; } int GetEmptySampleCount() const { return 0; } @@ -290,9 +286,9 @@ void SndBuffer::Cleanup() { mods[OutputModule]->Close(); - SAFE_DELETE_ARRAY( m_buffer ); - SAFE_DELETE_ARRAY( sndTempBuffer ); - SAFE_DELETE_ARRAY( sndTempBuffer16 ); + safe_delete_array( m_buffer ); + safe_delete_array( sndTempBuffer ); + safe_delete_array( sndTempBuffer16 ); } int SndBuffer::m_dsp_progress = 0; @@ -375,15 +371,3 @@ s32 SndBuffer::Test() return mods[OutputModule]->Test(); } - -#ifdef _MSC_VER -void SndBuffer::Configure(HWND parent, u32 module ) -#else -void SndBuffer::Configure(uptr parent, u32 module ) -#endif -{ - if( mods[module] == NULL ) - return; - - mods[module]->Configure(parent); -} diff --git a/plugins/spu2-x/src/SndOut.h b/plugins/spu2-x/src/SndOut.h index 9014323ef5..bf250ed71e 100644 --- a/plugins/spu2-x/src/SndOut.h +++ b/plugins/spu2-x/src/SndOut.h @@ -1,25 +1,21 @@ -//GiGaHeRz's SPU2 Driver -//Copyright (c) 2003-2008, David Quintana -// -//This library is free software; you can redistribute it and/or -//modify it under the terms of the GNU Lesser General Public -//License as published by the Free Software Foundation; either -//version 2.1 of the License, or (at your option) any later version. -// -//This library is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -//Lesser General Public License for more details. -// -//You should have received a copy of the GNU Lesser General Public -//License along with this library; if not, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -#ifndef SNDOUT_H_INCLUDE -#define SNDOUT_H_INCLUDE +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ -#include "BaseTypes.h" -#include "Lowpass.h" +#pragma once // Number of stereo samples per SndOut block. // All drivers must work in units of this size when communicating with @@ -35,7 +31,7 @@ static const int SndOutVolumeShift = 13; // is too problematic. :) static const int SampleRate = 48000; -int FindOutputModuleById( const wchar_t* omodid ); +extern int FindOutputModuleById( const wchar_t* omodid ); struct StereoOut16 { @@ -231,9 +227,9 @@ struct Stereo51Out16DplII s32 Tfl=(RAccum)*255/(LAccum); s32 Tfr=(LAccum)*255/(RAccum); - int gMax = max(Tfl,Tfr); - Tfl=Tfl*255/gMax; - Tfr=Tfr*255/gMax; + int gMax = std::max(Tfl,Tfr); + Tfl = Tfl*255/gMax; + Tfr = Tfr*255/gMax; if(Tfl>255) Tfl=255; if(Tfr>255) Tfr=255; @@ -393,12 +389,6 @@ public: static s32 Test(); static void ClearContents(); -#ifdef _MSC_VER - static void Configure(HWND parent, u32 module ); -#else - static void Configure(uptr parent, u32 module ); -#endif - // Note: When using with 32 bit output buffers, the user of this function is responsible // for shifting the values to where they need to be manually. The fixed point depth of // the sample output is determined by the SndOutVolumeShift, which is the number of bits @@ -474,11 +464,7 @@ public: virtual s32 Test() const=0; // Gui function: Used to open the configuration box for this driver. -#ifdef _MSC_VER - virtual void Configure(HWND parent)=0; -#else virtual void Configure(uptr parent)=0; -#endif // Loads settings from the INI file for this driver virtual void ReadSettings()=0; @@ -503,4 +489,13 @@ extern SndOutModule* XAudio2Out; extern SndOutModule* mods[]; -#endif // SNDOUT_H_INCLUDE +// ===================================================================================================== + +extern void RecordStart(); +extern void RecordStop(); +extern void RecordWrite( const StereoOut16& sample ); + +extern s32 DspLoadLibrary(wchar_t *fileName, int modNum); +extern void DspCloseLibrary(); +extern int DspProcess(s16 *buffer, int samples); +extern void DspUpdate(); // to let the Dsp process window messages diff --git a/plugins/spu2-x/src/Spu2.h b/plugins/spu2-x/src/Spu2.h deleted file mode 100644 index b3432b7695..0000000000 --- a/plugins/spu2-x/src/Spu2.h +++ /dev/null @@ -1,212 +0,0 @@ -/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 - * Developed and maintained by the Pcsx2 Development Team. - * - * SPU2-X is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with SPU2-X. If not, see . - */ - -#pragma once - -#include "BaseTypes.h" -#include "Pcsx2Defs.h" - -#include "Utilities/Exceptions.h" - -#ifdef __LINUX__ -#include -#include - -//Until I get around to putting in Linux svn code, this is an unknown svn version. -#define SVN_REV_UNKNOWN -#endif - -#include "ConvertUTF.h" - -namespace VersionInfo -{ - static const u8 PluginApi = PS2E_SPU2_VERSION; - static const u8 Release = 1; - static const u8 Revision = 2; // increase that with each version -} - -#ifdef _MSC_VER -#define EXPORT_C_(type) extern "C" __declspec(dllexport) type CALLBACK -#else -#define EXPORT_C_(type) extern "C" type -#endif - -// We have our own versions that have the DLLExport attribute configured: - -EXPORT_C_(s32) SPU2init(); -EXPORT_C_(s32) SPU2open(void *pDsp); -EXPORT_C_(void) SPU2close(); -EXPORT_C_(void) SPU2shutdown(); -EXPORT_C_(void) SPU2write(u32 mem, u16 value); -EXPORT_C_(u16) SPU2read(u32 mem); -EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size); -EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size); -EXPORT_C_(void) SPU2interruptDMA4(); -EXPORT_C_(void) SPU2readDMA7Mem(u16* pMem, u32 size); -EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size); - -// 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 -EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr); - -EXPORT_C_(void) SPU2interruptDMA7(); -EXPORT_C_(u32) SPU2ReadMemAddr(int core); -EXPORT_C_(void) SPU2WriteMemAddr(int core,u32 value); -EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)()); - -// extended funcs -// if start is 1, starts recording spu2 data, else stops -// returns a non zero value if successful -// for now, pData is not used -EXPORT_C_(int) SPU2setupRecording(int start, void* pData); - -EXPORT_C_(void) SPU2setClockPtr(u32* ptr); - -EXPORT_C_(void) SPU2async(u32 cycles); -EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data); -EXPORT_C_(void) SPU2configure(); -EXPORT_C_(void) SPU2about(); -EXPORT_C_(s32) SPU2test(); - - -//#define EFFECTS_DUMP - -//Plugin parts -#include "Config.h" -#include "defs.h" -#include "regs.h" -#include "Dma.h" -#include "SndOut.h" - -#include "Spu2replay.h" - -#ifdef SPU2X_DEVBUILD -#define SPU2_LOG -#endif - -#include "Debug.h" - -//-------------------------------------------------------------------------------------- -// Helper macros -//-------------------------------------------------------------------------------------- -#ifndef SAFE_FREE -# define SAFE_FREE(p) { if(p) { free(p); (p)=NULL; } } -#endif -#ifndef SAFE_DELETE_ARRAY -# define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } -#endif -#ifndef SAFE_DELETE_OBJ -# define SAFE_DELETE_OBJ(p) { if(p) { delete (p); (p)=NULL; } } -#endif -#ifndef SAFE_RELEASE -# define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } -#endif - -// The SPU2 has a dynamic memory range which is used for several internal operations, such as -// registers, CORE 1/2 mixing, AutoDMAs, and some other fancy stuff. We exclude this range -// from the cache here: -static const s32 SPU2_DYN_MEMLINE = 0x2800; - -// 8 short words per encoded PCM block. (as stored in SPU2 ram) -static const int pcm_WordsPerBlock = 8; - -// number of cachable ADPCM blocks (any blocks above the SPU2_DYN_MEMLINE) -static const int pcm_BlockCount = 0x100000 / pcm_WordsPerBlock; - -// 28 samples per decoded PCM block (as stored in our cache) -static const int pcm_DecodedSamplesPerBlock = 28; - -struct PcmCacheEntry -{ - bool Validated; - s16 Sampledata[pcm_DecodedSamplesPerBlock]; -}; - -extern void spdif_set51(u32 is_5_1_out); -extern u32 spdif_init(); -extern void spdif_shutdown(); -extern void spdif_get_samples(s32 *samples); // fills the buffer with [l,r,c,lfe,sl,sr] if using 5.1 output, or [l,r] if using stereo - -extern short *spu2regs; -extern short *_spu2mem; - -extern PcmCacheEntry* pcm_cache_data; - -extern s16* __fastcall GetMemPtr(u32 addr); -extern s16 __fastcall spu2M_Read( u32 addr ); -extern void __fastcall spu2M_Write( u32 addr, s16 value ); -extern void __fastcall spu2M_Write( u32 addr, u16 value ); - -#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem) & 0x1fff))) -#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem) & 0x1fff))) - -extern u8 callirq; - -extern void (* _irqcallback)(); -extern void (* dma4callback)(); -extern void (* dma7callback)(); - -extern void SetIrqCall(); - -extern double srate_pv; - -extern s16 *input_data; -extern u32 input_data_ptr; - -extern int PlayMode; -extern int recording; - -extern u32 lClocks; -extern u32* cyclePtr; - -extern void SPU2writeLog( const char* action, u32 rmem, u16 value ); - -extern void TimeUpdate(u32 cClocks); -extern u16 SPU_ps1_read(u32 mem); -extern void SPU_ps1_write(u32 mem, u16 value); -extern void SPU2_FastWrite( u32 rmem, u16 value ); - -extern void StartVoices(int core, u32 value); -extern void StopVoices(int core, u32 value); - -extern s32 DspLoadLibrary(wchar_t *fileName, int modNum); -extern void DspCloseLibrary(); -extern int DspProcess(s16 *buffer, int samples); -extern void DspUpdate(); // to let the Dsp process window messages - -extern void RecordStart(); -extern void RecordStop(); -extern void RecordWrite( const StereoOut16& sample ); - -extern void UpdateSpdifMode(); -extern void LowPassFilterInit(); -extern void InitADSR(); -extern void CalculateADSR( V_Voice& vc ); - -extern void __fastcall ReadInput( uint core, StereoOut32& PData ); - - -////////////////////////////// -// The Mixer Section // -////////////////////////////// - -extern void Mix(); -extern s32 clamp_mix( s32 x, u8 bitshift=0 ); -extern StereoOut32 clamp_mix( const StereoOut32& sample, u8 bitshift=0 ); -extern void Reverb_AdvanceBuffer( V_Core& thiscore ); -extern StereoOut32 DoReverb( V_Core& thiscore, const StereoOut32& Input ); -extern s32 MulShr32( s32 srcval, s32 mulval ); - -//#define PCM24_S1_INTERLEAVE diff --git a/plugins/spu2-x/src/Spu2replay.cpp b/plugins/spu2-x/src/Spu2replay.cpp index 1809de3763..acce80dd0a 100644 --- a/plugins/spu2-x/src/Spu2replay.cpp +++ b/plugins/spu2-x/src/Spu2replay.cpp @@ -16,9 +16,8 @@ //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -#include - -#include "Spu2.h" +#include "Global.h" +#include "PS2E-spu2.h" FILE* s2rfile; @@ -115,6 +114,7 @@ void dummy7() #define Cread(a,b,c,d) if(fread(a,b,c,d). */ -#include "Spu2.h" +#include "Global.h" #include "SoundTouch/SoundTouch.h" #include "SoundTouch/WavFile.h" @@ -304,9 +304,7 @@ void SndBuffer::soundtouchInit() pSoundTouch->setSetting( SETTING_USE_QUICKSEEK, 0 ); pSoundTouch->setSetting( SETTING_USE_AA_FILTER, 0 ); - pSoundTouch->setSetting( SETTING_SEQUENCE_MS, SoundtouchCfg::SequenceLenMS ); - pSoundTouch->setSetting( SETTING_SEEKWINDOW_MS, SoundtouchCfg::SeekWindowMS ); - pSoundTouch->setSetting( SETTING_OVERLAP_MS, SoundtouchCfg::OverlapMS ); + SoundtouchCfg::ApplySettings( *pSoundTouch ); pSoundTouch->setTempo(1); @@ -340,5 +338,5 @@ void SndBuffer::soundtouchClearContents() void SndBuffer::soundtouchCleanup() { - SAFE_DELETE_OBJ( pSoundTouch ); + safe_delete( pSoundTouch ); } diff --git a/plugins/spu2-x/src/Wavedump_wav.cpp b/plugins/spu2-x/src/Wavedump_wav.cpp index bc09a67b51..62f48100af 100644 --- a/plugins/spu2-x/src/Wavedump_wav.cpp +++ b/plugins/spu2-x/src/Wavedump_wav.cpp @@ -15,11 +15,7 @@ * along with SPU2-X. If not, see . */ -#include -#include - -#include "Spu2.h" - +#include "Global.h" #include "SoundTouch/WavFile.h" static WavOutFile* _new_WavOutFile( const char* destfile ) @@ -52,7 +48,7 @@ namespace WaveDump { for( int srcidx=0; srcidx. */ +#include "Global.h" #include "Dialogs.h" -#include #include "svnrev.h" #include "Hyperlinks.h" diff --git a/plugins/spu2-x/src/Windows/CfgHelpers.cpp b/plugins/spu2-x/src/Windows/CfgHelpers.cpp index b0b48b7a91..4969db6ac1 100644 --- a/plugins/spu2-x/src/Windows/CfgHelpers.cpp +++ b/plugins/spu2-x/src/Windows/CfgHelpers.cpp @@ -15,8 +15,22 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" #include "Dialogs.h" +void SysMessage(const char *fmt, ...) +{ + va_list list; + char tmp[512]; + wchar_t wtmp[512]; + + va_start(list,fmt); + sprintf_s(tmp,fmt,list); + va_end(list); + swprintf_s(wtmp, L"%S", tmp); + MessageBox(0, wtmp, L"SPU2-X System Message", 0); +} + ////// const TCHAR CfgFile[] = L"inis\\SPU2-X.ini"; diff --git a/plugins/spu2-x/src/Windows/Config.cpp b/plugins/spu2-x/src/Windows/Config.cpp index b1dc43f96c..576a2bb5b6 100644 --- a/plugins/spu2-x/src/Windows/Config.cpp +++ b/plugins/spu2-x/src/Windows/Config.cpp @@ -15,9 +15,10 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" #include "Dialogs.h" -#ifdef SPU2X_DEVBUILD +#ifdef PCSX2_DEVBUILD static const int LATENCY_MAX = 3000; #else static const int LATENCY_MAX = 750; @@ -25,8 +26,6 @@ static const int LATENCY_MAX = 750; static const int LATENCY_MIN = 40; -int AutoDMAPlayRate[2] = {0,0}; - // MIXING int Interpolation = 1; /* values: @@ -57,9 +56,6 @@ bool StereoExpansionEnabled = false; void ReadSettings() { - AutoDMAPlayRate[0] = CfgReadInt(L"MIXING",L"AutoDMA_Play_Rate_0",0); - AutoDMAPlayRate[1] = CfgReadInt(L"MIXING",L"AutoDMA_Play_Rate_1",0); - Interpolation = CfgReadInt( L"MIXING",L"Interpolation", 1 ); timeStretchDisabled = CfgReadBool( L"OUTPUT", L"Disable_Timestretch", false ); @@ -107,9 +103,6 @@ void WriteSettings() { CfgWriteInt(L"MIXING",L"Interpolation",Interpolation); - CfgWriteInt(L"MIXING",L"AutoDMA_Play_Rate_0",AutoDMAPlayRate[0]); - CfgWriteInt(L"MIXING",L"AutoDMA_Play_Rate_1",AutoDMAPlayRate[1]); - CfgWriteBool(L"MIXING",L"Disable_Effects",EffectsDisabled); CfgWriteStr(L"OUTPUT",L"Output_Module", mods[OutputModule]->GetIdent() ); @@ -204,9 +197,11 @@ BOOL CALLBACK ConfigProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) break; case IDC_OUTCONF: - SndBuffer::Configure( hWnd, - (int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0) - ); + { + const int module = (int)SendMessage(GetDlgItem(hWnd,IDC_OUTPUT),CB_GETCURSEL,0,0); + if( mods[module] == NULL ) break; + mods[module]->Configure((uptr)hWnd); + } break; case IDC_OPEN_CONFIG_DEBUG: diff --git a/plugins/spu2-x/src/Windows/Config.h b/plugins/spu2-x/src/Windows/Config.h deleted file mode 100644 index 031b287f0c..0000000000 --- a/plugins/spu2-x/src/Windows/Config.h +++ /dev/null @@ -1,147 +0,0 @@ -/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 - * Developed and maintained by the Pcsx2 Development Team. - * - * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] - * - * SPU2-X is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with SPU2-X. If not, see . - */ - -#pragma once - -#include - -extern bool DebugEnabled; - -extern bool _MsgToConsole; -extern bool _MsgKeyOnOff; -extern bool _MsgVoiceOff; -extern bool _MsgDMA; -extern bool _MsgAutoDMA; -extern bool _MsgOverruns; -extern bool _MsgCache; - -extern bool _AccessLog; -extern bool _DMALog; -extern bool _WaveLog; - -extern bool _CoresDump; -extern bool _MemDump; -extern bool _RegDump; - -static __forceinline bool MsgToConsole() { return _MsgToConsole & DebugEnabled; } - -static __forceinline bool MsgKeyOnOff() { return _MsgKeyOnOff & MsgToConsole(); } -static __forceinline bool MsgVoiceOff() { return _MsgVoiceOff & MsgToConsole(); } -static __forceinline bool MsgDMA() { return _MsgDMA & MsgToConsole(); } -static __forceinline bool MsgAutoDMA() { return _MsgAutoDMA & MsgDMA(); } -static __forceinline bool MsgOverruns() { return _MsgOverruns & MsgToConsole(); } -static __forceinline bool MsgCache() { return _MsgCache & MsgToConsole(); } - -static __forceinline bool AccessLog() { return _AccessLog & DebugEnabled; } -static __forceinline bool DMALog() { return _DMALog & DebugEnabled; } -static __forceinline bool WaveLog() { return _WaveLog & DebugEnabled; } - -static __forceinline bool CoresDump() { return _CoresDump & DebugEnabled; } -static __forceinline bool MemDump() { return _MemDump & DebugEnabled; } -static __forceinline bool RegDump() { return _RegDump & DebugEnabled; } - - -extern wchar_t AccessLogFileName[255]; -extern wchar_t WaveLogFileName[255]; -extern wchar_t DMA4LogFileName[255]; -extern wchar_t DMA7LogFileName[255]; -extern wchar_t CoresDumpFileName[255]; -extern wchar_t MemDumpFileName[255]; -extern wchar_t RegDumpFileName[255]; - -extern int Interpolation; - -extern bool EffectsDisabled; - -extern int AutoDMAPlayRate[2]; - -extern u32 OutputModule; -extern int SndOutLatencyMS; - -extern wchar_t dspPlugin[]; -extern int dspPluginModule; - -extern bool dspPluginEnabled; -extern bool timeStretchDisabled; -extern bool StereoExpansionEnabled; - -class SoundtouchCfg -{ - // Timestretch Slider Bounds, Min/Max - static const int SequenceLen_Min = 30; - static const int SequenceLen_Max = 90; - - static const int SeekWindow_Min = 10; - static const int SeekWindow_Max = 32; - - static const int Overlap_Min = 3; - static const int Overlap_Max = 15; - -public: - static int SequenceLenMS; - static int SeekWindowMS; - static int OverlapMS; - - static void ReadSettings(); - static void WriteSettings(); - static void OpenDialog( HWND hWnd ); - -protected: - static void ClampValues(); - static BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); - -}; - - -// *** BEGIN DRIVER-SPECIFIC CONFIGURATION *** -// ------------------------------------------- - -// DSOUND -struct CONFIG_XAUDIO2 -{ - std::wstring Device; - s8 NumBuffers; - - CONFIG_XAUDIO2() : - Device(), - NumBuffers( 2 ) - { - } -}; - -// WAVEOUT -struct CONFIG_WAVEOUT -{ - std::wstring Device; - s8 NumBuffers; - - CONFIG_WAVEOUT() : - Device(), - NumBuffers( 4 ) - { - } -}; - -extern CONFIG_WAVEOUT Config_WaveOut; -extern CONFIG_XAUDIO2 Config_XAudio2; - -////// - -void ReadSettings(); -void WriteSettings(); -void configure(); -void AboutBox(); diff --git a/plugins/spu2-x/src/Windows/ConfigDebug.cpp b/plugins/spu2-x/src/Windows/ConfigDebug.cpp index 0373c225c4..ef38cd54e4 100644 --- a/plugins/spu2-x/src/Windows/ConfigDebug.cpp +++ b/plugins/spu2-x/src/Windows/ConfigDebug.cpp @@ -15,6 +15,7 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" #include "Dialogs.h" diff --git a/plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp b/plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp index 781ef22002..864947eba3 100644 --- a/plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp +++ b/plugins/spu2-x/src/Windows/ConfigSoundtouch.cpp @@ -15,13 +15,33 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" #include "Dialogs.h" -int SoundtouchCfg::SequenceLenMS = 63; -int SoundtouchCfg::SeekWindowMS = 16; -int SoundtouchCfg::OverlapMS = 7; +#include "SoundTouch/SoundTouch.h" -void SoundtouchCfg::ClampValues() +static int SequenceLenMS = 63; +static int SeekWindowMS = 16; +static int OverlapMS = 7; + +// Timestretch Slider Bounds, Min/Max +static const int SequenceLen_Min = 30; +static const int SequenceLen_Max = 90; + +static const int SeekWindow_Min = 10; +static const int SeekWindow_Max = 32; + +static const int Overlap_Min = 3; +static const int Overlap_Max = 15; + +void SoundtouchCfg::ApplySettings( soundtouch::SoundTouch& sndtouch ) +{ + sndtouch.setSetting( SETTING_SEQUENCE_MS, SequenceLenMS ); + sndtouch.setSetting( SETTING_SEEKWINDOW_MS, SeekWindowMS ); + sndtouch.setSetting( SETTING_OVERLAP_MS, OverlapMS ); +} + +static void ClampValues() { Clampify( SequenceLenMS, SequenceLen_Min, SequenceLen_Max ); Clampify( SeekWindowMS, SeekWindow_Min, SeekWindow_Max ); @@ -101,7 +121,7 @@ void SoundtouchCfg::OpenDialog( HWND hWnd ) ret = DialogBox( hInstance, MAKEINTRESOURCE(IDD_CONFIG_SOUNDTOUCH), hWnd, (DLGPROC)DialogProc ); if(ret==-1) { - MessageBoxEx(GetActiveWindow(),L"Error Opening the Soundtouch advanced dialog.",L"OMG ERROR!",MB_OK,0); + MessageBoxEx(GetActiveWindow(), L"Error Opening the Soundtouch advanced dialog.", L"OMG ERROR!", MB_OK, 0); return; } ReadSettings(); diff --git a/plugins/spu2-x/src/Windows/Dialogs.h b/plugins/spu2-x/src/Windows/Dialogs.h index 72065d4d03..0568591da7 100644 --- a/plugins/spu2-x/src/Windows/Dialogs.h +++ b/plugins/spu2-x/src/Windows/Dialogs.h @@ -17,30 +17,11 @@ #pragma once -#ifndef _DIALOGS_H_ -#define _DIALOGS_H_ - -#include "../Spu2.h" - -#include -#include - -extern HINSTANCE hInstance; - -#define SET_CHECK(idc,value) SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,((value)==0)?BST_UNCHECKED:BST_CHECKED,0) -#define HANDLE_CHECK(idc,hvar) case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0); break -#define HANDLE_CHECKNB(idc,hvar)case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0) -#define ENABLE_CONTROL(idc,value) EnableWindow(GetDlgItem(hWnd,idc),value) - -#define INIT_SLIDER(idc,minrange,maxrange,tickfreq,pagesize,linesize) \ - SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMIN,FALSE,minrange); \ - SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMAX,FALSE,maxrange); \ - SendMessage(GetDlgItem(hWnd,idc),TBM_SETTICFREQ,tickfreq,0); \ - SendMessage(GetDlgItem(hWnd,idc),TBM_SETPAGESIZE,0,pagesize); \ - SendMessage(GetDlgItem(hWnd,idc),TBM_SETLINESIZE,0,linesize) - -#define HANDLE_SCROLL_MESSAGE(idc,idcDisplay) \ - if((HWND)lParam == GetDlgItem(hWnd,idc)) return DoHandleScrollMessage( GetDlgItem(hWnd,idcDisplay), wParam, lParam ) +#ifdef _WIN32 +# include "WinConfig.h" +#else +# include "LnxConfig.h" +#endif namespace DebugConfig { @@ -50,24 +31,32 @@ namespace DebugConfig extern void EnableControls( HWND hWnd ); } -extern int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam); -extern HRESULT GUIDFromString( const char *str, LPGUID guid ); +namespace SoundtouchCfg +{ + extern void ReadSettings(); + extern void WriteSettings(); + extern void OpenDialog( HWND hWnd ); + extern BOOL CALLBACK DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); +} -extern void AssignSliderValue( HWND idcwnd, HWND hwndDisplay, int value ); -extern void AssignSliderValue( HWND hWnd, int idc, int editbox, int value ); -extern int GetSliderValue( HWND hWnd, int idc ); -extern BOOL DoHandleScrollMessage( HWND hwndDisplay, WPARAM wParam, LPARAM lParam ); +extern int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam); +extern HRESULT GUIDFromString( const char *str, LPGUID guid ); -bool CfgFindName( const TCHAR *Section, const TCHAR* Name); +extern void AssignSliderValue( HWND idcwnd, HWND hwndDisplay, int value ); +extern void AssignSliderValue( HWND hWnd, int idc, int editbox, int value ); +extern int GetSliderValue( HWND hWnd, int idc ); +extern BOOL DoHandleScrollMessage( HWND hwndDisplay, WPARAM wParam, LPARAM lParam ); -void CfgWriteBool(const TCHAR* Section, const TCHAR* Name, bool Value); -void CfgWriteInt(const TCHAR* Section, const TCHAR* Name, int Value); -void CfgWriteStr(const TCHAR* Section, const TCHAR* Name, const wstring& Data); +extern bool CfgFindName( const TCHAR *Section, const TCHAR* Name); -bool CfgReadBool(const TCHAR *Section,const TCHAR* Name, bool Default); -void CfgReadStr(const TCHAR* Section, const TCHAR* Name, wstring& Data, int DataSize, const TCHAR* Default); -void CfgReadStr(const TCHAR* Section, const TCHAR* Name, TCHAR* Data, int DataSize, const TCHAR* Default); -int CfgReadInt(const TCHAR* Section, const TCHAR* Name,int Default); +extern void CfgWriteBool(const TCHAR* Section, const TCHAR* Name, bool Value); +extern void CfgWriteInt(const TCHAR* Section, const TCHAR* Name, int Value); +extern void CfgWriteStr(const TCHAR* Section, const TCHAR* Name, const wstring& Data); + +extern bool CfgReadBool(const TCHAR *Section,const TCHAR* Name, bool Default); +extern void CfgReadStr(const TCHAR* Section, const TCHAR* Name, wstring& Data, int DataSize, const TCHAR* Default); +extern void CfgReadStr(const TCHAR* Section, const TCHAR* Name, TCHAR* Data, int DataSize, const TCHAR* Default); +extern int CfgReadInt(const TCHAR* Section, const TCHAR* Name,int Default); // Items Specific to DirectSound @@ -83,4 +72,3 @@ struct ds_device_data bool hasGuid; }; -#endif diff --git a/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp b/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp index 5c4e0da69a..bfcf05904c 100644 --- a/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp +++ b/plugins/spu2-x/src/Windows/RealtimeDebugger.cpp @@ -16,6 +16,7 @@ */ +#include "Global.h" #include "Dialogs.h" #include "../RegTable.h" @@ -59,7 +60,7 @@ static BOOL CALLBACK DebugProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) return TRUE; } -#ifdef SPU2X_DEVBUILD +#ifdef PCSX2_DEVBUILD int FillRectangle(HDC dc, int left, int top, int width, int height) { diff --git a/plugins/spu2-x/src/Windows/SndOut_DSound.cpp b/plugins/spu2-x/src/Windows/SndOut_DSound.cpp index 9d89a78aa0..4edb1131f7 100644 --- a/plugins/spu2-x/src/Windows/SndOut_DSound.cpp +++ b/plugins/spu2-x/src/Windows/SndOut_DSound.cpp @@ -15,6 +15,8 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" + #define _WIN32_DCOM #include "Dialogs.h" @@ -103,6 +105,8 @@ private: public: s32 Init() { + CoInitializeEx( NULL, COINIT_MULTITHREADED ); + // // Initialize DSound // @@ -180,7 +184,7 @@ public: throw std::runtime_error( "DirectSound Error: Buffer could not be created." ); } - if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) ) + if( FAILED(buffer_->QueryInterface(IID_IDirectSoundBuffer8,(void**)&buffer)) || buffer == NULL ) throw std::runtime_error( "DirectSound Error: Interface could not be queried." ); buffer_->Release(); @@ -242,11 +246,12 @@ public: buffer_events[i] = NULL; } - SAFE_RELEASE( buffer_notify ); - SAFE_RELEASE( buffer ); + safe_release( buffer_notify ); + safe_release( buffer ); } - SAFE_RELEASE( dsound ); + safe_release( dsound ); + CoUninitialize(); } private: @@ -406,13 +411,13 @@ private: static BOOL CALLBACK DSEnumCallback( LPGUID lpGuid, LPCTSTR lpcstrDescription, LPCTSTR lpcstrModule, LPVOID lpContext ); public: - virtual void Configure(HWND parent) + virtual void Configure(uptr parent) { INT_PTR ret; - ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DSOUND),GetActiveWindow(),(DLGPROC)ConfigProc,1); + ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DSOUND),(HWND)parent,(DLGPROC)ConfigProc,1); if(ret==-1) { - MessageBoxEx(GetActiveWindow(),L"Error Opening the config dialog.",L"OMG ERROR!",MB_OK,0); + MessageBoxEx((HWND)parent,L"Error Opening the config dialog.",L"OMG ERROR!",MB_OK,0); return; } } diff --git a/plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp b/plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp index 225e0ddaac..5d4afb7711 100644 --- a/plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp +++ b/plugins/spu2-x/src/Windows/SndOut_XAudio2.cpp @@ -15,11 +15,13 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" + #define _WIN32_DCOM - #include "Dialogs.h" -#include +#include +#include namespace Exception { @@ -181,7 +183,7 @@ private: killMe->FlushSourceBuffers(); EnterCriticalSection( &cs ); killMe->DestroyVoice(); - SAFE_DELETE_ARRAY( qbuffer ); + safe_delete_array( qbuffer ); LeaveCriticalSection( &cs ); DeleteCriticalSection( &cs ); } @@ -225,7 +227,7 @@ private: }; - IXAudio2* pXAudio2; + CComPtr pXAudio2; IXAudio2MasteringVoice* pMasteringVoice; BaseStreamingVoice* voiceContext; @@ -314,7 +316,7 @@ public: catch( Exception::XAudio2Error& ex ) { SysMessage( ex.CMessage() ); - SAFE_RELEASE( pXAudio2 ); + pXAudio2.Release(); CoUninitialize(); return -1; } @@ -333,7 +335,7 @@ public: // But doing no cleanup at all causes XA2 under XP to crash. So after much trial // and error we found a happy compromise as follows: - SAFE_DELETE_OBJ( voiceContext ); + safe_delete( voiceContext ); voiceContext = NULL; @@ -342,12 +344,11 @@ public: pMasteringVoice = NULL; - SAFE_RELEASE( pXAudio2 ); - + pXAudio2.Release(); CoUninitialize(); } - virtual void Configure(HWND parent) + virtual void Configure(uptr parent) { } diff --git a/plugins/spu2-x/src/Windows/SndOut_waveOut.cpp b/plugins/spu2-x/src/Windows/SndOut_waveOut.cpp index eb0f07ca1c..378c0871de 100644 --- a/plugins/spu2-x/src/Windows/SndOut_waveOut.cpp +++ b/plugins/spu2-x/src/Windows/SndOut_waveOut.cpp @@ -15,8 +15,8 @@ * along with SPU2-X. If not, see . */ +#include "Global.h" #include "Dialogs.h" -#include class WaveOutModule: public SndOutModule @@ -197,7 +197,7 @@ public: } waveOutClose(hwodevice); - SAFE_DELETE_ARRAY( qbuffer ); + safe_delete_array( qbuffer ); } private: @@ -271,13 +271,13 @@ private: } public: - virtual void Configure(HWND parent) + virtual void Configure(uptr parent) { INT_PTR ret; - ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_WAVEOUT),GetActiveWindow(),(DLGPROC)ConfigProc,1); + ret=DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_WAVEOUT), (HWND)parent, (DLGPROC)ConfigProc,1); if(ret==-1) { - MessageBoxEx(GetActiveWindow(), L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK, 0); + MessageBoxEx((HWND)parent, L"Error Opening the config dialog.", L"OMG ERROR!", MB_OK, 0); return; } } diff --git a/plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj b/plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj index a83e1e8ba9..fe52c0d5ad 100644 --- a/plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj +++ b/plugins/spu2-x/src/Windows/Spu2-X_vs2008.vcproj @@ -5,6 +5,7 @@ Name="SPU2-X" ProjectGUID="{5307BBB7-EBB9-4AA4-8CB6-A94EC473C8C4}" RootNamespace="spu2x" + TargetFrameworkVersion="0" > @@ -129,10 +133,10 @@ /> @@ -295,9 +300,10 @@ + + + + + + + + + + + + + + + + + + + + + + - - @@ -488,11 +551,43 @@ + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + @@ -812,25 +1081,141 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -843,43 +1228,17 @@ > - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . */ +#include "Global.h" #include "Dialogs.h" int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam) diff --git a/plugins/spu2-x/src/Windows/WinConfig.h b/plugins/spu2-x/src/Windows/WinConfig.h new file mode 100644 index 0000000000..c768ecd0ae --- /dev/null +++ b/plugins/spu2-x/src/Windows/WinConfig.h @@ -0,0 +1,61 @@ + +#pragma once + +# define WINVER 0x0501 +# define _WIN32_WINNT 0x0501 + +#include +#include +#include +#include +#include + +#include "resource.h" + +extern HINSTANCE hInstance; + +#define SET_CHECK(idc,value) SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,((value)==0)?BST_UNCHECKED:BST_CHECKED,0) +#define HANDLE_CHECK(idc,hvar) case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0); break +#define HANDLE_CHECKNB(idc,hvar)case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0) +#define ENABLE_CONTROL(idc,value) EnableWindow(GetDlgItem(hWnd,idc),value) + +#define INIT_SLIDER(idc,minrange,maxrange,tickfreq,pagesize,linesize) \ + SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMIN,FALSE,minrange); \ + SendMessage(GetDlgItem(hWnd,idc),TBM_SETRANGEMAX,FALSE,maxrange); \ + SendMessage(GetDlgItem(hWnd,idc),TBM_SETTICFREQ,tickfreq,0); \ + SendMessage(GetDlgItem(hWnd,idc),TBM_SETPAGESIZE,0,pagesize); \ + SendMessage(GetDlgItem(hWnd,idc),TBM_SETLINESIZE,0,linesize) + +#define HANDLE_SCROLL_MESSAGE(idc,idcDisplay) \ + if((HWND)lParam == GetDlgItem(hWnd,idc)) return DoHandleScrollMessage( GetDlgItem(hWnd,idcDisplay), wParam, lParam ) + + +// *** BEGIN DRIVER-SPECIFIC CONFIGURATION *** +// ------------------------------------------- + +struct CONFIG_XAUDIO2 +{ + std::wstring Device; + s8 NumBuffers; + + CONFIG_XAUDIO2() : + Device(), + NumBuffers( 2 ) + { + } +}; + +struct CONFIG_WAVEOUT +{ + std::wstring Device; + s8 NumBuffers; + + CONFIG_WAVEOUT() : + Device(), + NumBuffers( 4 ) + { + } +}; + +extern CONFIG_WAVEOUT Config_WaveOut; +extern CONFIG_XAUDIO2 Config_XAudio2; diff --git a/plugins/spu2-x/src/Windows/dsp.cpp b/plugins/spu2-x/src/Windows/dsp.cpp index 442a5c919c..0171d36b68 100644 --- a/plugins/spu2-x/src/Windows/dsp.cpp +++ b/plugins/spu2-x/src/Windows/dsp.cpp @@ -15,7 +15,15 @@ //License along with this library; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -#include "../spu2.h" + +#include "Global.h" + +# define WINVER 0x0501 +# define _WIN32_WINNT 0x0501 + +#include +#include + extern "C" { #include "dsp.h" diff --git a/plugins/spu2-x/src/defs.h b/plugins/spu2-x/src/defs.h index fdbbc8eaf5..7df50a66ec 100644 --- a/plugins/spu2-x/src/defs.h +++ b/plugins/spu2-x/src/defs.h @@ -17,12 +17,27 @@ #pragma once +#include "Mixer.h" + +// -------------------------------------------------------------------------------------- +// SPU2 Memory Indexers +// -------------------------------------------------------------------------------------- + +#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem) & 0x1fff))) +#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem) & 0x1fff))) + +extern s16* __fastcall GetMemPtr(u32 addr); +extern s16 __fastcall spu2M_Read( u32 addr ); +extern void __fastcall spu2M_Write( u32 addr, s16 value ); +extern void __fastcall spu2M_Write( u32 addr, u16 value ); + + struct V_VolumeLR { static V_VolumeLR Max; - s32 Left; - s32 Right; + s32 Left; + s32 Right; V_VolumeLR() {} V_VolumeLR( s32 both ) : @@ -39,10 +54,10 @@ struct V_VolumeSlide // Holds the "original" value of the volume for this voice, prior to slides. // (ie, the volume as written to the register) - s16 Reg_VOL; - s32 Value; - s8 Increment; - s8 Mode; + s16 Reg_VOL; + s32 Value; + s8 Increment; + s8 Mode; public: V_VolumeSlide() {} @@ -57,7 +72,6 @@ public: void Update(); void RegSet( u16 src ); // used to set the volume from a register source (16 bit signed) void DebugDump( FILE* dump, const char* title, const char* nameLR ); - }; struct V_VolumeSlideLR @@ -304,135 +318,235 @@ struct V_VoiceGates s16 WetR; // 'AND Gate' for Effect Output for Right Channel }; -union V_CoreGates +struct V_CoreGates { - struct + union { - u64 lo; - u64 hi; - } v128; + u128 v128; - struct - { - s16 InpL; // Sound Data Input to Direct Output (Left) - s16 InpR; // Sound Data Input to Direct Output (Right) - s16 SndL; // Voice Data to Direct Output (Left) - s16 SndR; // Voice Data to Direct Output (Right) - s16 ExtL; // External Input to Direct Output (Left) - s16 ExtR; // External Input to Direct Output (Right) + struct + { + s16 InpL; // Sound Data Input to Direct Output (Left) + s16 InpR; // Sound Data Input to Direct Output (Right) + s16 SndL; // Voice Data to Direct Output (Left) + s16 SndR; // Voice Data to Direct Output (Right) + s16 ExtL; // External Input to Direct Output (Left) + s16 ExtR; // External Input to Direct Output (Right) + }; }; + +}; + +struct VoiceMixSet +{ + static const VoiceMixSet Empty; + StereoOut32 Dry, Wet; + + VoiceMixSet() {} + VoiceMixSet( const StereoOut32& dry, const StereoOut32& wet ) : + Dry( dry ), + Wet( wet ) + { + } }; struct V_Core { static const uint NumVoices = 24; + int Index; // Core index identifier. + // Voice Gates -- These are SSE-related values, and must always be // first to ensure 16 byte alignment - V_VoiceGates VoiceGates[NumVoices]; - V_CoreGates DryGate; - V_CoreGates WetGate; + V_VoiceGates VoiceGates[NumVoices]; + V_CoreGates DryGate; + V_CoreGates WetGate; - V_VolumeSlideLR MasterVol;// Master Volume - V_VolumeLR ExtVol; // Volume for External Data Input - V_VolumeLR InpVol; // Volume for Sound Data Input - V_VolumeLR FxVol; // Volume for Output from Effects + V_VolumeSlideLR MasterVol; // Master Volume + V_VolumeLR ExtVol; // Volume for External Data Input + V_VolumeLR InpVol; // Volume for Sound Data Input + V_VolumeLR FxVol; // Volume for Output from Effects - V_Voice Voices[NumVoices]; + V_Voice Voices[NumVoices]; -// Interrupt Address - u32 IRQA; -// DMA Transfer Start Address - u32 TSA; -// DMA Transfer Data Address (Internal...) - u32 TDA; + u32 IRQA; // Interrupt Address + u32 TSA; // DMA Transfer Start Address + u32 TDA; // DMA Transfer Data Address (Internal...) -// Interrupt Enable - s8 IRQEnable; -// DMA related? - s8 DMABits; -// Effect Enable - s8 FxEnable; -// Noise Clock - s8 NoiseClk; -// AutoDMA Status - u16 AutoDMACtrl; -// DMA Interrupt Counter - s32 DMAICounter; -// Mute - s8 Mute; -// Input Buffer - u32 InputDataLeft; - u32 InputPos; - u32 InputDataProgress; - u8 AdmaInProgress; + s8 IRQEnable; // Interrupt Enable + s8 DMABits; // DMA related? + s8 FxEnable; // Effect Enable + s8 NoiseClk; // Noise Clock + u16 AutoDMACtrl; // AutoDMA Status + s32 DMAICounter; // DMA Interrupt Counter + s8 Mute; // Mute + u32 InputDataLeft; // Input Buffer + u32 InputPos; + u32 InputDataProgress; + u8 AdmaInProgress; -// Reverb - V_Reverb Revb; - V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped. - u32 EffectsStartA; - u32 EffectsEndA; - u32 ReverbX; + V_Reverb Revb; // Reverb Registers + V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped. + u32 EffectsStartA; + u32 EffectsEndA; + u32 ReverbX; // Current size of the effects buffer. Pre-caculated when the effects start // or end position registers are written. CAN BE NEGATIVE OR ZERO, in which // case reverb should be disabled. - s32 EffectsBufferSize; + s32 EffectsBufferSize; -// Registers - V_CoreRegs Regs; + V_CoreRegs Regs; // Registers // Last samples to pass through the effects processor. // Used because the effects processor works at 24khz and just pulls // from this for the odd Ts. - StereoOut32 LastEffect; + StereoOut32 LastEffect; - u8 InitDelay; + u8 InitDelay; + u8 CoreEnabled; - u8 CoreEnabled; + u8 AttrBit0; + u8 AttrBit4; + u8 AttrBit5; - u8 AttrBit0; - u8 AttrBit4; - u8 AttrBit5; + u16* DMAPtr; + u32 MADR; + u32 TADR; - u16*DMAPtr; - u32 MADR; - u32 TADR; + // HACK -- This is a temp buffer which is (or isn't?) used to circumvent some memory + // corruption that originates elsewhere in the plugin. >_< The actual ADMA buffer + // is an area mapped to SPU2 main memory. + s16 ADMATempBuffer[0x1000]; - s16 ADMATempBuffer[0x1000]; +// ---------------------------------------------------------------------------------- +// V_Core Methods +// ---------------------------------------------------------------------------------- - u32 ADMAPV; - StereoOut32 ADMAP; + V_Core() : Index( -1 ) {} // uninitialized constructor + V_Core( int idx ); // our badass constructor + virtual ~V_Core() throw(); - void Reset(); - void UpdateEffectsBufferSize(); + void Reset(); + void UpdateEffectsBufferSize(); - V_Core(); // our badass constructor - s32 EffectsBufferIndexer( s32 offset ) const; - void UpdateFeedbackBuffersA(); - void UpdateFeedbackBuffersB(); + s32 EffectsBufferIndexer( s32 offset ) const; + void UpdateFeedbackBuffersA(); + void UpdateFeedbackBuffersB(); + + void WriteRegPS1( u32 mem, u16 value ); + u16 ReadRegPS1( u32 mem ); + +// -------------------------------------------------------------------------------------- +// Mixer Section +// -------------------------------------------------------------------------------------- + + StereoOut32 Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext ); + void Reverb_AdvanceBuffer(); + StereoOut32 DoReverb( const StereoOut32& Input ); + s32 RevbGetIndexer( s32 offset ); + + StereoOut32 ReadInput(); + StereoOut32 ReadInputPV(); + StereoOut32 ReadInput_HiFi( bool isCDDA ); + +// -------------------------------------------------------------------------- +// DMA Section +// -------------------------------------------------------------------------- + + // Returns the index of the DMA channel (4 for Core 0, or 7 for Core 1) + int GetDmaIndex() const + { + return (Index == 0) ? 4 : 7; + } + + // returns either '4' or '7' + char GetDmaIndexChar() const + { + return 0x30 + GetDmaIndex(); + } + + __forceinline u16 DmaRead() + { + const u16 ret = (u16)spu2M_Read(TDA); + ++TDA; TDA &= 0xfffff; + return ret; + } + + __forceinline void DmaWrite(u16 value) + { + spu2M_Write( TSA, value ); + ++TSA; TSA &= 0xfffff; + } + + void LogAutoDMA( FILE* fp ); + + void DoDMAwrite(u16* pMem, u32 size); + void DoDMAread(u16* pMem, u32 size); + + void AutoDMAReadBuffer(int mode); + void StartADMAWrite(u16 *pMem, u32 sz); + void PlainDMAWrite(u16 *pMem, u32 sz); }; -extern V_Core Cores[2]; -extern V_SPDIF Spdif; +extern V_Core Cores[2]; +extern V_SPDIF Spdif; // Output Buffer Writing Position (the same for all data); -extern s16 OutPos; +extern s16 OutPos; // Input Buffer Reading Position (the same for all data); -extern s16 InputPos; +extern s16 InputPos; // SPU Mixing Cycles ("Ticks mixed" counter) -extern u32 Cycles; +extern u32 Cycles; -#ifdef __LINUX__ +extern short* spu2regs; +extern short* _spu2mem; +extern int PlayMode; -#include -#include +extern void SetIrqCall(); +extern void StartVoices(int core, u32 value); +extern void StopVoices(int core, u32 value); +extern void InitADSR(); +extern void CalculateADSR( V_Voice& vc ); -static __forceinline u32 timeGetTime() +extern void spdif_set51(u32 is_5_1_out); +extern u32 spdif_init(); +extern void spdif_shutdown(); +extern void spdif_get_samples(s32 *samples); // fills the buffer with [l,r,c,lfe,sl,sr] if using 5.1 output, or [l,r] if using stereo +extern void UpdateSpdifMode(); + +namespace Savestate { - struct timeb t; - ftime(&t); - return (u32)(t.time*1000+t.millitm); + struct DataBlock; + + extern s32 __fastcall FreezeIt( DataBlock& spud ); + extern s32 __fastcall ThawIt( DataBlock& spud ); + extern s32 __fastcall SizeIt(); } -#endif + +// -------------------------------------------------------------------------------------- +// ADPCM Decoder Cache +// -------------------------------------------------------------------------------------- + +// The SPU2 has a dynamic memory range which is used for several internal operations, such as +// registers, CORE 1/2 mixing, AutoDMAs, and some other fancy stuff. We exclude this range +// from the cache here: +static const s32 SPU2_DYN_MEMLINE = 0x2800; + +// 8 short words per encoded PCM block. (as stored in SPU2 ram) +static const int pcm_WordsPerBlock = 8; + +// number of cachable ADPCM blocks (any blocks above the SPU2_DYN_MEMLINE) +static const int pcm_BlockCount = 0x100000 / pcm_WordsPerBlock; + +// 28 samples per decoded PCM block (as stored in our cache) +static const int pcm_DecodedSamplesPerBlock = 28; + +struct PcmCacheEntry +{ + bool Validated; + s16 Sampledata[pcm_DecodedSamplesPerBlock]; +}; + +extern PcmCacheEntry* pcm_cache_data; diff --git a/plugins/spu2-x/src/regs.h b/plugins/spu2-x/src/regs.h index 10a789118f..7b1f92c7aa 100644 --- a/plugins/spu2-x/src/regs.h +++ b/plugins/spu2-x/src/regs.h @@ -147,21 +147,21 @@ Core attributes (SD_C) *********************************************************************/ -#define SPDIF_OUT_OFF 0x0000 //no spdif output -#define SPDIF_OUT_PCM 0x0020 //encode spdif from spu2 pcm output -#define SPDIF_OUT_BYPASS 0x0100 //bypass spu2 processing +#define SPDIF_OUT_OFF 0x0000 // no spdif output +#define SPDIF_OUT_PCM 0x0020 // encode spdif from spu2 pcm output +#define SPDIF_OUT_BYPASS 0x0100 // bypass spu2 processing -#define SPDIF_MODE_BYPASS_BITSTREAM 0x0002 //bypass mode for digital bitstream data -#define SPDIF_MODE_BYPASS_PCM 0x0000 //bypass mode for pcm data (using analog output) +#define SPDIF_MODE_BYPASS_BITSTREAM 0x0002 // bypass mode for digital bitstream data +#define SPDIF_MODE_BYPASS_PCM 0x0000 // bypass mode for pcm data (using analog output) -#define SPDIF_MODE_MEDIA_CD 0x0800 //source media is a CD -#define SPDIF_MODE_MEDIA_DVD 0x0000 //source media is a DVD +#define SPDIF_MODE_MEDIA_CD 0x0800 // source media is a CD +#define SPDIF_MODE_MEDIA_DVD 0x0000 // source media is a DVD -#define SPDIF_MEDIA_CDVD 0x0200 -#define SPDIF_MEDIA_400 0x0000 +#define SPDIF_MEDIA_CDVD 0x0200 +#define SPDIF_MEDIA_400 0x0000 -#define SPDIF_PROTECT_NORMAL 0x0000 // spdif stream is not protected -#define SPDIF_PROTECT_PROHIBIT 0x8000 // spdif stream can't be copied +#define SPDIF_PROTECT_NORMAL 0x0000 // spdif stream is not protected +#define SPDIF_PROTECT_PROHIBIT 0x8000 // spdif stream can't be copied /********************************************************************/ diff --git a/plugins/spu2-x/src/spu2freeze.cpp b/plugins/spu2-x/src/spu2freeze.cpp new file mode 100644 index 0000000000..e35e3825a9 --- /dev/null +++ b/plugins/spu2-x/src/spu2freeze.cpp @@ -0,0 +1,146 @@ +/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2 + * Developed and maintained by the Pcsx2 Development Team. + * + * Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz] + * + * SPU2-X is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SPU2-X. If not, see . + */ + +#include "Global.h" +#include "PS2E-spu2.h" // hopefully temporary, until I resolve lClocks depdendency + +namespace Savestate +{ + // Arbitrary ID to identify SPU2-X saves. + static const u32 SAVE_ID = 0x1227521; + + // versioning for saves. + // Increment this when changes to the savestate system are made. + static const u32 SAVE_VERSION = 0x0005; + + static void wipe_the_cache() + { + memset( pcm_cache_data, 0, pcm_BlockCount * sizeof(PcmCacheEntry) ); + } + + static s16 old_state_sBuffer[pcm_DecodedSamplesPerBlock] = {0}; +} + +struct Savestate::DataBlock +{ + u32 spu2id; // SPU2-X state identifier lets ZeroGS/PeopsSPU2 know this isn't their state) + u8 unkregs[0x10000]; // SPU2 raw register memory + u8 mem[0x200000]; // SPU2 raw sample memory + + u32 version; // SPU2-X version identifier + V_Core Cores[2]; + V_SPDIF Spdif; + s16 OutPos; + s16 InputPos; + u32 Cycles; + u32 lClocks; + int PlayMode; +}; + +s32 __fastcall Savestate::FreezeIt( DataBlock& spud ) +{ + spud.spu2id = SAVE_ID; + spud.version = SAVE_VERSION; + + memcpy(spud.unkregs, spu2regs, sizeof(spud.unkregs)); + memcpy(spud.mem, _spu2mem, sizeof(spud.mem)); + memcpy(spud.Cores, Cores, sizeof(Cores)); + memcpy(&spud.Spdif, &Spdif, sizeof(Spdif)); + + spud.OutPos = OutPos; + spud.InputPos = InputPos; + spud.Cycles = Cycles; + spud.lClocks = lClocks; + spud.PlayMode = PlayMode; + + // note: Don't save the cache. PCSX2 doesn't offer a safe method of predicting + // the required size of the savestate prior to saving, plus this is just too + // "implementation specific" for the intended spec of a savestate. Let's just + // force the user to rebuild their cache instead. + + return 0; +} + +s32 __fastcall Savestate::ThawIt( DataBlock& spud ) +{ + if( spud.spu2id != SAVE_ID || spud.version < SAVE_VERSION ) + { + fprintf(stderr, "\n*** SPU2-X Warning:\n"); + if( spud.spu2id == SAVE_ID ) + fprintf(stderr, "\tSavestate version is from an older version of this plugin.\n"); + else + fprintf(stderr, "\tThe savestate you are trying to load was not made with this plugin.\n"); + + fprintf(stderr, + "\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n" + "\tand then continue from there.\n\n" + ); + + // Do *not* reset the cores. + // We'll need some "hints" as to how the cores should be initialized, and the + // only way to get that is to use the game's existing core settings and hope + // they kinda match the settings for the savestate (IRQ enables and such). + + // adpcm cache : Clear all the cache flags and buffers. + + wipe_the_cache(); + } + else + { + SndBuffer::ClearContents(); + + // base stuff + memcpy(spu2regs, spud.unkregs, sizeof(spud.unkregs)); + memcpy(_spu2mem, spud.mem, sizeof(spud.mem)); + + memcpy(Cores, spud.Cores, sizeof(Cores)); + memcpy(&Spdif, &spud.Spdif, sizeof(Spdif)); + + OutPos = spud.OutPos; + InputPos = spud.InputPos; + Cycles = spud.Cycles; + lClocks = spud.lClocks; + PlayMode = spud.PlayMode; + + wipe_the_cache(); + + // Go through the V_Voice structs and recalculate SBuffer pointer from + // the NextA setting. + + for( int c=0; c<2; c++ ) + { + for( int v=0; v<24; v++ ) + { + const int cacheIdx = Cores[c].Voices[v].NextA / pcm_WordsPerBlock; + Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata; + } + } + + // HACKFIX!! DMAPtr can be invalid after a savestate load, so force it to NULL and + // ignore it on any pending ADMA writes. (the DMAPtr concept used to work in old VM + // editions of PCSX2 with fixed addressing, but new PCSX2s have dynamic memory + // addressing). + + Cores[0].DMAPtr = Cores[1].DMAPtr = NULL; + } + return 0; +} + +s32 __fastcall Savestate::SizeIt() +{ + return sizeof(DataBlock); +} diff --git a/plugins/spu2-x/src/Spu2.cpp b/plugins/spu2-x/src/spu2sys.cpp similarity index 81% rename from plugins/spu2-x/src/Spu2.cpp rename to plugins/spu2-x/src/spu2sys.cpp index ffe65eae89..9798ed1fc0 100644 --- a/plugins/spu2-x/src/Spu2.cpp +++ b/plugins/spu2-x/src/spu2sys.cpp @@ -15,50 +15,31 @@ * along with SPU2-X. If not, see . */ -#include "Spu2.h" +// ====================================================================================== +// spu2sys.cpp -- Emulation module for the SPU2 'virtual machine' +// ====================================================================================== +// This module contains (most!) stuff which is directly related to SPU2 emulation. +// Contents should be cross-platform compatible whenever possible. + + +#include "Global.h" #include "RegTable.h" +#include "dma.h" -#ifdef __LINUX__ -#include "Linux.h" -#endif - -void StartVoices(int core, u32 value); -void StopVoices(int core, u32 value); - -void InitADSR(); - -#ifdef _MSC_VER -DWORD CALLBACK TimeThread(PVOID /* unused param */); -#endif - -void (* _irqcallback)(); -void (* dma4callback)(); -void (* dma7callback)(); +#include "PS2E-spu2.h" // needed until I figure out a nice solution for irqcallback dependencies. short *spu2regs; short *_spu2mem; -u8 callirq; +V_CoreDebug DebugCores[2]; +V_Core Cores[2]; +V_SPDIF Spdif; -V_CoreDebug DebugCores[2]; -V_Core Cores[2]; -V_SPDIF Spdif; +s16 OutPos; +s16 InputPos; +u32 Cycles; -s16 OutPos; -s16 InputPos; -u32 Cycles; - -u32* cyclePtr = NULL; -u32 lClocks = 0; - -int PlayMode; - -#ifdef _MSC_VER -HINSTANCE hInstance; -CRITICAL_SECTION threadSync; -HANDLE hThreadFunc; -u32 ThreadFuncID; -#endif +int PlayMode; bool has_to_call_irq=false; @@ -67,33 +48,6 @@ void SetIrqCall() has_to_call_irq=true; } -#ifndef __LINUX__ -void SysMessage(const char *fmt, ...) -{ - va_list list; - char tmp[512]; - wchar_t wtmp[512]; - - va_start(list,fmt); - sprintf_s(tmp,fmt,list); - va_end(list); - swprintf_s(wtmp, L"%S", tmp); - MessageBox(0, wtmp, L"SPU2-X System Message", 0); -} -#else -void SysMessage(const char *fmt, ...) -{ - va_list list; - char tmp[512]; - wchar_t wtmp[512]; - - va_start(list,fmt); - sprintf(tmp,fmt,list); - va_end(list); - printf("%s", tmp); -} -#endif - __forceinline s16 * __fastcall GetMemPtr(u32 addr) { #ifndef DEBUG_FAST @@ -111,9 +65,7 @@ __forceinline s16 __fastcall spu2M_Read( u32 addr ) // writes a signed value to the SPU2 ram // Invalidates the ADPCM cache in the process. -// Optimization note: don't use __forceinline because the footprint of this -// function is a little too heavy now. Better to let the compiler decide. -__inline void __fastcall spu2M_Write( u32 addr, s16 value ) +__forceinline void __fastcall spu2M_Write( u32 addr, s16 value ) { // Make sure the cache is invalidated: // (note to self : addr address WORDs, not bytes) @@ -135,50 +87,55 @@ __inline void __fastcall spu2M_Write( u32 addr, u16 value ) spu2M_Write( addr, (s16)value ); } -V_VolumeLR V_VolumeLR::Max( 0x7FFFFFFF ); -V_VolumeSlideLR V_VolumeSlideLR::Max( 0x3FFF, 0x7FFFFFFF ); +V_VolumeLR V_VolumeLR::Max( 0x7FFFFFFF ); +V_VolumeSlideLR V_VolumeSlideLR::Max( 0x3FFF, 0x7FFFFFFF ); -V_Core::V_Core() +V_Core::V_Core( int coreidx ) : Index( coreidx ) + //LogFile_AutoDMA( NULL ) { + /*char fname[128]; + sprintf( fname, "logs/adma%d.raw", GetDmaIndex() ); + LogFile_AutoDMA = fopen( fname, "wb" );*/ +} + +V_Core::~V_Core() throw() +{ + // Can't use this yet because we dumb V_Core into savestates >_< + /*if( LogFile_AutoDMA != NULL ) + { + fclose( LogFile_AutoDMA ); + LogFile_AutoDMA = NULL; + }*/ } void V_Core::Reset() { memset( this, 0, sizeof(V_Core) ); - const int c = (this == Cores) ? 0 : 1; + const int c = Index; - Regs.STATX=0; - Regs.ATTR=0; - ExtVol = V_VolumeLR::Max; - InpVol = V_VolumeLR::Max; - FxVol = V_VolumeLR::Max; + Regs.STATX = 0; + Regs.ATTR = 0; + ExtVol = V_VolumeLR::Max; + InpVol = V_VolumeLR::Max; + FxVol = V_VolumeLR::Max; - MasterVol = V_VolumeSlideLR::Max; + MasterVol = V_VolumeSlideLR::Max; - DryGate.ExtL = -1; - DryGate.ExtR = -1; - WetGate.ExtL = -1; - WetGate.ExtR = -1; - DryGate.InpL = -1; - DryGate.InpR = -1; - WetGate.InpR = -1; - WetGate.InpL = -1; - DryGate.SndL = -1; - DryGate.SndR = -1; - WetGate.SndL = -1; - WetGate.SndR = -1; + memset( &DryGate, -1, sizeof(DryGate) ); + memset( &WetGate, -1, sizeof(WetGate) ); - Regs.MMIX = 0xFFCF; - Regs.VMIXL = 0xFFFFFF; - Regs.VMIXR = 0xFFFFFF; - Regs.VMIXEL = 0xFFFFFF; - Regs.VMIXER = 0xFFFFFF; - EffectsStartA= 0xEFFF8 + 0x10000*c; - EffectsEndA = 0xEFFFF + 0x10000*c; - FxEnable=0; - IRQA=0xFFFF0; - IRQEnable=1; + Regs.MMIX = 0xFFCF; + Regs.VMIXL = 0xFFFFFF; + Regs.VMIXR = 0xFFFFFF; + Regs.VMIXEL = 0xFFFFFF; + Regs.VMIXER = 0xFFFFFF; + EffectsStartA = 0xEFFF8 + (0x10000*c); + EffectsEndA = 0xEFFFF + (0x10000*c); + + FxEnable = 0; + IRQA = 0xFFFF0; + IRQEnable = 1; for( uint v=0; v=0x1c00)&&(reg<0x1d80)) { @@ -530,42 +489,42 @@ void SPU_ps1_write(u32 mem, u16 value) switch(vval) { case 0: //VOLL (Volume L) - Cores[0].Voices[voice].Volume.Left.Mode = 0; - Cores[0].Voices[voice].Volume.Left.RegSet( value << 1 ); - Cores[0].Voices[voice].Volume.Left.Reg_VOL = value; + Voices[voice].Volume.Left.Mode = 0; + Voices[voice].Volume.Left.RegSet( value << 1 ); + Voices[voice].Volume.Left.Reg_VOL = value; break; case 1: //VOLR (Volume R) - Cores[0].Voices[voice].Volume.Right.Mode = 0; - Cores[0].Voices[voice].Volume.Right.RegSet( value << 1 ); - Cores[0].Voices[voice].Volume.Right.Reg_VOL = value; + Voices[voice].Volume.Right.Mode = 0; + Voices[voice].Volume.Right.RegSet( value << 1 ); + Voices[voice].Volume.Right.Reg_VOL = value; break; - case 2: Cores[0].Voices[voice].Pitch = value; break; - case 3: Cores[0].Voices[voice].StartA = (u32)value<<8; break; + case 2: Voices[voice].Pitch = value; break; + case 3: Voices[voice].StartA = (u32)value<<8; break; case 4: // ADSR1 (Envelope) - Cores[0].Voices[voice].ADSR.AttackMode = (value & 0x8000)>>15; - Cores[0].Voices[voice].ADSR.AttackRate = (value & 0x7F00)>>8; - Cores[0].Voices[voice].ADSR.DecayRate = (value & 0xF0)>>4; - Cores[0].Voices[voice].ADSR.SustainLevel = (value & 0xF); - Cores[0].Voices[voice].ADSR.Reg_ADSR1 = value; + Voices[voice].ADSR.AttackMode = (value & 0x8000)>>15; + Voices[voice].ADSR.AttackRate = (value & 0x7F00)>>8; + Voices[voice].ADSR.DecayRate = (value & 0xF0)>>4; + Voices[voice].ADSR.SustainLevel = (value & 0xF); + Voices[voice].ADSR.Reg_ADSR1 = value; break; case 5: // ADSR2 (Envelope) - Cores[0].Voices[voice].ADSR.SustainMode = (value & 0xE000)>>13; - Cores[0].Voices[voice].ADSR.SustainRate = (value & 0x1FC0)>>6; - Cores[0].Voices[voice].ADSR.ReleaseMode = (value & 0x20)>>5; - Cores[0].Voices[voice].ADSR.ReleaseRate = (value & 0x1F); - Cores[0].Voices[voice].ADSR.Reg_ADSR2 = value; + Voices[voice].ADSR.SustainMode = (value & 0xE000)>>13; + Voices[voice].ADSR.SustainRate = (value & 0x1FC0)>>6; + Voices[voice].ADSR.ReleaseMode = (value & 0x20)>>5; + Voices[voice].ADSR.ReleaseRate = (value & 0x1F); + Voices[voice].ADSR.Reg_ADSR2 = value; break; case 6: - Cores[0].Voices[voice].ADSR.Value = ((s32)value<<16) | value; + Voices[voice].ADSR.Value = ((s32)value<<16) | value; ConLog( "* SPU2: Mysterious ADSR Volume Set to 0x%x", value ); break; - case 7: Cores[0].Voices[voice].LoopStartA = (u32)value <<8; break; + case 7: Voices[voice].LoopStartA = (u32)value <<8; break; jNO_DEFAULT; } @@ -574,21 +533,21 @@ void SPU_ps1_write(u32 mem, u16 value) else switch(reg) { case 0x1d80:// Mainvolume left - Cores[0].MasterVol.Left.Mode = 0; - Cores[0].MasterVol.Left.RegSet( value ); + MasterVol.Left.Mode = 0; + MasterVol.Left.RegSet( value ); break; case 0x1d82:// Mainvolume right - Cores[0].MasterVol.Right.Mode = 0; - Cores[0].MasterVol.Right.RegSet( value ); + MasterVol.Right.Mode = 0; + MasterVol.Right.RegSet( value ); break; case 0x1d84:// Reverberation depth left - Cores[0].FxVol.Left = GetVol32( value ); + FxVol.Left = GetVol32( value ); break; case 0x1d86:// Reverberation depth right - Cores[0].FxVol.Right = GetVol32( value ); + FxVol.Right = GetVol32( value ); break; case 0x1d88:// Voice ON (0-15) @@ -652,11 +611,11 @@ void SPU_ps1_write(u32 mem, u16 value) break; case 0x1da4: - Cores[0].IRQA=(u32)value<<8; + IRQA = (u32)value<<8; break; case 0x1da6: - Cores[0].TSA=(u32)value<<8; + TSA = (u32)value<<8; break; case 0x1daa: @@ -668,7 +627,7 @@ void SPU_ps1_write(u32 mem, u16 value) break; case 0x1da8:// Spu Write to Memory - DmaWrite(0,value); + DmaWrite(value); show=false; break; } @@ -678,8 +637,10 @@ void SPU_ps1_write(u32 mem, u16 value) spu2Ru16(mem)=value; } -u16 SPU_ps1_read(u32 mem) +u16 V_Core::ReadRegPS1(u32 mem) { + jASSUME( Index == 0 ); // Valid on Core 0 only! + bool show=true; u16 value = spu2Ru16(mem); @@ -693,60 +654,60 @@ u16 SPU_ps1_read(u32 mem) switch(vval) { case 0: //VOLL (Volume L) - //value=Cores[0].Voices[voice].VolumeL.Mode; - //value=Cores[0].Voices[voice].VolumeL.Value; - value = Cores[0].Voices[voice].Volume.Left.Reg_VOL; + //value=Voices[voice].VolumeL.Mode; + //value=Voices[voice].VolumeL.Value; + value = Voices[voice].Volume.Left.Reg_VOL; break; case 1: //VOLR (Volume R) - //value=Cores[0].Voices[voice].VolumeR.Mode; - //value=Cores[0].Voices[voice].VolumeR.Value; - value = Cores[0].Voices[voice].Volume.Right.Reg_VOL; + //value=Voices[voice].VolumeR.Mode; + //value=Voices[voice].VolumeR.Value; + value = Voices[voice].Volume.Right.Reg_VOL; break; - case 2: value = Cores[0].Voices[voice].Pitch; break; - case 3: value = Cores[0].Voices[voice].StartA; break; - case 4: value = Cores[0].Voices[voice].ADSR.Reg_ADSR1; break; - case 5: value = Cores[0].Voices[voice].ADSR.Reg_ADSR2; break; - case 6: value = Cores[0].Voices[voice].ADSR.Value >> 16; break; - case 7: value = Cores[0].Voices[voice].LoopStartA; break; + case 2: value = Voices[voice].Pitch; break; + case 3: value = Voices[voice].StartA; break; + case 4: value = Voices[voice].ADSR.Reg_ADSR1; break; + case 5: value = Voices[voice].ADSR.Reg_ADSR2; break; + case 6: value = Voices[voice].ADSR.Value >> 16; break; + case 7: value = Voices[voice].LoopStartA; break; jNO_DEFAULT; } } else switch(reg) { - case 0x1d80: value = Cores[0].MasterVol.Left.Value >> 16; break; - case 0x1d82: value = Cores[0].MasterVol.Right.Value >> 16; break; - case 0x1d84: value = Cores[0].FxVol.Left >> 16; break; - case 0x1d86: value = Cores[0].FxVol.Right >> 16; break; + case 0x1d80: value = MasterVol.Left.Value >> 16; break; + case 0x1d82: value = MasterVol.Right.Value >> 16; break; + case 0x1d84: value = FxVol.Left >> 16; break; + case 0x1d86: value = FxVol.Right >> 16; break; case 0x1d88: value = 0; break; case 0x1d8a: value = 0; break; case 0x1d8c: value = 0; break; case 0x1d8e: value = 0; break; - case 0x1d90: value = Cores[0].Regs.PMON&0xFFFF; break; - case 0x1d92: value = Cores[0].Regs.PMON>>16; break; + case 0x1d90: value = Regs.PMON&0xFFFF; break; + case 0x1d92: value = Regs.PMON>>16; break; - case 0x1d94: value = Cores[0].Regs.NON&0xFFFF; break; - case 0x1d96: value = Cores[0].Regs.NON>>16; break; + case 0x1d94: value = Regs.NON&0xFFFF; break; + case 0x1d96: value = Regs.NON>>16; break; - case 0x1d98: value = Cores[0].Regs.VMIXEL&0xFFFF; break; - case 0x1d9a: value = Cores[0].Regs.VMIXEL>>16; break; - case 0x1d9c: value = Cores[0].Regs.VMIXL&0xFFFF; break; - case 0x1d9e: value = Cores[0].Regs.VMIXL>>16; break; + case 0x1d98: value = Regs.VMIXEL&0xFFFF; break; + case 0x1d9a: value = Regs.VMIXEL>>16; break; + case 0x1d9c: value = Regs.VMIXL&0xFFFF; break; + case 0x1d9e: value = Regs.VMIXL>>16; break; case 0x1da2: - if( value != Cores[0].EffectsStartA>>3 ) + if( value != EffectsStartA>>3 ) { - value = Cores[0].EffectsStartA>>3; - Cores[0].UpdateEffectsBufferSize(); - Cores[0].ReverbX = 0; + value = EffectsStartA>>3; + UpdateEffectsBufferSize(); + ReverbX = 0; } break; - case 0x1da4: value = Cores[0].IRQA>>3; break; - case 0x1da6: value = Cores[0].TSA>>3; break; + case 0x1da4: value = IRQA>>3; break; + case 0x1da6: value = TSA>>3; break; case 0x1daa: value = SPU2read(REG_C_ATTR); @@ -755,7 +716,7 @@ u16 SPU_ps1_read(u32 mem) value = 0; //SPU2read(REG_P_STATX)<<3; break; case 0x1da8: - value = DmaRead(0); + value = DmaRead(); show=false; break; } @@ -930,6 +891,30 @@ void SPU2_FastWrite( u32 rmem, u16 value ) V_Core& thiscore = Cores[core]; switch(omem) { + case 0x1ac: + // ---------------------------------------------------------------------------- + // 0x1ac / 0x5ac : direct-write to DMA address : special register (undocumented) + // ---------------------------------------------------------------------------- + // On the GS, DMAs are actually pushed through a hardware register. Chances are the + // SPU works the same way, and "technically" *all* DMA data actually passes through + // the HW registers at 0x1ac (core0) and 0x5ac (core1). We handle normal DMAs in + // optimized block copy fashion elsewhere, but some games will write this register + // directly, so handle those here: + + // Performance Note: If a game uses this extensively, it *will* be slow. I plan to + // fix that using a proper paged LUT someday. + + for( int i=0; i<2; i++ ) + { + if(Cores[i].IRQEnable && (Cores[i].IRQA == Cores[i].TSA)) + { + Spdif.Info = 4 << i; + SetIrqCall(); + } + } + thiscore.DmaWrite( value ); + break; + case REG_C_ATTR: { int irqe = thiscore.IRQEnable;