diff --git a/src/engine/fileOps/tfm.cpp b/src/engine/fileOps/tfm.cpp index 9927a0fa6..9c675a106 100644 --- a/src/engine/fileOps/tfm.cpp +++ b/src/engine/fileOps/tfm.cpp @@ -246,6 +246,7 @@ void TFMparsePattern(struct TFMparsePatternInfo info) { info.reader->read(effectNum,256); info.reader->read(effectVal,256); + unsigned short lastSlide=0; for (int k=0; k<256; k++) { switch (effectNum[k]) { case 0: @@ -258,6 +259,14 @@ void TFMparsePattern(struct TFMparsePatternInfo info) { // pitch slide up case 2: // pitch slide down + pat->data[k][4]=effectNum[k]; + if (effectVal[k]) { + lastSlide=effectVal[k]; + pat->data[k][5]=effectVal[k]; + } else { + pat->data[k][5]=lastSlide; + } + break; case 3: // portamento case 4: @@ -297,7 +306,7 @@ bool DivEngine::loadTFMv1(unsigned char* file, size_t len) { ds.systemName="Sega Genesis/Mega Drive or TurboSound FM"; ds.subsong[0]->hz=50; ds.systemLen=1; - ds.resetEffectsOnNewNote=true; + ds.resetEffectsOnRowChange=true; ds.system[0]=DIV_SYSTEM_YM2612; @@ -483,7 +492,7 @@ bool DivEngine::loadTFMv2(unsigned char* file, size_t len) { ds.systemName="Sega Genesis/Mega Drive or TurboSound FM"; ds.subsong[0]->hz=50; ds.systemLen=1; - ds.resetEffectsOnNewNote=true; + ds.resetEffectsOnRowChange=true; ds.system[0]=DIV_SYSTEM_YM2612; unsigned char magic[8]={0}; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 9364f1a89..f784dd707 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -653,6 +653,14 @@ void DivEngine::processRow(int i, bool afterDelay) { bool surroundPanChanged=false; // effects + if (song.resetEffectsOnRowChange) { + chan[i].portaSpeed=-1; + chan[i].portaNote=-1; + dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); + chan[i].inPorta=false; + if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); + } + for (int j=0; jdata[whatRow][4+(j<<1)]; short effectVal=pat->data[whatRow][5+(j<<1)]; @@ -697,6 +705,7 @@ void DivEngine::processRow(int i, bool afterDelay) { break; case 0x01: // ramp up if (song.ignoreDuplicateSlides && (lastSlide==0x01 || lastSlide==0x1337)) break; + chan[i].lastPorta2=effectVal; lastSlide=0x01; if (effectVal==0) { chan[i].portaNote=-1; @@ -719,6 +728,7 @@ void DivEngine::processRow(int i, bool afterDelay) { break; case 0x02: // ramp down if (song.ignoreDuplicateSlides && (lastSlide==0x02 || lastSlide==0x1337)) break; + chan[i].lastPorta2=effectVal; lastSlide=0x02; if (effectVal==0) { chan[i].portaNote=-1; @@ -1116,33 +1126,6 @@ void DivEngine::processRow(int i, bool afterDelay) { } } - if (song.resetEffectsOnNewNote) { - if (chan[i].lastArp) { - chan[i].lastArp=0; - } else { - chan[i].arp=0; - dispatchCmd(DivCommand(DIV_CMD_HINT_ARPEGGIO,i,chan[i].arp)); - } - - if (chan[i].lastVibrato2) { - chan[i].lastVibrato2=0; - } else { - chan[i].vibratoDepth=0; - chan[i].vibratoRate=0; - dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate)); - } - - if (chan[i].lastPorta2) { - chan[i].lastPorta2=0; - } else { - chan[i].portaSpeed=-1; - chan[i].portaNote=-1; - dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0))); - chan[i].inPorta=false; - dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); - } - } - if (panChanged) { dispatchCmd(DivCommand(DIV_CMD_PANNING,i,chan[i].panL,chan[i].panR)); } @@ -1155,10 +1138,28 @@ void DivEngine::processRow(int i, bool afterDelay) { dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,DIV_NOTE_NULL)); } + if (song.resetEffectsOnRowChange) { + if (chan[i].lastArp) { + chan[i].lastArp=0; + } else { + chan[i].arp=0; + dispatchCmd(DivCommand(DIV_CMD_HINT_ARPEGGIO,i,chan[i].arp)); + } + + if (chan[i].lastVibrato2) { + chan[i].lastVibrato2=0; + } else { + chan[i].vibratoDepth=0; + chan[i].vibratoRate=0; + dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate)); + } + } + if (chan[i].doNote) { if (!song.continuousVibrato) { chan[i].vibratoPos=0; } + dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15))); if (chan[i].legato && (!chan[i].inPorta || song.brokenPortaLegato)) { dispatchCmd(DivCommand(DIV_CMD_LEGATO,i,chan[i].note)); @@ -1187,6 +1188,7 @@ void DivEngine::processRow(int i, bool afterDelay) { } } chan[i].doNote=false; + if (!chan[i].keyOn && chan[i].scheduledSlideReset) { chan[i].portaNote=-1; chan[i].portaSpeed=-1; diff --git a/src/engine/song.h b/src/engine/song.h index 0d99cc747..871973900 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -331,7 +331,7 @@ struct DivSong { bool resetArpPhaseOnNewNote; bool ceilVolumeScaling; bool oldAlwaysSetVolume; - bool resetEffectsOnNewNote; + bool resetEffectsOnRowChange; std::vector ins; std::vector wave; @@ -456,7 +456,7 @@ struct DivSong { resetArpPhaseOnNewNote(false), ceilVolumeScaling(false), oldAlwaysSetVolume(false), - resetEffectsOnNewNote(false) { + resetEffectsOnRowChange(false) { for (int i=0; isong.resetEffectsOnRowChange); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("when enabled, effects in a row will be canceled after the row changes"); + } ImGui::EndTabItem(); } ImGui::EndTabBar();