diff --git a/plugins/spu2-x/src/Global.h b/plugins/spu2-x/src/Global.h index d7d4d8b3ba..c1f42586a4 100644 --- a/plugins/spu2-x/src/Global.h +++ b/plugins/spu2-x/src/Global.h @@ -34,13 +34,10 @@ namespace soundtouch #include #include #include -#include #include #include #include #include -#include -#include // This will be brought in later anyways, but if we bring it in now, it'll avoid // warnings about redefining __LINUX__. diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index a575efff17..2f1c7c8c18 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -627,10 +627,10 @@ static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx ) // Note: Results from MixVoice are ranged at 16 bits. - dest.Dry.Left += VVal.Left & thiscore.VoiceGates[voiceidx].DryL; - dest.Dry.Right += VVal.Right & thiscore.VoiceGates[voiceidx].DryR; - dest.Wet.Left += VVal.Left & thiscore.VoiceGates[voiceidx].WetL; - dest.Wet.Right += VVal.Right & thiscore.VoiceGates[voiceidx].WetR; + dest.Dry.Left += VVal.Left & thiscore.VoiceGates[voiceidx].DryL; + dest.Dry.Right += VVal.Right & thiscore.VoiceGates[voiceidx].DryR; + dest.Wet.Left += VVal.Left & thiscore.VoiceGates[voiceidx].WetL; + dest.Wet.Right += VVal.Right & thiscore.VoiceGates[voiceidx].WetR; } } @@ -655,45 +655,54 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input, // Mix in the Input data StereoOut32 TD( - Input.Left & DryGate.InpL, - Input.Right & DryGate.InpR + Input.Left & DryGate.InpL, + Input.Right & DryGate.InpR ); // Mix in the Voice data - TD.Left += Voices.Dry.Left & DryGate.SndL; - TD.Right += Voices.Dry.Right & 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 & DryGate.ExtL; - TD.Right += Ext.Right & DryGate.ExtR; + TD.Left += Ext.Left & DryGate.ExtL; + TD.Right += Ext.Right & DryGate.ExtR; + // User-level Effects disabling. Nice speedup but breaks games that depend on + // reverb IRQs (very few -- if you find one name it here!). if( EffectsDisabled ) return TD; // ---------------------------------------------------------------------------- // Reverberation Effects Processing // ---------------------------------------------------------------------------- - // The FxEnable bit is, like many other things in the SPU2, only a partial systems - // toogle. It disables the *inputs* to the reverb, such that the reverb is fed silence, - // but it does not actually disable reverb effects processing. In practical terms - // this means that when a game turns off reverb, an existing reverb effect should trail - // off naturally, instead of being chopped off dead silent. + // SPU2 has an FxEnable bit which seems to disable all reverb processing *and* + // output, but does *not* disable the advancing buffers. IRQs are not triggered + // and reverb is rendered silent. + // + // Technically we should advance the buffers even when fx are disabled. However + // there are two things that make this very unlikely to matter: + // + // 1. Any SPU2 app wanting to avoid noise or pops needs to clear the reverb buffers + // when adjusting settings anyway; so the read/write positions in the reverb + // buffer after FxEnabled is set back to 1 doesn't really matter. + // + // 2. Writes to ESA (and possibly EEA) reset the buffer pointers to 0. + // + // On the other hand, updating the buffer is cheap and easy, so might as well. ;) Reverb_AdvanceBuffer(); + if (!FxEnable) return TD; StereoOut32 TW; - if( FxEnable ) - { - // Mix Input, Voice, and External data: + // Mix Input, Voice, and External data: - TW.Left = Input.Left & WetGate.InpL; - TW.Right = Input.Right & WetGate.InpR; + TW.Left = Input.Left & WetGate.InpL; + TW.Right = Input.Right & WetGate.InpR; - 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; - } + 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( Index, CoreSrc_PreReverb, TW ); diff --git a/plugins/spu2-x/src/Timestretcher.cpp b/plugins/spu2-x/src/Timestretcher.cpp index 6f0b613a26..b36770a229 100644 --- a/plugins/spu2-x/src/Timestretcher.cpp +++ b/plugins/spu2-x/src/Timestretcher.cpp @@ -18,7 +18,6 @@ #include "Global.h" #include "soundtouch/SoundTouch.h" - static soundtouch::SoundTouch* pSoundTouch = NULL; static int ts_stats_stretchblocks = 0; static int ts_stats_normalblocks = 0; diff --git a/plugins/spu2-x/src/spu2sys.cpp b/plugins/spu2-x/src/spu2sys.cpp index fa739419fb..3053fcb229 100644 --- a/plugins/spu2-x/src/spu2sys.cpp +++ b/plugins/spu2-x/src/spu2sys.cpp @@ -930,9 +930,11 @@ static void __fastcall RegWrite_Core( u16 value ) case REG_C_ATTR: { - bool irqe = thiscore.IRQEnable; - int bit0 = thiscore.AttrBit0; - u8 oldDmaMode = thiscore.DmaMode; + bool fxenable = thiscore.FxEnable; + bool irqe = thiscore.IRQEnable; + int bit0 = thiscore.AttrBit0; + u8 oldDmaMode = thiscore.DmaMode; + if( ((value>>15)&1) && (!thiscore.CoreEnabled) && (thiscore.InitDelay==0) ) // on init/reset { @@ -959,11 +961,14 @@ static void __fastcall RegWrite_Core( u16 value ) thiscore.IRQEnable =(value>> 6) & 0x01; //1 bit thiscore.FxEnable =(value>> 7) & 0x01; //1 bit thiscore.NoiseClk =(value>> 8) & 0x3f; //6 bits - //thiscore.Mute =(value>>14) & 0x01; //1 bit - thiscore.Mute=0; + //thiscore.Mute =(value>>14) & 0x01; //1 bit + thiscore.Mute =0; thiscore.CoreEnabled=(value>>15) & 0x01; //1 bit thiscore.Regs.ATTR =value&0x7fff; + if (!fxenable && thiscore.FxEnable) + thiscore.RevBuffers.NeedsUpdated = true; + if(oldDmaMode != thiscore.DmaMode) { // FIXME... maybe: if this mode was cleared in the middle of a DMA, should we interrupt it? @@ -1111,31 +1116,36 @@ static void __fastcall RegWrite_Core( u16 value ) break; // Reverb Start and End Address Writes! + // * These regs are only writable when Effects are *DISABLED* (FxEnable is false). + // Writes while enabled should be ignored. // * Yes, these are backwards from all the volumes -- the hiword comes FIRST (wtf!) // * End position is a hiword only! Loword is always ffff. // * The Reverb buffer position resets on writes to StartA. It probably resets // on writes to End too. Docs don't say, but they're for PSX, which couldn't // change the end address anyway. - + // case REG_A_ESA: - //if (thiscore.FxEnable){printf("!! ESA\n"); return;} - SetHiWord( thiscore.EffectsStartA, value ); - thiscore.RevBuffers.NeedsUpdated = true; - thiscore.ReverbX = 0; + if (!thiscore.FxEnable) + { + SetHiWord( thiscore.EffectsStartA, value ); + thiscore.ReverbX = 0; + } break; case (REG_A_ESA + 2): - //if (thiscore.FxEnable){printf("!! ESA\n"); return;} - SetLoWord( thiscore.EffectsStartA, value ); - thiscore.RevBuffers.NeedsUpdated = true; - thiscore.ReverbX = 0; + if (!thiscore.FxEnable) + { + SetLoWord( thiscore.EffectsStartA, value ); + thiscore.ReverbX = 0; + } break; case REG_A_EEA: - //if (thiscore.FxEnable){printf("!! EEA\n"); return;} - thiscore.EffectsEndA = ((u32)value<<16) | 0xFFFF; - thiscore.RevBuffers.NeedsUpdated = true; - thiscore.ReverbX = 0; + if (!thiscore.FxEnable) + { + thiscore.EffectsEndA = ((u32)value<<16) | 0xFFFF; + thiscore.ReverbX = 0; + } break; case REG_S_ADMAS: