mirror of https://github.com/PCSX2/pcsx2.git
SPU2-X:
* Potential Bugfix: Core1's DMA IRQ trigger was being ignored in some instances; might fix some hangs. * Major code cleanups, using C++ structure member methods and functions. * Improved gui / plugin api / core emulation code separation -- hoping to switch to wxWidgets eventually. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1930 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
15d2824d1b
commit
158b01b58d
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <gtk/gtk.h>
|
||||
#else
|
||||
# define WINVER 0x0501
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# include <windows.h>
|
||||
# include <mmsystem.h>
|
||||
# include <tchar.h>
|
||||
# include "resource.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
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 <algorithm>
|
||||
|
||||
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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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();
|
|
@ -38,13 +38,9 @@
|
|||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
#include "PS2Etypes.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include "Global.h"
|
||||
#include "ConvertUTF.h"
|
||||
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Spu2.h"
|
||||
#include "Global.h"
|
||||
|
||||
int crazy_debug=0;
|
||||
|
||||
|
|
|
@ -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<data_rate;i++)
|
||||
{
|
||||
// Right side data should be zero / ignored
|
||||
ReadInput( 0, Data ); // read from core 0
|
||||
// Source is Core 0
|
||||
// .. and Right side data should be zero / ignored
|
||||
StereoOut32 Data( Cores[0].ReadInput() );
|
||||
|
||||
if(fSpdifDump)
|
||||
{
|
||||
|
|
|
@ -15,23 +15,20 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<<i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
}
|
||||
TDA = (buff2end+0x20) & 0xfffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Buffer doesn't wrap/overflow!
|
||||
// Just set the TDA and check for an IRQ...
|
||||
|
||||
Cores[core].TDA = (buff1end + 0x20) & 0xfffff;
|
||||
TDA = (buff1end + 0x20) & 0xfffff;
|
||||
}
|
||||
|
||||
for( int i=0; i<2; i++ )
|
||||
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||
// Important: Test both core IRQ settings for either DMA!
|
||||
|
||||
for( int i=0; i<2; i++ )
|
||||
{
|
||||
if( Cores[i].IRQEnable && (Cores[i].IRQA >= Cores[i].TSA) && (Cores[i].IRQA < Cores[i].TDA) )
|
||||
{
|
||||
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<<i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
Spdif.Info = 4 << i;
|
||||
SetIrqCall();
|
||||
}
|
||||
}
|
||||
|
||||
TSA = TDA & 0xFFFFF;
|
||||
|
||||
Cores[core].TSA=Cores[core].TDA & 0xFFFFF;
|
||||
|
||||
Cores[core].DMAICounter=size;
|
||||
Cores[core].Regs.STATX &= ~0x80;
|
||||
//Cores[core].Regs.ATTR |= 0x30;
|
||||
Cores[core].TADR=Cores[core].MADR+(size<<1);
|
||||
|
||||
DMAICounter = size;
|
||||
Regs.STATX &= ~0x80;
|
||||
//Regs.ATTR |= 0x30;
|
||||
TADR = MADR + (size<<1);
|
||||
}
|
||||
|
||||
void SPU2writeDMA(int core, u16* pMem, u32 size)
|
||||
void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
||||
{
|
||||
if(cyclePtr != NULL) TimeUpdate(*cyclePtr);
|
||||
|
||||
Cores[core].DMAPtr=pMem;
|
||||
DMAPtr = pMem;
|
||||
|
||||
if(size<2) {
|
||||
//if(dma7callback) dma7callback();
|
||||
Cores[core].Regs.STATX &= ~0x80;
|
||||
//Cores[core].Regs.ATTR |= 0x30;
|
||||
Cores[core].DMAICounter=1;
|
||||
Regs.STATX &= ~0x80;
|
||||
//Regs.ATTR |= 0x30;
|
||||
DMAICounter=1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( IsDevBuild )
|
||||
DebugCores[core].lastsize = size;
|
||||
DebugCores[Index].lastsize = size;
|
||||
|
||||
Cores[core].TSA&=~7;
|
||||
TSA &= ~7;
|
||||
|
||||
bool adma_enable = ((Cores[core].AutoDMACtrl&(core+1))==(core+1));
|
||||
bool adma_enable = ((AutoDMACtrl&(Index+1))==(Index+1));
|
||||
|
||||
if(adma_enable)
|
||||
{
|
||||
Cores[core].TSA&=0x1fff;
|
||||
StartADMAWrite(core,pMem,size);
|
||||
TSA&=0x1fff;
|
||||
StartADMAWrite(pMem,size);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDMAWrite(core,pMem,size);
|
||||
PlainDMAWrite(pMem,size);
|
||||
}
|
||||
Cores[core].Regs.STATX &= ~0x80;
|
||||
//Cores[core].Regs.ATTR |= 0x30;
|
||||
Regs.STATX &= ~0x80;
|
||||
//Regs.ATTR |= 0x30;
|
||||
}
|
||||
|
||||
u32 CALLBACK SPU2ReadMemAddr(int core)
|
||||
{
|
||||
return Cores[core].MADR;
|
||||
}
|
||||
void CALLBACK SPU2WriteMemAddr(int core,u32 value)
|
||||
{
|
||||
Cores[core].MADR=value;
|
||||
}
|
||||
|
||||
void CALLBACK SPU2setDMABaseAddr(uptr baseaddr)
|
||||
{
|
||||
DMABaseAddr = (u16*)baseaddr;
|
||||
}
|
||||
|
||||
void CALLBACK SPU2readDMA4Mem(u16 *pMem, u32 size) { //size now in 16bit units
|
||||
FileLog("[%10d] SPU2 readDMA4Mem size %x\n",Cycles, size<<1);
|
||||
SPU2readDMA(0,pMem,size);
|
||||
}
|
||||
|
||||
void CALLBACK SPU2writeDMA4Mem(u16* pMem, u32 size) { //size now in 16bit units
|
||||
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
|
||||
SPU2writeDMA(0,pMem,size);
|
||||
}
|
||||
|
||||
void CALLBACK SPU2interruptDMA4() {
|
||||
FileLog("[%10d] SPU2 interruptDMA4\n",Cycles);
|
||||
Cores[0].Regs.STATX |= 0x80;
|
||||
//Cores[0].Regs.ATTR &= ~0x30;
|
||||
}
|
||||
|
||||
void CALLBACK SPU2readDMA7Mem(u16* pMem, u32 size) {
|
||||
FileLog("[%10d] SPU2 readDMA7Mem size %x\n",Cycles, size<<1);
|
||||
|
||||
SPU2readDMA(1,pMem,size);
|
||||
}
|
||||
|
||||
void CALLBACK SPU2writeDMA7Mem(u16* pMem, u32 size) {
|
||||
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
|
||||
SPU2writeDMA(1,pMem,size);
|
||||
}
|
||||
|
||||
void CALLBACK SPU2interruptDMA7() {
|
||||
FileLog("[%10d] SPU2 interruptDMA7\n",Cycles);
|
||||
Cores[1].Regs.STATX |= 0x80;
|
||||
//Cores[1].Regs.ATTR &= ~0x30;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +1,23 @@
|
|||
//GiGaHeRz's SPU2 Driver
|
||||
//Copyright (c) 2003-2008, David Quintana <gigaherz@gmail.com>
|
||||
//
|
||||
//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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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 //
|
||||
extern void DMALogOpen();
|
||||
extern void DMA4LogWrite(void *lpData, u32 ulSize);
|
||||
extern void DMA7LogWrite(void *lpData, u32 ulSize);
|
||||
extern void DMALogClose();
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SPU2X_GLOBAL_H_
|
||||
#define _SPU2X_GLOBAL_H_
|
||||
|
||||
struct StereoOut16;
|
||||
struct StereoOut32;
|
||||
struct StereoOutFloat;
|
||||
|
||||
struct V_Core;
|
||||
|
||||
namespace soundtouch
|
||||
{
|
||||
class SoundTouch;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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*, ...)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -103,8 +103,6 @@ public:
|
|||
|
||||
protected:
|
||||
static void ClampValues();
|
||||
//static bool CALLBACK DialogProc(uptr hWnd,u32 uMsg,WPARAM wParam,LPARAM lParam);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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();
|
||||
}
|
||||
|
|
|
@ -19,35 +19,39 @@
|
|||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
LPF_data::LPF_data( double freq, double srate )
|
||||
template< typename FloatType > __forceinline
|
||||
LowPassFilter<FloatType>::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<FloatType>::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 );
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<float> impl_lpf;
|
||||
|
||||
LowPassFilter32( float freq, float srate );
|
||||
float sample( float inval );
|
||||
};
|
||||
|
||||
struct LowPassFilter64
|
||||
{
|
||||
LowPassFilter<double> impl_lpf;
|
||||
|
||||
LowPassFilter64( double freq, double srate );
|
||||
double sample( double inval );
|
||||
};
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Spu2.h"
|
||||
#include <float.h>
|
||||
#include "Global.h"
|
||||
//#include <float.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#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 );
|
|
@ -15,33 +15,40 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <stdio.h>
|
||||
#include <string.h>
|
||||
# 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;
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#include "Global.h"
|
|
@ -15,172 +15,138 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Spu2.h"
|
||||
#include "Global.h"
|
||||
#include "RegTable.h"
|
||||
|
||||
const char *ParamNames[8]={"VOLL","VOLR","PITCH","ADSR1","ADSR2","ENVX","VOLXL","VOLXR"};
|
||||
|
|
|
@ -15,14 +15,13 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -15,52 +15,56 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<pcm_BlockCount; bidx++ )
|
||||
{
|
||||
if( pcm_cache_data[bidx].Validated )
|
||||
{
|
||||
// save a cache block!
|
||||
memcpy( pcmDst, &pcm_cache_data[bidx], sizeof(PcmCacheEntry) );
|
||||
pcmDst++;
|
||||
blksSaved++;
|
||||
}
|
||||
}
|
||||
|
||||
printf( " * SPU2 > 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; bidx<pcm_BlockCount; bidx++ )
|
||||
{
|
||||
if( pcm_cache_data[bidx].Validated )
|
||||
{
|
||||
// load a cache block!
|
||||
memcpy( &pcm_cache_data[bidx], pcmSrc, sizeof(PcmCacheEntry) );
|
||||
pcmSrc++;
|
||||
blksLoaded++;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
SndBuffer::ClearContents();
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 __fastcall SizeIt()
|
||||
{
|
||||
int size = sizeof(SPU2freezeData);
|
||||
|
||||
// calculate the amount of memory consumed by our cache:
|
||||
|
||||
for( int bidx=0; bidx<pcm_BlockCount; bidx++ )
|
||||
{
|
||||
if( pcm_cache_data[bidx].Validated )
|
||||
size += sizeof(PcmCacheEntry);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace Savestate;
|
||||
|
||||
EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data)
|
||||
{
|
||||
if( mode == FREEZE_SIZE )
|
||||
{
|
||||
data->size = 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;
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -1,25 +1,21 @@
|
|||
//GiGaHeRz's SPU2 Driver
|
||||
//Copyright (c) 2003-2008, David Quintana <gigaherz@gmail.com>
|
||||
//
|
||||
//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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BaseTypes.h"
|
||||
#include "Pcsx2Defs.h"
|
||||
|
||||
#include "Utilities/Exceptions.h"
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
//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
|
|
@ -16,9 +16,8 @@
|
|||
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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)<b) break;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "Windows/Dialogs.h"
|
||||
EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow)
|
||||
{
|
||||
// load file
|
||||
|
|
|
@ -26,11 +26,4 @@ void s2r_writedma4(u32 ticks,u16*data,u32 len);
|
|||
void s2r_writedma7(u32 ticks,u16*data,u32 len);
|
||||
void s2r_close();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// s2r playing
|
||||
EXPORT_C_(void) s2r_replay(HWND hwnd, HINSTANCE hinst, LPSTR filename, int nCmdShow);
|
||||
#else
|
||||
#define s2r_replay 0&&
|
||||
#endif
|
||||
|
||||
extern bool replay_mode;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 );
|
||||
}
|
||||
|
|
|
@ -15,11 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <new>
|
||||
|
||||
#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<CoreSrc_Count; srcidx++ )
|
||||
{
|
||||
SAFE_DELETE_OBJ( m_CoreWav[cidx][srcidx] );
|
||||
safe_delete( m_CoreWav[cidx][srcidx] );
|
||||
|
||||
sprintf( wavfilename, "logs\\spu2x-Core%d-%s.wav",
|
||||
cidx, m_tbl_CoreOutputTypeNames[ srcidx ] );
|
||||
|
@ -77,7 +73,7 @@ namespace WaveDump
|
|||
{
|
||||
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
|
||||
{
|
||||
SAFE_DELETE_OBJ( m_CoreWav[cidx][srcidx] );
|
||||
safe_delete( m_CoreWav[cidx][srcidx] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +95,7 @@ WavOutFile* m_wavrecord = NULL;
|
|||
|
||||
void RecordStart()
|
||||
{
|
||||
SAFE_DELETE_OBJ( m_wavrecord );
|
||||
safe_delete( m_wavrecord );
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -114,7 +110,7 @@ void RecordStart()
|
|||
|
||||
void RecordStop()
|
||||
{
|
||||
SAFE_DELETE_OBJ( m_wavrecord );
|
||||
safe_delete( m_wavrecord );
|
||||
}
|
||||
|
||||
void RecordWrite( const StereoOut16& sample )
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
#include <CommCtrl.h>
|
||||
|
||||
#include "svnrev.h"
|
||||
#include "Hyperlinks.h"
|
||||
|
|
|
@ -15,8 +15,22 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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";
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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:
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
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();
|
|
@ -15,6 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
|
||||
|
|
|
@ -15,13 +15,33 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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();
|
||||
|
|
|
@ -17,30 +17,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef _DIALOGS_H_
|
||||
#define _DIALOGS_H_
|
||||
|
||||
#include "../Spu2.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <initguid.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 )
|
||||
#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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Global.h"
|
||||
|
||||
#define _WIN32_DCOM
|
||||
|
||||
#include "Dialogs.h"
|
||||
#include <xaudio2.h>
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <xaudio2.h>
|
||||
|
||||
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<IXAudio2> 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,6 +15,7 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Global.h"
|
||||
#include "Dialogs.h"
|
||||
|
||||
int SendDialogMsg( HWND hwnd, int dlgId, UINT code, WPARAM wParam, LPARAM lParam)
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
# define WINVER 0x0501
|
||||
# define _WIN32_WINNT 0x0501
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <commctrl.h>
|
||||
#include <initguid.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#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;
|
|
@ -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 <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "dsp.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 <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
|
@ -15,50 +15,31 @@
|
|||
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<NumVoices; ++v )
|
||||
{
|
||||
|
@ -187,19 +144,20 @@ void V_Core::Reset()
|
|||
VoiceGates[v].WetL = -1;
|
||||
VoiceGates[v].WetR = -1;
|
||||
|
||||
Voices[v].Volume = V_VolumeSlideLR::Max;
|
||||
Voices[v].Volume = V_VolumeSlideLR::Max;
|
||||
|
||||
Voices[v].ADSR.Value = 0;
|
||||
Voices[v].ADSR.Phase = 0;
|
||||
Voices[v].Pitch = 0x3FFF;
|
||||
Voices[v].NextA = 2800;
|
||||
Voices[v].StartA = 2800;
|
||||
Voices[v].LoopStartA = 2800;
|
||||
Voices[v].ADSR.Value = 0;
|
||||
Voices[v].ADSR.Phase = 0;
|
||||
Voices[v].Pitch = 0x3FFF;
|
||||
Voices[v].NextA = 2800;
|
||||
Voices[v].StartA = 2800;
|
||||
Voices[v].LoopStartA = 2800;
|
||||
}
|
||||
DMAICounter = 0;
|
||||
AdmaInProgress = 0;
|
||||
|
||||
Regs.STATX = 0x80;
|
||||
DMAICounter = 0;
|
||||
AdmaInProgress = 0;
|
||||
|
||||
Regs.STATX = 0x80;
|
||||
}
|
||||
|
||||
s32 V_Core::EffectsBufferIndexer( s32 offset ) const
|
||||
|
@ -456,7 +414,7 @@ __forceinline void TimeUpdate(u32 cClocks)
|
|||
lClocks+=TickInterval;
|
||||
Cycles++;
|
||||
|
||||
// Note: IPU does not use MMX regs, so no need to save them.
|
||||
// Note: IOP does not use MMX regs, so no need to save them.
|
||||
//SaveMMXRegs();
|
||||
Mix();
|
||||
//RestoreMMXRegs();
|
||||
|
@ -516,11 +474,12 @@ void V_VolumeSlide::RegSet( u16 src )
|
|||
Value = GetVol32( src );
|
||||
}
|
||||
|
||||
void SPU_ps1_write(u32 mem, u16 value)
|
||||
void V_Core::WriteRegPS1( u32 mem, u16 value )
|
||||
{
|
||||
bool show=true;
|
||||
jASSUME( Index == 0 ); // Valid on Core 0 only!
|
||||
|
||||
u32 reg = mem&0xffff;
|
||||
bool show = true;
|
||||
u32 reg = mem & 0xffff;
|
||||
|
||||
if((reg>=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;
|
Loading…
Reference in New Issue