aboutsummaryrefslogblamecommitdiff
path: root/src/portmod.rs
blob: a271ead4ed93c06e794868f199a06587f6b9b3cd (plain) (tree)
1
2
3
4
5
6
7
8
9
                







                
                




                  
































                             

                  

                  
                  
                       


                       






                             







                                             
                                           




                                          
                                            






















                                                                        


                                                          
                  
                                            








                                                                           
                                            









                                                                              
                                            









                                                                       
                                            







                                                                     

                                                           
                  
                                            























                                                                          
                                            




                                                          
                                                         

                                                
                                            








                                                                              
                                                         








                                                                                            
         









                                                                     



                                 
#[derive(Debug)]
pub enum Slide
{
    Up(u8),
    Down(u8),
    FineUp(u8),
    FineDown(u8)
}

#[derive(Debug)]
pub enum Effect
{
    SetSpeed(u8),
    PosJump(u8),
    PattBreak(u8),
    SetVolume(u8),
    VolumeSlide(Slide),
    PortaDown(u8),
    PortaFineDown(u8),
    PortaExFineDown(u8),
    PortaUp(u8),
    PortaFineUp(u8),
    PortaExFineUp(u8),
    TonePorta(u8),
    Vibrato(u8, u8),
    Tremor(u8, u8),
    Arpeggio(u8, u8),
    VolumeSlideVib(Slide),
    VolumeSlideTPorta(Slide),
    SetChannelVolume(u8),
    ChVolSlide(Slide),
    SampleOffset(u8),
    PanSlide(Slide),
    Retrigger(u8, u8),
    Tremolo(u8, u8),
    GlissandoCtrl(bool),
    SetFinetune(u8),
    SetVibWaveform(u8),
    SetTremWaveform(u8),
    SetPanWaveform(u8),
    RowExtention(u8),
    VirtChanOp(u8),
    NNAOverride(u8),
    VolumeEnvEnable(bool),
    PanEnvEnable(bool),
    PitchEnvEnable(bool),
    SoundCtrl(u8),
    SampleOffsetHigh(u8),
    PattLoopStart,
    PattLoop(u8),
    NoteCut(u8),
    NoteDelay(u8),
    PattDelay(u8),
    SetActiveMacro(u8),
    SetTempo(u8),
    TempoSlideDown(u8),
    TempoSlideUp(u8),
    VibFine(u8, u8),
    SetGlobalVolume(u8),
    GlobalVolumeSlide(Slide),
    SetPan(u8),
    AutoPan(u8, u8),
    MidiMacro(u8),
    SmoothMidiMacro(u8),
    NoEffect
}

