diff --git a/TODO.md b/TODO.md index e2826a605..603f0cb70 100644 --- a/TODO.md +++ b/TODO.md @@ -4,8 +4,9 @@ - CSM - MSM6258 pitch and clock select - the last three compat flags + - newVolumeScaling + - brokenOutVol - collapse/expand pattern and song -- add OPL drum instrument type - Game Boy envelope macro/sequence - rewrite the system name detection function anyway - volume commands should work on Game Boy diff --git a/src/engine/macroInt.cpp b/src/engine/macroInt.cpp index 00fee080e..6f853bffa 100644 --- a/src/engine/macroInt.cpp +++ b/src/engine/macroInt.cpp @@ -21,6 +21,12 @@ #include "instrument.h" #include "engine.h" +void DivMacroStruct::prepare(DivInstrumentMacro& source, DivEngine* e) { + has=had=actualHad=will=true; + mode=source.mode; + linger=(source.name=="vol" && e->song.volMacroLinger); +} + void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tick) { if (!tick) { had=false; @@ -46,6 +52,8 @@ void DivMacroStruct::doMacro(DivInstrumentMacro& source, bool released, bool tic if (pos>=source.len) { if (source.loop=0 && (source.loop>=source.rel || source.rel>=source.len)) { pos=source.loop; + } else if (linger) { + pos--; } else { has=false; } @@ -228,7 +236,7 @@ void DivMacroInt::init(DivInstrument* which) { } for (size_t i=0; iprepare(*macroSource[i]); + macroList[i]->prepare(*macroSource[i],e); } } diff --git a/src/engine/macroInt.h b/src/engine/macroInt.h index f1cd29a7e..d82cb2b21 100644 --- a/src/engine/macroInt.h +++ b/src/engine/macroInt.h @@ -27,19 +27,17 @@ class DivEngine; struct DivMacroStruct { int pos; int val; - bool has, had, actualHad, finished, will; + bool has, had, actualHad, finished, will, linger; unsigned int mode; void doMacro(DivInstrumentMacro& source, bool released, bool tick); void init() { pos=mode=0; has=had=actualHad=will=false; + linger=false; // TODO: test whether this breaks anything? val=0; } - void prepare(DivInstrumentMacro& source) { - has=had=actualHad=will=true; - mode=source.mode; - } + void prepare(DivInstrumentMacro& source, DivEngine* e); DivMacroStruct(): pos(0), val(0), @@ -48,6 +46,7 @@ struct DivMacroStruct { actualHad(false), finished(false), will(false), + linger(false), mode(0) {} }; diff --git a/src/gui/compatFlags.cpp b/src/gui/compatFlags.cpp index 03e13594c..d15f1722e 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -123,6 +123,18 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("when enabled, the pitch macro of an instrument is in linear space."); } + ImGui::Checkbox("Proper volume scaling strategy",&e->song.newVolumeScaling); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("when disabled:\n- log scaling: multiply\n- linear scaling: subtract\nwhen enabled:\n- log scaling: subtract\n- linear scaling: multiply"); + } + ImGui::Checkbox("Persist volume macro after it finishes",&e->song.volMacroLinger); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("when disabled, a value in the volume column that happens after the volume macro is done will disregard the macro."); + } + ImGui::Checkbox("Broken output volume on instrument change",&e->song.brokenOutVol); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("if enabled, no checks for the presence of a volume macro will be made.\nthis will cause the last macro value to linger unless a value in the volume column is present."); + } ImGui::Text("Pitch linearity:"); if (ImGui::RadioButton("None",e->song.linearPitch==0)) {