Worked on savestate support a bit. It now remembers an update timing variable more (could fix a few crashes).
This increases the savestate version though, so make sure you have a memory card save ready before upgrading!

Also implemented a way of delaying audio output after loading states. This masks the ugly noise that some games produce directly after loading, keeping your valuable speakers intact :p

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@963 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
ramapcsx2 2009-04-12 21:19:29 +00:00
parent 6830f07f27
commit ad6dce5e9c
6 changed files with 43 additions and 13 deletions

View File

@ -35,6 +35,7 @@ struct SPU2freezeData
s16 OutPos;
s16 InputPos;
u32 Cycles;
u32 lClocks;
int PlayMode;
// Used as a base pointer to a series PcmCache blocks.
@ -47,7 +48,7 @@ static const u32 SAVE_ID = 0x1227521;
// versioning for saves.
// Increment this when changes to the savestate system are made.
static const u32 SAVE_VERSION = 0x0004;
static const u32 SAVE_VERSION = 0x0005;
static void wipe_the_cache()
{
@ -71,6 +72,7 @@ s32 __fastcall FreezeIt( SPU2freezeData& spud )
spud.OutPos = OutPos;
spud.InputPos = InputPos;
spud.Cycles = Cycles;
spud.lClocks = lClocks;
spud.PlayMode = PlayMode;
// Save our cache:
@ -115,8 +117,6 @@ s32 __fastcall ThawIt( SPU2freezeData& spud )
printf("\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n");
printf(" and then continue from there.\n\n");
resetClock = true;
// 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
@ -141,6 +141,7 @@ s32 __fastcall ThawIt( SPU2freezeData& spud )
OutPos = spud.OutPos;
InputPos = spud.InputPos;
Cycles = spud.Cycles;
lClocks = spud.lClocks;
PlayMode = spud.PlayMode;
// Load the ADPCM cache:
@ -172,6 +173,9 @@ s32 __fastcall ThawIt( SPU2freezeData& spud )
Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata;
}
}
SndBuffer::ClearContents();
}
return 0;
}

View File

@ -303,6 +303,13 @@ int SndBuffer::m_dsp_progress = 0;
int SndBuffer::m_dsp_writepos = 0;
int SndBuffer::m_timestretch_progress = 0;
int SndBuffer::ssFreeze = 0;
void SndBuffer::ClearContents()
{
SndBuffer::soundtouchClearContents();
SndBuffer::ssFreeze = 30; //Delays sound output for about half a second.
}
void SndBuffer::Write( const StereoOut32& Sample )
{
@ -320,7 +327,13 @@ void SndBuffer::Write( const StereoOut32& Sample )
if(sndTempProgress < SndOutPacketSize) return;
sndTempProgress = 0;
if( dspPluginEnabled )
//Don't play anything directly after loading a savestate, avoids static killing your speakers.
if ( ssFreeze > 0 )
{
ssFreeze--;
return;
}
else if( dspPluginEnabled )
{
// Convert in, send to winamp DSP, and convert out.

View File

@ -251,13 +251,14 @@ private:
static float cTempo;
static float eTempo;
static int freezeTempo;
static int ssFreeze;
static void _InitFail();
static void _WriteSamples(StereoOut32* bData, int nSamples);
static bool CheckUnderrunStatus( int& nSamples, int& quietSampleCount );
static void soundtouchInit();
static void soundtouchClearContents();
static void soundtouchCleanup();
static void timeStretchWrite();
static void timeStretchUnderrun();
@ -272,6 +273,7 @@ public:
static void Cleanup();
static void Write( const StereoOut32& Sample );
static s32 Test();
static void ClearContents();
#ifdef _MSC_VER
static void Configure(HWND parent, u32 module );

View File

@ -36,9 +36,6 @@ void InitADSR();
DWORD CALLBACK TimeThread(PVOID /* unused param */);
#endif
// [Air]: fixed the hacky part of UpdateTimer with this:
bool resetClock = true;
void (* _irqcallback)();
void (* dma4callback)();
void (* dma7callback)();

View File

@ -174,7 +174,6 @@ extern int recording;
extern u32 lClocks;
extern u32* cPtr;
extern bool hasPtr;
extern bool resetClock;
extern void SPU2writeLog( const char* action, u32 rmem, u16 value );

View File

@ -128,7 +128,7 @@ void SndBuffer::UpdateTempoChange()
// "non-emergency" deadzone: In this area stretching will be strongly discouraged.
// Note: due tot he nature of timestretch latency, it's always a wee bit harder to
// cope with low fps (underruns) tha it is high fps (overruns). So to help out a
// cope with low fps (underruns) than it is high fps (overruns). So to help out a
// little, the low-end portions of this check are less forgiving than the high-sides.
if( cTempo < 0.965f || cTempo > 1.060f ||
@ -323,7 +323,22 @@ void SndBuffer::soundtouchInit()
// just freeze tempo changes for a while at startup.
// the driver buffers are bogus anyway.
freezeTempo = 8;
freezeTempo = 16;
m_predictData = 0;
}
// reset timestretch management vars, and delay updates a bit:
void SndBuffer::soundtouchClearContents()
{
pSoundTouch->clear();
pSoundTouch->setTempo(1);
cTempo = 1.0;
eTempo = 1.0;
lastPct = 0;
lastEmergencyAdj = 0;
freezeTempo = 16;
m_predictData = 0;
}