diff --git a/tracker/agb-tracker-interop/src/lib.rs b/tracker/agb-tracker-interop/src/lib.rs index 4e787bdc..61b4deb9 100644 --- a/tracker/agb-tracker-interop/src/lib.rs +++ b/tracker/agb-tracker-interop/src/lib.rs @@ -48,6 +48,7 @@ pub enum PatternEffect { Panning(Num), Volume(Num), VolumeSlide(Num), + FineVolumeSlide(Num), NoteCut(u32), Portamento(Num), /// Slide each tick the first amount to at most the second amount @@ -205,6 +206,10 @@ impl quote::ToTokens for PatternEffect { let amount = amount.to_raw(); quote! { VolumeSlide(agb_tracker::__private::Num::from_raw(#amount))} } + PatternEffect::FineVolumeSlide(amount) => { + let amount = amount.to_raw(); + quote! { FineVolumeSlide(agb_tracker::__private::Num::from_raw(#amount))} + } PatternEffect::NoteCut(wait) => quote! { NoteCut(#wait) }, PatternEffect::Portamento(amount) => { let amount = amount.to_raw(); diff --git a/tracker/agb-tracker/src/lib.rs b/tracker/agb-tracker/src/lib.rs index 1f4faca4..22ffb5d0 100644 --- a/tracker/agb-tracker/src/lib.rs +++ b/tracker/agb-tracker/src/lib.rs @@ -124,7 +124,7 @@ impl Tracker { tick: 0, current_row: 0, - current_pattern: 6, + current_pattern: 0x10, } } @@ -143,7 +143,7 @@ impl Tracker { let pattern_slots = &self.track.pattern_data[pattern_data_pos..pattern_data_pos + self.track.num_channels]; - for (channel, pattern_slot) in self.channels.iter_mut().zip(pattern_slots) { + for (channel, pattern_slot) in self.channels.iter_mut().zip(pattern_slots).skip(3) { if pattern_slot.sample != 0 && self.tick == 0 { let sample = &self.track.samples[pattern_slot.sample as usize - 1]; channel.play_sound(mixer, sample); @@ -219,7 +219,7 @@ impl TrackerChannel { } self.channel_id = mixer.play_sound(new_channel); - self.volume = 1.into(); + self.volume = sample.volume; } fn set_speed(&mut self, mixer: &mut Mixer<'_>, speed: Num) { @@ -264,10 +264,13 @@ impl TrackerChannel { } PatternEffect::VolumeSlide(amount) => { if tick != 0 { - self.volume += *amount; - if self.volume < 0.into() { - self.volume = 0.into(); - } + self.volume = (self.volume + *amount).max(0.into()); + channel.volume(self.volume); + } + } + PatternEffect::FineVolumeSlide(amount) => { + if tick == 0 { + self.volume = (self.volume + *amount).max(0.into()); channel.volume(self.volume); } } diff --git a/tracker/agb-xm-core/src/lib.rs b/tracker/agb-xm-core/src/lib.rs index 553179f7..34fd935c 100644 --- a/tracker/agb-xm-core/src/lib.rs +++ b/tracker/agb-xm-core/src/lib.rs @@ -162,6 +162,12 @@ pub fn parse_module(module: &Module) -> TokenStream { .map(|note_and_sample| note_and_sample.1.volume) .unwrap_or(1.into()), ), + 0x80..=0x8F => PatternEffect::FineVolumeSlide( + -Num::new((slot.volume - 0x80) as i16) / 16, + ), + 0x90..=0x9F => PatternEffect::FineVolumeSlide( + Num::new((slot.volume - 0x90) as i16) / 16, + ), 0xC0..=0xCF => PatternEffect::Panning( Num::new(slot.volume as i16 - (0xC0 + (0xCF - 0xC0) / 2)) / 64, ), @@ -292,6 +298,12 @@ pub fn parse_module(module: &Module) -> TokenStream { } } 0xE => match slot.effect_parameter >> 4 { + 0xA => PatternEffect::FineVolumeSlide( + Num::new((slot.effect_parameter & 0xf) as i16) / 16, + ), + 0xB => PatternEffect::FineVolumeSlide( + -Num::new((slot.effect_parameter & 0xf) as i16) / 16, + ), 0xC => PatternEffect::NoteCut((slot.effect_parameter & 0xf).into()), _ => PatternEffect::None, },