diff --git a/agb/src/sound/mixer.rs b/agb/src/sound/mixer.rs index 5d3a345..159714c 100644 --- a/agb/src/sound/mixer.rs +++ b/agb/src/sound/mixer.rs @@ -1,20 +1,24 @@ use crate::memory_mapped::MemoryMapped; #[non_exhaustive] -pub struct Mixer {} +pub struct Mixer { + buffer: MixerBuffer, +} impl Mixer { pub(crate) const unsafe fn new() -> Self { - Mixer {} + Mixer { + buffer: MixerBuffer::new(), + } } pub fn enable(&self) { set_sound_control_register_for_mixer(); + set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); } - pub fn play_sound_starting_at(&self, sound_memory: &[u8]) { - set_timer_counter_for_frequency_and_enable(SOUND_FREQUENCY); - enable_dma1_for_sound(sound_memory); + pub fn vblank(&mut self) { + self.buffer.swap(); } } @@ -23,6 +27,34 @@ impl Mixer { const SOUND_FREQUENCY: i32 = 10512; const SOUND_BUFFER_SIZE: usize = 176; +struct MixerBuffer { + buffer1: [i8; SOUND_BUFFER_SIZE], + buffer2: [i8; SOUND_BUFFER_SIZE], + + buffer_1_active: bool, +} + +impl MixerBuffer { + fn new() -> Self { + MixerBuffer { + buffer1: Default::default(), + buffer2: Default::default(), + + buffer_1_active: true, + } + } + + fn swap(&mut self) { + if self.buffer_1_active { + enable_dma1_for_sound(&self.buffer1); + } else { + enable_dma1_for_sound(&self.buffer2); + } + + self.buffer_1_active = !self.buffer_1_active; + } +} + // Once we have proper DMA support, we should use that rather than hard coding these here too const DMA1_SOURCE_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00bc) }; const DMA1_DEST_ADDR: MemoryMapped = unsafe { MemoryMapped::new(0x0400_00c0) }; @@ -38,14 +70,14 @@ const TIMER0_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0102 const SOUND_CONTROL: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0082) }; const SOUND_CONTROL_X: MemoryMapped = unsafe { MemoryMapped::new(0x0400_0084) }; -fn enable_dma1_for_sound(sound_memory: &[u8]) { +fn enable_dma1_for_sound(sound_memory: &[i8]) { let dest_fixed: u16 = 2 << 5; // dest addr control = fixed let repeat: u16 = 1 << 9; let transfer_type: u16 = 1 << 10; // transfer in words let dma_start_timing: u16 = 3 << 12; // sound fifo timing let enable: u16 = 1 << 15; // enable - let address: *const u8 = &sound_memory[0]; + let address: *const i8 = &sound_memory[0]; DMA1_SOURCE_ADDR.set(address as u32); DMA1_DEST_ADDR.set(FIFOA_DEST_ADDR); DMA1_CONTROL.set(dest_fixed | repeat | transfer_type | dma_start_timing | enable);