mirror of https://github.com/PCSX2/pcsx2.git
SPU2ghz: Corrected another ADSR bug that muted audio in Shadow of the Colossus; implemented some minor speedups.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@473 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
3476172c49
commit
8630529f8e
|
@ -72,13 +72,13 @@ typedef struct {
|
|||
// Source (Wave/Noise)
|
||||
s8 Noise;
|
||||
// Direct Output for Left Channel
|
||||
s8 DryL;
|
||||
s32 DryL;
|
||||
// Direct Output for Right Channel
|
||||
s8 DryR;
|
||||
s32 DryR;
|
||||
// Effect Output for Left Channel
|
||||
s8 WetL;
|
||||
s32 WetL;
|
||||
// Effect Output for Right Channel
|
||||
s8 WetR;
|
||||
s32 WetR;
|
||||
// Loop Start Adress (also Reg_LSAH/L)
|
||||
u32 LoopStartA;
|
||||
// Sound Start Adress (also Reg_SSAH/L)
|
||||
|
@ -237,29 +237,29 @@ typedef struct {
|
|||
// DMA Transfer Data Address (Internal...)
|
||||
u32 TDA;
|
||||
// External Input to Direct Output (Left)
|
||||
s8 ExtDryL;
|
||||
s32 ExtDryL;
|
||||
// External Input to Direct Output (Right)
|
||||
s8 ExtDryR;
|
||||
s32 ExtDryR;
|
||||
// External Input to Effects (Left)
|
||||
s8 ExtWetL;
|
||||
s32 ExtWetL;
|
||||
// External Input to Effects (Right)
|
||||
s8 ExtWetR;
|
||||
s32 ExtWetR;
|
||||
// Sound Data Input to Direct Output (Left)
|
||||
s8 InpDryL;
|
||||
s32 InpDryL;
|
||||
// Sound Data Input to Direct Output (Right)
|
||||
s8 InpDryR;
|
||||
s32 InpDryR;
|
||||
// Sound Data Input to Effects (Left)
|
||||
s8 InpWetL;
|
||||
s32 InpWetL;
|
||||
// Sound Data Input to Effects (Right)
|
||||
s8 InpWetR;
|
||||
s32 InpWetR;
|
||||
// Voice Data to Direct Output (Left)
|
||||
s8 SndDryL;
|
||||
s32 SndDryL;
|
||||
// Voice Data to Direct Output (Right)
|
||||
s8 SndDryR;
|
||||
s32 SndDryR;
|
||||
// Voice Data to Effects (Left)
|
||||
s8 SndWetL;
|
||||
s32 SndWetL;
|
||||
// Voice Data to Effects (Right)
|
||||
s8 SndWetR;
|
||||
s32 SndWetR;
|
||||
// Interrupt Enable
|
||||
s8 IRQEnable;
|
||||
// DMA related?
|
||||
|
|
|
@ -389,22 +389,20 @@ static void __forceinline CalculateADSR( V_Voice& vc )
|
|||
u32 off = InvExpOffsets[(env.Value>>28)&7];
|
||||
env.Value-=PsxRates[((env.Dr^0x1f)*4)-0x18+off+32];
|
||||
|
||||
// Clamp decay to SLevel or Zero
|
||||
if (env.Value < 0)
|
||||
env.Value = 0;
|
||||
else
|
||||
{
|
||||
// calculate sustain level by mirroring the bits
|
||||
// of the sustain var into the lower bits as we shift up
|
||||
// (total shift, 27 bits)
|
||||
|
||||
u32 suslev = (env.Sl << 4) | env.Sl;
|
||||
suslev = (suslev << 8) | suslev; // brings us to 12 bits!
|
||||
suslev = (suslev << 12) | suslev; // 24 bits!
|
||||
// calculate sustain level by mirroring the bits
|
||||
// of the sustain var into the lower bits as we shift up
|
||||
// (total shift, 27 bits)
|
||||
|
||||
s32 suslev = (env.Sl << 4) | env.Sl;
|
||||
suslev = (suslev << 8) | suslev; // brings us to 12 bits!
|
||||
suslev = (suslev << 12) | suslev; // 24 bits!
|
||||
|
||||
if( env.Value <= (suslev<<3) )
|
||||
env.Phase++;
|
||||
}
|
||||
if( env.Value <= (suslev<<3) )
|
||||
{
|
||||
if (env.Value < 0)
|
||||
env.Value = 0;
|
||||
env.Phase++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1090,10 +1088,10 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
|
|||
// Note: Results from MixVoice are ranged at 16 bits.
|
||||
// Following muls are toggles only (0 or 1)
|
||||
|
||||
SDL += VValL * vc.DryL;
|
||||
SDR += VValR * vc.DryR;
|
||||
SWL += VValL * vc.WetL;
|
||||
SWR += VValR * vc.WetR;
|
||||
SDL += VValL & vc.DryL;
|
||||
SDR += VValR & vc.DryR;
|
||||
SWL += VValL & vc.WetL;
|
||||
SWR += VValR & vc.WetR;
|
||||
}
|
||||
|
||||
// Saturate final result to standard 16 bit range.
|
||||
|
@ -1116,28 +1114,28 @@ static void __fastcall MixCore(s32& OutL, s32& OutR, s32 ExtL, s32 ExtR)
|
|||
s32 TDL,TDR;
|
||||
|
||||
// Mix in the Input data
|
||||
TDL = OutL * thiscore.InpDryL;
|
||||
TDR = OutR * thiscore.InpDryR;
|
||||
TDL = OutL & thiscore.InpDryL;
|
||||
TDR = OutR & thiscore.InpDryR;
|
||||
|
||||
// Mix in the Voice data
|
||||
TDL += SDL * thiscore.SndDryL;
|
||||
TDR += SDR * thiscore.SndDryR;
|
||||
TDL += SDL & thiscore.SndDryL;
|
||||
TDR += SDR & thiscore.SndDryR;
|
||||
|
||||
// Mix in the External (nothing/core0) data
|
||||
TDL += ExtL * thiscore.ExtDryL;
|
||||
TDR += ExtR * thiscore.ExtDryR;
|
||||
TDL += ExtL & thiscore.ExtDryL;
|
||||
TDR += ExtR & thiscore.ExtDryR;
|
||||
|
||||
if(EffectsEnabled)
|
||||
{
|
||||
s32 TWL,TWR;
|
||||
|
||||
// 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;
|
||||
TWL = OutL & thiscore.InpWetL;
|
||||
TWR = OutR & thiscore.InpWetR;
|
||||
TWL += SWL & thiscore.SndWetL;
|
||||
TWR += SWR & thiscore.SndWetR;
|
||||
TWL += ExtL & thiscore.ExtWetL;
|
||||
TWR += ExtR & thiscore.ExtWetR;
|
||||
|
||||
WaveDump::WriteCore( core, CoreSrc_PreReverb, TWL, TWR );
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ struct SPU2freezeData
|
|||
// Increment this if changes to V_Core or V_Voice structs are made.
|
||||
// Chances are we'll never explicitly support older save versions,
|
||||
// but might as well version them anyway. Could come in handly someday!
|
||||
#define SAVE_VERSION 0x0101
|
||||
#define SAVE_VERSION 0x0102
|
||||
|
||||
static int getFreezeSize()
|
||||
{
|
||||
|
@ -81,12 +81,20 @@ EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data)
|
|||
{
|
||||
const SPU2freezeData *spud = (SPU2freezeData*)data->data;
|
||||
|
||||
if( spud->id != SAVE_ID || spud->version < 0x100 )
|
||||
if( spud->id != SAVE_ID || spud->version < SAVE_VERSION )
|
||||
{
|
||||
printf("\n*** SPU2Ghz Warning:\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");
|
||||
if( spud->id == SAVE_ID )
|
||||
{
|
||||
printf("\tSavestate version is from an older version of this plugin.\n");
|
||||
printf("\tAudio may not recover correctly.\n\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
disableFreezes=true;
|
||||
lClocks = 0;
|
||||
|
@ -127,39 +135,34 @@ EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data)
|
|||
// Load the ADPCM cache:
|
||||
|
||||
wipe_the_cache();
|
||||
if( spud->version == 0x100 ) // don't support 0x100 cache anymore.
|
||||
|
||||
const PcmCacheEntry* pcmSrc = &spud->cacheData;
|
||||
int blksLoaded=0;
|
||||
|
||||
for( int bidx=0; bidx<pcm_BlockCount; bidx++ )
|
||||
{
|
||||
printf("\n*** SPU2Ghz Warning:\n");
|
||||
printf("\tSavestate version is from an older version of this plugin.\n");
|
||||
printf("\tAudio may not recover correctly.\n\n");
|
||||
|
||||
const PcmCacheEntry* pcmSrc = &spud->cacheData;
|
||||
int blksLoaded=0;
|
||||
|
||||
for( int bidx=0; bidx<pcm_BlockCount; bidx++ )
|
||||
if( pcm_cache_data[bidx].Validated )
|
||||
{
|
||||
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;
|
||||
}
|
||||
// load a cache block!
|
||||
memcpy( &pcm_cache_data[bidx], pcmSrc, sizeof(PcmCacheEntry) );
|
||||
pcmSrc++;
|
||||
blksLoaded++;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*else
|
||||
{
|
||||
// We don't support the cache, so make sure the SBuffer pointers
|
||||
// are safe (don't want any GPFs reading bad data)
|
||||
|
@ -169,7 +172,7 @@ EXPORT_C_(s32) SPU2freeze(int mode, freezeData *data)
|
|||
for( int v=0; v<24; v++ )
|
||||
Cores[c].Voices[v].SBuffer = old_state_sBuffer;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
//printf( " * SPU2 > FreezeLoad > Loaded %d cache blocks.\n", blksLoaded++ );
|
||||
|
|
|
@ -180,18 +180,18 @@ void CoreReset(int c)
|
|||
Cores[c].MasterL.Value=0x7FFF;
|
||||
Cores[c].MasterR.Reg_VOL=0x3FFF;
|
||||
Cores[c].MasterR.Value=0x7FFF;
|
||||
Cores[c].ExtWetR=1;
|
||||
Cores[c].ExtWetL=1;
|
||||
Cores[c].ExtDryR=1;
|
||||
Cores[c].ExtDryL=1;
|
||||
Cores[c].InpWetR=1;
|
||||
Cores[c].InpWetL=1;
|
||||
Cores[c].InpDryR=1;
|
||||
Cores[c].InpDryL=1;
|
||||
Cores[c].SndWetR=1;
|
||||
Cores[c].SndWetL=1;
|
||||
Cores[c].SndDryR=1;
|
||||
Cores[c].SndDryL=1;
|
||||
Cores[c].ExtWetR = -1;
|
||||
Cores[c].ExtWetL = -1;
|
||||
Cores[c].ExtDryR = -1;
|
||||
Cores[c].ExtDryL = -1;
|
||||
Cores[c].InpWetR = -1;
|
||||
Cores[c].InpWetL = -1;
|
||||
Cores[c].InpDryR = -1;
|
||||
Cores[c].InpDryL = -1;
|
||||
Cores[c].SndWetR = -1;
|
||||
Cores[c].SndWetL = -1;
|
||||
Cores[c].SndDryR = -1;
|
||||
Cores[c].SndDryL = -1;
|
||||
Cores[c].Regs.MMIX = 0xFFCF;
|
||||
Cores[c].Regs.VMIXL = 0xFFFFFF;
|
||||
Cores[c].Regs.VMIXR = 0xFFFFFF;
|
||||
|
@ -209,10 +209,10 @@ void CoreReset(int c)
|
|||
Cores[c].Voices[v].ADSR.Value=0;
|
||||
Cores[c].Voices[v].ADSR.Phase=0;
|
||||
Cores[c].Voices[v].Pitch=0x3FFF;
|
||||
Cores[c].Voices[v].DryL=1;
|
||||
Cores[c].Voices[v].DryR=1;
|
||||
Cores[c].Voices[v].WetL=1;
|
||||
Cores[c].Voices[v].WetR=1;
|
||||
Cores[c].Voices[v].DryL = -1;
|
||||
Cores[c].Voices[v].DryR = -1;
|
||||
Cores[c].Voices[v].WetL = -1;
|
||||
Cores[c].Voices[v].WetR = -1;
|
||||
Cores[c].Voices[v].NextA=2800;
|
||||
Cores[c].Voices[v].StartA=2800;
|
||||
Cores[c].Voices[v].LoopStartA=2800;
|
||||
|
@ -1111,6 +1111,9 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
|||
}
|
||||
return;
|
||||
|
||||
#define vx_SetSomeBits( varname, start, done ) \
|
||||
{ for (uint vc=start, vx=1;vc<done;vc++) { Cores[core].Voices[vc].varname = (value & vx) ? -1 : 0; vx<<=1; } }
|
||||
|
||||
case REG_S_PMON:
|
||||
vx=2; for (vc=1;vc<16;vc++) { Cores[core].Voices[vc].Modulated=(s8)((value & vx)/vx); vx<<=1; }
|
||||
Cores[core].Regs.PMON = (Cores[core].Regs.PMON & 0xFFFF0000) | value;
|
||||
|
@ -1132,60 +1135,60 @@ __forceinline void SPU2_FastWrite( u32 rmem, u16 value )
|
|||
return;
|
||||
|
||||
case REG_S_VMIXL:
|
||||
vx=1; for (vc=0;vc<16;vc++) { Cores[core].Voices[vc].DryL=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( DryL, 0, 16 );
|
||||
Cores[core].Regs.VMIXL = (Cores[core].Regs.VMIXL & 0xFFFF0000) | value;
|
||||
return;
|
||||
|
||||
case (REG_S_VMIXL + 2):
|
||||
vx=1; for (vc=16;vc<24;vc++) { Cores[core].Voices[vc].DryL=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( DryL, 16, 24 );
|
||||
Cores[core].Regs.VMIXL = (Cores[core].Regs.VMIXL & 0xFFFF) | (value << 16);
|
||||
return;
|
||||
|
||||
case REG_S_VMIXEL:
|
||||
vx=1; for (vc=0;vc<16;vc++) { Cores[core].Voices[vc].WetL=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( WetL, 0, 16 );
|
||||
Cores[core].Regs.VMIXEL = (Cores[core].Regs.VMIXEL & 0xFFFF0000) | value;
|
||||
return;
|
||||
|
||||
case (REG_S_VMIXEL + 2):
|
||||
vx=1; for (vc=16;vc<24;vc++) { Cores[core].Voices[vc].WetL=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( WetL, 16, 24 );
|
||||
Cores[core].Regs.VMIXEL = (Cores[core].Regs.VMIXEL & 0xFFFF) | (value << 16);
|
||||
return;
|
||||
|
||||
case REG_S_VMIXR:
|
||||
vx=1; for (vc=0;vc<16;vc++) { Cores[core].Voices[vc].DryR=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( DryR, 0, 16 );
|
||||
Cores[core].Regs.VMIXR = (Cores[core].Regs.VMIXR & 0xFFFF0000) | value;
|
||||
return;
|
||||
|
||||
case (REG_S_VMIXR + 2):
|
||||
vx=1; for (vc=16;vc<24;vc++) { Cores[core].Voices[vc].DryR=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( DryR, 16, 24 );
|
||||
Cores[core].Regs.VMIXR = (Cores[core].Regs.VMIXR & 0xFFFF) | (value << 16);
|
||||
return;
|
||||
|
||||
case REG_S_VMIXER:
|
||||
vx=1; for (vc=0;vc<16;vc++) { Cores[core].Voices[vc].WetR=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( WetR, 0, 16 );
|
||||
Cores[core].Regs.VMIXER = (Cores[core].Regs.VMIXER & 0xFFFF0000) | value;
|
||||
return;
|
||||
|
||||
case (REG_S_VMIXER + 2):
|
||||
vx=1; for (vc=16;vc<24;vc++) { Cores[core].Voices[vc].WetR=(s8)((value & vx)/vx); vx<<=1; }
|
||||
vx_SetSomeBits( WetR, 16, 24 );
|
||||
Cores[core].Regs.VMIXER = (Cores[core].Regs.VMIXER & 0xFFFF) | (value << 16);
|
||||
return;
|
||||
|
||||
case REG_P_MMIX:
|
||||
vx=value;
|
||||
if (core == 0) vx&=0xFF0;
|
||||
Cores[core].ExtWetR=(vx & 0x001);
|
||||
Cores[core].ExtWetL=(vx & 0x002)>>1;
|
||||
Cores[core].ExtDryR=(vx & 0x004)>>2;
|
||||
Cores[core].ExtDryL=(vx & 0x008)>>3;
|
||||
Cores[core].InpWetR=(vx & 0x010)>>4;
|
||||
Cores[core].InpWetL=(vx & 0x020)>>5;
|
||||
Cores[core].InpDryR=(vx & 0x040)>>6;
|
||||
Cores[core].InpDryL=(vx & 0x080)>>7;
|
||||
Cores[core].SndWetR=(vx & 0x100)>>8;
|
||||
Cores[core].SndWetL=(vx & 0x200)>>9;
|
||||
Cores[core].SndDryR=(vx & 0x400)>>10;
|
||||
Cores[core].SndDryL=(vx & 0x800)>>11;
|
||||
Cores[core].ExtWetR = (vx & 0x001) ? -1 : 0;
|
||||
Cores[core].ExtWetL = (vx & 0x002) ? -1 : 0;
|
||||
Cores[core].ExtDryR = (vx & 0x004) ? -1 : 0;
|
||||
Cores[core].ExtDryL = (vx & 0x008) ? -1 : 0;
|
||||
Cores[core].InpWetR = (vx & 0x010) ? -1 : 0;
|
||||
Cores[core].InpWetL = (vx & 0x020) ? -1 : 0;
|
||||
Cores[core].InpDryR = (vx & 0x040) ? -1 : 0;
|
||||
Cores[core].InpDryL = (vx & 0x080) ? -1 : 0;
|
||||
Cores[core].SndWetR = (vx & 0x100) ? -1 : 0;
|
||||
Cores[core].SndWetL = (vx & 0x200) ? -1 : 0;
|
||||
Cores[core].SndDryR = (vx & 0x400) ? -1 : 0;
|
||||
Cores[core].SndDryL = (vx & 0x800) ? -1 : 0;
|
||||
Cores[core].Regs.MMIX = value;
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue