mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66cd51bcd5 | ||
|
|
ed7ebb77ca | ||
|
|
10fc9a790d | ||
|
|
c42330eebf | ||
|
|
680e05fead | ||
|
|
1f7b98bf6b | ||
|
|
c3a20d421e | ||
|
|
f03ab6f728 | ||
|
|
e9275d78b5 |
@@ -25,7 +25,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.53
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=11.1.5.3
|
||||
NVENC=13.0.19.0
|
||||
SDL=SDL3-3.4.0
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
@@ -57,7 +57,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
082cbf5f429e0d80820f68dc2b507a94d4cc1b4e70817b119bbb8ec6a69584b8 $SDL.tar.gz
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
2974b91062197e0527dffa3aadd8fe3bfa6681ae45f5ff9181bc0ca6479abd59 nv-codec-headers-$NVENC.tar.gz
|
||||
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
|
||||
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -123,6 +123,11 @@ void BreakpointDialog::accept()
|
||||
bp->cond.expression = expr;
|
||||
bp->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
bp->hasCond = false;
|
||||
bp->cond = {};
|
||||
}
|
||||
}
|
||||
if (auto* mc = std::get_if<MemCheck>(&m_bp_mc))
|
||||
{
|
||||
@@ -159,6 +164,11 @@ void BreakpointDialog::accept()
|
||||
mc->cond.expression = expr;
|
||||
mc->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
mc->hasCond = false;
|
||||
mc->cond = {};
|
||||
}
|
||||
|
||||
int condition = 0;
|
||||
if (m_ui.chkRead->isChecked())
|
||||
|
||||
@@ -2223,7 +2223,7 @@ Leaderboard Position: {1} of {2}</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/BIOSSettingsWidget.ui" line="138"/>
|
||||
<source>Options and Patches</source>
|
||||
<source>Fast Boot Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@@ -2339,18 +2339,18 @@ Leaderboard Position: {1} of {2}</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="103"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="132"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="137"/>
|
||||
<source>Invalid Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="119"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="155"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="160"/>
|
||||
<source>Invalid Condition</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="139"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="144"/>
|
||||
<source>Invalid Size</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -6804,11 +6804,6 @@ The URL was: %1</source>
|
||||
<source>BIOS Selection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9512"/>
|
||||
<source>Options and Patches</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9513"/>
|
||||
<source>Skips the intro screen, and bypasses region checks.</source>
|
||||
@@ -9942,6 +9937,11 @@ Do you want to shutdown anyway and IRREVERSIBLY CORRUPT YOUR MEMORY CARD?</sourc
|
||||
<source>Shows the number of dumped and loaded texture replacements on the OSD.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9512"/>
|
||||
<source>Fast Boot Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9604"/>
|
||||
<source>Bilinear Dirty Upscale</source>
|
||||
@@ -11893,7 +11893,7 @@ This action cannot be undone.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="5055"/>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="5052"/>
|
||||
<source>Spin GPU During Readbacks is enabled, but calibrated timestamps are unavailable. This might be really slow.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
@@ -244,7 +244,7 @@ const char* GSDevice::RenderAPIToString(RenderAPI api)
|
||||
|
||||
bool GSDevice::GetRequestedExclusiveFullscreenMode(u32* width, u32* height, float* refresh_rate)
|
||||
{
|
||||
const std::string mode = Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", "");
|
||||
const std::string mode = Host::GetStringSettingValue("EmuCore/GS", "FullscreenMode", "");
|
||||
if (!mode.empty())
|
||||
{
|
||||
const std::string_view mode_view = mode;
|
||||
|
||||
@@ -938,6 +938,7 @@ void GSDevice12::SetVSyncMode(GSVSyncMode mode, bool allow_present_throttle)
|
||||
|
||||
if (GetSwapChainBufferCount() != old_buffer_count)
|
||||
{
|
||||
ExecuteCommandList(true);
|
||||
DestroySwapChain();
|
||||
if (!CreateSwapChain())
|
||||
pxFailRel("Failed to recreate swap chain after vsync change.");
|
||||
|
||||
@@ -200,7 +200,6 @@ void SPU2::DoFullDump()
|
||||
fprintf(dump, " - Sound Start Address: %x\n", Cores[c].Voices[v].StartA);
|
||||
fprintf(dump, " - Next Data Address: %x\n", Cores[c].Voices[v].NextA);
|
||||
fprintf(dump, " - Play Status: %s\n", (Cores[c].Voices[v].ADSR.Phase > 0) ? "Playing" : "Not Playing");
|
||||
fprintf(dump, " - Block Sample: %d\n", Cores[c].Voices[v].SCurrent);
|
||||
}
|
||||
fprintf(dump, "#### END OF DUMP.\n\n");
|
||||
}
|
||||
|
||||
@@ -89,55 +89,13 @@ int g_counter_cache_ignores = 0;
|
||||
#define XAFLAG_LOOP (1ul << 1)
|
||||
#define XAFLAG_LOOP_START (1ul << 2)
|
||||
|
||||
static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
static __forceinline void GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
if ((vc.SCurrent & 3) == 0)
|
||||
if (vc.SBuffer == nullptr)
|
||||
{
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
}
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
vc.SCurrent = 0;
|
||||
|
||||
// We'll need the loop flags and buffer pointers regardless of cache status:
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
|
||||
const int cacheIdx = vc.NextA / pcm_WordsPerBlock;
|
||||
const int cacheIdx = (vc.NextA & 0xFFFF8) / pcm_WordsPerBlock;
|
||||
PcmCacheEntry& cacheLine = pcm_cache_data[cacheIdx];
|
||||
vc.SBuffer = cacheLine.Sampledata;
|
||||
|
||||
@@ -172,46 +130,18 @@ static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
g_counter_cache_misses++;
|
||||
}
|
||||
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
XA_decode_block(vc.SBuffer, memptr, vc.Prev1, vc.Prev2);
|
||||
}
|
||||
}
|
||||
|
||||
return vc.SBuffer[vc.SCurrent++];
|
||||
}
|
||||
|
||||
static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
// Get the sample index for NextA, we have to subtract 1 to ignore the loop header
|
||||
int sampleIdx = ((vc.NextA % pcm_WordsPerBlock) - 1) * 4;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
vc.DecodeFifo[(vc.DecPosWrite + i) % 32] = vc.SBuffer[sampleIdx + i];
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
vc.LoopFlags = *GetMemPtr(vc.NextA & 0xFFFF8) >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
|
||||
vc.SCurrent = 0;
|
||||
}
|
||||
|
||||
vc.SP -= 0x1000 * (4 - (vc.SCurrent & 3));
|
||||
vc.SCurrent += 4 - (vc.SCurrent & 3);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -237,6 +167,69 @@ static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_Vo
|
||||
ApplyVolume(data.Right, volume.Right.Value));
|
||||
}
|
||||
|
||||
static __forceinline void UpdateBlockHeader(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void DecodeSamples(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// Update the block header on every audio frame
|
||||
UpdateBlockHeader(thiscore, voiceidx);
|
||||
|
||||
// When a voice is started at 0 pitch, NAX quickly advances to SSA + 5
|
||||
// So that would mean the decode buffer holds around 12 samples
|
||||
if (((int)(vc.DecPosWrite - vc.DecPosRead)) > 12) {
|
||||
// Sufficient data buffered
|
||||
return;
|
||||
}
|
||||
|
||||
if (vc.ADSR.Phase > V_ADSR::PHASE_STOPPED)
|
||||
{
|
||||
GetNextDataBuffered(thiscore, voiceidx);
|
||||
}
|
||||
|
||||
vc.DecPosWrite += 4;
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
if ((vc.NextA & 7) == 0)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
vc.SBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(Cores[coreidx].Voices[voiceidx]);
|
||||
@@ -278,33 +271,27 @@ static __forceinline void CalculateADSR(V_Core& thiscore, uint voiceidx)
|
||||
pxAssume(vc.ADSR.Value >= 0); // ADSR should never be negative...
|
||||
}
|
||||
|
||||
__forceinline static s32 GaussianInterpolate(s32 pv4, s32 pv3, s32 pv2, s32 pv1, s32 i)
|
||||
static __forceinline void ConsumeSamples(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
s32 out = 0;
|
||||
out = (interpTable[i][0] * pv4) >> 15;
|
||||
out += (interpTable[i][1] * pv3) >> 15;
|
||||
out += (interpTable[i][2] * pv2) >> 15;
|
||||
out += (interpTable[i][3] * pv1) >> 15;
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
return out;
|
||||
int consumed = vc.SP >> 12;
|
||||
vc.SP &= 0xfff;
|
||||
vc.DecPosRead += consumed;
|
||||
}
|
||||
|
||||
static __forceinline s32 GetVoiceValues(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
while (vc.SP >= 0)
|
||||
{
|
||||
vc.PV4 = vc.PV3;
|
||||
vc.PV3 = vc.PV2;
|
||||
vc.PV2 = vc.PV1;
|
||||
vc.PV1 = GetNextDataBuffered(thiscore, voiceidx);
|
||||
vc.SP -= 0x1000;
|
||||
}
|
||||
int phase = (vc.SP & 0x0ff0) >> 4;
|
||||
s32 out = 0;
|
||||
out += (interpTable[phase][0] * vc.DecodeFifo[(vc.DecPosRead + 0) % 32]) >> 15;
|
||||
out += (interpTable[phase][1] * vc.DecodeFifo[(vc.DecPosRead + 1) % 32]) >> 15;
|
||||
out += (interpTable[phase][2] * vc.DecodeFifo[(vc.DecPosRead + 2) % 32]) >> 15;
|
||||
out += (interpTable[phase][3] * vc.DecodeFifo[(vc.DecPosRead + 3) % 32]) >> 15;
|
||||
|
||||
const s32 mu = vc.SP + 0x1000;
|
||||
|
||||
return GaussianInterpolate(vc.PV4, vc.PV3, vc.PV2, vc.PV1, (mu & 0x0ff0) >> 4);
|
||||
return out;
|
||||
}
|
||||
|
||||
// This is Dr. Hell's noise algorithm as implemented in pcsxr
|
||||
@@ -382,21 +369,13 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// If this assertion fails, it mans SCurrent is being corrupted somewhere, or is not initialized
|
||||
// properly. Invalid values in SCurrent will cause errant IRQs and corrupted audio.
|
||||
pxAssertMsg((vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28");
|
||||
|
||||
// Most games don't use much volume slide effects. So only call the UpdateVolume
|
||||
// methods when needed by checking the flag outside the method here...
|
||||
// (Note: Ys 6 : Ark of Nephistm uses these effects)
|
||||
|
||||
vc.Volume.Update();
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
DecodeSamples(coreidx, voiceidx);
|
||||
|
||||
StereoOut32 voiceOut(0, 0);
|
||||
s32 Value = 0;
|
||||
@@ -419,11 +398,14 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
|
||||
voiceOut = ApplyVolume(StereoOut32(Value, Value), vc.Volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (vc.SP >= 0)
|
||||
GetNextDataDummy(thiscore, voiceidx); // Dummy is enough
|
||||
}
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
|
||||
ConsumeSamples(thiscore, voiceidx);
|
||||
|
||||
// Write-back of raw voice data (post ADSR applied)
|
||||
if (voiceidx == 1)
|
||||
@@ -533,7 +515,8 @@ StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, c
|
||||
return TD + ApplyVolume(RV, FxVol);
|
||||
}
|
||||
|
||||
static StereoOut32 DCFilter(StereoOut32 input) {
|
||||
static StereoOut32 DCFilter(StereoOut32 input)
|
||||
{
|
||||
// A simple DC blocking high-pass filter
|
||||
// Implementation from http://peabody.sapp.org/class/dmp2/lab/dcblock/
|
||||
// The magic number 0x7f5c is ceil(INT16_MAX * 0.995)
|
||||
@@ -634,9 +617,9 @@ __forceinline void spu2Mix()
|
||||
if (SPU2::MsgCache())
|
||||
{
|
||||
SPU2::ConLog(" * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
}
|
||||
|
||||
g_counter_cache_hits =
|
||||
|
||||
@@ -256,29 +256,16 @@ struct V_Voice
|
||||
// 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;
|
||||
s32 NextCrest; // temp value for Crest calculation
|
||||
|
||||
// SBuffer now points directly to an ADPCM cache entry.
|
||||
s16* SBuffer;
|
||||
|
||||
// sample position within the current decoded packet.
|
||||
s32 SCurrent;
|
||||
// Each voice has a buffer of decoded samples
|
||||
s32 DecodeFifo[32];
|
||||
u32 DecPosWrite;
|
||||
u32 DecPosRead;
|
||||
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void Start();
|
||||
|
||||
@@ -181,7 +181,6 @@ void V_Core::Init(int index)
|
||||
VoiceGates[v].WetR = -1;
|
||||
|
||||
Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Voices[v].SCurrent = 28;
|
||||
|
||||
Voices[v].ADSR.Counter = 0;
|
||||
Voices[v].ADSR.Value = 0;
|
||||
@@ -190,6 +189,10 @@ void V_Core::Init(int index)
|
||||
Voices[v].NextA = 0x2801;
|
||||
Voices[v].StartA = 0x2800;
|
||||
Voices[v].LoopStartA = 0x2800;
|
||||
|
||||
memset(Voices[v].DecodeFifo, 0, sizeof(Voices[v].DecodeFifo));
|
||||
Voices[v].DecPosRead = 0;
|
||||
Voices[v].DecPosWrite = 0;
|
||||
}
|
||||
|
||||
DMAICounter = 0;
|
||||
@@ -212,23 +215,18 @@ void V_Voice::Start()
|
||||
}
|
||||
|
||||
ADSR.Attack();
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
|
||||
// When SP >= 0 the next sample will be grabbed, we don't want this to happen
|
||||
// instantly because in the case of pitch being 0 we want to delay getting
|
||||
// the next block header. This is a hack to work around the fact that unlike
|
||||
// the HW we don't update the block header on every cycle.
|
||||
SP = -1;
|
||||
SP = 0;
|
||||
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
Prev2 = 0;
|
||||
|
||||
PV1 = PV2 = 0;
|
||||
PV3 = PV4 = 0;
|
||||
NextCrest = -0x8000;
|
||||
SBuffer = nullptr;
|
||||
DecPosRead = 0;
|
||||
DecPosWrite = 0;
|
||||
}
|
||||
|
||||
void V_Voice::Stop()
|
||||
@@ -989,12 +987,10 @@ static void RegWrite_VoiceAddr(u16 value)
|
||||
// Wallace And Gromit: Curse Of The Were-Rabbit.
|
||||
|
||||
thisvoice.NextA = ((u32)(value & 0x0F) << 16) | (thisvoice.NextA & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
thisvoice.NextA = (thisvoice.NextA & 0x0F0000) | (value & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1212,7 +1208,6 @@ static void RegWrite_Core(u16 value)
|
||||
for (uint v = 0; v < 24; ++v)
|
||||
{
|
||||
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Cores[1].Voices[v].SCurrent = 28;
|
||||
|
||||
Cores[1].Voices[v].ADSR.Value = 0;
|
||||
Cores[1].Voices[v].ADSR.Phase = 0;
|
||||
|
||||
@@ -26,7 +26,7 @@ enum class FreezeAction
|
||||
// [SAVEVERSION+]
|
||||
// This informs the auto updater that the users savestates will be invalidated.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A55 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A57 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
||||
Reference in New Issue
Block a user