summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2014-08-01 22:19:50 -0400
committerLioncash <mathew1800@gmail.com>2014-08-01 22:19:50 -0400
commit44f751f752ce7faf23c5a1eb2f2d9c081a4c162d (patch)
treec94ab5ebc0d15609ab53278bf1717404343cd4f6 /Source/Core
parent1aab63bef75e62de19e0887b79232b3a858ec99e (diff)
parent47ba8cc4c1bf9c77bdb74a8213e625da1d06cf8e (diff)
Merge pull request #692 from booto/dma-audio-fix
DSP: latch dma parameters
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/DSP.cpp70
1 files changed, 43 insertions, 27 deletions
diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp
index 23bf23cf3b..a0d3a35337 100644
--- a/Source/Core/Core/HW/DSP.cpp
+++ b/Source/Core/Core/HW/DSP.cpp
@@ -105,17 +105,17 @@ union UAudioDMAControl
// AudioDMA
struct AudioDMA
{
+ u32 current_source_address;
+ u16 remaining_blocks_count;
u32 SourceAddress;
- u32 ReadAddress;
UAudioDMAControl AudioDMAControl;
- int BlocksLeft;
- AudioDMA()
+ AudioDMA():
+ current_source_address(0),
+ remaining_blocks_count(0),
+ SourceAddress(0),
+ AudioDMAControl(0)
{
- SourceAddress = 0;
- ReadAddress = 0;
- AudioDMAControl.Hex = 0;
- BlocksLeft = 0;
}
};
@@ -392,18 +392,31 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | AUDIO_DMA_CONTROL_LEN,
MMIO::DirectRead<u16>(&g_audioDMA.AudioDMAControl.Hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) {
+ bool already_enabled = g_audioDMA.AudioDMAControl.Enable;
g_audioDMA.AudioDMAControl.Hex = val;
- g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
- g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
+
+ // Only load new values if were not already doing a DMA transfer,
+ // otherwise just let the new values be autoloaded in when the
+ // current transfer ends.
+ if (!already_enabled && g_audioDMA.AudioDMAControl.Enable)
+ {
+ g_audioDMA.current_source_address = g_audioDMA.SourceAddress;
+ g_audioDMA.remaining_blocks_count = g_audioDMA.AudioDMAControl.NumBlocks;
+
+ if (g_audioDMA.AudioDMAControl.NumBlocks == 0)
+ {
+ g_audioDMA.AudioDMAControl.Enable = 0;
+ }
+
+ GenerateDSPInterrupt(DSP::INT_AID);
+ }
})
);
// Audio DMA blocks remaining is invalid to write to, and requires logic on
// the read side.
mmio->Register(base | AUDIO_DMA_BLOCKS_LEFT,
- MMIO::ComplexRead<u16>([](u32) {
- return (g_audioDMA.BlocksLeft > 0 ? g_audioDMA.BlocksLeft - 1 : 0);
- }),
+ MMIO::DirectRead<u16>(&g_audioDMA.remaining_blocks_count),
MMIO::InvalidWrite<u16>()
);
@@ -472,31 +485,34 @@ void UpdateDSPSlice(int cycles)
// This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm)
void UpdateAudioDMA()
{
- if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft)
+ static short zero_samples[8*2] = { 0 };
+ if (g_audioDMA.AudioDMAControl.Enable)
{
- // Read audio at g_audioDMA.ReadAddress in RAM and push onto an
+ // 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. If that audio queue fills up, we delay the
- // emulator.
+ // streaming output.
+ void *address = Memory::GetPointer(g_audioDMA.current_source_address);
+ AudioCommon::SendAIBuffer((short*)address, 8);
- g_audioDMA.BlocksLeft--;
- g_audioDMA.ReadAddress += 32;
+ g_audioDMA.remaining_blocks_count--;
+ g_audioDMA.current_source_address += 32;
- if (g_audioDMA.BlocksLeft == 0)
+ if (g_audioDMA.remaining_blocks_count == 0)
{
- void *address = Memory::GetPointer(g_audioDMA.SourceAddress);
- unsigned samples = 8 * g_audioDMA.AudioDMAControl.NumBlocks;
- AudioCommon::SendAIBuffer((short*)address, samples);
+ g_audioDMA.current_source_address = g_audioDMA.SourceAddress;
+ g_audioDMA.remaining_blocks_count = g_audioDMA.AudioDMAControl.NumBlocks;
+
+ if (g_audioDMA.AudioDMAControl.NumBlocks == 0)
+ {
+ g_audioDMA.AudioDMAControl.Enable = 0;
+ }
+
GenerateDSPInterrupt(DSP::INT_AID);
- g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
- g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
}
}
else
{
- // Send silence. Yeah, it's a bit of a waste to sample rate convert
- // silence. or hm. Maybe we shouldn't do this :)
- AudioCommon::SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
+ AudioCommon::SendAIBuffer(&zero_samples[0], 8);
}
}