Jake.Stine "completed" his work on SPU2Ghz, I tested a whole lot of games with this and it sounds great! Savestates work very well, the mixer is fast, even the dreaded buffer over/underflows are handled quite well (even without timestretch!).

All in all great additions which imo make SPU2Ghz the best SPU2 plugin to use now :)

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@229 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
ramapcsx2 2008-10-23 09:22:20 +00:00 committed by Gregory Hainaut
parent 55ba76be5d
commit 37f2a95289
10 changed files with 166 additions and 180 deletions

View File

@ -106,7 +106,7 @@ void* GSThreadProc(void* idp);
#endif
bool gsHasToExit=false;
static bool gsHasToExit=false;
int g_FFXHack=0;
#ifdef PCSX2_DEVBUILD
@ -1471,6 +1471,7 @@ int HasToExit()
}
#if defined(_WIN32) && !defined(WIN32_PTHREADS)
#pragma optimize ("", off)
DWORD WINAPI GSThreadProc(LPVOID lpParam)
{
HANDLE handles[2] = { g_hGsEvent, g_hVuGSExit };
@ -1744,7 +1745,7 @@ ExitGS:
GSclose();
return 0;
}
#pragma optimize ("", on)
int gsFreeze(gzFile f, int Mode) {
gzfreeze(PS2MEM_GS, 0x2000);

View File

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="windows-1253"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="9,00"
Name="pcsx2"
ProjectGUID="{1CEFD830-2B76-4596-A4EE-BCD7280A60BD}"
RootNamespace="pcsx2"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@ -102,6 +103,8 @@
AdditionalLibraryDirectories="..\"
ProgramDatabaseFile=".\Release/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@ -122,9 +125,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -210,6 +210,8 @@
AdditionalLibraryDirectories="..\"
ProgramDatabaseFile=".\Release/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@ -230,9 +232,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -311,6 +310,8 @@
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
@ -330,9 +331,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -410,6 +408,8 @@
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@ -430,9 +430,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -511,6 +508,8 @@
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug TLB/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
/>
<Tool
Name="VCALinkTool"
@ -530,9 +529,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -610,6 +606,8 @@
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Debug TLB/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@ -630,9 +628,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -717,6 +712,8 @@
AdditionalLibraryDirectories="..\"
ProgramDatabaseFile=".\ReleaseTLB/pcsx2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@ -737,9 +734,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
@ -779,14 +773,13 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/Ob0"
Optimization="2"
InlineFunctionExpansion="0"
Optimization="3"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
WholeProgramOptimization="false"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="./;../../;../../IPU;../../ZLIB;../../DebugTools;../../x86;&quot;../../x86/ix86-32&quot;;../libs;../../pcl"
PreprocessorDefinitions="NDEBUG,WIN32,_WINDOWS,__MSCW32__,__WIN32__,__i386__,ENABLE_NLS,PACKAGE=\&quot;pcsx2\&quot;;PCSX2_DEVBUILD;_CRT_SECURE_NO_DEPRECATE;TIXML_USE_STL;__x86_64__"
StringPooling="true"
@ -795,7 +788,6 @@
StructMemberAlignment="5"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="0"
PrecompiledHeaderFile=".\ReleaseTLB/pcsx2.pch"
AssemblerListingLocation=".\ReleaseTLB/"
ObjectFile=".\ReleaseTLB/"
@ -819,13 +811,17 @@
Name="VCLinkerTool"
AdditionalOptions="/LARGEADDRESSAWARE:NO"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib ../libs/gnu_gettext.lib ws2_32.lib winmm.lib ../libs/pthreadVC2.lib"
OutputFile="..\..\..\bin\pcsx2t.exe"
OutputFile="E:\pcsx2NEWSVN - clean\bin\pcsx2t64.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\"
ProgramDatabaseFile=".\ReleaseTLB/pcsx2.pdb"
SubSystem="2"
LinkTimeCodeGeneration="0"
OptimizeReferences="2"
EnableCOMDATFolding="2"
LinkTimeCodeGeneration="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
CLRThreadAttribute="1"
/>
@ -847,9 +843,6 @@
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>

View File

@ -372,7 +372,7 @@
/>
<Tool
Name="VCLinkerTool"
OutputFile="..\..\..\bin\pcsx2r.exe"
OutputFile="G:\pcsx2NEWSVN - clean\bin\pcsx2r.exe"
ProgramDatabaseFile="&quot;$(TargetDir)$(TargetName).pdb&quot;"
/>
<Tool

View File

@ -17,8 +17,8 @@
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory="c:\spu2ghz_temp\"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
@ -87,12 +87,14 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib dsound.lib"
OutputFile=".\bin\SPU2ghz.dll"
OutputFile="G:\pcsx2NEWSVN - clean\bin\plugins\SPU2ghzMOD.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
ModuleDefinitionFile=".\SPU2ghz.def"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\Release/SPU2ghz.pdb"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/SPU2ghz.lib"
@ -184,7 +186,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib dsound.lib"
OutputFile="F:\Pcsx2\plugins\SPU2ghz.dll"
OutputFile="G:\pcsx2NEWSVN - clean\bin\plugins\SPU2ghzMOD.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
ModuleDefinitionFile=".\SPU2ghz.def"
@ -263,8 +265,8 @@
StringPooling="true"
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableFunctionLevelLinking="false"
EnableEnhancedInstructionSet="1"
EnableFunctionLevelLinking="true"
EnableEnhancedInstructionSet="2"
FloatingPointModel="2"
UsePrecompiledHeader="0"
PrecompiledHeaderFile=""
@ -292,7 +294,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib dsound.lib"
OutputFile=".\bin\SPU2ghz.dll"
OutputFile="G:\pcsx2NEWSVN - clean\bin\plugins\SPU2ghzMOD.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
ModuleDefinitionFile=".\SPU2ghz.def"

View File

@ -227,8 +227,6 @@ void DoDMAWrite(int core,u16 *pMem,u32 size)
void SPU2readDMA(int core, u16* pMem, u32 size)
{
if( disableEverything ) return;
if(hasPtr) TimeUpdate(*cPtr,1);
u32 i;
@ -255,8 +253,6 @@ void SPU2readDMA(int core, u16* pMem, u32 size)
void SPU2writeDMA(int core, u16* pMem, u32 size)
{
if( disableEverything ) return;
if(hasPtr) TimeUpdate(*cPtr,1);
Cores[core].DMAPtr=pMem;

View File

@ -534,15 +534,14 @@ static void __forceinline GetVoiceValues_Linear(V_Core& thiscore, V_Voice& vc, s
{
if(Interpolation==0) // || vc.SP == 0)
{
Value = vc.PV1;
Value = MulShr32su( vc.PV1, vc.ADSR.Value );
}
else //if(Interpolation==1) //must be linear
{
s32 t0 = vc.PV2 - vc.PV1;
s32 t1 = vc.PV1<<12;
Value = t1 - (t0*vc.SP);
Value = MulShr32su( t1 - (t0*vc.SP), vc.ADSR.Value>>12 );
}
Value = MulShr32su( Value, vc.ADSR.Value>>12 );
}
}
@ -781,7 +780,7 @@ void __fastcall ReadInput(V_Core& thiscore, s32& PDataL,s32& PDataR)
/////////////////////////////////////////////////////////////////////////////////////////
// //
void __fastcall ReadInputPV(V_Core& thiscore, s32& ValL,s32& ValR)
static void __forceinline __fastcall ReadInputPV(V_Core& thiscore, s32& ValL,s32& ValR)
{
s32 DL=0, DR=0;
@ -800,6 +799,18 @@ void __fastcall ReadInputPV(V_Core& thiscore, s32& ValL,s32& ValR)
ValL=thiscore.ADMAPL;
ValR=thiscore.ADMAPR;
#ifndef PUBLIC
s32 InputPeak = max(abs(ValL),abs(ValR));
if(DebugCores[core].AutoDMAPeak<InputPeak) DebugCores[core].AutoDMAPeak=InputPeak;
#endif
// Apply volumes:
ValL *= thiscore.InpL;
ValR *= thiscore.InpR;
ValL >>= 1;
ValR >>= 1;
}
/////////////////////////////////////////////////////////////////////////////////////////
@ -1050,55 +1061,13 @@ static void __forceinline MixVoice( V_Core& thiscore, V_Voice& vc, s32& VValL, s
static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
{
s32 InpL=0, InpR=0;
s32 RVL,RVR;
s32 TDL=0,TDR=0,TWL=0,TWR=0;
s32 SDL=0,SDR=0,SWL=0,SWR=0;
s32 TDL=0,TDR=0;
s32 SDL=0,SDR=0;
s32 SWL=0,SWR=0;
TDL=TDR=TWL=TWR=(s32)0;
if (core == 1) { //Core 0 doesn't have External input
spu2M_WriteFast( 0x800 + OutPos, (s16)(ExtL>>16) );
spu2M_WriteFast( 0xA00 + OutPos, (s16)(ExtR>>16) );
}
V_Core& thiscore( Cores[core] );
if((core==0)&&((PlayMode&4)!=4))
{
ReadInputPV(thiscore, InpL,InpR); // get input data from input buffers
}
if((core==1)&&((PlayMode&8)!=8))
{
ReadInputPV(thiscore, InpL,InpR); // get input data from input buffers
}
#ifndef PUBLIC
s32 InputPeak = max(abs(InpL),abs(InpR));
if(DebugCores[core].AutoDMAPeak<InputPeak) DebugCores[core].AutoDMAPeak=InputPeak;
#endif
//MulShr32( InpL, thiscore.InpL, 1 );
//MulShr32( InpR, thiscore.InpR, 1 );
// [Air] : InpL and InpR don't need 64 bit muls.
InpL *= thiscore.InpL;
InpR *= thiscore.InpR;
InpL >>= 1;
InpR >>= 1;
// shift inputs by 20 collectively, so that the result is
// effectively downshifted by 12:
ExtL = MulShr32su( ExtL<<3, ((int)thiscore.ExtL)<<16);
ExtR = MulShr32su( ExtR<<3, ((int)thiscore.ExtR)<<16);
//InpL = MulDiv(InpL,(thiscore.InpL),1<<1);
//InpR = MulDiv(InpR,(thiscore.InpR),1<<1);
//ExtL = MulDiv(ExtL,(thiscore.ExtL),1<<12);
//ExtR = MulDiv(ExtR,(thiscore.ExtR),1<<12);
SDL=SDR=SWL=SWR=(s32)0;
for (voice=0;voice<24;voice++)
@ -1120,42 +1089,46 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
spu2M_WriteFast( 0x1400 + (core<<12) + OutPos, (s16)(SWL>>16) );
spu2M_WriteFast( 0x1600 + (core<<12) + OutPos, (s16)(SWR>>16) );
// Mix in the Input data
TDL = OutL * thiscore.InpDryL;
TDR = OutR * thiscore.InpDryR;
// Mix in the Voice data
TDL += SDL * thiscore.SndDryL;
TDR += SDR * thiscore.SndDryR;
TWL += SWL * thiscore.SndWetL;
TWR += SWR * thiscore.SndWetR;
// Mix in the Input data
TDL += InpL * thiscore.InpDryL;
TDR += InpR * thiscore.InpDryR;
TWL += InpL * thiscore.InpWetL;
TWR += InpR * thiscore.InpWetR;
// Mix in the External (nothing/core0) data
TDL += ExtL * thiscore.ExtDryL;
TDR += ExtR * thiscore.ExtDryR;
TWL += ExtL * thiscore.ExtWetL;
TWR += ExtR * thiscore.ExtWetR;
if(EffectsEnabled)
{
s32 TWL=0,TWR=0;
// Mix Input, Voice, and External data:
TWL = OutL * thiscore.InpWetL;
TWR = OutR * thiscore.InpWetR;
TWL += SWL * thiscore.SndWetL;
TWR += SWR * thiscore.SndWetR;
TWL += ExtL * thiscore.ExtWetL;
TWR += ExtR * thiscore.ExtWetR;
//Apply Effects
DoReverb( thiscore, RVL,RVR,TWL>>16,TWR>>16);
TWL=ApplyVolume(RVL,VOL(thiscore.FxL));
TWR=ApplyVolume(RVR,VOL(thiscore.FxR));
//Mix Wet,Dry
OutL=(TDL + TWL);
OutR=(TDR + TWR);
}
else
{
TWL=0;
TWR=0;
OutL = TDL;
OutR = TDR;
}
//Mix Wet,Dry
OutL=(TDL + TWL);
OutR=(TDR + TWR);
//Apply Master Volume
if( thiscore.MasterL.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume(thiscore.MasterL);
if( thiscore.MasterR.Mode & VOLFLAG_SLIDE_ENABLE ) UpdateVolume(thiscore.MasterR);
@ -1170,17 +1143,6 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
OutL=0;
OutR=0;
}
if((core==1)&&(PlayMode&8))
{
ReadInput(thiscore, OutL,OutR);
}
if((core==0)&&(PlayMode&4))
{
OutL=0;
OutR=0;
}
}
// used to throttle the output rate of cache stat reports
@ -1190,11 +1152,45 @@ void __fastcall Mix()
{
s32 ExtL=0, ExtR=0, OutL, OutR;
// **** CORE ZERO ****
core=0;
MixCore(ExtL,ExtR,0,0);
if( (PlayMode&4) != 4 )
{
// get input data from input buffers
ReadInputPV(Cores[0], ExtL, ExtR);
}
MixCore( ExtL, ExtR, 0, 0 );
if( PlayMode & 4 )
{
ExtL=0;
ExtR=0;
}
// Commit Core 0 output to ram before mixing Core 1:
ExtL>>=13;
ExtR>>=13;
spu2M_WriteFast( 0x800 + OutPos, ExtL>>3 );
spu2M_WriteFast( 0xA00 + OutPos, ExtR>>3 );
// **** CORE ONE ****
core=1;
MixCore(OutL,OutR,ExtL,ExtR);
if( (PlayMode&8) != 8 )
{
ReadInputPV(Cores[1], OutL, OutR); // get input data from input buffers
}
// Apply volume to the external (Core 0) input data.
MixCore( OutL, OutR, ExtL*Cores[1].ExtL, ExtR*Cores[1].ExtR );
if( PlayMode & 8 )
{
ReadInput(Cores[1], OutL, OutR);
}
#ifndef PUBLIC
static s32 Peak0,Peak1;

View File

@ -128,9 +128,9 @@ public:
{
//isWaiting=true;
LeaveCriticalSection(&cs);
ConLog( " * SPU2 : Waiting for object... " );
//ConLog( " * SPU2 : Waiting for object... " );
WaitForSingleObject(hSyncEvent,1000);
ConLog( " Signaled! \n" );
//ConLog( " Signaled! \n" );
EnterCriticalSection(&cs);
#ifdef DYNAMIC_BUFFER_LIMITING
free = buffer_limit-data;
@ -150,14 +150,28 @@ public:
// several seconds).
//
// Compromise:
// Same as with underruns below, an overrun can be handled by aborting
// the write operation before the writepos goes past the readpos, and then
// ignoring the rest of the incoming data. The resultant sound will have
// a single hiccup when an overflow occurs, instead of getting crapped out
// for several seconds (or in many cases, until the SPU sndout driver was
// manually reset.. grr!).
// When an overrun occurs, we adapt by discarding a portion of the buffer.
// The older portion of the buffer is discarded rather than incoming data,
// so that the overall audio synchronization is better.
#ifndef DYNAMIC_BUFFER_LIMITING
if( data+nSamples > size )
{
// Buffer overrun!
// Dump samples from the read portion of the buffer instead of dropping
// the newly written stuff.
// Toss half the buffer plus whatever's being written anew:
s32 comp = (size / 2) + nSamples;
comp = (comp + 128) & ~127; // probably not important but it makes the log look nicer. :P
if( comp > size ) comp = size;
data-=comp;
rpos=(rpos+comp)%size;
ConLog(" * SPU2 > Overrun Compensation (%d samples tossed)\n", size );
}
while(data<size && nSamples>0)
{
buffer[wpos] = *(bData++);
@ -213,7 +227,13 @@ public:
#ifndef DYNAMIC_BUFFER_LIMITING
if( underrun_freeze )
{
if( data < (int)(size * 0.85) )
// Let's fill up 80% of our buffer.
// (I just picked 80% arbitrarily.. there might be a better value)
int toFill = (int)(size * 0.80);
toFill = (toFill + 128) & ~127; // probably not important but it makes the log look nicer. :P
if( data < toFill )
{
while( nSamples>0 )
{
@ -225,7 +245,7 @@ public:
}
underrun_freeze = false;
//ConLog( " * SPU2 > Underrun Freeze Finished!\n" );
ConLog( " * SPU2 > Underrun compensation (%d samples buffered)\n", toFill );
}
while(data>0 && nSamples>0)
@ -250,7 +270,6 @@ public:
if( data == 0 && !pw )
{
ConLog( " * SPU2 > Underrun compensation\n" );
underrun_freeze = true;
}

View File

@ -60,9 +60,8 @@ static bool spu2init=false; // has spu2init plugin interface been called?
static bool resetClock = true;
// Used to make spu2 more robust at loading incompatible saves.
// You won't get any sound but it won't cause mass instability either.
// (should allow players to get to their next save point more easily)
bool disableEverything=false;
// Disables re-freezing of save state data.
bool disableFreezes=false;
void (* _irqcallback)();
void (* dma4callback)();
@ -281,7 +280,7 @@ s32 CALLBACK SPU2init()
#endif
srand((unsigned)time(NULL));
disableEverything=false;
disableFreezes=false;
if (spu2init)
{
@ -653,10 +652,10 @@ void __fastcall TimeUpdate(u32 cClocks, u32 syncType)
// If for some reason our clock value seems way off base, just mix
// out a little bit, skip the rest, and hope the ship "rights" itself later on.
if( dClocks > TickInterval*32 )
if( dClocks > TickInterval*48 )
{
ConLog( " * SPU2 > TimeUpdate > Sanity Check Failed: %d (cc: %d)\n", dClocks/TickInterval, cClocks/TickInterval );
dClocks = TickInterval*32;
ConLog( " * SPU2 > TimeUpdate Sanity Check (Tick Delta: %d) (PS2 Ticks: %d)\n", dClocks/TickInterval, cClocks/TickInterval );
dClocks = TickInterval*48;
lClocks = cClocks-dClocks;
}
@ -734,8 +733,6 @@ bool numpad_minus = false;
void CALLBACK SPU2async(u32 cycles)
{
if( disableEverything ) return;
#ifndef PUBLIC
u32 oldClocks = lClocks;
static u32 timer=0,time1=0,time2=0;
@ -1251,8 +1248,6 @@ void CALLBACK SPU2writeLog(u32 rmem, u16 value)
void CALLBACK SPU2write(u32 rmem, u16 value)
{
if( disableEverything ) return;
#ifdef S2R_ENABLE
if(!replay_mode)
s2r_writereg(Cycles,rmem,value);
@ -1583,8 +1578,6 @@ void CALLBACK SPU2write(u32 rmem, u16 value)
u16 CALLBACK SPU2read(u32 rmem)
{
if( disableEverything ) return 0;
// if(!replay_mode)
// s2r_readreg(Cycles,rmem);
@ -1677,14 +1670,12 @@ typedef struct
static int getFreezeSize()
{
if( disableEverything ) return 7; // length of the string id "invalid"
if( disableFreezes ) return 7; // length of the string id "invalid"
int size = sizeof(SPU2freezeData);
// calculate the amount of memory consumed by our cache:
//size += PCM_CACHE_BLOCK_COUNT / 8;
for( int bidx=0; bidx<PCM_CACHE_BLOCK_COUNT; bidx++ )
{
const u32 flagmask = 1ul << (bidx & 31);
@ -1705,39 +1696,32 @@ s32 CALLBACK SPU2freeze(int mode, freezeData *data)
if( spud->id != SAVE_ID || spud->version != SAVE_VERSION )
{
// [Air]: Running the SPU2 from an "empty" state this way is pretty unreliable.
// It usually didn't crash at least, but it never output sound anyway and would
// confuse the new cache system.
//
// To fix it I introduced a new global flag that disables the SPU2 logic completely.
// This is the safest way to recover from an unsupported SPU2 save, since it pretty
// well garauntees the user will have a stable enough environment to reach a save spot.
printf("\n*** SPU2Ghz Warning:\n");
printf("The savestate you are trying to load was not made with this plugin.\n");
printf("Sound will be disabled until the emulator is reset.\n");
printf("Find a memorycard savespot to save your game, reset, and then continue from there.\n\n");
printf(" The savestate you are trying to load was not made with this plugin.\n");
printf(" The emulator will not be stable! Find a memorycard savespot to save your\n");
printf(" game, reset, and then continue from there.\n\n");
// Clear stuff, not that it matters:
disableEverything=true;
disableFreezes=true;
lClocks = 0;
resetClock = true;
// Reset the cores.
// 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 );
//CoreReset( 0 );
//CoreReset( 1 );
// adpcm cache : Just clear all the cache flags, which forces the mixer
// to re-decode everything.
// adpcm cache : Clear all the cache flags and buffers.
memset( pcm_cache_flags, 0, (0x200000 / (16*32)) * 4 );
memset( pcm_cache_data, 0, (0x200000 / 16) * 28 * 2 );
}
else
{
disableEverything=false;
disableFreezes=false;
// base stuff
memcpy(spu2regs, spud->unkregs, 0x010000);
@ -1795,7 +1779,7 @@ s32 CALLBACK SPU2freeze(int mode, freezeData *data)
{
if (data->data == NULL) return -1;
if( disableEverything )
if( disableFreezes )
{
// No point in making a save state since the SPU2
// state is completely bogus anyway... Let's just
@ -1971,7 +1955,8 @@ void StopVoices(int core, u32 value)
// for now, pData is not used
int CALLBACK SPU2setupRecording(int start, void* pData)
{
if( disableEverything ) return 0;
// Don't record if we have a bogus state.
if( disableFreezes ) return 0;
if(start==0)
{

View File

@ -141,7 +141,7 @@ extern u32 lClocks;
extern u32* cPtr;
extern bool hasPtr;
extern bool disableEverything;
extern bool disableFreezes;
void __fastcall TimeUpdate(u32 cClocks, u32 syncType);

View File

@ -127,12 +127,6 @@ public:
whbuffer[i].reserved=0;
waveOutPrepareHeader(hwodevice,whbuffer+i,sizeof(WAVEHDR));
whbuffer[i].dwFlags|=WHDR_DONE; //avoid deadlock
// Feed blocks into the device.
// It'll all be empty samples, but it helps reduce some of the pop-on-init.
//whbuffer[i].dwFlags&=~WHDR_DONE;
//waveOutWrite(hwodevice,&whbuffer[i],sizeof(WAVEHDR));
}
// Start Thread