aboutsummaryrefslogtreecommitdiff
path: root/src/portmod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/portmod.rs')
-rw-r--r--src/portmod.rs203
1 files changed, 193 insertions, 10 deletions
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
}
}