diff --git a/papers/format.md b/papers/format.md index d3d4f1353..44faff0b2 100644 --- a/papers/format.md +++ b/papers/format.md @@ -361,7 +361,8 @@ size | description 1 | broken macro during note off in some FM chips (>=155) 1 | pre note (C64) does not compensate for portamento or legato (>=168) 1 | disable new NES DPCM features (>=183) - 4 | reserved + 1 | reset arp effect phase on new note (>=184) + 3 | reserved --- | **speed pattern of first song** (>=139) 1 | length of speed pattern (fail if this is lower than 0 or higher than 16) 16 | speed pattern (this overrides speed 1 and speed 2 settings) diff --git a/src/engine/engine.h b/src/engine/engine.h index fe604a61a..164379948 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -54,8 +54,8 @@ class DivWorkPool; #define DIV_UNSTABLE -#define DIV_VERSION "dev183" -#define DIV_ENGINE_VERSION 183 +#define DIV_VERSION "dev184" +#define DIV_ENGINE_VERSION 184 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 14dfe18ff..91305cb62 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1860,6 +1860,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { if (ds.version<183) { ds.oldDPCM=true; } + if (ds.version<184) { + ds.resetArpPhaseOnNewNote=false; + } ds.isDMF=false; reader.readS(); // reserved @@ -2383,7 +2386,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } else { reader.readC(); } - for (int i=0; i<4; i++) { + if (ds.version>=184) { + ds.resetArpPhaseOnNewNote=reader.readC(); + } else { + reader.readC(); + } + for (int i=0; i<3; i++) { reader.readC(); } } @@ -5448,7 +5456,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary, bool newPatternFormat) { w->writeC(song.brokenFMOff); w->writeC(song.preNoteNoEffect); w->writeC(song.oldDPCM); - for (int i=0; i<4; i++) { + w->writeC(song.resetArpPhaseOnNewNote); + for (int i=0; i<3; i++) { w->writeC(0); } diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index d0b36ddf9..438641797 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1070,6 +1070,9 @@ void DivEngine::processRow(int i, bool afterDelay) { } else if (!chan[i].noteOnInhibit) { dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,chan[i].note,chan[i].volume>>8)); chan[i].releasing=false; + if (song.resetArpPhaseOnNewNote) { + chan[i].arpStage=-1; + } chan[i].goneThroughNote=true; chan[i].wentThroughNote=true; keyHit[i]=true; diff --git a/src/engine/song.h b/src/engine/song.h index 00a7dbbf6..7a7e267c2 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -378,6 +378,7 @@ struct DivSong { bool brokenFMOff; bool preNoteNoEffect; bool oldDPCM; + bool resetArpPhaseOnNewNote; std::vector ins; std::vector wave; @@ -498,7 +499,8 @@ struct DivSong { brokenPortaLegato(false), brokenFMOff(false), preNoteNoEffect(false), - oldDPCM(false) { + oldDPCM(false), + resetArpPhaseOnNewNote(false) { for (int i=0; isong.resetArpPhaseOnNewNote); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("when enabled, arpeggio effect (00xy) position is reset on a new note."); + } ImGui::EndTabItem(); } ImGui::EndTabBar();