mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-24 03:11:29 +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 display;
|
||||||
pub mod dma;
|
pub mod dma;
|
||||||
pub mod keypad;
|
pub mod keypad;
|
||||||
|
pub mod sound;
|
||||||
pub mod timers;
|
pub mod timers;
|
||||||
|
|
|
@ -30,7 +30,6 @@ newtype! {
|
||||||
KeyInput, u16
|
KeyInput, u16
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
impl KeyInput {
|
impl KeyInput {
|
||||||
phantom_fields! {
|
phantom_fields! {
|
||||||
self.0: u16,
|
self.0: u16,
|
||||||
|
@ -84,6 +83,11 @@ pub fn read_key_input() -> KeyInput {
|
||||||
KeyInput(KEYINPUT.read() ^ 0b0000_0011_1111_1111)
|
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! {
|
newtype! {
|
||||||
/// Allows configuration of when a keypad interrupt fires.
|
/// Allows configuration of when a keypad interrupt fires.
|
||||||
///
|
///
|
||||||
|
@ -119,8 +123,3 @@ impl KeyInterruptSetting {
|
||||||
irq_logical_and: 15,
|
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)]
|
#![feature(const_int_rotate)]
|
||||||
#![allow(clippy::cast_lossless)]
|
#![allow(clippy::cast_lossless)]
|
||||||
#![deny(clippy::float_arithmetic)]
|
#![deny(clippy::float_arithmetic)]
|
||||||
#![warn(missing_docs)]
|
//#![warn(missing_docs)]
|
||||||
|
|
||||||
//! This crate helps you write GBA ROMs.
|
//! This crate helps you write GBA ROMs.
|
||||||
//!
|
//!
|
||||||
|
|
Loading…
Reference in a new issue