From 2a83b17ffbc6587bf0bfe1fa1755d2f5d248395c Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sat, 11 Jun 2022 11:33:25 -0700 Subject: [PATCH 1/2] DSP: Copy audio dma samples one block at a time Reverts 9f8e1e2a0dbca38b53ac7d91f5e714baaa72bfa0, but keeps the changes from e4e44909d5ffa60abf81d4685a156654c463bbf9. This fixes missing audio in Datel titles; see https://bugs.dolphin-emu.org/issues/12281. --- Source/Core/Core/HW/DSP.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index 3952133748..5ebe4a6680 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -418,7 +418,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) bool already_enabled = state.audio_dma.AudioDMAControl.Enable; state.audio_dma.AudioDMAControl.Hex = val; - // Only load new values if were not already doing a DMA transfer, + // Only load new values if we're not already doing a DMA transfer, // otherwise just let the new values be autoloaded in when the // current transfer ends. if (!already_enabled && state.audio_dma.AudioDMAControl.Enable) @@ -429,10 +429,6 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) INFO_LOG_FMT(AUDIO_INTERFACE, "Audio DMA configured: {} blocks from {:#010x}", state.audio_dma.AudioDMAControl.NumBlocks, state.audio_dma.SourceAddress); - // We make the samples ready as soon as possible - void* address = Memory::GetPointer(state.audio_dma.SourceAddress); - AudioCommon::SendAIBuffer((short*)address, state.audio_dma.AudioDMAControl.NumBlocks * 8); - // TODO: need hardware tests for the timing of this interrupt. // Sky Crawlers crashes at boot if this is scheduled less than 87 cycles in the future. // Other Namco games crash too, see issue 9509. For now we will just push it to 200 cycles @@ -524,6 +520,8 @@ void UpdateAudioDMA() // Read audio at g_audioDMA.current_source_address in RAM and push onto an // external audio fifo in the emulator, to be mixed with the disc // streaming output. + void* address = Memory::GetPointer(state.audio_dma.current_source_address); + AudioCommon::SendAIBuffer(reinterpret_cast(address), 8); if (state.audio_dma.remaining_blocks_count != 0) { @@ -536,12 +534,6 @@ void UpdateAudioDMA() state.audio_dma.current_source_address = state.audio_dma.SourceAddress; state.audio_dma.remaining_blocks_count = state.audio_dma.AudioDMAControl.NumBlocks; - if (state.audio_dma.remaining_blocks_count != 0) - { - // We make the samples ready as soon as possible - void* address = Memory::GetPointer(state.audio_dma.SourceAddress); - AudioCommon::SendAIBuffer((short*)address, state.audio_dma.AudioDMAControl.NumBlocks * 8); - } GenerateDSPInterrupt(DSP::INT_AID); } } From 6de55e416b337dd7eee3df85d967a31a12169186 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sat, 11 Jun 2022 11:40:38 -0700 Subject: [PATCH 2/2] WaveFile: Fix size check `count` is the number of stereo samples to write (where each stereo sample is two shorts), while `BUFFER_SIZE` is the size of the buffer in shorts. So `count` needs to be multiplied by `2`, not `BUFFER_SIZE`. Also, when this check was failed, the previous code just clobbered whatever was past the end of the buffer after logging the warning, which corrupted `basename`, eventually resulting in Dolphin crashing. This affected Datel's Wii-compatible Action Replay, which uses a block size of 2298, or 18384 stereo samples, which is 36768 shorts, which is bigger than the buffer size of 32768. (However, the previous commit means that only one block is transfered at a time, eliminating this issue; fixing the bounds check is just a general safety thing instead of an actual bugfix now.) --- Source/Core/AudioCommon/WaveFile.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Core/AudioCommon/WaveFile.cpp b/Source/Core/AudioCommon/WaveFile.cpp index dc689e74dd..2e67d86519 100644 --- a/Source/Core/AudioCommon/WaveFile.cpp +++ b/Source/Core/AudioCommon/WaveFile.cpp @@ -119,10 +119,16 @@ void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count, u32 sample_rate_divisor, int l_volume, int r_volume) { if (!file) + { ERROR_LOG_FMT(AUDIO, "WaveFileWriter - file not open."); + return; + } - if (count > BUFFER_SIZE * 2) + if (count * 2 > BUFFER_SIZE) + { ERROR_LOG_FMT(AUDIO, "WaveFileWriter - buffer too small (count = {}).", count); + return; + } if (skip_silence) {