diff options
author | Chris Xiong <chirs241097@gmail.com> | 2022-11-12 20:02:58 -0500 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2022-11-12 20:02:58 -0500 |
commit | 343db25d7f94f579c92d3e2d8be6dd8a612a0a7c (patch) | |
tree | 7b2462700886ab8c82c4582677c56a5fae5b37ed /src | |
parent | af733bc521d1f8578e4ec4d704c3e776be185603 (diff) | |
download | it2midi-343db25d7f94f579c92d3e2d8be6dd8a612a0a7c.tar.xz |
All original IT effects in portmod. Handle S6x in timing code.
Diffstat (limited to 'src')
-rw-r--r-- | src/convert.rs | 8 | ||||
-rw-r--r-- | src/portmod.rs | 203 |
2 files changed, 198 insertions, 13 deletions
diff --git a/src/convert.rs b/src/convert.rs index 05866f3..2cbe15b 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -17,6 +17,7 @@ struct PlayerState tempo: u8, loop_start: u8, loop_ctr: u8, + row_extension: u8, in_rep: bool } @@ -85,6 +86,7 @@ impl<'a> Player<'a> Effect::SetSpeed(s) => PlayerState{speed: s, ..ps}, Effect::PattLoopStart => PlayerState{loop_start: ps.current_row, ..ps}, Effect::SetTempo(t) => PlayerState{tempo: t, ..ps}, + Effect::RowExtention(t) => PlayerState{row_extension: ps.row_extension + t, ..ps}, _ => ps } } @@ -130,7 +132,7 @@ impl<'a> Player<'a> { ret.current_row = r; ret.current_tick = 0; - while ret.current_tick < ret.speed + while ret.current_tick < ret.speed + ret.row_extension { for c in 0..64 { @@ -141,6 +143,7 @@ impl<'a> Player<'a> ret.current_tick += 1; } ret = (&self.h).borrow_mut().process(!0, itfile::Cell::default(), ret); + ret.row_extension = 0; if (!ret.skip_row) != 0 || (!ret.skip_ord) != 0 { return ret; } } ret @@ -148,8 +151,6 @@ impl<'a> Player<'a> /// Used for effects Bxx, Cxx and SBx /// /// passing !0 to row or ord if it's unused - /// - /// in_loop == true inhibits loop detection and should only be used for SBx fn skip_to(&self, row: u8, ord: u8, ps: PlayerState) -> PlayerState { PlayerState { @@ -172,6 +173,7 @@ impl<'a> Player<'a> tempo: self.it.header.tempo, loop_start: 0, loop_ctr: !0, + row_extension: 0, in_rep: false }; 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 } } |