From f592565532a350157798704f9a390753d0dba4a9 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 27 Aug 2021 03:07:27 +0200 Subject: [PATCH] DSPHLE/AX: Reload resampling coefficients on savestate load if necessary. --- Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp | 66 ++++++++++++++------- Source/Core/Core/HW/DSPHLE/UCodes/AX.h | 9 ++- Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp | 4 +- Source/Core/Core/State.cpp | 2 +- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp index fe14ae1cc1..d9619a0408 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp @@ -5,14 +5,17 @@ #include #include +#include #include #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" +#include "Common/Hash.h" #include "Common/IOFile.h" #include "Common/Logging/Log.h" #include "Common/Swap.h" +#include "Core/Core.h" #include "Core/DolphinAnalytics.h" #include "Core/HW/DSP.h" #include "Core/HW/DSPHLE/DSPHLE.h" @@ -38,41 +41,44 @@ void AXUCode::Initialize() { m_mail_handler.PushMail(DSP_INIT, true); - LoadResamplingCoefficients(); + LoadResamplingCoefficients(false, 0); } -void AXUCode::LoadResamplingCoefficients() +bool AXUCode::LoadResamplingCoefficients(bool require_same_checksum, u32 desired_checksum) { - m_coeffs_available = false; + constexpr size_t raw_coeffs_size = 0x800 * 2; + m_coeffs_checksum = std::nullopt; const std::array filenames{ File::GetUserPath(D_GCUSER_IDX) + "dsp_coef.bin", File::GetSysDirectory() + "/GC/dsp_coef.bin", }; - size_t fidx; - std::string filename; - for (fidx = 0; fidx < filenames.size(); ++fidx) + for (const std::string& filename : filenames) { - filename = filenames[fidx]; - if (File::GetSize(filename) != 0x1000) + INFO_LOG_FMT(DSPHLE, "Checking for polyphase resampling coeffs at {}", filename); + + if (File::GetSize(filename) != raw_coeffs_size) continue; - break; + File::IOFile fp(filename, "rb"); + std::array raw_coeffs; + fp.ReadBytes(raw_coeffs.data(), raw_coeffs_size); + + u32 checksum = Common::HashAdler32(raw_coeffs.data(), raw_coeffs_size); + if (require_same_checksum && checksum != desired_checksum) + continue; + + std::memcpy(m_coeffs.data(), raw_coeffs.data(), raw_coeffs_size); + for (auto& coef : m_coeffs) + coef = Common::swap16(coef); + + INFO_LOG_FMT(DSPHLE, "Using polyphase resampling coeffs from {}", filename); + m_coeffs_checksum = checksum; + return true; } - if (fidx >= filenames.size()) - return; - - INFO_LOG_FMT(DSPHLE, "Loading polyphase resampling coeffs from {}", filename); - - File::IOFile fp(filename, "rb"); - fp.ReadBytes(m_coeffs, 0x1000); - - for (auto& coef : m_coeffs) - coef = Common::swap16(coef); - - m_coeffs_available = true; + return false; } void AXUCode::SignalWorkEnd() @@ -432,7 +438,7 @@ void AXUCode::ProcessPBList(u32 pb_addr) ApplyUpdatesForMs(curr_ms, pb, pb.updates.num_updates, updates); ProcessVoice(pb, buffers, spms, ConvertMixerControl(pb.mixer_control), - m_coeffs_available ? m_coeffs : nullptr); + m_coeffs_checksum ? m_coeffs.data() : nullptr); // Forward the buffers for (auto& ptr : buffers.ptrs) @@ -749,6 +755,22 @@ void AXUCode::DoAXState(PointerWrap& p) p.Do(m_samples_auxB_right); p.Do(m_samples_auxB_surround); + auto old_checksum = m_coeffs_checksum; + p.Do(m_coeffs_checksum); + + if (p.GetMode() == PointerWrap::MODE_READ && m_coeffs_checksum && + old_checksum != m_coeffs_checksum) + { + if (!LoadResamplingCoefficients(true, *m_coeffs_checksum)) + { + Core::DisplayMessage("Could not find the DSP polyphase resampling coefficients used by the " + "savestate. Aborting load state.", + 3000); + p.SetMode(PointerWrap::MODE_VERIFY); + return; + } + } + p.Do(m_compressor_pos); } diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AX.h b/Source/Core/Core/HW/DSPHLE/UCodes/AX.h index 514dc24bc6..d0f73a6c2e 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AX.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AX.h @@ -11,6 +11,9 @@ #pragma once +#include +#include + #include "Common/BitUtils.h" #include "Common/CommonTypes.h" #include "Common/Swap.h" @@ -95,12 +98,12 @@ protected: // Table of coefficients for polyphase sample rate conversion. // The coefficients aren't always available (they are part of the DSP DROM) // so we also need to know if they are valid or not. - bool m_coeffs_available = false; - s16 m_coeffs[0x800]; + std::optional m_coeffs_checksum = std::nullopt; + std::array m_coeffs; u16 m_compressor_pos = 0; - void LoadResamplingCoefficients(); + bool LoadResamplingCoefficients(bool require_same_checksum, u32 desired_checksum); // Copy a command list from memory to our temp buffer void CopyCmdList(u32 addr, u16 size); diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp index f5839a055a..a960f5c6c7 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXWii.cpp @@ -472,7 +472,7 @@ void AXWiiUCode::ProcessPBList(u32 pb_addr) { ApplyUpdatesForMs(curr_ms, pb, num_updates, updates); ProcessVoice(pb, buffers, spms, ConvertMixerControl(HILO_TO_32(pb.mixer_control)), - m_coeffs_available ? m_coeffs : nullptr); + m_coeffs_checksum ? m_coeffs.data() : nullptr); // Forward the buffers for (auto& ptr : buffers.ptrs) @@ -483,7 +483,7 @@ void AXWiiUCode::ProcessPBList(u32 pb_addr) else { ProcessVoice(pb, buffers, 96, ConvertMixerControl(HILO_TO_32(pb.mixer_control)), - m_coeffs_available ? m_coeffs : nullptr); + m_coeffs_checksum ? m_coeffs.data() : nullptr); } WritePB(pb_addr, pb, m_crc); diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index a9cf8694e9..3b59b18907 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -73,7 +73,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 -constexpr u32 STATE_VERSION = 135; // Last changed in PR 9976 +constexpr u32 STATE_VERSION = 136; // Last changed in PR 10058 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list,