From 5e36a84f5111220329644bb3a15ddd62474ef487 Mon Sep 17 00:00:00 2001 From: lif <> Date: Mon, 15 Jan 2024 20:09:23 -0800 Subject: [PATCH] split out module --- src/lsdpack.rs | 347 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 352 +------------------------------------------------ 2 files changed, 352 insertions(+), 347 deletions(-) create mode 100644 src/lsdpack.rs diff --git a/src/lsdpack.rs b/src/lsdpack.rs new file mode 100644 index 0000000..a2d8a11 --- /dev/null +++ b/src/lsdpack.rs @@ -0,0 +1,347 @@ +use gba::prelude::*; +use voladdress::{Safe, VolAddress}; + +#[allow(dead_code)] +#[repr(u8)] +#[derive(Copy, Clone)] +enum LsdpackCmd { + // special commands (not just plain register writes) + EndTick = 0, + SampleStart = 1, + SongStop = 2, + NextBank = 3, + AmpDecPu0 = 4, + AmpDecPu1 = 5, + AmpDecNoi = 6, + PitchPu0 = 7, + PitchPu1 = 8, + PitchWav = 9, + SampleNext = 10, + + _Invalid0B = 0x0b, + _Invalid0C = 0x0c, + _Invalid0D = 0x0d, + _Invalid0E = 0x0e, + _Invalid0F = 0x0f, + + // ch1 pulse + Pu0Sweep = 0x10, + Pu0LengthWave = 0x11, + Pu0Env = 0x12, + Pu0PitchLsb = 0x13, + Pu0PitchMsb = 0x14, + + _Invalid15 = 0x15, + + // ch2 pulse + Pu1LengthWave = 0x16, + Pu1Env = 0x17, + Pu1PitchLsb = 0x18, + Pu1PitchMsb = 0x19, + + // ch3 wave + WavOnOff = 0x1a, + WavLength = 0x1b, + WavEnv = 0x1c, + WavPitchLsb = 0x1d, + WavPitchMsb = 0x1e, + + _Invalid1F = 0x1f, + + // ch4 noise + NoiLength = 0x20, + NoiEnv = 0x21, + NoiWave = 0x22, + NoiTrig = 0x23, + + // general + ChannelVolume = 0x24, + Pan = 0x25, + SoundOffOn = 0x26, + + _Invalid27 = 0x27, + _Invalid28 = 0x28, + _Invalid29 = 0x29, + _Invalid2A = 0x2a, + _Invalid2B = 0x2b, + _Invalid2C = 0x2c, + _Invalid2D = 0x2d, + _Invalid2E = 0x2e, + _Invalid2F = 0x2f, + + // wave pattern + WavePattern0 = 0x30, + WavePattern1 = 0x31, + WavePattern2 = 0x32, + WavePattern3 = 0x33, + WavePattern4 = 0x34, + WavePattern5 = 0x35, + WavePattern6 = 0x36, + WavePattern7 = 0x37, + WavePattern8 = 0x38, + WavePattern9 = 0x39, + WavePatternA = 0x3a, + WavePatternB = 0x3b, + WavePatternC = 0x3c, + WavePatternD = 0x3d, + WavePatternE = 0x3e, + WavePatternF = 0x3f, +} + +impl From for LsdpackCmd { + fn from(val: u8) -> Self { + assert!(val <= 0x3f); + unsafe { core::mem::transmute(val) } + } +} + +pub struct Lsdpack { + data: &'static [u8], + setlist: &'static [usize], + current_ptr: usize, + sample_ptr: usize, + repeat_cmd: Option<(LsdpackCmd, bool)>, + repeat_cmd_counter: usize, + sample_pitch: u16, + stopped: bool, +} + +impl Lsdpack { + pub const fn new(data: &'static [u8], setlist: &'static [usize]) -> Self { + Self { + data, + setlist, + current_ptr: setlist[0], + sample_ptr: 0, + repeat_cmd: None, + repeat_cmd_counter: 0, + sample_pitch: 0, + stopped: false, + } + } + + pub fn play_song(&mut self, song_id: usize) { + self.current_ptr = self.setlist[song_id]; + self.sample_ptr = 0; + self.repeat_cmd = None; + self.repeat_cmd_counter = 0; + self.stopped = false; + } + + #[link_section = ".iwram"] + fn next_byte(&mut self) -> u8 { + let val = self.data[self.current_ptr]; + self.current_ptr += 1; + val + } + + #[link_section = ".iwram"] + fn write_next_samples(&mut self) { + let ptr = self.sample_ptr; + self.sample_ptr += 16; + //let sound_enabled = SOUND_ENABLED.read(); + //SOUND_ENABLED.write(sound_enabled.with_wave_playing(false)); + let lrvol = LEFT_RIGHT_VOLUME.read(); + LEFT_RIGHT_VOLUME.write(lrvol.with_wave_left(false).with_wave_right(false)); + WAVE_BANK.write(WaveBank::new().with_enabled(false)); + WAVE_RAM.index(0).write(u32::from_le_bytes( + TryFrom::try_from(&self.data[ptr..ptr + 4]).unwrap(), + )); + WAVE_RAM.index(1).write(u32::from_le_bytes( + TryFrom::try_from(&self.data[ptr + 4..ptr + 8]).unwrap(), + )); + WAVE_RAM.index(2).write(u32::from_le_bytes( + TryFrom::try_from(&self.data[ptr + 8..ptr + 12]).unwrap(), + )); + WAVE_RAM.index(3).write(u32::from_le_bytes( + TryFrom::try_from(&self.data[ptr + 12..ptr + 16]).unwrap(), + )); + WAVE_BANK.write(WaveBank::new().with_enabled(true)); + //SOUND_ENABLED.write(sound_enabled); + LEFT_RIGHT_VOLUME.write(lrvol); + WAVE_FREQ.write(WaveFrequency::new().with_length(self.sample_pitch)); + } + + #[link_section = ".iwram"] + pub fn tick(&mut self) { + if self.stopped { + return; + } + let mut ongoing = true; + while ongoing { + if let Some((cmd, flagged_ongoing)) = self.repeat_cmd { + if self.repeat_cmd_counter > 0 { + self.repeat_cmd_counter -= 1; + ongoing = flagged_ongoing; + ongoing &= self.apply_cmd(cmd); + continue; + } else { + self.repeat_cmd = None; + } + } + let (cmd, flagged_ongoing) = self.load_new_cmd_from_stream(); + ongoing = flagged_ongoing; + ongoing &= self.apply_cmd(cmd); + } + } + + #[link_section = ".iwram"] + fn load_new_cmd_from_stream(&mut self) -> (LsdpackCmd, bool) { + const FLAG_REPEAT: u8 = 0x40; + const FLAG_END_TICK: u8 = 0x80; + let mut cmd = self.next_byte(); + let mut ongoing = true; + if cmd & FLAG_END_TICK != 0 { + cmd &= !FLAG_END_TICK; + ongoing = false; + } + if cmd & FLAG_REPEAT != 0 { + cmd &= !FLAG_REPEAT; + self.repeat_cmd = Some((cmd.into(), ongoing)); + self.repeat_cmd_counter = self.next_byte() as usize; + } + (cmd.into(), ongoing) + } + + #[link_section = ".iwram"] + fn write_lsb(&mut self, voladdr: VolAddress) { + let voladdr = unsafe { voladdr.cast::() }; + voladdr.write((voladdr.read() & 0xFF00) | (self.next_byte() as u16)); + } + + #[link_section = ".iwram"] + fn write_msb(&mut self, voladdr: VolAddress) { + let voladdr = unsafe { voladdr.cast::() }; + voladdr.write((voladdr.read() & 0xFF) | ((self.next_byte() as u16) << 8)); + } + + #[link_section = ".iwram"] + fn write_u16le(&mut self, voladdr: VolAddress) { + let voladdr = unsafe { voladdr.cast::() }; + let halfword = u16::from_le_bytes([self.next_byte(), self.next_byte()]); + voladdr.write(halfword); + } + + #[link_section = ".iwram"] + fn apply_cmd(&mut self, cmd: LsdpackCmd) -> bool { + use LsdpackCmd::*; + match cmd { + // special commands: + EndTick => return false, + SampleStart => { + let _sample_bank = self.next_byte(); // TODO? + self.sample_ptr = u16::from_le_bytes([self.next_byte(), self.next_byte()]) as usize; + // big endian order for the pitch here? don't know why + self.sample_pitch = u16::from_be_bytes([self.next_byte(), self.next_byte()]); + self.write_next_samples(); // also writes pitch + } + SongStop => { + self.stopped = true; + return false; + } + NextBank => { /* lol */ } + AmpDecPu0 => { + // https://github.com/LIJI32/SameBoy/blob/27b5935b8d0e0af988bcac8e55e92703af24f335/Core/apu.c#L341 + let base = TONE1_PATTERN.read(); + TONE1_PATTERN.write( + base.with_volume(0) + .with_step_increasing(true) + .with_step_time(1), + ); // $FF12 <- $9 + TONE1_PATTERN.write( + base.with_volume(1) + .with_step_increasing(false) + .with_step_time(1), + ); // $FF12 <- $11 + TONE1_PATTERN.write( + base.with_volume(1) + .with_step_increasing(true) + .with_step_time(0), + ); // $FF12 <- $18 + } + AmpDecPu1 => { + let base = TONE2_PATTERN.read(); + TONE2_PATTERN.write( + base.with_volume(0) + .with_step_increasing(true) + .with_step_time(1), + ); // $FF17 <- $9 + TONE2_PATTERN.write( + base.with_volume(1) + .with_step_increasing(false) + .with_step_time(1), + ); // $FF17 <- $11 + TONE2_PATTERN.write( + base.with_volume(1) + .with_step_increasing(true) + .with_step_time(0), + ); // $FF17 <- $18 + } + AmpDecNoi => { + let base = NOISE_LEN_ENV.read(); + NOISE_LEN_ENV.write( + base.with_volume(0) + .with_step_increasing(true) + .with_step_time(1), + ); // $FF21 <- $9 + NOISE_LEN_ENV.write( + base.with_volume(1) + .with_step_increasing(false) + .with_step_time(1), + ); // $FF21 <- $11 + NOISE_LEN_ENV.write( + base.with_volume(1) + .with_step_increasing(true) + .with_step_time(0), + ); // $FF21 <- $18 + } + PitchPu0 => self.write_u16le(TONE1_FREQUENCY), + PitchPu1 => self.write_u16le(TONE2_FREQUENCY), + PitchWav => self.write_u16le(WAVE_FREQ), + SampleNext => self.write_next_samples(), + + // general register writes: + Pu0Sweep => unsafe { TONE1_SWEEP.cast() }.write(self.next_byte()), + Pu0LengthWave => self.write_lsb(TONE1_PATTERN), + Pu0Env => self.write_msb(TONE1_PATTERN), + Pu0PitchLsb => self.write_lsb(TONE1_FREQUENCY), + Pu0PitchMsb => self.write_msb(TONE1_FREQUENCY), + Pu1LengthWave => self.write_lsb(TONE2_PATTERN), + Pu1Env => self.write_msb(TONE2_PATTERN), + Pu1PitchLsb => self.write_lsb(TONE2_FREQUENCY), + Pu1PitchMsb => self.write_msb(TONE2_FREQUENCY), + WavOnOff => WAVE_BANK.write(WaveBank::new().with_enabled(self.next_byte() != 0)), + WavLength => self.write_lsb(WAVE_LEN_VOLUME), + WavEnv => self.write_msb(WAVE_LEN_VOLUME), + WavPitchLsb => self.write_lsb(WAVE_FREQ), + WavPitchMsb => self.write_msb(WAVE_FREQ), + NoiLength => self.write_lsb(NOISE_LEN_ENV), + NoiEnv => self.write_msb(NOISE_LEN_ENV), + NoiWave => self.write_lsb(NOISE_FREQ), + NoiTrig => self.write_msb(NOISE_FREQ), + ChannelVolume => self.write_lsb(LEFT_RIGHT_VOLUME), + Pan => self.write_msb(LEFT_RIGHT_VOLUME), + SoundOffOn => unsafe { SOUND_ENABLED.cast() }.write(self.next_byte()), + WavePattern0 => todo!(), + WavePattern1 => todo!(), + WavePattern2 => todo!(), + WavePattern3 => todo!(), + WavePattern4 => todo!(), + WavePattern5 => todo!(), + WavePattern6 => todo!(), + WavePattern7 => todo!(), + WavePattern8 => todo!(), + WavePattern9 => todo!(), + WavePatternA => todo!(), + WavePatternB => todo!(), + WavePatternC => todo!(), + WavePatternD => todo!(), + WavePatternE => todo!(), + WavePatternF => todo!(), + _Invalid0B | _Invalid0C | _Invalid0D | _Invalid0E | _Invalid0F | _Invalid15 + | _Invalid1F | _Invalid27 | _Invalid28 | _Invalid29 | _Invalid2A | _Invalid2B + | _Invalid2C | _Invalid2D | _Invalid2E | _Invalid2F => unimplemented!(), + } + true + } +} diff --git a/src/main.rs b/src/main.rs index a365ae0..a30d400 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,9 @@ #![allow(unused_imports)] mod halfwidth; +mod lsdpack; + +use lsdpack::*; use core::fmt::Write; @@ -21,6 +24,8 @@ build_const!("lsdpack_bc"); #[allow(unused_must_use)] #[panic_handler] fn panic_handler(info: &core::panic::PanicInfo) -> ! { + IE.write(IrqBits::VBLANK); + let mut text_painter = halfwidth::TextPainter::new(); text_painter.setup_display(); @@ -73,353 +78,6 @@ extern "C" fn irq_handler(bits: IrqBits) { } } -#[allow(dead_code)] -#[repr(u8)] -#[derive(Copy, Clone)] -enum LsdpackCmd { - // special commands (not just plain register writes) - EndTick = 0, - SampleStart = 1, - SongStop = 2, - NextBank = 3, - AmpDecPu0 = 4, - AmpDecPu1 = 5, - AmpDecNoi = 6, - PitchPu0 = 7, - PitchPu1 = 8, - PitchWav = 9, - SampleNext = 10, - - _Invalid0B = 0x0b, - _Invalid0C = 0x0c, - _Invalid0D = 0x0d, - _Invalid0E = 0x0e, - _Invalid0F = 0x0f, - - // ch1 pulse - Pu0Sweep = 0x10, - Pu0LengthWave = 0x11, - Pu0Env = 0x12, - Pu0PitchLsb = 0x13, - Pu0PitchMsb = 0x14, - - _Invalid15 = 0x15, - - // ch2 pulse - Pu1LengthWave = 0x16, - Pu1Env = 0x17, - Pu1PitchLsb = 0x18, - Pu1PitchMsb = 0x19, - - // ch3 wave - WavOnOff = 0x1a, - WavLength = 0x1b, - WavEnv = 0x1c, - WavPitchLsb = 0x1d, - WavPitchMsb = 0x1e, - - _Invalid1F = 0x1f, - - // ch4 noise - NoiLength = 0x20, - NoiEnv = 0x21, - NoiWave = 0x22, - NoiTrig = 0x23, - - // general - ChannelVolume = 0x24, - Pan = 0x25, - SoundOffOn = 0x26, - - _Invalid27 = 0x27, - _Invalid28 = 0x28, - _Invalid29 = 0x29, - _Invalid2A = 0x2a, - _Invalid2B = 0x2b, - _Invalid2C = 0x2c, - _Invalid2D = 0x2d, - _Invalid2E = 0x2e, - _Invalid2F = 0x2f, - - // wave pattern - WavePattern0 = 0x30, - WavePattern1 = 0x31, - WavePattern2 = 0x32, - WavePattern3 = 0x33, - WavePattern4 = 0x34, - WavePattern5 = 0x35, - WavePattern6 = 0x36, - WavePattern7 = 0x37, - WavePattern8 = 0x38, - WavePattern9 = 0x39, - WavePatternA = 0x3a, - WavePatternB = 0x3b, - WavePatternC = 0x3c, - WavePatternD = 0x3d, - WavePatternE = 0x3e, - WavePatternF = 0x3f, -} - -impl From for LsdpackCmd { - fn from(val: u8) -> Self { - assert!(val <= 0x3f); - unsafe { core::mem::transmute(val) } - } -} - -struct Lsdpack { - data: &'static [u8], - setlist: &'static [usize], - current_ptr: usize, - sample_ptr: usize, - repeat_cmd: Option<(LsdpackCmd, bool)>, - repeat_cmd_counter: usize, - sample_pitch: u16, - stopped: bool, -} - -impl Lsdpack { - const fn new(data: &'static [u8], setlist: &'static [usize]) -> Self { - Self { - data, - setlist, - current_ptr: setlist[0], - sample_ptr: 0, - repeat_cmd: None, - repeat_cmd_counter: 0, - sample_pitch: 0, - stopped: false, - } - } -} - -impl Lsdpack { - fn play_song(&mut self, song_id: usize) { - self.current_ptr = self.setlist[song_id]; - self.sample_ptr = 0; - self.repeat_cmd = None; - self.repeat_cmd_counter = 0; - self.stopped = false; - } - - #[link_section = ".iwram"] - fn next_byte(&mut self) -> u8 { - let val = self.data[self.current_ptr]; - self.current_ptr += 1; - val - } - - #[link_section = ".iwram"] - fn write_next_samples(&mut self) { - let ptr = self.sample_ptr; - self.sample_ptr += 16; - //let sound_enabled = SOUND_ENABLED.read(); - //SOUND_ENABLED.write(sound_enabled.with_wave_playing(false)); - let lrvol = LEFT_RIGHT_VOLUME.read(); - LEFT_RIGHT_VOLUME.write(lrvol.with_wave_left(false).with_wave_right(false)); - WAVE_BANK.write(WaveBank::new().with_enabled(false)); - WAVE_RAM.index(0).write(u32::from_le_bytes( - TryFrom::try_from(&self.data[ptr..ptr + 4]).unwrap(), - )); - WAVE_RAM.index(1).write(u32::from_le_bytes( - TryFrom::try_from(&self.data[ptr + 4..ptr + 8]).unwrap(), - )); - WAVE_RAM.index(2).write(u32::from_le_bytes( - TryFrom::try_from(&self.data[ptr + 8..ptr + 12]).unwrap(), - )); - WAVE_RAM.index(3).write(u32::from_le_bytes( - TryFrom::try_from(&self.data[ptr + 12..ptr + 16]).unwrap(), - )); - WAVE_BANK.write(WaveBank::new().with_enabled(true)); - //SOUND_ENABLED.write(sound_enabled); - LEFT_RIGHT_VOLUME.write(lrvol); - WAVE_FREQ.write(WaveFrequency::new().with_length(self.sample_pitch)); - } - - #[link_section = ".iwram"] - fn tick(&mut self) { - if self.stopped { - return; - } - let mut ongoing = true; - while ongoing { - if let Some((cmd, flagged_ongoing)) = self.repeat_cmd { - if self.repeat_cmd_counter > 0 { - self.repeat_cmd_counter -= 1; - ongoing = flagged_ongoing; - ongoing &= self.apply_cmd(cmd); - continue; - } else { - self.repeat_cmd = None; - } - } - let (cmd, flagged_ongoing) = self.load_new_cmd_from_stream(); - ongoing = flagged_ongoing; - ongoing &= self.apply_cmd(cmd); - } - } - - #[link_section = ".iwram"] - fn load_new_cmd_from_stream(&mut self) -> (LsdpackCmd, bool) { - const FLAG_REPEAT: u8 = 0x40; - const FLAG_END_TICK: u8 = 0x80; - let mut cmd = self.next_byte(); - let mut ongoing = true; - if cmd & FLAG_END_TICK != 0 { - cmd &= !FLAG_END_TICK; - ongoing = false; - } - if cmd & FLAG_REPEAT != 0 { - cmd &= !FLAG_REPEAT; - self.repeat_cmd = Some((cmd.into(), ongoing)); - self.repeat_cmd_counter = self.next_byte() as usize; - } - (cmd.into(), ongoing) - } - - #[link_section = ".iwram"] - fn write_lsb(&mut self, voladdr: VolAddress) { - let voladdr = unsafe { voladdr.cast::() }; - voladdr.write((voladdr.read() & 0xFF00) | (self.next_byte() as u16)); - } - - #[link_section = ".iwram"] - fn write_msb(&mut self, voladdr: VolAddress) { - let voladdr = unsafe { voladdr.cast::() }; - voladdr.write((voladdr.read() & 0xFF) | ((self.next_byte() as u16) << 8)); - } - - #[link_section = ".iwram"] - fn write_u16le(&mut self, voladdr: VolAddress) { - let voladdr = unsafe { voladdr.cast::() }; - let halfword = u16::from_le_bytes([self.next_byte(), self.next_byte()]); - voladdr.write(halfword); - } - - #[link_section = ".iwram"] - fn apply_cmd(&mut self, cmd: LsdpackCmd) -> bool { - use LsdpackCmd::*; - match cmd { - // special commands: - EndTick => return false, - SampleStart => { - let _sample_bank = self.next_byte(); // TODO? - self.sample_ptr = u16::from_le_bytes([self.next_byte(), self.next_byte()]) as usize; - // big endian order for the pitch here? don't know why - self.sample_pitch = u16::from_be_bytes([self.next_byte(), self.next_byte()]); - self.write_next_samples(); // also writes pitch - } - SongStop => { - self.stopped = true; - return false; - } - NextBank => { /* lol */ } - AmpDecPu0 => { - // https://github.com/LIJI32/SameBoy/blob/27b5935b8d0e0af988bcac8e55e92703af24f335/Core/apu.c#L341 - let base = TONE1_PATTERN.read(); - TONE1_PATTERN.write( - base.with_volume(0) - .with_step_increasing(true) - .with_step_time(1), - ); // $FF12 <- $9 - TONE1_PATTERN.write( - base.with_volume(1) - .with_step_increasing(false) - .with_step_time(1), - ); // $FF12 <- $11 - TONE1_PATTERN.write( - base.with_volume(1) - .with_step_increasing(true) - .with_step_time(0), - ); // $FF12 <- $18 - } - AmpDecPu1 => { - let base = TONE2_PATTERN.read(); - TONE2_PATTERN.write( - base.with_volume(0) - .with_step_increasing(true) - .with_step_time(1), - ); // $FF17 <- $9 - TONE2_PATTERN.write( - base.with_volume(1) - .with_step_increasing(false) - .with_step_time(1), - ); // $FF17 <- $11 - TONE2_PATTERN.write( - base.with_volume(1) - .with_step_increasing(true) - .with_step_time(0), - ); // $FF17 <- $18 - } - AmpDecNoi => { - let base = NOISE_LEN_ENV.read(); - NOISE_LEN_ENV.write( - base.with_volume(0) - .with_step_increasing(true) - .with_step_time(1), - ); // $FF21 <- $9 - NOISE_LEN_ENV.write( - base.with_volume(1) - .with_step_increasing(false) - .with_step_time(1), - ); // $FF21 <- $11 - NOISE_LEN_ENV.write( - base.with_volume(1) - .with_step_increasing(true) - .with_step_time(0), - ); // $FF21 <- $18 - } - PitchPu0 => self.write_u16le(TONE1_FREQUENCY), - PitchPu1 => self.write_u16le(TONE2_FREQUENCY), - PitchWav => self.write_u16le(WAVE_FREQ), - SampleNext => self.write_next_samples(), - - // general register writes: - Pu0Sweep => unsafe { TONE1_SWEEP.cast() }.write(self.next_byte()), - Pu0LengthWave => self.write_lsb(TONE1_PATTERN), - Pu0Env => self.write_msb(TONE1_PATTERN), - Pu0PitchLsb => self.write_lsb(TONE1_FREQUENCY), - Pu0PitchMsb => self.write_msb(TONE1_FREQUENCY), - Pu1LengthWave => self.write_lsb(TONE2_PATTERN), - Pu1Env => self.write_msb(TONE2_PATTERN), - Pu1PitchLsb => self.write_lsb(TONE2_FREQUENCY), - Pu1PitchMsb => self.write_msb(TONE2_FREQUENCY), - WavOnOff => WAVE_BANK.write(WaveBank::new().with_enabled(self.next_byte() != 0)), - WavLength => self.write_lsb(WAVE_LEN_VOLUME), - WavEnv => self.write_msb(WAVE_LEN_VOLUME), - WavPitchLsb => self.write_lsb(WAVE_FREQ), - WavPitchMsb => self.write_msb(WAVE_FREQ), - NoiLength => self.write_lsb(NOISE_LEN_ENV), - NoiEnv => self.write_msb(NOISE_LEN_ENV), - NoiWave => self.write_lsb(NOISE_FREQ), - NoiTrig => self.write_msb(NOISE_FREQ), - ChannelVolume => self.write_lsb(LEFT_RIGHT_VOLUME), - Pan => self.write_msb(LEFT_RIGHT_VOLUME), - SoundOffOn => unsafe { SOUND_ENABLED.cast() }.write(self.next_byte()), - WavePattern0 => todo!(), - WavePattern1 => todo!(), - WavePattern2 => todo!(), - WavePattern3 => todo!(), - WavePattern4 => todo!(), - WavePattern5 => todo!(), - WavePattern6 => todo!(), - WavePattern7 => todo!(), - WavePattern8 => todo!(), - WavePattern9 => todo!(), - WavePatternA => todo!(), - WavePatternB => todo!(), - WavePatternC => todo!(), - WavePatternD => todo!(), - WavePatternE => todo!(), - WavePatternF => todo!(), - _Invalid0B | _Invalid0C | _Invalid0D | _Invalid0E | _Invalid0F | _Invalid15 - | _Invalid1F | _Invalid27 | _Invalid28 | _Invalid29 | _Invalid2A | _Invalid2B - | _Invalid2C | _Invalid2D | _Invalid2E | _Invalid2F => unimplemented!(), - } - true - } -} - #[no_mangle] extern "C" fn main() -> ! { RUST_IRQ_HANDLER.write(Some(irq_handler));