mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-23 19:01:30 +11:00
add sound
This commit is contained in:
parent
d62fbae4f0
commit
4217a2b795
|
@ -12,4 +12,5 @@ pub mod background;
|
|||
pub mod display;
|
||||
pub mod dma;
|
||||
pub mod keypad;
|
||||
pub mod sound;
|
||||
pub mod timers;
|
||||
|
|
|
@ -30,7 +30,6 @@ newtype! {
|
|||
KeyInput, u16
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl KeyInput {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
|
@ -84,6 +83,11 @@ pub fn read_key_input() -> KeyInput {
|
|||
KeyInput(KEYINPUT.read() ^ 0b0000_0011_1111_1111)
|
||||
}
|
||||
|
||||
/// Use this to configure when a keypad interrupt happens.
|
||||
///
|
||||
/// See the `KeyInterruptSetting` type for more.
|
||||
pub const KEYCNT: VolAddress<KeyInterruptSetting> = unsafe { VolAddress::new_unchecked(0x400_0132) };
|
||||
|
||||
newtype! {
|
||||
/// Allows configuration of when a keypad interrupt fires.
|
||||
///
|
||||
|
@ -119,8 +123,3 @@ impl KeyInterruptSetting {
|
|||
irq_logical_and: 15,
|
||||
}
|
||||
}
|
||||
|
||||
/// Use this to configure when a keypad interrupt happens.
|
||||
///
|
||||
/// See the `KeyInterruptSetting` type for more.
|
||||
pub const KEYCNT: VolAddress<KeyInterruptSetting> = unsafe { VolAddress::new_unchecked(0x400_0132) };
|
||||
|
|
239
src/io/sound.rs
Normal file
239
src/io/sound.rs
Normal file
|
@ -0,0 +1,239 @@
|
|||
///! Module for sound registers.
|
||||
use super::*;
|
||||
|
||||
//TODO within these "read/write" registers only some bits are actually read/write!
|
||||
|
||||
/// Sound Channel 1 Sweep Register (`NR10`). Read/Write.
|
||||
pub const SOUND1CNT_L: VolAddress<SweepRegisterSetting> = unsafe { VolAddress::new_unchecked(0x400_0060) };
|
||||
|
||||
newtype! {
|
||||
SweepRegisterSetting, u16
|
||||
}
|
||||
|
||||
impl SweepRegisterSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
sweep_shift: 0-2,
|
||||
sweep_decreasing: 3,
|
||||
sweep_time: 4-6,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 1 Duty/Length/Envelope (`NR11`, `NR12`). Read/Write.
|
||||
pub const SOUND1CNT_H: VolAddress<DutyLenEnvelopeSetting> = unsafe { VolAddress::new_unchecked(0x400_0062) };
|
||||
|
||||
newtype! {
|
||||
DutyLenEnvelopeSetting, u16
|
||||
}
|
||||
|
||||
impl DutyLenEnvelopeSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
sound_length: 0-5,
|
||||
wave_pattern_duty: 6-7, //TODO: enum this
|
||||
envelope_step_time: 8-10,
|
||||
envelope_increasing: 11,
|
||||
initial_envelope_volume: 12-15,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 1 Frequency/Control (`NR13`, `NR14`). Read/Write.
|
||||
pub const SOUND1CNT_X: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0064) };
|
||||
|
||||
newtype! {
|
||||
FrequencyControlSetting, u32 // TODO: u16 or u32?
|
||||
}
|
||||
|
||||
impl FrequencyControlSetting {
|
||||
phantom_fields! {
|
||||
self.0: u32,
|
||||
frequency: 0-10,
|
||||
length_flag: 14,
|
||||
is_initial: 15,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 2 Channel 2 Duty/Length/Envelope (`NR21`, `NR22`). Read/Write.
|
||||
pub const SOUND2CNT_L: VolAddress<DutyLenEnvelopeSetting> = unsafe { VolAddress::new_unchecked(0x400_0068) };
|
||||
|
||||
/// Sound Channel 2 Frequency/Control (`NR23`, `NR24`). Read/Write.
|
||||
pub const SOUND2CNT_H: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new_unchecked(0x400_006C) };
|
||||
|
||||
/// Sound Channel 3 Stop/Wave RAM select (`NR23`, `NR24`). Read/Write.
|
||||
pub const SOUND3CNT_L: VolAddress<StopWaveRAMSelectSetting> = unsafe { VolAddress::new_unchecked(0x400_0070) };
|
||||
|
||||
newtype! {
|
||||
StopWaveRAMSelectSetting, u16
|
||||
}
|
||||
|
||||
impl StopWaveRAMSelectSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
wave_ram_dimension_2d: 5,
|
||||
wave_ram_bank_number: 6,
|
||||
sound_channel_3_playing: 7,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 3 Length/Volume (`NR23`, `NR24`). Read/Write.
|
||||
pub const SOUND3CNT_H: VolAddress<LengthVolumeSetting> = unsafe { VolAddress::new_unchecked(0x400_0072) };
|
||||
|
||||
newtype! {
|
||||
LengthVolumeSetting, u16
|
||||
}
|
||||
|
||||
impl LengthVolumeSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
sound_length: 0-7,
|
||||
sound_volume: 13-14,
|
||||
force_75percent: 15,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 3 Frequency/Control (`NR33`, `NR34`). Read/Write.
|
||||
pub const SOUND3CNT_X: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new_unchecked(0x400_0074) };
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM0_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0090) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM0_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0092) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM1_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0094) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM1_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0096) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM2_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_0098) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM2_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_009A) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM3_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_009C) };
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM3_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_009E) };
|
||||
|
||||
/// Sound Channel 4 Length/Envelope (`NR41`, `NR42`). Read/Write.
|
||||
pub const SOUND4CNT_L: VolAddress<LengthEnvelopeSetting> = unsafe { VolAddress::new_unchecked(0x400_0078) };
|
||||
|
||||
newtype! {
|
||||
LengthEnvelopeSetting, u32 // TODO: is this u32?
|
||||
}
|
||||
|
||||
impl LengthEnvelopeSetting {
|
||||
phantom_fields! {
|
||||
self.0: u32,
|
||||
sound_length: 0-5,
|
||||
envelope_step_time: 8-10,
|
||||
envelope_increasing: 11,
|
||||
initial_envelope_volume: 12-15,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound Channel 4 Frequency/Control (`NR43`, `NR44`). Read/Write.
|
||||
pub const SOUND4CNT_H: VolAddress<NoiseFrequencySetting> = unsafe { VolAddress::new_unchecked(0x400_007C) };
|
||||
|
||||
newtype! {
|
||||
NoiseFrequencySetting, u32 // TODO: is this u32?
|
||||
}
|
||||
|
||||
impl NoiseFrequencySetting {
|
||||
phantom_fields! {
|
||||
self.0: u32,
|
||||
frequency_divide_ratio: 0-2,
|
||||
counter_step_width_7bit: 3,
|
||||
shift_clock_frequency: 4-7,
|
||||
length_flag_stop: 14,
|
||||
initial_restart: 15,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: unify FIFO as
|
||||
|
||||
/// Sound A FIFO, Data 0 and Data 1 (W)
|
||||
pub const FIFO_A_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00A0) };
|
||||
/// Sound A FIFO, Data 2 and Data 3 (W)
|
||||
pub const FIFO_A_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00A2) };
|
||||
/// Sound B FIFO, Data 0 and Data 1 (W)
|
||||
pub const FIFO_B_L: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00A4) };
|
||||
/// Sound B FIFO, Data 2 and Data 3 (W)
|
||||
pub const FIFO_B_H: VolAddress<u16> = unsafe { VolAddress::new_unchecked(0x400_00A6) };
|
||||
|
||||
/// Channel L/R Volume/Enable (`NR50`, `NR51`). Read/Write.
|
||||
pub const SOUNDCNT_L: VolAddress<NonWaveVolumeEnableSetting> = unsafe { VolAddress::new_unchecked(0x400_0080) };
|
||||
|
||||
newtype! {
|
||||
NonWaveVolumeEnableSetting, u16
|
||||
}
|
||||
|
||||
impl NonWaveVolumeEnableSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
right_master_volume: 0-2,
|
||||
left_master_volume: 4-6,
|
||||
right_enable_flags: 8-11, // TODO: this is junk
|
||||
left_enable_flags: 12-15, // TODO: junk
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA Sound Control/Mixing. Read/Write.
|
||||
pub const SOUNDCNT_H: VolAddress<WaveVolumeEnableSetting> = unsafe { VolAddress::new_unchecked(0x400_0082) };
|
||||
|
||||
newtype! {
|
||||
WaveVolumeEnableSetting, u16
|
||||
}
|
||||
|
||||
impl WaveVolumeEnableSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
sound_number_volume: 0-1=NumberSoundVolume<Quarter, Half, Full>,
|
||||
dma_sound_a_full_volume: 2,
|
||||
dma_sound_b_full_volume: 3,
|
||||
dma_sound_a_enable_right: 8,
|
||||
dma_sound_a_enable_left: 9,
|
||||
dma_sound_a_timer_select: 10,
|
||||
dma_sound_a_reset_fifo: 11,
|
||||
dma_sound_b_enable_right: 12,
|
||||
dma_sound_b_enable_left: 13,
|
||||
dma_sound_b_timer_select: 14,
|
||||
dma_sound_b_reset_fifo: 15,
|
||||
}
|
||||
}
|
||||
|
||||
newtype_enum! {
|
||||
NumberSoundVolume = u16,
|
||||
Quarter = 0,
|
||||
Half = 1,
|
||||
Full = 2,
|
||||
}
|
||||
|
||||
/// Sound on/off (`NR52`). Read/Write.
|
||||
pub const SOUNDCNT_X: VolAddress<SoundMasterSetting> = unsafe { VolAddress::new_unchecked(0x400_0084) };
|
||||
|
||||
newtype! {
|
||||
SoundMasterSetting, u16
|
||||
}
|
||||
|
||||
impl SoundMasterSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
sound1_on: 0,
|
||||
sound2_on: 1,
|
||||
sound3_on: 2,
|
||||
sound4_on: 3,
|
||||
psg_fifo_master_enabled: 7,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound on/off (`NR52`). Read/Write.
|
||||
pub const SOUNDBIAS: VolAddress<SoundPWMSetting> = unsafe { VolAddress::new_unchecked(0x400_0088) };
|
||||
|
||||
newtype! {
|
||||
SoundPWMSetting, u16
|
||||
}
|
||||
|
||||
impl SoundMasterSetting {
|
||||
phantom_fields! {
|
||||
self.0: u16,
|
||||
bias_level: 1-9,
|
||||
amplitude_resolution: 14-15, // TODO: enum this
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
#![feature(const_int_rotate)]
|
||||
#![allow(clippy::cast_lossless)]
|
||||
#![deny(clippy::float_arithmetic)]
|
||||
#![warn(missing_docs)]
|
||||
//#![warn(missing_docs)]
|
||||
|
||||
//! This crate helps you write GBA ROMs.
|
||||
//!
|
||||
|
|
Loading…
Reference in a new issue