Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #692 from booto/dma-audio-fix
DSP: latch dma parameters
  • Loading branch information
lioncash committed Aug 2, 2014
2 parents 1aab63b + 47ba8cc commit 44f751f
Showing 1 changed file with 43 additions and 27 deletions.
70 changes: 43 additions & 27 deletions Source/Core/Core/HW/DSP.cpp
Expand Up @@ -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;
}
};

Expand Down Expand Up @@ -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>()
);

Expand Down Expand Up @@ -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);
}
}

Expand Down

2 comments on commit 44f751f

@Tinob
Copy link
Contributor

@Tinob Tinob commented on 44f751f Aug 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this changes seems to break, dtk audio in xenoblade cronicles.
To correct as i was wrong in my knowledge of the hardware what is brocken is dma audio streaming.

@booto
Copy link
Contributor

@booto booto commented on 44f751f Aug 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made a new PR which I believes addresses this problem: #720
Please test this and report your findings on that PR.
A Windows binary is available https://dl.dolphin-emu.org/prs/pr-720-dolphin-latest-x64.7z if you need it.
(Also, if you notice regressions like this, please open a new issue here: https://code.google.com/p/dolphin-emu/issues/list )

Looks like it has been merged now, so you can just use the normal download from https://dolphin-emu.org/download/ if you like.

Please sign in to comment.