impl Effect
{
    pub fn from_it_efx(f: (u8, u8)) -> Effect
    {
        let (efx, fxp) = f;
        match (efx + 'A' as u8 - 1) as char
        {
            'A' => Effect::SetSpeed(fxp),
            'B' => Effect::PosJump(fxp),
            'C' => Effect::PattBreak(fxp),
            'D' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::VolumeSlide(Slide::Down(y)),
                    (x, 0) => Effect::VolumeSlide(Slide::Up(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::VolumeSlide(Slide::FineDown(y)),
                    (x, 0xf) => Effect::VolumeSlide(Slide::FineUp(x)),
                    _ => Effect::NoEffect
                },
            'E' =>
                match fxp & 0xf0
                {
                    0xF0 => Effect::PortaFineDown(fxp & 0x0f),
                    0xE0 => Effect::PortaExFineDown(fxp & 0x0f),
                    _ => Effect::PortaDown(fxp)
                },
            'F' =>
                match fxp & 0xf0
                {
                    0xF0 => Effect::PortaFineUp(fxp & 0x0f),
                    0xE0 => Effect::PortaExFineUp(fxp & 0x0f),
                    _ => Effect::PortaUp(fxp)
                },
            'G' => Effect::TonePorta(fxp),
            'H' => Effect::Vibrato(fxp >> 4, fxp & 0x0f),
            'I' => Effect::Tremor(fxp >> 4, fxp & 0x0f),
            'J' => Effect::Arpeggio(fxp >> 4, fxp & 0x0f),
            'K' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::VolumeSlideVib(Slide::Down(y)),
                    (x, 0) => Effect::VolumeSlideVib(Slide::Up(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::VolumeSlideVib(Slide::FineDown(y)),
                    (x, 0xf) => Effect::VolumeSlideVib(Slide::FineUp(x)),
                    _ => Effect::NoEffect
                },
            'L' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::VolumeSlideTPorta(Slide::Down(y)),
                    (x, 0) => Effect::VolumeSlideTPorta(Slide::Up(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::VolumeSlideTPorta(Slide::FineDown(y)),
                    (x, 0xf) => Effect::VolumeSlideTPorta(Slide::FineUp(x)),
                    _ => Effect::NoEffect
                },
            'M' => Effect::SetChannelVolume(fxp),
            'N' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::ChVolSlide(Slide::Down(y)),
                    (x, 0) => Effect::ChVolSlide(Slide::Up(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::ChVolSlide(Slide::FineDown(y)),
                    (x, 0xf) => Effect::ChVolSlide(Slide::FineUp(x)),
                    _ => Effect::NoEffect
                },
            'O' => Effect::SampleOffset(fxp),
            'P' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::PanSlide(Slide::Up(y)),
                    (x, 0) => Effect::PanSlide(Slide::Down(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::PanSlide(Slide::FineUp(y)),
                    (x, 0xf) => Effect::PanSlide(Slide::FineDown(x)),
                    _ => Effect::NoEffect
                },
            'Q' => Effect::Retrigger(fxp >> 4, fxp & 0x0f),
            'R' => Effect::Tremolo(fxp >> 4, fxp & 0x0f),
            'S' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0x1, e) => Effect::GlissandoCtrl(e != 0),
                    (0x2, t) => Effect::SetFinetune(t),
                    (0x3, w) => Effect::SetVibWaveform(w),
                    (0x4, w) => Effect::SetTremWaveform(w),
                    (0x5, w) => Effect::SetPanWaveform(w),
                    (0x6, d) => Effect::RowExtention(d),
                    (0x7, x @ 0..=2) => Effect::VirtChanOp(x),
                    (0x7, x @ 3..=6) => Effect::NNAOverride(x - 3),
                    (0x7, x @ 7..=8) => Effect::VolumeEnvEnable(x == 8),
                    (0x7, x @ 9..=10) => Effect::PanEnvEnable(x == 10),
                    (0x7, x @ 11..=12) => Effect::PitchEnvEnable(x == 10),
                    (0x8, p) => Effect::SetPan(p * (255 / 15)),
                    (0x9, c) => Effect::SoundCtrl(c),
                    (0xa, o) => Effect::SampleOffsetHigh(o),
                    (0xb, 0x0) => Effect::PattLoopStart,
                    (0xb, r) => Effect::PattLoop(r),
                    (0xc, t) => Effect::NoteCut(t),
                    (0xd, t) => Effect::NoteDelay(t),
                    (0xe, d) => Effect::PattDelay(d),
                    (0xf, m) => Effect::SetActiveMacro(m),
                    _ => Effect::NoEffect
                },
            'T' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0x0, v) => Effect::TempoSlideDown(v),
                    (0x1, v) => Effect::TempoSlideUp(v),
                    _ => Effect::SetTempo(fxp)
                },
            'U' => Effect::VibFine(fxp >> 4, fxp & 0x0f),
            'V' => Effect::SetGlobalVolume(fxp),
            'W' =>
                match (fxp >> 4, fxp & 0x0f)
                {
                    (0, y) => Effect::GlobalVolumeSlide(Slide::Down(y)),
                    (x, 0) => Effect::GlobalVolumeSlide(Slide::Up(x)),
                    (0xf, 0xf) => Effect::NoEffect,
                    (0xf, y) => Effect::GlobalVolumeSlide(Slide::FineDown(y)),
                    (x, 0xf) => Effect::GlobalVolumeSlide(Slide::FineUp(x)),
                    _ => Effect::NoEffect
                },
            'X' => Effect::SetPan(fxp),
            'Y' => Effect::AutoPan(fxp >> 4, fxp & 0x0f),
            'Z' => Effect::MidiMacro(fxp),
            '\\' => Effect::SmoothMidiMacro(fxp),
            _ => Effect::NoEffect
        }
    }
    pub fn from_it_vol(v: u8) -> Effect
    {
        const GMAP: [u8; 10] = [0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60, 0x80, 0xFF];
        match v
        {
            0..=64 => Effect::SetVolume(v),
            65..=74 => Effect::VolumeSlide(Slide::FineUp(v - 65)),
            75..=84 => Effect::VolumeSlide(Slide::FineDown(v - 75)),
            85..=94 => Effect::VolumeSlide(Slide::Up(v - 85)),
            95..=104 => Effect::VolumeSlide(Slide::Down(v - 95)),
            105..=114 => Effect::PortaDown((v - 105) * 4),
            115..=124 => Effect::PortaUp((v - 115) * 4),
            128..=192 => Effect::SetPan(v - 128),
            193..=202 => Effect::TonePorta(GMAP[(v - 193) as usize]),
            203..=212 => Effect::Vibrato(0, v - 203),
            _ => Effect::NoEffect
        }
    }
}