mirror of https://github.com/PCSX2/pcsx2.git
SPU2: Rewrite volume slides [SAVEVERSION+]
This commit is contained in:
parent
7bf8f6115f
commit
07d4a65a45
|
@ -19,34 +19,8 @@
|
|||
|
||||
#include "common/Assertions.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
static constexpr s32 ADSR_MAX_VOL = 0x7fff;
|
||||
|
||||
static const int InvExpOffsets[] = {0, 4, 6, 8, 9, 10, 11, 12};
|
||||
|
||||
using PSXRateTable = std::array<u32, 160>;
|
||||
|
||||
static constexpr PSXRateTable ComputePSXRates()
|
||||
{
|
||||
PSXRateTable rates = {};
|
||||
for (int i = 0; i < (32 + 128); i++)
|
||||
{
|
||||
const int shift = (i - 32) >> 2;
|
||||
s64 rate = (i & 3) + 4;
|
||||
if (shift < 0)
|
||||
rate >>= -shift;
|
||||
else
|
||||
rate <<= shift;
|
||||
|
||||
// Maximum rate is 0x4000.
|
||||
rates[i] = (int)std::min(rate, (s64)0x40000000LL);
|
||||
}
|
||||
return rates;
|
||||
}
|
||||
|
||||
static constexpr const PSXRateTable PsxRates = ComputePSXRates();
|
||||
|
||||
void V_ADSR::UpdateCache()
|
||||
{
|
||||
CachedPhases[PHASE_ATTACK].Decr = false;
|
||||
|
@ -152,15 +126,44 @@ void V_VolumeSlide::RegSet(u16 src)
|
|||
Reg_VOL = src;
|
||||
if (!Enable)
|
||||
{
|
||||
// Shift and sign extend;
|
||||
Value = (s16)(src << 1);
|
||||
Value = SignExtend16(src << 1);
|
||||
}
|
||||
}
|
||||
|
||||
void V_VolumeSlide::Update()
|
||||
{
|
||||
if (!Enable)
|
||||
{
|
||||
return;
|
||||
|
||||
s32 step_size = 7 - Step;
|
||||
|
||||
if (Decr)
|
||||
{
|
||||
step_size = ~step_size;
|
||||
}
|
||||
|
||||
u32 counter_inc = 0x8000 >> std::max(0, Shift - 11);
|
||||
s16 level_inc = (s16)(step_size << std::max(0, 11 - Shift));
|
||||
|
||||
if (Exp)
|
||||
{
|
||||
if (!Decr && Value > 0x6000)
|
||||
{
|
||||
counter_inc >>= 2;
|
||||
}
|
||||
|
||||
if (Decr)
|
||||
{
|
||||
level_inc = (s16)((level_inc * Value) >> 15);
|
||||
}
|
||||
}
|
||||
|
||||
counter_inc = std::max<u32>(1, counter_inc);
|
||||
Counter += counter_inc;
|
||||
|
||||
if (Counter >= 0x8000)
|
||||
{
|
||||
Counter = 0;
|
||||
Value = std::clamp<s32>(Value + level_inc, 0, INT16_MAX);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,10 +82,8 @@ void SPU2::ConLog(const char* fmt, ...)
|
|||
void V_VolumeSlide::DebugDump(FILE* dump, const char* title, const char* nameLR)
|
||||
{
|
||||
fprintf(dump, "%s Volume for %s Channel:\t%x\n"
|
||||
" - Value: %x\n"
|
||||
" - Mode: %x\n"
|
||||
" - Increment: %x\n",
|
||||
title, nameLR, Reg_VOL, Value, Mode, Increment);
|
||||
" - Value: %x\n",
|
||||
title, nameLR, Reg_VOL, Value);
|
||||
}
|
||||
|
||||
void V_VolumeSlideLR::DebugDump(FILE* dump, const char* title)
|
||||
|
|
|
@ -302,8 +302,8 @@ static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_Vo
|
|||
static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_VolumeSlideLR& volume)
|
||||
{
|
||||
return StereoOut32(
|
||||
ApplyVolume(data.Left, volume.Left.Value),
|
||||
ApplyVolume(data.Right, volume.Right.Value));
|
||||
ApplyVolume16(data.Left, volume.Left.Value),
|
||||
ApplyVolume16(data.Right, volume.Right.Value));
|
||||
}
|
||||
|
||||
static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
|
||||
|
@ -684,8 +684,8 @@ __forceinline
|
|||
}
|
||||
else
|
||||
{
|
||||
Out.Left = MulShr32(Out.Left, Cores[1].MasterVol.Left.Value);
|
||||
Out.Right = MulShr32(Out.Right, Cores[1].MasterVol.Right.Value);
|
||||
Out.Left = ApplyVolume16(Out.Left, Cores[1].MasterVol.Left.Value);
|
||||
Out.Right = ApplyVolume16(Out.Right, Cores[1].MasterVol.Right.Value);
|
||||
}
|
||||
|
||||
// Final Clamp!
|
||||
|
|
|
@ -28,18 +28,17 @@
|
|||
PCORE(c, Voices[v].p)
|
||||
|
||||
#define PVC(c, v) \
|
||||
PVCP(c, v, Volume.Left.Reg_VOL) \
|
||||
, \
|
||||
PVCP(c, v, Volume.Left.Reg_VOL), \
|
||||
PVCP(c, v, Volume.Right.Reg_VOL), \
|
||||
PVCP(c, v, Pitch), \
|
||||
PVCP(c, v, ADSR.regADSR1), \
|
||||
PVCP(c, v, ADSR.regADSR2), \
|
||||
PVCP(c, v, ADSR.Value), \
|
||||
PVCP(c, v, Volume.Left.Value) + 1, \
|
||||
PVCP(c, v, Volume.Right.Value) + 1
|
||||
PVCP(c, v, Volume.Left.Value), \
|
||||
PVCP(c, v, Volume.Right.Value)
|
||||
|
||||
#define PVCA(c, v) \
|
||||
PVCP(c, v, StartA) + 1, \
|
||||
PVCP(c, v, StartA) + 1, \
|
||||
PVCP(c, v, StartA), \
|
||||
PVCP(c, v, LoopStartA) + 1, \
|
||||
PVCP(c, v, LoopStartA), \
|
||||
|
|
|
@ -38,6 +38,10 @@ extern s16 spu2M_Read(u32 addr);
|
|||
extern void spu2M_Write(u32 addr, s16 value);
|
||||
extern void spu2M_Write(u32 addr, u16 value);
|
||||
|
||||
static inline s16 SignExtend16(u16 v)
|
||||
{
|
||||
return (s16)v;
|
||||
}
|
||||
|
||||
struct V_VolumeLR
|
||||
{
|
||||
|
@ -61,23 +65,34 @@ struct V_VolumeSlide
|
|||
// Holds the "original" value of the volume for this voice, prior to slides.
|
||||
// (ie, the volume as written to the register)
|
||||
|
||||
s16 Reg_VOL;
|
||||
union
|
||||
{
|
||||
u16 Reg_VOL;
|
||||
struct
|
||||
{
|
||||
u16 Step : 2;
|
||||
u16 Shift : 5;
|
||||
u16 : 5;
|
||||
u16 Phase : 1;
|
||||
u16 Decr : 1;
|
||||
u16 Exp : 1;
|
||||
u16 Enable : 1;
|
||||
};
|
||||
};
|
||||
|
||||
u32 Counter;
|
||||
s32 Value;
|
||||
s8 Increment;
|
||||
s8 Mode;
|
||||
|
||||
public:
|
||||
V_VolumeSlide() = default;
|
||||
V_VolumeSlide(s16 regval, s32 fullvol)
|
||||
: Reg_VOL(regval)
|
||||
, Value(fullvol)
|
||||
, Increment(0)
|
||||
, Mode(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Update();
|
||||
void RegSet(u16 src); // used to set the volume from a register source (16 bit signed)
|
||||
void RegSet(u16 src); // used to set the volume from a register source
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
void DebugDump(FILE* dump, const char* title, const char* nameLR);
|
||||
|
|
|
@ -104,7 +104,7 @@ __forceinline void spu2M_Write(u32 addr, u16 value)
|
|||
}
|
||||
|
||||
V_VolumeLR V_VolumeLR::Max(0x7FFFFFFF);
|
||||
V_VolumeSlideLR V_VolumeSlideLR::Max(0x3FFF, 0x7FFFFFFF);
|
||||
V_VolumeSlideLR V_VolumeSlideLR::Max(0x3FFF, 0x7FFF);
|
||||
|
||||
V_Core::V_Core(int coreidx)
|
||||
: Index(coreidx)
|
||||
|
@ -485,11 +485,6 @@ static s32 GetVol32(u16 src)
|
|||
return ((static_cast<s32>(src)) << 16) | ((src << 1) & 0xffff);
|
||||
}
|
||||
|
||||
void V_VolumeSlide::RegSet(u16 src)
|
||||
{
|
||||
Value = GetVol32(src);
|
||||
}
|
||||
|
||||
static u32 map_spu1to2(u32 addr)
|
||||
{
|
||||
return addr * 4 + (addr >= 0x200 ? 0xc0000 : 0);
|
||||
|
@ -519,26 +514,7 @@ void V_Core::WriteRegPS1(u32 mem, u16 value)
|
|||
case 0x2: //VOLR (Volume R)
|
||||
{
|
||||
V_VolumeSlide& thisvol = vval == 0 ? Voices[voice].Volume.Left : Voices[voice].Volume.Right;
|
||||
thisvol.Reg_VOL = value;
|
||||
|
||||
if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp
|
||||
{
|
||||
thisvol.Mode = (value & 0xF000) >> 12;
|
||||
thisvol.Increment = (value & 0x7F);
|
||||
// We're not sure slides work 100%
|
||||
if (SPU2::MsgToConsole())
|
||||
SPU2::ConLog("* SPU2: Voice uses Slides in Mode = %x, Increment = %x\n", thisvol.Mode, thisvol.Increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Constant Volume mode (no slides or envelopes)
|
||||
// Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as
|
||||
// the "sign" bit, so a simple bitwise extension will do the trick:
|
||||
|
||||
thisvol.RegSet(value << 1);
|
||||
thisvol.Mode = 0;
|
||||
thisvol.Increment = 0;
|
||||
}
|
||||
thisvol.RegSet(value);
|
||||
//ConLog("voice %x VOL%c write: %x\n", voice, vval == 0 ? 'L' : 'R', value);
|
||||
break;
|
||||
}
|
||||
|
@ -581,12 +557,10 @@ void V_Core::WriteRegPS1(u32 mem, u16 value)
|
|||
switch (reg)
|
||||
{
|
||||
case 0x1d80: // Mainvolume left
|
||||
MasterVol.Left.Mode = 0;
|
||||
MasterVol.Left.RegSet(value);
|
||||
break;
|
||||
|
||||
case 0x1d82: // Mainvolume right
|
||||
MasterVol.Right.Mode = 0;
|
||||
MasterVol.Right.RegSet(value);
|
||||
break;
|
||||
|
||||
|
@ -895,10 +869,10 @@ u16 V_Core::ReadRegPS1(u32 mem)
|
|||
switch (reg)
|
||||
{
|
||||
case 0x1d80:
|
||||
value = MasterVol.Left.Value >> 16;
|
||||
value = MasterVol.Left.Value;
|
||||
break;
|
||||
case 0x1d82:
|
||||
value = MasterVol.Right.Value >> 16;
|
||||
value = MasterVol.Right.Value;
|
||||
break;
|
||||
case 0x1d84:
|
||||
value = FxVol.Left >> 16;
|
||||
|
@ -1007,26 +981,7 @@ static void RegWrite_VoiceParams(u16 value)
|
|||
case 1: //VOLR (Volume R)
|
||||
{
|
||||
V_VolumeSlide& thisvol = (param == 0) ? thisvoice.Volume.Left : thisvoice.Volume.Right;
|
||||
thisvol.Reg_VOL = value;
|
||||
|
||||
if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp
|
||||
{
|
||||
thisvol.Mode = (value & 0xF000) >> 12;
|
||||
thisvol.Increment = (value & 0x7F);
|
||||
// We're not sure slides work 100%
|
||||
if (SPU2::MsgToConsole())
|
||||
SPU2::ConLog("* SPU2: Voice uses Slides in Mode = %x, Increment = %x\n", thisvol.Mode, thisvol.Increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Constant Volume mode (no slides or envelopes)
|
||||
// Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as
|
||||
// the "sign" bit, so a simple bitwise extension will do the trick:
|
||||
|
||||
thisvol.RegSet(value << 1);
|
||||
thisvol.Mode = 0;
|
||||
thisvol.Increment = 0;
|
||||
}
|
||||
thisvol.RegSet(value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1429,24 +1384,7 @@ static void RegWrite_CoreExt(u16 value)
|
|||
case REG_P_MVOLR:
|
||||
{
|
||||
V_VolumeSlide& thisvol = (addr == REG_P_MVOLL) ? thiscore.MasterVol.Left : thiscore.MasterVol.Right;
|
||||
|
||||
if (value & 0x8000) // +Lin/-Lin/+Exp/-Exp
|
||||
{
|
||||
thisvol.Mode = (value & 0xF000) >> 12;
|
||||
thisvol.Increment = (value & 0x7F);
|
||||
//printf("slides Mode = %x, Increment = %x\n",thisvol.Mode,thisvol.Increment);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Constant Volume mode (no slides or envelopes)
|
||||
// Volumes range from 0x3fff to 0x7fff, with 0x4000 serving as
|
||||
// the "sign" bit, so a simple bitwise extension will do the trick:
|
||||
|
||||
thisvol.Value = GetVol32(value << 1);
|
||||
thisvol.Mode = 0;
|
||||
thisvol.Increment = 0;
|
||||
}
|
||||
thisvol.Reg_VOL = value;
|
||||
thisvol.RegSet(value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1835,7 +1773,7 @@ void StartVoices(int core, u32 value)
|
|||
(Cores[core].VoiceGates[vc].WetL) ? "+" : "-", (Cores[core].VoiceGates[vc].WetR) ? "+" : "-",
|
||||
*(u16*)GetMemPtr(thisvc.StartA),
|
||||
thisvc.Pitch,
|
||||
thisvc.Volume.Left.Value >> 16, thisvc.Volume.Right.Value >> 16,
|
||||
thisvc.Volume.Left.Value, thisvc.Volume.Right.Value,
|
||||
thisvc.ADSR.regADSR1, thisvc.ADSR.regADSR2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = (0x9A44 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A45 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
|
Loading…
Reference in New Issue