[SAVEVERSION+] SPU: Revork reverb buffer logic

This commit is contained in:
Ziemas 2023-09-10 04:42:08 +02:00 committed by refractionpcsx2
parent 5c6f72ac57
commit 2a3ba03226
6 changed files with 70 additions and 278 deletions

View File

@ -576,14 +576,6 @@ StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, c
//
// On the other hand, updating the buffer is cheap and easy, so might as well. ;)
Reverb_AdvanceBuffer(); // Updates the reverb work area as well, if needed.
// ToDo:
// Bad EndA causes memory corruption. Bad for us, unknown on PS2!
// According to no$psx, effects always run but don't always write back, so the FxEnable check may be wrong
if (!FxEnable || EffectsEndA >= 0x100000)
return TD;
StereoOut32 TW;
// Mix Input, Voice, and External data:

View File

@ -100,8 +100,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PVCA(0, 12), PVCA(0, 13), PVCA(0, 14), PVCA(0, 15), PVCA(0, 16), PVCA(0, 17),
PVCA(0, 18), PVCA(0, 19), PVCA(0, 20), PVCA(0, 21), PVCA(0, 22), PVCA(0, 23),
PCORE(0, ExtEffectsStartA) + 1,
PCORE(0, ExtEffectsStartA),
PCORE(0, EffectsStartA) + 1,
PCORE(0, EffectsStartA),
PREVB_REG(0, APF1_SIZE),
PREVB_REG(0, APF2_SIZE),
@ -126,8 +126,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PREVB_REG(0, APF2_L_DST),
PREVB_REG(0, APF2_R_DST),
PCORE(0, ExtEffectsEndA) + 1,
PCORE(0, ExtEffectsEndA),
PCORE(0, EffectsEndA) + 1,
PCORE(0, EffectsEndA),
PCORE(0, Regs.ENDX),
PCORE(0, Regs.ENDX) + 1,
@ -203,8 +203,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PVCA(1, 12), PVCA(1, 13), PVCA(1, 14), PVCA(1, 15), PVCA(1, 16), PVCA(1, 17),
PVCA(1, 18), PVCA(1, 19), PVCA(1, 20), PVCA(1, 21), PVCA(1, 22), PVCA(1, 23),
PCORE(1, ExtEffectsStartA) + 1,
PCORE(1, ExtEffectsStartA),
PCORE(1, EffectsStartA) + 1,
PCORE(1, EffectsStartA),
PREVB_REG(1, APF1_SIZE),
PREVB_REG(1, APF2_SIZE),
@ -229,8 +229,8 @@ static std::array<u16*, 0x401> ComputeRegTable()
PREVB_REG(1, APF2_L_DST),
PREVB_REG(1, APF2_R_DST),
PCORE(1, ExtEffectsEndA) + 1,
PCORE(1, ExtEffectsEndA),
PCORE(1, EffectsEndA) + 1,
PCORE(1, EffectsEndA),
PCORE(1, Regs.ENDX),
PCORE(1, Regs.ENDX) + 1,

View File

