SPU2-X: Reverb compatibility improvements (fixes Ys6).

* EEA / ESA writes are ignored when Effects are enabled.
 * When effects are disabled, reverb does not process IRQs or produce sound.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3326 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-06-27 13:11:38 +00:00
parent 7dbbaf1c04
commit af40a22ee8
4 changed files with 62 additions and 47 deletions

View File

@ -34,13 +34,10 @@ namespace soundtouch
#include <assert.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cstdarg>
#include <cmath>
#include <ctime>
#include <stdexcept>
#include <string>
#include <algorithm>
// This will be brought in later anyways, but if we bring it in now, it'll avoid
// warnings about redefining __LINUX__.

View File

@ -667,23 +667,33 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
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:
TW.Left = Input.Left & WetGate.InpL;
@ -693,7 +703,6 @@ StereoOut32 V_Core::Mix( const VoiceMixSet& inVoices, const StereoOut32& Input,
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 );

View File

@ -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;

View File

@ -930,10 +930,12 @@ static void __fastcall RegWrite_Core( u16 value )
case REG_C_ATTR:
{
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
{
// When we have exact cycle update info from the Pcsx2 IOP unit, then use
@ -960,10 +962,13 @@ static void __fastcall RegWrite_Core( u16 value )
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 =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;}
if (!thiscore.FxEnable)
{
SetHiWord( thiscore.EffectsStartA, value );
thiscore.RevBuffers.NeedsUpdated = true;
thiscore.ReverbX = 0;
}
break;
case (REG_A_ESA + 2):
//if (thiscore.FxEnable){printf("!! ESA\n"); return;}
if (!thiscore.FxEnable)
{
SetLoWord( thiscore.EffectsStartA, value );
thiscore.RevBuffers.NeedsUpdated = true;
thiscore.ReverbX = 0;
}
break;
case REG_A_EEA:
//if (thiscore.FxEnable){printf("!! EEA\n"); return;}
if (!thiscore.FxEnable)
{
thiscore.EffectsEndA = ((u32)value<<16) | 0xFFFF;
thiscore.RevBuffers.NeedsUpdated = true;
thiscore.ReverbX = 0;
}
break;
case REG_S_ADMAS: