From 343db25d7f94f579c92d3e2d8be6dd8a612a0a7c Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Sat, 12 Nov 2022 20:02:58 -0500 Subject: All original IT effects in portmod. Handle S6x in timing code. --- src/portmod.rs | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 193 insertions(+), 10 deletions(-) (limited to 'src/portmod.rs') diff --git a/src/portmod.rs b/src/portmod.rs index 52c27ee..125fdab 100644 --- a/src/portmod.rs +++ b/src/portmod.rs @@ -1,14 +1,65 @@ +pub enum Slide +{ + Up(u8), + Down(u8), + FineUp(u8), + FineDown(u8) +} + 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 } @@ -17,17 +68,149 @@ impl Effect pub fn from_it_efx(f: (u8, u8)) -> Effect { let (efx, fxp) = f; - match (efx as char, fxp) + match efx as char + { + 'A' => Effect::SetSpeed(fxp), + 'B' => Effect::PosJump(fxp), + 'C' => Effect::PattBreak(fxp), + 'D' => + match (fxp >> 8, 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 >> 8, fxp & 0x0f), + 'I' => Effect::Tremor(fxp >> 8, fxp & 0x0f), + 'J' => Effect::Arpeggio(fxp >> 8, fxp & 0x0f), + 'K' => + match (fxp >> 8, 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 >> 8, 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 >> 8, 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 >> 8, 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 >> 8, fxp & 0x0f), + 'R' => Effect::Tremolo(fxp >> 8, fxp & 0x0f), + 'S' => + match (fxp >> 8, 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 >> 8, fxp & 0x0f) + { + (0x0, v) => Effect::TempoSlideDown(v), + (0x1, v) => Effect::TempoSlideUp(v), + _ => Effect::SetTempo(fxp) + }, + 'U' => Effect::VibFine(fxp >> 8, fxp & 0x0f), + 'V' => Effect::SetGlobalVolume(fxp), + 'W' => + match (fxp >> 8, 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 >> 8, 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 { - ('A', _) => Effect::SetSpeed(fxp), - ('B', _) => Effect::PosJump(fxp), - ('C', _) => Effect::PattBreak(fxp), - ('S', 0xb0) => Effect::PattLoopStart, - ('S', _) if fxp & 0xf0 == 0xb0 => Effect::PattLoop(fxp & 0x0f), - ('S', _) if fxp & 0xf0 == 0xe0 => Effect::PattDelay(fxp & 0x0f), - ('T', _) if fxp & 0xf0 == 0x00 => Effect::TempoSlideDown(fxp & 0x0f), - ('T', _) if fxp & 0xf0 == 0x10 => Effect::TempoSlideUp(fxp & 0x0f), - ('T', _) => Effect::SetTempo(fxp), + 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 } } -- cgit v1.2.3