2009-02-15 05:15:39 +00:00
|
|
|
/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
|
|
|
|
* Developed and maintained by the Pcsx2 Development Team.
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-02-15 05:15:39 +00:00
|
|
|
* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz]
|
|
|
|
*
|
2009-06-21 11:00:53 +00:00
|
|
|
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* SPU2-X is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE. See the GNU Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
|
|
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
|
2009-02-15 05:15:39 +00:00
|
|
|
*/
|
|
|
|
|
2009-06-21 11:00:53 +00:00
|
|
|
#pragma once
|
2009-02-15 05:15:39 +00:00
|
|
|
|
2009-09-29 19:18:50 +00:00
|
|
|
#include "Mixer.h"
|
2016-10-13 14:28:01 +00:00
|
|
|
#include "SndOut.h"
|
2009-09-29 19:18:50 +00:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// SPU2 Memory Indexers
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
#define spu2Rs16(mmem) (*(s16 *)((s8 *)spu2regs + ((mmem)&0x1fff)))
|
|
|
|
#define spu2Ru16(mmem) (*(u16 *)((s8 *)spu2regs + ((mmem)&0x1fff)))
|
2009-09-29 19:18:50 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
extern s16 *GetMemPtr(u32 addr);
|
|
|
|
extern s16 spu2M_Read(u32 addr);
|
|
|
|
extern void spu2M_Write(u32 addr, s16 value);
|
|
|
|
extern void spu2M_Write(u32 addr, u16 value);
|
2009-09-29 19:18:50 +00:00
|
|
|
|
|
|
|
|
2009-02-18 13:36:20 +00:00
|
|
|
struct V_VolumeLR
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
static V_VolumeLR Max;
|
2009-02-18 13:36:20 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
s32 Left;
|
|
|
|
s32 Right;
|
2009-02-18 13:36:20 +00:00
|
|
|
|
2017-01-22 15:06:54 +00:00
|
|
|
V_VolumeLR() = default;
|
2016-10-10 18:35:26 +00:00
|
|
|
V_VolumeLR(s32 both)
|
|
|
|
: Left(both)
|
|
|
|
, Right(both)
|
|
|
|
{
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
void DebugDump(FILE *dump, const char *title);
|
2009-02-18 13:36:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct V_VolumeSlide
|
2009-02-15 05:15:39 +00:00
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
// Holds the "original" value of the volume for this voice, prior to slides.
|
|
|
|
// (ie, the volume as written to the register)
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
s16 Reg_VOL;
|
|
|
|
s32 Value;
|
|
|
|
s8 Increment;
|
|
|
|
s8 Mode;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2009-02-16 20:00:31 +00:00
|
|
|
public:
|
2017-01-22 15:06:54 +00:00
|
|
|
V_VolumeSlide() = default;
|
2016-10-10 18:35:26 +00:00
|
|
|
V_VolumeSlide(s16 regval, s32 fullvol)
|
|
|
|
: Reg_VOL(regval)
|
|
|
|
, Value(fullvol)
|
|
|
|
, Increment(0)
|
|
|
|
, Mode(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Update();
|
2016-10-16 19:39:56 +00:00
|
|
|
void RegSet(u16 src); // used to set the volume from a register source (16 bit signed)
|
2016-10-10 18:35:26 +00:00
|
|
|
void DebugDump(FILE *dump, const char *title, const char *nameLR);
|
2009-02-18 13:36:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct V_VolumeSlideLR
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
static V_VolumeSlideLR Max;
|
2009-02-18 13:36:20 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
V_VolumeSlide Left;
|
|
|
|
V_VolumeSlide Right;
|
2009-02-18 13:36:20 +00:00
|
|
|
|
|
|
|
public:
|
2017-01-22 15:06:54 +00:00
|
|
|
V_VolumeSlideLR() = default;
|
2016-10-10 18:35:26 +00:00
|
|
|
V_VolumeSlideLR(s16 regval, s32 bothval)
|
|
|
|
: Left(regval, bothval)
|
|
|
|
, Right(regval, bothval)
|
|
|
|
{
|
|
|
|
}
|
2009-02-18 13:36:20 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
void Update()
|
|
|
|
{
|
|
|
|
Left.Update();
|
|
|
|
Right.Update();
|
|
|
|
}
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
void DebugDump(FILE *dump, const char *title);
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct V_ADSR
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
u32 reg32;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u16 regADSR1;
|
|
|
|
u16 regADSR2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u32 SustainLevel : 4,
|
|
|
|
DecayRate : 4,
|
|
|
|
AttackRate : 7,
|
2016-10-16 19:39:56 +00:00
|
|
|
AttackMode : 1, // 0 for linear (+lin), 1 for pseudo exponential (+exp)
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
ReleaseRate : 5,
|
2016-10-16 19:39:56 +00:00
|
|
|
ReleaseMode : 1, // 0 for linear (-lin), 1 for exponential (-exp)
|
2016-10-10 18:35:26 +00:00
|
|
|
SustainRate : 7,
|
2016-10-16 19:39:56 +00:00
|
|
|
SustainMode : 3; // 0 = +lin, 1 = -lin, 2 = +exp, 3 = -exp
|
2016-10-10 18:35:26 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
s32 Value; // Ranges from 0 to 0x7fffffff (signed values are clamped to 0) [Reg_ENVX]
|
|
|
|
u8 Phase; // monitors current phase of ADSR envelope
|
|
|
|
bool Releasing; // Ready To Release, triggered by Voice.Stop();
|
2009-02-16 20:00:31 +00:00
|
|
|
|
|
|
|
public:
|
2016-10-10 18:35:26 +00:00
|
|
|
bool Calculate();
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct V_Voice
|
|
|
|
{
|
2016-10-16 19:39:56 +00:00
|
|
|
u32 PlayCycle; // SPU2 cycle where the Playing started
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
V_VolumeSlideLR Volume;
|
|
|
|
|
|
|
|
// Envelope
|
|
|
|
V_ADSR ADSR;
|
|
|
|
// Pitch (also Reg_PITCH)
|
|
|
|
u16 Pitch;
|
|
|
|
// Loop Start address (also Reg_LSAH/L)
|
|
|
|
u32 LoopStartA;
|
|
|
|
// Sound Start address (also Reg_SSAH/L)
|
|
|
|
u32 StartA;
|
|
|
|
// Next Read Data address (also Reg_NAXH/L)
|
|
|
|
u32 NextA;
|
|
|
|
// Voice Decoding State
|
|
|
|
s32 Prev1;
|
|
|
|
s32 Prev2;
|
|
|
|
|
|
|
|
// Pitch Modulated by previous voice
|
|
|
|
bool Modulated;
|
|
|
|
// Source (Wave/Noise)
|
|
|
|
bool Noise;
|
|
|
|
|
|
|
|
s8 LoopMode;
|
|
|
|
s8 LoopFlags;
|
|
|
|
|
|
|
|
// Sample pointer (19:12 bit fixed point)
|
|
|
|
s32 SP;
|
|
|
|
|
|
|
|
// Sample pointer for Cubic Interpolation
|
|
|
|
// Cubic interpolation mixes a sample behind Linear, so that it
|
|
|
|
// can have sample data to either side of the end points from which
|
|
|
|
// to extrapolate. This SP represents that late sample position.
|
|
|
|
s32 SPc;
|
|
|
|
|
|
|
|
// Previous sample values - used for interpolation
|
|
|
|
// Inverted order of these members to match the access order in the
|
|
|
|
// code (might improve cache hits).
|
|
|
|
s32 PV4;
|
|
|
|
s32 PV3;
|
|
|
|
s32 PV2;
|
|
|
|
s32 PV1;
|
|
|
|
|
|
|
|
// Last outputted audio value, used for voice modulation.
|
|
|
|
s32 OutX;
|
2016-10-16 19:39:56 +00:00
|
|
|
s32 NextCrest; // temp value for Crest calculation
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
// SBuffer now points directly to an ADPCM cache entry.
|
|
|
|
s16 *SBuffer;
|
|
|
|
|
|
|
|
// sample position within the current decoded packet.
|
|
|
|
s32 SCurrent;
|
|
|
|
|
|
|
|
// it takes a few ticks for voices to start on the real SPU2?
|
|
|
|
void QueueStart();
|
|
|
|
bool Start();
|
|
|
|
void Stop();
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// ** Begin Debug-only variables section **
|
|
|
|
// Separated from the V_Voice struct to improve cache performance of
|
|
|
|
// the Public Release build.
|
|
|
|
struct V_VoiceDebug
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
s8 FirstBlock;
|
|
|
|
s32 SampleData;
|
|
|
|
s32 PeakX;
|
|
|
|
s32 displayPeak;
|
|
|
|
s32 lastSetStartA;
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct V_CoreDebug
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
V_VoiceDebug Voices[24];
|
|
|
|
// Last Transfer Size
|
|
|
|
u32 lastsize;
|
2011-01-15 23:41:22 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
// draw adma waveform in the visual debugger
|
|
|
|
s32 admaWaveformL[0x100];
|
|
|
|
s32 admaWaveformR[0x100];
|
2011-01-16 02:10:19 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
// Enabled when a dma write starts, disabled when the visual debugger showed it once
|
|
|
|
s32 dmaFlag;
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Debug tracking information - 24 voices and 2 cores.
|
|
|
|
extern V_CoreDebug DebugCores[2];
|
|
|
|
|
|
|
|
struct V_Reverb
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
s16 IN_COEF_L;
|
|
|
|
s16 IN_COEF_R;
|
|
|
|
|
2016-10-21 20:21:04 +00:00
|
|
|
u32 APF1_SIZE;
|
|
|
|
u32 APF2_SIZE;
|
|
|
|
|
|
|
|
s16 APF1_VOL;
|
|
|
|
s16 APF2_VOL;
|
|
|
|
|
|
|
|
u32 SAME_L_SRC;
|
|
|
|
u32 SAME_R_SRC;
|
|
|
|
u32 DIFF_L_SRC;
|
|
|
|
u32 DIFF_R_SRC;
|
|
|
|
u32 SAME_L_DST;
|
|
|
|
u32 SAME_R_DST;
|
|
|
|
u32 DIFF_L_DST;
|
|
|
|
u32 DIFF_R_DST;
|
|
|
|
|
|
|
|
s16 IIR_VOL;
|
|
|
|
s16 WALL_VOL;
|
|
|
|
|
|
|
|
u32 COMB1_L_SRC;
|
|
|
|
u32 COMB1_R_SRC;
|
|
|
|
u32 COMB2_L_SRC;
|
|
|
|
u32 COMB2_R_SRC;
|
|
|
|
u32 COMB3_L_SRC;
|
|
|
|
u32 COMB3_R_SRC;
|
|
|
|
u32 COMB4_L_SRC;
|
|
|
|
u32 COMB4_R_SRC;
|
|
|
|
|
|
|
|
s16 COMB1_VOL;
|
|
|
|
s16 COMB2_VOL;
|
|
|
|
s16 COMB3_VOL;
|
|
|
|
s16 COMB4_VOL;
|
|
|
|
|
|
|
|
u32 APF1_L_DST;
|
|
|
|
u32 APF1_R_DST;
|
|
|
|
u32 APF2_L_DST;
|
|
|
|
u32 APF2_R_DST;
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
2009-02-18 13:36:20 +00:00
|
|
|
struct V_ReverbBuffers
|
|
|
|
{
|
2016-10-21 20:21:04 +00:00
|
|
|
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;
|
2016-10-10 18:35:26 +00:00
|
|
|
|
2016-10-13 14:28:01 +00:00
|
|
|
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;
|
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
bool NeedsUpdated;
|
2009-02-18 13:36:20 +00:00
|
|
|
};
|
|
|
|
|
2009-02-15 05:15:39 +00:00
|
|
|
struct V_SPDIF
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
u16 Out;
|
|
|
|
u16 Info;
|
|
|
|
u16 Unknown1;
|
|
|
|
u16 Mode;
|
|
|
|
u16 Media;
|
|
|
|
u16 Unknown2;
|
|
|
|
u16 Protection;
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct V_CoreRegs
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
u32 PMON;
|
|
|
|
u32 NON;
|
|
|
|
u32 VMIXL;
|
|
|
|
u32 VMIXR;
|
|
|
|
u32 VMIXEL;
|
|
|
|
u32 VMIXER;
|
|
|
|
u32 ENDX;
|
|
|
|
|
|
|
|
u16 MMIX;
|
|
|
|
u16 STATX;
|
|
|
|
u16 ATTR;
|
|
|
|
u16 _1AC;
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
2009-03-04 21:32:48 +00:00
|
|
|
struct V_VoiceGates
|
|
|
|
{
|
2016-10-16 19:39:56 +00:00
|
|
|
s16 DryL; // 'AND Gate' for Direct Output to Left Channel
|
|
|
|
s16 DryR; // 'AND Gate' for Direct Output for Right Channel
|
|
|
|
s16 WetL; // 'AND Gate' for Effect Output for Left Channel
|
|
|
|
s16 WetR; // 'AND Gate' for Effect Output for Right Channel
|
2009-03-04 21:32:48 +00:00
|
|
|
};
|
|
|
|
|
2009-09-29 19:18:50 +00:00
|
|
|
struct V_CoreGates
|
2009-03-04 21:32:48 +00:00
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
u128 v128;
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
2016-10-16 19:39:56 +00:00
|
|
|
s16 InpL; // Sound Data Input to Direct Output (Left)
|
|
|
|
s16 InpR; // Sound Data Input to Direct Output (Right)
|
|
|
|
s16 SndL; // Voice Data to Direct Output (Left)
|
|
|
|
s16 SndR; // Voice Data to Direct Output (Right)
|
|
|
|
s16 ExtL; // External Input to Direct Output (Left)
|
|
|
|
s16 ExtR; // External Input to Direct Output (Right)
|
2016-10-10 18:35:26 +00:00
|
|
|
};
|
|
|
|
};
|
2009-09-29 19:18:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct VoiceMixSet
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
static const VoiceMixSet Empty;
|
|
|
|
StereoOut32 Dry, Wet;
|
|
|
|
|
|
|
|
VoiceMixSet() {}
|
|
|
|
VoiceMixSet(const StereoOut32 &dry, const StereoOut32 &wet)
|
|
|
|
: Dry(dry)
|
|
|
|
, Wet(wet)
|
|
|
|
{
|
|
|
|
}
|
2009-03-04 21:32:48 +00:00
|
|
|
};
|
|
|
|
|
2009-02-15 05:15:39 +00:00
|
|
|
struct V_Core
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
static const uint NumVoices = 24;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
int Index; // Core index identifier.
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
// Voice Gates -- These are SSE-related values, and must always be
|
|
|
|
// first to ensure 16 byte alignment
|
|
|
|
|
|
|
|
V_VoiceGates VoiceGates[NumVoices];
|
|
|
|
V_CoreGates DryGate;
|
|
|
|
V_CoreGates WetGate;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
V_VolumeSlideLR MasterVol; // Master Volume
|
|
|
|
V_VolumeLR ExtVol; // Volume for External Data Input
|
|
|
|
V_VolumeLR InpVol; // Volume for Sound Data Input
|
|
|
|
V_VolumeLR FxVol; // Volume for Output from Effects
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
V_Voice Voices[NumVoices];
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
u32 IRQA; // Interrupt Address
|
|
|
|
u32 TSA; // DMA Transfer Start Address
|
2016-10-10 18:35:26 +00:00
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
bool IRQEnable; // Interrupt Enable
|
|
|
|
bool FxEnable; // Effect Enable
|
|
|
|
bool Mute; // Mute
|
2016-10-10 18:35:26 +00:00
|
|
|
bool AdmaInProgress;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
s8 DMABits; // DMA related?
|
|
|
|
s8 NoiseClk; // Noise Clock
|
|
|
|
u16 AutoDMACtrl; // AutoDMA Status
|
|
|
|
s32 DMAICounter; // DMA Interrupt Counter
|
|
|
|
u32 InputDataLeft; // Input Buffer
|
2016-10-10 18:35:26 +00:00
|
|
|
u32 InputPosRead;
|
|
|
|
u32 InputPosWrite;
|
|
|
|
u32 InputDataProgress;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
V_Reverb Revb; // Reverb Registers
|
|
|
|
V_ReverbBuffers RevBuffers; // buffer pointers for reverb, pre-calculated and pre-clipped.
|
2016-10-10 18:35:26 +00:00
|
|
|
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;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
V_CoreRegs Regs; // Registers
|
2016-10-10 18:35:26 +00:00
|
|
|
|
2016-10-13 14:28:01 +00:00
|
|
|
// Preserves the channel processed last cycle
|
2016-10-10 18:35:26 +00:00
|
|
|
StereoOut32 LastEffect;
|
|
|
|
|
|
|
|
u8 CoreEnabled;
|
|
|
|
|
|
|
|
u8 AttrBit0;
|
|
|
|
u8 DmaMode;
|
|
|
|
|
|
|
|
// new dma only
|
|
|
|
bool DmaStarted;
|
|
|
|
u32 AutoDmaFree;
|
|
|
|
|
|
|
|
// old dma only
|
|
|
|
u16 *DMAPtr;
|
|
|
|
u32 MADR;
|
|
|
|
u32 TADR;
|
|
|
|
|
2016-10-16 19:39:56 +00:00
|
|
|
u32 KeyOn; // not the KON register (though maybe it is)
|
2016-10-10 18:35:26 +00:00
|
|
|
|
|
|
|
// psxmode caches
|
|
|
|
u16 psxSoundDataTransferControl;
|
|
|
|
u16 psxSPUSTAT;
|
|
|
|
|
|
|
|
// HACK -- This is a temp buffer which is (or isn't?) used to circumvent some memory
|
|
|
|
// corruption that originates elsewhere in the plugin. >_< The actual ADMA buffer
|
|
|
|
// is an area mapped to SPU2 main memory.
|
|
|
|
//s16 ADMATempBuffer[0x1000];
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
|
|
// V_Core Methods
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// uninitialized constructor
|
|
|
|
V_Core()
|
|
|
|
: Index(-1)
|
|
|
|
, DMAPtr(NULL)
|
|
|
|
{
|
|
|
|
}
|
2016-10-16 19:39:56 +00:00
|
|
|
V_Core(int idx); // our badass constructor
|
2016-10-10 18:35:26 +00:00
|
|
|
~V_Core() throw();
|
|
|
|
|
|
|
|
void Init(int index);
|
|
|
|
void UpdateEffectsBufferSize();
|
|
|
|
void AnalyzeReverbPreset();
|
|
|
|
|
|
|
|
s32 EffectsBufferIndexer(s32 offset) const;
|
|
|
|
|
|
|
|
void WriteRegPS1(u32 mem, u16 value);
|
|
|
|
u16 ReadRegPS1(u32 mem);
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// Mixer Section
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
StereoOut32 Mix(const VoiceMixSet &inVoices, const StereoOut32 &Input, const StereoOut32 &Ext);
|
|
|
|
void Reverb_AdvanceBuffer();
|
|
|
|
StereoOut32 DoReverb(const StereoOut32 &Input);
|
|
|
|
s32 RevbGetIndexer(s32 offset);
|
|
|
|
|
|
|
|
StereoOut32 ReadInput();
|
|
|
|
StereoOut32 ReadInput_HiFi();
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// DMA Section
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Returns the index of the DMA channel (4 for Core 0, or 7 for Core 1)
|
|
|
|
int GetDmaIndex() const
|
|
|
|
{
|
|
|
|
return (Index == 0) ? 4 : 7;
|
|
|
|
}
|
|
|
|
|
|
|
|
// returns either '4' or '7'
|
|
|
|
char GetDmaIndexChar() const
|
|
|
|
{
|
|
|
|
return 0x30 + GetDmaIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
__forceinline u16 DmaRead()
|
|
|
|
{
|
|
|
|
const u16 ret = (u16)spu2M_Read(TSA);
|
|
|
|
++TSA;
|
|
|
|
TSA &= 0xfffff;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
__forceinline void DmaWrite(u16 value)
|
|
|
|
{
|
|
|
|
spu2M_Write(TSA, value);
|
|
|
|
++TSA;
|
|
|
|
TSA &= 0xfffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LogAutoDMA(FILE *fp);
|
|
|
|
|
|
|
|
s32 NewDmaRead(u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
|
|
|
s32 NewDmaWrite(u32 *data, u32 bytesLeft, u32 *bytesProcessed);
|
|
|
|
void NewDmaInterrupt();
|
|
|
|
|
|
|
|
// old dma only
|
|
|
|
void DoDMAwrite(u16 *pMem, u32 size);
|
|
|
|
void DoDMAread(u16 *pMem, u32 size);
|
|
|
|
|
|
|
|
void AutoDMAReadBuffer(int mode);
|
|
|
|
void StartADMAWrite(u16 *pMem, u32 sz);
|
|
|
|
void PlainDMAWrite(u16 *pMem, u32 sz);
|
2009-02-15 05:15:39 +00:00
|
|
|
};
|
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
extern V_Core Cores[2];
|
|
|
|
extern V_SPDIF Spdif;
|
2009-02-15 05:15:39 +00:00
|
|
|
|
|
|
|
// Output Buffer Writing Position (the same for all data);
|
2016-10-10 18:35:26 +00:00
|
|
|
extern s16 OutPos;
|
2009-02-15 05:15:39 +00:00
|
|
|
// Input Buffer Reading Position (the same for all data);
|
2016-10-10 18:35:26 +00:00
|
|
|
extern s16 InputPos;
|
2009-02-15 05:15:39 +00:00
|
|
|
// SPU Mixing Cycles ("Ticks mixed" counter)
|
2016-10-10 18:35:26 +00:00
|
|
|
extern u32 Cycles;
|
2009-09-29 19:18:50 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
extern s16 *spu2regs;
|
|
|
|
extern s16 *_spu2mem;
|
|
|
|
extern int PlayMode;
|
2009-02-15 05:15:39 +00:00
|
|
|
|
2010-06-25 01:49:26 +00:00
|
|
|
extern void SetIrqCall(int core);
|
2009-09-29 19:18:50 +00:00
|
|
|
extern void StartVoices(int core, u32 value);
|
|
|
|
extern void StopVoices(int core, u32 value);
|
|
|
|
extern void InitADSR();
|
2016-10-10 18:35:26 +00:00
|
|
|
extern void CalculateADSR(V_Voice &vc);
|
2009-09-29 19:18:50 +00:00
|
|
|
extern void UpdateSpdifMode();
|
2009-02-20 21:48:59 +00:00
|
|
|
|
2009-09-29 19:18:50 +00:00
|
|
|
namespace Savestate
|
2009-02-20 21:48:59 +00:00
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
struct DataBlock;
|
2009-09-29 19:18:50 +00:00
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
extern s32 __fastcall FreezeIt(DataBlock &spud);
|
|
|
|
extern s32 __fastcall ThawIt(DataBlock &spud);
|
|
|
|
extern s32 __fastcall SizeIt();
|
2009-02-20 21:48:59 +00:00
|
|
|
}
|
2009-09-29 19:18:50 +00:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// ADPCM Decoder Cache
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// The SPU2 has a dynamic memory range which is used for several internal operations, such as
|
|
|
|
// registers, CORE 1/2 mixing, AutoDMAs, and some other fancy stuff. We exclude this range
|
|
|
|
// from the cache here:
|
|
|
|
static const s32 SPU2_DYN_MEMLINE = 0x2800;
|
|
|
|
|
|
|
|
// 8 short words per encoded PCM block. (as stored in SPU2 ram)
|
|
|
|
static const int pcm_WordsPerBlock = 8;
|
|
|
|
|
|
|
|
// number of cachable ADPCM blocks (any blocks above the SPU2_DYN_MEMLINE)
|
|
|
|
static const int pcm_BlockCount = 0x100000 / pcm_WordsPerBlock;
|
|
|
|
|
|
|
|
// 28 samples per decoded PCM block (as stored in our cache)
|
|
|
|
static const int pcm_DecodedSamplesPerBlock = 28;
|
|
|
|
|
|
|
|
struct PcmCacheEntry
|
|
|
|
{
|
2016-10-10 18:35:26 +00:00
|
|
|
bool Validated;
|
|
|
|
s16 Sampledata[pcm_DecodedSamplesPerBlock];
|
2009-09-29 19:18:50 +00:00
|
|
|
};
|
|
|
|
|
2016-10-10 18:35:26 +00:00
|
|
|
extern PcmCacheEntry *pcm_cache_data;
|