diff --git a/OpenMPT/soundlib/Load_sfx.cpp b/OpenMPT/soundlib/Load_sfx.cpp index c83ef78..2c61d1a 100644 --- a/OpenMPT/soundlib/Load_sfx.cpp +++ b/OpenMPT/soundlib/Load_sfx.cpp @@ -10,6 +10,7 @@ #include "stdafx.h" #include "Loaders.h" +#include "Tables.h" OPENMPT_NAMESPACE_BEGIN @@ -73,6 +74,27 @@ struct SFXSampleHeader MPT_BINARY_STRUCT(SFXSampleHeader, 30) +static uint8 ClampSlideParam(uint8 value, uint8 lowNote, uint8 highNote) +//---------------------------------------------------------------------- +{ + uint16 lowPeriod, highPeriod; + + if(lowNote < highNote && + lowNote >= 36 + NOTE_MIN && + highNote >= 36 + NOTE_MIN && + lowNote < CountOf(ProTrackerPeriodTable) + 36 + NOTE_MIN && + highNote < CountOf(ProTrackerPeriodTable) + 36 + NOTE_MIN) + { + lowPeriod = ProTrackerPeriodTable[lowNote - 36 - NOTE_MIN]; + highPeriod = ProTrackerPeriodTable[highNote - 36 - NOTE_MIN]; + + // with a fixed speed of 6 ticks/row, and excluding the first row, + // 1xx/2xx param has a max value of (low-high)/5 to avoid sliding too far + return std::min(value, static_cast((lowPeriod - highPeriod) / 5)); + } + + return 0; +} bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags) //------------------------------------------------------------------- @@ -241,11 +263,23 @@ bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags) break; case 0x3: // enable filter/LED + // give precedence to 7xy/8xy slides + if(slideRate[chn]) + { + m.command = m.param = 0; + break; + } m.command = CMD_MODCMDEX; m.param = 0; break; case 0x4: // disable filter/LED + // give precedence to 7xy/8xy slides + if(slideRate[chn]) + { + m.command = m.param = 0; + break; + } m.command = CMD_MODCMDEX; m.param = 1; break; @@ -255,6 +289,15 @@ bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags) { m.command = CMD_VOLUME; m.param = std::min(ModCommand::PARAM(0x3F), static_cast((Samples[m.instr].nVolume / 4u) + m.param)); + + // give precedence to 7xy/8xy slides (and move this to the volume column) + if(slideRate[chn]) + { + m.volcmd = VOLCMD_VOLUME; + m.vol = m.param; + m.command = m.param = 0; + break; + } } else { m.command = m.param = 0; @@ -269,6 +312,15 @@ bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags) m.param = static_cast(Samples[m.instr].nVolume / 4u) - m.param; else m.param = 0; + + // give precedence to 7xy/8xy slides (and move this to the volume column) + if(slideRate[chn]) + { + m.volcmd = VOLCMD_VOLUME; + m.vol = m.param; + m.command = m.param = 0; + break; + } } else { m.command = m.param = 0; @@ -279,14 +331,20 @@ bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags) slideTo[chn] = lastNote[chn] - (m.param >> 4); m.command = CMD_PORTAMENTODOWN; - m.param = slideRate[chn] = m.param & 0xF; + slideRate[chn] = m.param & 0xF; + m.param = ClampSlideParam(slideRate[chn], slideTo[chn], lastNote[chn]); break; case 0x8: // 8xy: slide up x semitones at speed y slideTo[chn] = lastNote[chn] + (m.param >> 4); m.command = CMD_PORTAMENTOUP; - m.param = slideRate[chn] = m.param & 0xF; + slideRate[chn] = m.param & 0xF; + m.param = ClampSlideParam(slideRate[chn], lastNote[chn], slideTo[chn]); + break; + + case 0x9: // 9xx: set sample offset + m.command = CMD_OFFSET; break; default: