diff --git a/Source/Core/Core/DSP/DSPAccelerator.cpp b/Source/Core/Core/DSP/DSPAccelerator.cpp index a6a2695364..6e40d7f930 100644 --- a/Source/Core/Core/DSP/DSPAccelerator.cpp +++ b/Source/Core/Core/DSP/DSPAccelerator.cpp @@ -60,6 +60,9 @@ void Accelerator::WriteD3(u16 value) u16 Accelerator::Read(s16* coefs) { + if (m_reads_stopped) + return 0x0000; + u16 val; u8 step_size_bytes = 0; @@ -148,6 +151,7 @@ u16 Accelerator::Read(s16* coefs) { // Set address back to start address. m_current_address = m_start_address; + m_reads_stopped = true; OnEndException(); } @@ -164,6 +168,7 @@ void Accelerator::DoState(PointerWrap& p) p.Do(m_yn1); p.Do(m_yn2); p.Do(m_pred_scale); + p.Do(m_reads_stopped); } constexpr u32 START_END_ADDRESS_MASK = 0x3fffffff; @@ -197,6 +202,7 @@ void Accelerator::SetYn1(s16 yn1) void Accelerator::SetYn2(s16 yn2) { m_yn2 = yn2; + m_reads_stopped = false; } void Accelerator::SetPredScale(u16 pred_scale) diff --git a/Source/Core/Core/DSP/DSPAccelerator.h b/Source/Core/Core/DSP/DSPAccelerator.h index 1c12da3417..3ee0e9f2b0 100644 --- a/Source/Core/Core/DSP/DSPAccelerator.h +++ b/Source/Core/Core/DSP/DSPAccelerator.h @@ -50,5 +50,10 @@ protected: s16 m_yn1 = 0; s16 m_yn2 = 0; u16 m_pred_scale = 0; + + // When an ACCOV is triggered, the accelerator stops reading back anything + // and updating the current address register, unless the YN2 register is written to. + // This is kept track of internally; this state is not exposed via any register. + bool m_reads_stopped = false; }; } // namespace DSP diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h index 29e43dd49f..f061848fac 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h @@ -199,10 +199,10 @@ protected: #ifdef AX_WII // One of the few meaningful differences between AXGC and AXWii: - // while AXGC handles non looping voices ending by having 0000 - // samples at the loop address, AXWii has the 0000 samples - // internally in DRAM and use an internal pointer to it (loop addr - // does not contain 0000 samples on AXWii!). + // while AXGC handles non looping voices ending by relying on the + // accelerator to stop reads once the loop address is reached, + // AXWii has the 0000 samples internally in DRAM and use an internal + // pointer to it (loop addr does not contain 0000 samples on AXWii!). acc_end_reached = true; #endif } diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 4c22756e53..b17daba6ca 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 89; // Last changed in PR 5890 +static const u32 STATE_VERSION = 90; // Last changed in PR 6077 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,