mirror of https://github.com/PCSX2/pcsx2.git
[SAVEVERSION+] SPU: Revork reverb buffer logic
This commit is contained in:
parent
5c6f72ac57
commit
2a3ba03226
|
@ -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. ;)
|
// 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;
|
StereoOut32 TW;
|
||||||
|
|
||||||
// Mix Input, Voice, and External data:
|
// Mix Input, Voice, and External data:
|
||||||
|
|
|
@ -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, 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),
|
PVCA(0, 18), PVCA(0, 19), PVCA(0, 20), PVCA(0, 21), PVCA(0, 22), PVCA(0, 23),
|
||||||
|
|
||||||
PCORE(0, ExtEffectsStartA) + 1,
|
PCORE(0, EffectsStartA) + 1,
|
||||||
PCORE(0, ExtEffectsStartA),
|
PCORE(0, EffectsStartA),
|
||||||
|
|
||||||
PREVB_REG(0, APF1_SIZE),
|
PREVB_REG(0, APF1_SIZE),
|
||||||
PREVB_REG(0, APF2_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_L_DST),
|
||||||
PREVB_REG(0, APF2_R_DST),
|
PREVB_REG(0, APF2_R_DST),
|
||||||
|
|
||||||
PCORE(0, ExtEffectsEndA) + 1,
|
PCORE(0, EffectsEndA) + 1,
|
||||||
PCORE(0, ExtEffectsEndA),
|
PCORE(0, EffectsEndA),
|
||||||
|
|
||||||
PCORE(0, Regs.ENDX),
|
PCORE(0, Regs.ENDX),
|
||||||
PCORE(0, Regs.ENDX) + 1,
|
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, 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),
|
PVCA(1, 18), PVCA(1, 19), PVCA(1, 20), PVCA(1, 21), PVCA(1, 22), PVCA(1, 23),
|
||||||
|
|
||||||
PCORE(1, ExtEffectsStartA) + 1,
|
PCORE(1, EffectsStartA) + 1,
|
||||||
PCORE(1, ExtEffectsStartA),
|
PCORE(1, EffectsStartA),
|
||||||
|
|
||||||
PREVB_REG(1, APF1_SIZE),
|
PREVB_REG(1, APF1_SIZE),
|
||||||
PREVB_REG(1, APF2_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_L_DST),
|
||||||
PREVB_REG(1, APF2_R_DST),
|
PREVB_REG(1, APF2_R_DST),
|
||||||
|
|
||||||
PCORE(1, ExtEffectsEndA) + 1,
|
PCORE(1, EffectsEndA) + 1,
|
||||||
PCORE(1, ExtEffectsEndA),
|
PCORE(1, EffectsEndA),
|
||||||
|
|
||||||
PCORE(1, Regs.ENDX),
|
PCORE(1, Regs.ENDX),
|
||||||
PCORE(1, Regs.ENDX) + 1,
|
PCORE(1, Regs.ENDX) + 1,
|
||||||
|
|
|
@ -17,38 +17,42 @@
|
||||||
#include "Global.h"
|
#include "Global.h"
|
||||||
#include <array>
|
#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
|
Console.WriteLn(" IN_COEF_L, IN_COEF_R 0x%08x, 0x%08x", Revb.IN_COEF_L, Revb.IN_COEF_R);
|
||||||
// effects buffer addresses.
|
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)
|
Console.WriteLn(" COMB1_VOL 0x%08x", Revb.COMB1_VOL);
|
||||||
{
|
Console.WriteLn(" COMB2_VOL 0x%08x", Revb.COMB2_VOL);
|
||||||
pos -= EffectsEndA + 1;
|
Console.WriteLn(" COMB3_VOL 0x%08x", Revb.COMB3_VOL);
|
||||||
pos += EffectsStartA;
|
Console.WriteLn(" COMB4_VOL 0x%08x", Revb.COMB4_VOL);
|
||||||
|
|
||||||
|
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("----------------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pos >= EffectsStartA && pos <= EffectsEndA);
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
static constexpr u32 NUM_TAPS = 39;
|
||||||
// 39 tap filter, the 0's could be optimized out
|
// 39 tap filter, the 0's could be optimized out
|
||||||
static constexpr std::array<s32, NUM_TAPS> filter_coefs = {
|
static constexpr std::array<s32, NUM_TAPS> filter_coefs = {
|
||||||
|
@ -112,7 +116,6 @@ s32 __forceinline V_Core::ReverbDownsample(bool right)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
|
StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
|
||||||
{
|
{
|
||||||
s32 ls = 0, rs = 0;
|
s32 ls = 0, rs = 0;
|
||||||
|
@ -124,7 +127,6 @@ StereoOut32 __forceinline V_Core::ReverbUpsample(bool phase)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
for (u32 i = 0; i < (NUM_TAPS >> 1) + 1; i++)
|
for (u32 i = 0; i < (NUM_TAPS >> 1) + 1; i++)
|
||||||
{
|
{
|
||||||
ls += RevbUpBuf[0][(((RevbSampleBufPos - NUM_TAPS) >> 1) + i) & 63] * filter_coefs[i * 2];
|
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 >>= 14;
|
||||||
rs = std::clamp<s32>(rs, INT16_MIN, INT16_MAX);
|
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)
|
StereoOut32 V_Core::DoReverb(const StereoOut32& Input)
|
||||||
{
|
{
|
||||||
if (EffectsBufferSize <= 0)
|
if (EffectsStartA >= EffectsEndA)
|
||||||
{
|
{
|
||||||
return StereoOut32::Empty;
|
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.
|
// 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_src = RevbGetIndexer(R ? Revb.SAME_R_SRC : Revb.SAME_L_SRC);
|
||||||
const u32 same_dst = RevbGetIndexer(R ? RevBuffers.SAME_R_DST : RevBuffers.SAME_L_DST);
|
const u32 same_dst = RevbGetIndexer(R ? Revb.SAME_R_DST : Revb.SAME_L_DST);
|
||||||
const u32 same_prv = RevbGetIndexer(R ? RevBuffers.SAME_R_PRV : RevBuffers.SAME_L_PRV);
|
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_src = RevbGetIndexer(R ? Revb.DIFF_L_SRC : Revb.DIFF_R_SRC);
|
||||||
const u32 diff_dst = RevbGetIndexer(R ? RevBuffers.DIFF_R_DST : RevBuffers.DIFF_L_DST);
|
const u32 diff_dst = RevbGetIndexer(R ? Revb.DIFF_R_DST : Revb.DIFF_L_DST);
|
||||||
const u32 diff_prv = RevbGetIndexer(R ? RevBuffers.DIFF_R_PRV : RevBuffers.DIFF_L_PRV);
|
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 comb1_src = RevbGetIndexer(R ? Revb.COMB1_R_SRC : Revb.COMB1_L_SRC);
|
||||||
const u32 comb2_src = RevbGetIndexer(R ? RevBuffers.COMB2_R_SRC : RevBuffers.COMB2_L_SRC);
|
const u32 comb2_src = RevbGetIndexer(R ? Revb.COMB2_R_SRC : Revb.COMB2_L_SRC);
|
||||||
const u32 comb3_src = RevbGetIndexer(R ? RevBuffers.COMB3_R_SRC : RevBuffers.COMB3_L_SRC);
|
const u32 comb3_src = RevbGetIndexer(R ? Revb.COMB3_R_SRC : Revb.COMB3_L_SRC);
|
||||||
const u32 comb4_src = RevbGetIndexer(R ? RevBuffers.COMB4_R_SRC : RevBuffers.COMB4_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_src = RevbGetIndexer(R ? (Revb.APF1_R_DST - Revb.APF1_SIZE) : (Revb.APF1_L_DST - Revb.APF1_SIZE));
|
||||||
const u32 apf1_dst = RevbGetIndexer(R ? RevBuffers.APF1_R_DST : RevBuffers.APF1_L_DST);
|
const u32 apf1_dst = RevbGetIndexer(R ? Revb.APF1_R_DST : Revb.APF1_L_DST);
|
||||||
const u32 apf2_src = RevbGetIndexer(R ? RevBuffers.APF2_R_SRC : RevBuffers.APF2_L_SRC);
|
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 ? RevBuffers.APF2_R_DST : RevBuffers.APF2_L_DST);
|
const u32 apf2_dst = RevbGetIndexer(R ? Revb.APF2_R_DST : Revb.APF2_L_DST);
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Optimized IRQ Testing !
|
// Optimized IRQ Testing !
|
||||||
|
|
|
@ -279,44 +279,6 @@ struct V_Reverb
|
||||||
u32 APF2_R_DST;
|
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
|
struct V_SPDIF
|
||||||
{
|
{
|
||||||
u16 Out;
|
u16 Out;
|
||||||
|
@ -425,22 +387,12 @@ struct V_Core
|
||||||
u32 InputDataProgress;
|
u32 InputDataProgress;
|
||||||
|
|
||||||
V_Reverb Revb; // Reverb Registers
|
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 RevbDownBuf[2][64]; // Downsample buffer for reverb, one for each channel
|
||||||
s32 RevbUpBuf[2][64]; // Upsample buffer for reverb, one for each channel
|
s32 RevbUpBuf[2][64]; // Upsample buffer for reverb, one for each channel
|
||||||
u32 RevbSampleBufPos;
|
u32 RevbSampleBufPos;
|
||||||
u32 EffectsStartA;
|
u32 EffectsStartA;
|
||||||
u32 EffectsEndA;
|
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
|
V_CoreRegs Regs; // Registers
|
||||||
|
|
||||||
|
@ -490,8 +442,6 @@ struct V_Core
|
||||||
void UpdateEffectsBufferSize();
|
void UpdateEffectsBufferSize();
|
||||||
void AnalyzeReverbPreset();
|
void AnalyzeReverbPreset();
|
||||||
|
|
||||||
s32 EffectsBufferIndexer(s32 offset) const;
|
|
||||||
|
|
||||||
void WriteRegPS1(u32 mem, u16 value);
|
void WriteRegPS1(u32 mem, u16 value);
|
||||||
u16 ReadRegPS1(u32 mem);
|
u16 ReadRegPS1(u32 mem);
|
||||||
|
|
||||||
|
@ -500,7 +450,6 @@ struct V_Core
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
StereoOut32 Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext);
|
StereoOut32 Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, const StereoOut32& Ext);
|
||||||
void Reverb_AdvanceBuffer();
|
|
||||||
StereoOut32 DoReverb(const StereoOut32& Input);
|
StereoOut32 DoReverb(const StereoOut32& Input);
|
||||||
s32 RevbGetIndexer(s32 offset);
|
s32 RevbGetIndexer(s32 offset);
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,6 @@ void V_Core::Init(int index)
|
||||||
InputPosWrite = 0x100;
|
InputPosWrite = 0x100;
|
||||||
InputDataProgress = 0;
|
InputDataProgress = 0;
|
||||||
InputDataTransferred = 0;
|
InputDataTransferred = 0;
|
||||||
ReverbX = 0;
|
|
||||||
LastEffect.Left = 0;
|
LastEffect.Left = 0;
|
||||||
LastEffect.Right = 0;
|
LastEffect.Right = 0;
|
||||||
CoreEnabled = 0;
|
CoreEnabled = 0;
|
||||||
|
@ -182,8 +181,6 @@ void V_Core::Init(int index)
|
||||||
Regs.VMIXER = 0xFFFFFF;
|
Regs.VMIXER = 0xFFFFFF;
|
||||||
EffectsStartA = c ? 0xFFFF8 : 0xEFFF8;
|
EffectsStartA = c ? 0xFFFF8 : 0xEFFF8;
|
||||||
EffectsEndA = c ? 0xFFFFF : 0xEFFFF;
|
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.
|
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.
|
// 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.STATX = 0x80;
|
||||||
Regs.ENDX = 0xffffff; // PS2 confirmed
|
Regs.ENDX = 0xffffff; // PS2 confirmed
|
||||||
|
|
||||||
RevBuffers.NeedsUpdated = true;
|
|
||||||
RevbSampleBufPos = 0;
|
RevbSampleBufPos = 0;
|
||||||
memset(RevbDownBuf, 0, sizeof(RevbDownBuf));
|
memset(RevbDownBuf, 0, sizeof(RevbDownBuf));
|
||||||
memset(RevbUpBuf, 0, sizeof(RevbUpBuf));
|
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()
|
void V_Voice::Start()
|
||||||
|
@ -776,12 +670,7 @@ void V_Core::WriteRegPS1(u32 mem, u16 value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1da2: // Reverb work area start
|
case 0x1da2: // Reverb work area start
|
||||||
{
|
|
||||||
EffectsStartA = map_spu1to2(value);
|
EffectsStartA = map_spu1to2(value);
|
||||||
//EffectsEndA = 0xFFFFF; // fixed EndA in psx mode
|
|
||||||
Cores[0].RevBuffers.NeedsUpdated = true;
|
|
||||||
ReverbX = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1da4:
|
case 0x1da4:
|
||||||
|
@ -1285,7 +1174,7 @@ static void RegWrite_Core(u16 value)
|
||||||
{
|
{
|
||||||
bool irqe = thiscore.IRQEnable;
|
bool irqe = thiscore.IRQEnable;
|
||||||
int bit0 = thiscore.AttrBit0;
|
int bit0 = thiscore.AttrBit0;
|
||||||
bool fxenable = thiscore.FxEnable;
|
bool oldFXenable = thiscore.FxEnable;
|
||||||
u8 oldDmaMode = thiscore.DmaMode;
|
u8 oldDmaMode = thiscore.DmaMode;
|
||||||
|
|
||||||
thiscore.AttrBit0 = (value >> 0) & 0x01; //1 bit
|
thiscore.AttrBit0 = (value >> 0) & 0x01; //1 bit
|
||||||
|
@ -1300,12 +1189,10 @@ static void RegWrite_Core(u16 value)
|
||||||
// no clue
|
// no clue
|
||||||
thiscore.Regs.ATTR = value & 0xffff;
|
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;
|
if (SPU2::MsgToConsole())
|
||||||
thiscore.EffectsEndA = thiscore.ExtEffectsEndA;
|
thiscore.AnalyzeReverbPreset();
|
||||||
thiscore.ReverbX = 0;
|
|
||||||
thiscore.RevBuffers.NeedsUpdated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!thiscore.DmaMode && !(thiscore.Regs.STATX & 0x400))
|
if (!thiscore.DmaMode && !(thiscore.Regs.STATX & 0x400))
|
||||||
|
@ -1464,48 +1351,6 @@ static void RegWrite_Core(u16 value)
|
||||||
thiscore.Regs.ENDX &= 0xffff;
|
thiscore.Regs.ENDX &= 0xffff;
|
||||||
break;
|
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:
|
case REG_S_ADMAS:
|
||||||
if (SPU2::MsgToConsole())
|
if (SPU2::MsgToConsole())
|
||||||
{
|
{
|
||||||
|
@ -1523,12 +1368,6 @@ static void RegWrite_Core(u16 value)
|
||||||
Cores[1].FxEnable = 0;
|
Cores[1].FxEnable = 0;
|
||||||
Cores[1].EffectsStartA = 0x7FFF8; // park core1 effect area in inaccessible mem
|
Cores[1].EffectsStartA = 0x7FFF8; // park core1 effect area in inaccessible mem
|
||||||
Cores[1].EffectsEndA = 0x7FFFF;
|
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)
|
for (uint v = 0; v < 24; ++v)
|
||||||
{
|
{
|
||||||
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||||
|
|
|
@ -37,7 +37,7 @@ enum class FreezeAction
|
||||||
// [SAVEVERSION+]
|
// [SAVEVERSION+]
|
||||||
// This informs the auto updater that the users savestates will be invalidated.
|
// 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
|
// the freezing data between submodules and core
|
||||||
|
|
Loading…
Reference in New Issue