@ -17,38 +17,42 @@
#include "Global.h"
#include <array>
__forceinline s32 V_Core::RevbGetIndexer(s32 offset)
void V_Core::AnalyzeReverbPreset()
{
u32 pos = ReverbX + offset;
Console.WriteLn("Reverb Parameter Update for Core %d:", Index);
Console.WriteLn("----------------------------------------------------------");
// Fast and simple single step wrapping, made possible by the preparation of the
// effects buffer addresses.
Console.WriteLn(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x", Revb.IN_COEF_L, Revb.IN_COEF_R);
Console.WriteLn(" APF1_SIZE, APF2_SIZE 0x%08x, 0x%08x", Revb.APF1_SIZE, Revb.APF2_SIZE);
Console.WriteLn(" APF1_VOL, APF2_VOL 0x%08x, 0x%08x", Revb.APF1_VOL, Revb.APF2_VOL);
if (pos > EffectsEndA)
{
pos -= EffectsEndA + 1;
pos += EffectsStartA;
}
Console.WriteLn(" COMB1_VOL 0x%08x", Revb.COMB1_VOL);
Console.WriteLn(" COMB2_VOL 0x%08x", Revb.COMB2_VOL);
Console.WriteLn(" COMB3_VOL 0x%08x", Revb.COMB3_VOL);
Console.WriteLn(" COMB4_VOL 0x%08x", Revb.COMB4_VOL);
assert(pos >= EffectsStartA && pos <= EffectsEndA);
return pos;
Console.WriteLn(" COMB1_L_SRC, COMB1_R_SRC 0x%08x, 0x%08x", Revb.COMB1_L_SRC, Revb.COMB1_R_SRC);
Console.WriteLn(" COMB2_L_SRC, COMB2_R_SRC 0x%08x, 0x%08x", Revb.COMB2_L_SRC, Revb.COMB2_R_SRC);
Console.WriteLn(" COMB3_L_SRC, COMB3_R_SRC 0x%08x, 0x%08x", Revb.COMB3_L_SRC, Revb.COMB3_R_SRC);
Console.WriteLn(" COMB4_L_SRC, COMB4_R_SRC 0x%08x, 0x%08x", Revb.COMB4_L_SRC, Revb.COMB4_R_SRC);
Console.WriteLn(" SAME_L_SRC, SAME_R_SRC 0x%08x, 0x%08x", Revb.SAME_L_SRC, Revb.SAME_R_SRC);
Console.WriteLn(" DIFF_L_SRC, DIFF_R_SRC 0x%08x, 0x%08x", Revb.DIFF_L_SRC, Revb.DIFF_R_SRC);
Console.WriteLn(" SAME_L_DST, SAME_R_DST 0x%08x, 0x%08x", Revb.SAME_L_DST, Revb.SAME_R_DST);
Console.WriteLn(" DIFF_L_DST, DIFF_R_DST 0x%08x, 0x%08x", Revb.DIFF_L_DST, Revb.DIFF_R_DST);
Console.WriteLn(" IIR_VOL, WALL_VOL 0x%08x, 0x%08x", Revb.IIR_VOL, Revb.WALL_VOL);
Console.WriteLn(" APF1_L_DST 0x%08x", Revb.APF1_L_DST);
Console.WriteLn(" APF1_R_DST 0x%08x", Revb.APF1_R_DST);
Console.WriteLn(" APF2_L_DST 0x%08x", Revb.APF2_L_DST);
Console.WriteLn(" APF2_R_DST 0x%08x", Revb.APF2_R_DST);
Console.WriteLn(" EffectStartA 0x%x", EffectsStartA & 0x3f'ffff);
Console.WriteLn(" EffectsEndA 0x%x", EffectsEndA & 0x3f'ffff);
Console.WriteLn("----------------------------------------------------------");
}
void V_Core::Reverb_AdvanceBuffer()
{
if (RevBuffers.NeedsUpdated)
UpdateEffectsBufferSize();
if ((Cycles & 1) && (EffectsBufferSize > 0))
{
ReverbX += 1;
if (ReverbX >= (u32)EffectsBufferSize)
ReverbX = 0;
}
}
static constexpr u32 NUM_TAPS = 39;
// 39 tap filter, the 0's could be optimized out
static constexpr std::array<s32, NUM_TAPS> filter_coefs = {
@ -112,7 +116,6 @@ s32 __forceinline V_Core::ReverbDownsample(bool right)
return out;
}
StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
{
s32 ls = 0, rs = 0;
@ -124,7 +127,6 @@ StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
}
else
{
for (u32 i = 0; i < (NUM_TAPS >> 1) + 1; i++)
{
ls += RevbUpBuf[0][(((RevbSampleBufPos - NUM_TAPS) >> 1) + i) & 63] * filter_coefs[i * 2];
@ -140,14 +142,24 @@ StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
rs >>= 14;
rs = std::clamp<s32>(rs, INT16_MIN, INT16_MAX);
return StereoOut32(ls, rs);
return {ls, rs};
}
/////////////////////////////////////////////////////////////////////////////////////////
__forceinline s32 V_Core::RevbGetIndexer(s32 offset)
{
u32 start = EffectsStartA & 0x3f'ffff;
u32 end = (EffectsEndA & 0x3f'ffff) | 0xffff;
u32 x = ((Cycles >> 1) + offset) % ((end - start) + 1);
x += start;
return x & 0xf'ffff;
}
StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
{
if (EffectsBufferSize <= 0)
if (EffectsStartA >= EffectsEndA)
{
return StereoOut32::Empty;
}
@ -159,23 +171,23 @@ StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
// Calculate the read/write addresses we'll be needing for this session of reverb.
const u32 same_src = RevbGetIndexer(R ? RevBuffers.SAME_R_SRC : RevBuffers.SAME_L_SRC);
const u32 same_dst = RevbGetIndexer(R ? RevBuffers.SAME_R_DST : RevBuffers.SAME_L_DST);
const u32 same_prv = RevbGetIndexer(R ? RevBuffers.SAME_R_PRV : RevBuffers.SAME_L_PRV);
const u32 same_src = RevbGetIndexer(R ? Revb.SAME_R_SRC : Revb.SAME_L_SRC);
const u32 same_dst = RevbGetIndexer(R ? Revb.SAME_R_DST : Revb.SAME_L_DST);
const u32 same_prv = RevbGetIndexer(R ? Revb.SAME_R_DST - 1 : Revb.SAME_L_DST - 1);
const u32 diff_src = RevbGetIndexer(R ? RevBuffers.DIFF_L_SRC : RevBuffers.DIFF_R_SRC);
const u32 diff_dst = RevbGetIndexer(R ? RevBuffers.DIFF_R_DST : RevBuffers.DIFF_L_DST);
const u32 diff_prv = RevbGetIndexer(R ? RevBuffers.DIFF_R_PRV : RevBuffers.DIFF_L_PRV);
const u32 diff_src = RevbGetIndexer(R ? Revb.DIFF_L_SRC : Revb.DIFF_R_SRC);
const u32 diff_dst = RevbGetIndexer(R ? Revb.DIFF_R_DST : Revb.DIFF_L_DST);
const u32 diff_prv = RevbGetIndexer(R ? Revb.DIFF_R_DST - 1 : Revb.DIFF_L_DST - 1);
const u32 comb1_src = RevbGetIndexer(R ? RevBuffers.COMB1_R_SRC : RevBuffers.COMB1_L_SRC);
const u32 comb2_src = RevbGetIndexer(R ? RevBuffers.COMB2_R_SRC : RevBuffers.COMB2_L_SRC);
const u32 comb3_src = RevbGetIndexer(R ? RevBuffers.COMB3_R_SRC : RevBuffers.COMB3_L_SRC);
const u32 comb4_src = RevbGetIndexer(R ? RevBuffers.COMB4_R_SRC : RevBuffers.COMB4_L_SRC);
const u32 comb1_src = RevbGetIndexer(R ? Revb.COMB1_R_SRC : Revb.COMB1_L_SRC);
const u32 comb2_src = RevbGetIndexer(R ? Revb.COMB2_R_SRC : Revb.COMB2_L_SRC);
const u32 comb3_src = RevbGetIndexer(R ? Revb.COMB3_R_SRC : Revb.COMB3_L_SRC);
const u32 comb4_src = RevbGetIndexer(R ? Revb.COMB4_R_SRC : Revb.COMB4_L_SRC);
const u32 apf1_src = RevbGetIndexer(R ? RevBuffers.APF1_R_SRC : RevBuffers.APF1_L_SRC);
const u32 apf1_dst = RevbGetIndexer(R ? RevBuffers.APF1_R_DST : RevBuffers.APF1_L_DST);
const u32 apf2_src = RevbGetIndexer(R ? RevBuffers.APF2_R_SRC : RevBuffers.APF2_L_SRC);
const u32 apf2_dst = RevbGetIndexer(R ? RevBuffers.APF2_R_DST : RevBuffers.APF2_L_DST);
const u32 apf1_src = RevbGetIndexer(R ? (Revb.APF1_R_DST - Revb.APF1_SIZE) : (Revb.APF1_L_DST - Revb.APF1_SIZE));
const u32 apf1_dst = RevbGetIndexer(R ? Revb.APF1_R_DST : Revb.APF1_L_DST);
const u32 apf2_src = RevbGetIndexer(R ? (Revb.APF2_R_DST - Revb.APF2_SIZE) : (Revb.APF2_L_DST - Revb.APF2_SIZE));
const u32 apf2_dst = RevbGetIndexer(R ? Revb.APF2_R_DST : Revb.APF2_L_DST);
// -----------------------------------------
// Optimized IRQ Testing !

View File

@ -279,44 +279,6 @@ struct V_Reverb
u32 APF2_R_DST;
};
struct V_ReverbBuffers
{
s32 SAME_L_SRC;
s32 SAME_R_SRC;
s32 DIFF_R_SRC;
s32 DIFF_L_SRC;
s32 SAME_L_DST;
s32 SAME_R_DST;
s32 DIFF_L_DST;
s32 DIFF_R_DST;
s32 COMB1_L_SRC;
s32 COMB1_R_SRC;
s32 COMB2_L_SRC;
s32 COMB2_R_SRC;
s32 COMB3_L_SRC;
s32 COMB3_R_SRC;
s32 COMB4_L_SRC;
s32 COMB4_R_SRC;
s32 APF1_L_DST;
s32 APF1_R_DST;
s32 APF2_L_DST;
s32 APF2_R_DST;
s32 SAME_L_PRV;
s32 SAME_R_PRV;
s32 DIFF_L_PRV;
s32 DIFF_R_PRV;
s32 APF1_L_SRC;
s32 APF1_R_SRC;
s32 APF2_L_SRC;
s32 APF2_R_SRC;
bool NeedsUpdated;
};
struct V_SPDIF
{
u16 Out;
@ -425,22 +387,12 @@ struct V_Core
u32 InputDataProgress;
V_Reverb Revb; // Reverb Registers
V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped.
s32 RevbDownBuf[2][64]; // Downsample buffer for reverb, one for each channel
s32 RevbUpBuf[2][64]; // Upsample buffer for reverb, one for each channel
u32 RevbSampleBufPos;
u32 EffectsStartA;
u32 EffectsEndA;
u32 ExtEffectsStartA;
u32 ExtEffectsEndA;
u32 ReverbX;
// Current size of and position of the effects buffer. Pre-caculated when the effects start
// or end position registers are written. CAN BE NEGATIVE OR ZERO, in which
// case reverb should be disabled.
s32 EffectsBufferSize;
u32 EffectsBufferStart;
V_CoreRegs Regs; // Registers
@ -490,8 +442,6 @@ struct V_Core
void UpdateEffectsBufferSize();
void AnalyzeReverbPreset();
s32 EffectsBufferIndexer(s32 offset) const;
void WriteRegPS1(u32 mem, u16 value);
u16 ReadRegPS1(u32 mem);
@ -500,7 +450,6 @@ struct V_Core
// --------------------------------------------------------------------------------------
StereoOut32 Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext);
void Reverb_AdvanceBuffer();
StereoOut32 DoReverb(const StereoOut32& Input);
s32 RevbGetIndexer(s32 offset);

View File

@ -141,7 +141,6 @@ void V_Core::Init(int index)
InputPosWrite = 0x100;
InputDataProgress = 0;
InputDataTransferred = 0;
ReverbX = 0;
LastEffect.Left = 0;
LastEffect.Right = 0;
CoreEnabled = 0;
@ -182,8 +181,6 @@ void V_Core::Init(int index)
Regs.VMIXER = 0xFFFFFF;
EffectsStartA = c ? 0xFFFF8 : 0xEFFF8;
EffectsEndA = c ? 0xFFFFF : 0xEFFFF;
ExtEffectsStartA = EffectsStartA;
ExtEffectsEndA = EffectsEndA;
FxEnable = false; // Uninitialized it's 0 for both cores. Resetting libs however may set this to 0 or 1.
// These are real PS2 values, mainly constant apart from a few bits: 0x3220EAA4, 0x40505E9C.
@ -221,112 +218,9 @@ void V_Core::Init(int index)
Regs.STATX = 0x80;
Regs.ENDX = 0xffffff; // PS2 confirmed
RevBuffers.NeedsUpdated = true;
RevbSampleBufPos = 0;
memset(RevbDownBuf, 0, sizeof(RevbDownBuf));
memset(RevbUpBuf, 0, sizeof(RevbUpBuf));
UpdateEffectsBufferSize();
}
void V_Core::AnalyzeReverbPreset()
{
SPU2::ConLog("Reverb Parameter Update for Core %d:\n", Index);
SPU2::ConLog("----------------------------------------------------------\n");
SPU2::ConLog(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x\n", Revb.IN_COEF_L, Revb.IN_COEF_R);
SPU2::ConLog(" APF1_SIZE, APF2_SIZE 0x%08x, 0x%08x\n", Revb.APF1_SIZE, Revb.APF2_SIZE);
SPU2::ConLog(" APF1_VOL, APF2_VOL 0x%08x, 0x%08x\n", Revb.APF1_VOL, Revb.APF2_VOL);
SPU2::ConLog(" COMB1_VOL 0x%08x\n", Revb.COMB1_VOL);
SPU2::ConLog(" COMB2_VOL 0x%08x\n", Revb.COMB2_VOL);
SPU2::ConLog(" COMB3_VOL 0x%08x\n", Revb.COMB3_VOL);
SPU2::ConLog(" COMB4_VOL 0x%08x\n", Revb.COMB4_VOL);
SPU2::ConLog(" COMB1_L_SRC, COMB1_R_SRC 0x%08x, 0x%08x\n", Revb.COMB1_L_SRC, Revb.COMB1_R_SRC);
SPU2::ConLog(" COMB2_L_SRC, COMB2_R_SRC 0x%08x, 0x%08x\n", Revb.COMB2_L_SRC, Revb.COMB2_R_SRC);
SPU2::ConLog(" COMB3_L_SRC, COMB3_R_SRC 0x%08x, 0x%08x\n", Revb.COMB3_L_SRC, Revb.COMB3_R_SRC);
SPU2::ConLog(" COMB4_L_SRC, COMB4_R_SRC 0x%08x, 0x%08x\n", Revb.COMB4_L_SRC, Revb.COMB4_R_SRC);
SPU2::ConLog(" SAME_L_SRC, SAME_R_SRC 0x%08x, 0x%08x\n", Revb.SAME_L_SRC, Revb.SAME_R_SRC);
SPU2::ConLog(" DIFF_L_SRC, DIFF_R_SRC 0x%08x, 0x%08x\n", Revb.DIFF_L_SRC, Revb.DIFF_R_SRC);
SPU2::ConLog(" SAME_L_DST, SAME_R_DST 0x%08x, 0x%08x\n", Revb.SAME_L_DST, Revb.SAME_R_DST);
SPU2::ConLog(" DIFF_L_DST, DIFF_R_DST 0x%08x, 0x%08x\n", Revb.DIFF_L_DST, Revb.DIFF_R_DST);
SPU2::ConLog(" IIR_VOL, WALL_VOL 0x%08x, 0x%08x\n", Revb.IIR_VOL, Revb.WALL_VOL);
SPU2::ConLog(" APF1_L_DST 0x%08x\n", Revb.APF1_L_DST);
SPU2::ConLog(" APF1_R_DST 0x%08x\n", Revb.APF1_R_DST);
SPU2::ConLog(" APF2_L_DST 0x%08x\n", Revb.APF2_L_DST);
SPU2::ConLog(" APF2_R_DST 0x%08x\n", Revb.APF2_R_DST);
SPU2::ConLog(" EffectsBufferSize 0x%x\n", EffectsBufferSize);
SPU2::ConLog("----------------------------------------------------------\n");
}
s32 V_Core::EffectsBufferIndexer(s32 offset) const
{
// Should offsets be multipled by 4 or not? Reverse-engineering of IOP code reveals
// that it *4's all addresses before upping them to the SPU2 -- so our buffers are
// already x4'd. It doesn't really make sense that we should x4 them again, and this
// seems to work. (feedback-free in bios and DDS) --air
// Need to use modulus here, because games can and will drop the buffer size
// without notice, and it leads to offsets several times past the end of the buffer.
if (static_cast<u32>(offset) >= static_cast<u32>(EffectsBufferSize))
return EffectsStartA + (offset % EffectsBufferSize) + (offset < 0 ? EffectsBufferSize : 0);
else
return EffectsStartA + offset;
}
void V_Core::UpdateEffectsBufferSize()
{
const s32 newbufsize = EffectsEndA - EffectsStartA + 1;
RevBuffers.NeedsUpdated = false;
EffectsBufferSize = newbufsize;
EffectsBufferStart = EffectsStartA;
if (EffectsBufferSize <= 0)
return;
// debug: shows reverb parameters in console
if (SPU2::MsgToConsole())
AnalyzeReverbPreset();
// Rebuild buffer indexers.
RevBuffers.COMB1_L_SRC = EffectsBufferIndexer(Revb.COMB1_L_SRC);
RevBuffers.COMB1_R_SRC = EffectsBufferIndexer(Revb.COMB1_R_SRC);
RevBuffers.COMB2_L_SRC = EffectsBufferIndexer(Revb.COMB2_L_SRC);
RevBuffers.COMB2_R_SRC = EffectsBufferIndexer(Revb.COMB2_R_SRC);
RevBuffers.COMB3_L_SRC = EffectsBufferIndexer(Revb.COMB3_L_SRC);
RevBuffers.COMB3_R_SRC = EffectsBufferIndexer(Revb.COMB3_R_SRC);
RevBuffers.COMB4_L_SRC = EffectsBufferIndexer(Revb.COMB4_L_SRC);
RevBuffers.COMB4_R_SRC = EffectsBufferIndexer(Revb.COMB4_R_SRC);
RevBuffers.SAME_L_DST = EffectsBufferIndexer(Revb.SAME_L_DST);
RevBuffers.SAME_R_DST = EffectsBufferIndexer(Revb.SAME_R_DST);
RevBuffers.DIFF_L_DST = EffectsBufferIndexer(Revb.DIFF_L_DST);
RevBuffers.DIFF_R_DST = EffectsBufferIndexer(Revb.DIFF_R_DST);
RevBuffers.SAME_L_SRC = EffectsBufferIndexer(Revb.SAME_L_SRC);
RevBuffers.SAME_R_SRC = EffectsBufferIndexer(Revb.SAME_R_SRC);
RevBuffers.DIFF_L_SRC = EffectsBufferIndexer(Revb.DIFF_L_SRC);
RevBuffers.DIFF_R_SRC = EffectsBufferIndexer(Revb.DIFF_R_SRC);
RevBuffers.APF1_L_DST = EffectsBufferIndexer(Revb.APF1_L_DST);
RevBuffers.APF1_R_DST = EffectsBufferIndexer(Revb.APF1_R_DST);
RevBuffers.APF2_L_DST = EffectsBufferIndexer(Revb.APF2_L_DST);
RevBuffers.APF2_R_DST = EffectsBufferIndexer(Revb.APF2_R_DST);
RevBuffers.SAME_L_PRV = EffectsBufferIndexer(Revb.SAME_L_DST - 1);
RevBuffers.SAME_R_PRV = EffectsBufferIndexer(Revb.SAME_R_DST - 1);
RevBuffers.DIFF_L_PRV = EffectsBufferIndexer(Revb.DIFF_L_DST - 1);
RevBuffers.DIFF_R_PRV = EffectsBufferIndexer(Revb.DIFF_R_DST - 1);
RevBuffers.APF1_L_SRC = EffectsBufferIndexer(Revb.APF1_L_DST - Revb.APF1_SIZE);
RevBuffers.APF1_R_SRC = EffectsBufferIndexer(Revb.APF1_R_DST - Revb.APF1_SIZE);
RevBuffers.APF2_L_SRC = EffectsBufferIndexer(Revb.APF2_L_DST - Revb.APF2_SIZE);
RevBuffers.APF2_R_SRC = EffectsBufferIndexer(Revb.APF2_R_DST - Revb.APF2_SIZE);
}
void V_Voice::Start()
@ -776,12 +670,7 @@ void V_Core::WriteRegPS1(u32 mem, u16 value)
break;
case 0x1da2: // Reverb work area start
{
EffectsStartA = map_spu1to2(value);
//EffectsEndA = 0xFFFFF; // fixed EndA in psx mode
Cores[0].RevBuffers.NeedsUpdated = true;
ReverbX = 0;
}
break;
case 0x1da4:
@ -1285,7 +1174,7 @@ static void RegWrite_Core(u16 value)
{
bool irqe = thiscore.IRQEnable;
int bit0 = thiscore.AttrBit0;
bool fxenable = thiscore.FxEnable;
bool oldFXenable = thiscore.FxEnable;
u8 oldDmaMode = thiscore.DmaMode;
thiscore.AttrBit0 = (value >> 0) & 0x01; //1 bit
@ -1300,12 +1189,10 @@ static void RegWrite_Core(u16 value)
// no clue
thiscore.Regs.ATTR = value & 0xffff;
if (fxenable && !thiscore.FxEnable && (thiscore.EffectsStartA != thiscore.ExtEffectsStartA || thiscore.EffectsEndA != thiscore.ExtEffectsEndA))
if (thiscore.FxEnable && !oldFXenable)
{
thiscore.EffectsStartA = thiscore.ExtEffectsStartA;
thiscore.EffectsEndA = thiscore.ExtEffectsEndA;
thiscore.ReverbX = 0;
thiscore.RevBuffers.NeedsUpdated = true;
if (SPU2::MsgToConsole())
thiscore.AnalyzeReverbPreset();
}
if (!thiscore.DmaMode && !(thiscore.Regs.STATX & 0x400))
@ -1464,48 +1351,6 @@ static void RegWrite_Core(u16 value)
thiscore.Regs.ENDX &= 0xffff;
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.
// NOTE: Above is false by testing but there are references saying this, so for
// now we think that writing is allowed but the internal register doesn't reflect
// the value until effects area writing is disabled.
// * 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:
SetHiWord(thiscore.ExtEffectsStartA, value & 0xF);
if (!thiscore.FxEnable)
{
thiscore.EffectsStartA = thiscore.ExtEffectsStartA;
thiscore.ReverbX = 0;
thiscore.RevBuffers.NeedsUpdated = true;
}
break;
case (REG_A_ESA + 2):
SetLoWord(thiscore.ExtEffectsStartA, value);
if (!thiscore.FxEnable)
{
thiscore.EffectsStartA = thiscore.ExtEffectsStartA;
thiscore.ReverbX = 0;
thiscore.RevBuffers.NeedsUpdated = true;
}
break;
case REG_A_EEA:
thiscore.ExtEffectsEndA = ((u32)(value & 0xF) << 16) | 0xFFFF;
if (!thiscore.FxEnable)
{
thiscore.EffectsEndA = thiscore.ExtEffectsEndA;
thiscore.ReverbX = 0;
thiscore.RevBuffers.NeedsUpdated = true;
}
break;
case REG_S_ADMAS:
if (SPU2::MsgToConsole())
{
@ -1523,12 +1368,6 @@ static void RegWrite_Core(u16 value)
Cores[1].FxEnable = 0;
Cores[1].EffectsStartA = 0x7FFF8; // park core1 effect area in inaccessible mem
Cores[1].EffectsEndA = 0x7FFFF;
Cores[1].ExtEffectsStartA = 0x7FFF8;
Cores[1].ExtEffectsEndA = 0x7FFFF;
Cores[1].ReverbX = 0;
Cores[1].RevBuffers.NeedsUpdated = true;
Cores[0].ReverbX = 0;
Cores[0].RevBuffers.NeedsUpdated = true;
for (uint v = 0; v < 24; ++v)
{
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;

View File

@ -37,7 +37,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.
static const u32 g_SaveVersion = (0x9A41 << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A42 << 16) | 0x0000;
// the freezing data between submodules and core