mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
55ba76be5d
commit
37f2a95289
|
@ -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);
|
||||
|
|
|
@ -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;"../../x86/ix86-32";../libs;../../pcl"
|
||||
PreprocessorDefinitions="NDEBUG,WIN32,_WINDOWS,__MSCW32__,__WIN32__,__i386__,ENABLE_NLS,PACKAGE=\"pcsx2\";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"
|
||||
/>
|
||||
|
|
|
@ -372,7 +372,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="..\..\..\bin\pcsx2r.exe"
|
||||
OutputFile="G:\pcsx2NEWSVN - clean\bin\pcsx2r.exe"
|
||||
ProgramDatabaseFile=""$(TargetDir)$(TargetName).pdb""
|
||||
/>
|
||||
<Tool
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue