diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index b7db4c353..e802b22e0 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1424,6 +1424,8 @@ void DivEngine::setLoops(int loops) { void DivEngine::playSub(bool preserveDrift) { reset(); if (preserveDrift && curOrder==0) return; + bool oldRepeatPattern=repeatPattern; + repeatPattern=false; int goal=curOrder; curOrder=0; curRow=0; @@ -1446,6 +1448,7 @@ void DivEngine::playSub(bool preserveDrift) { if (goal>0) { dispatch->forceIns(); } + repeatPattern=oldRepeatPattern; if (preserveDrift) { clockDrift=prevDrift; } else { @@ -1548,6 +1551,16 @@ int DivEngine::getTotalTicks() { return totalTicks; } +bool DivEngine::getRepeatPattern() { + return repeatPattern; +} + +void DivEngine::setRepeatPattern(bool value) { + isBusy.lock(); + repeatPattern=value; + isBusy.unlock(); +} + bool DivEngine::hasExtValue() { return extValuePresent; } diff --git a/src/engine/engine.h b/src/engine/engine.h index 3b125b0a8..5e85b24ba 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -78,6 +78,7 @@ class DivEngine { bool endOfSong; bool consoleMode; bool extValuePresent; + bool repeatPattern; int ticks, cycles, curRow, curOrder, remainingLoops, nextSpeed, clockDrift; int changeOrd, changePos, totalTicks, totalCmds, lastCmds, cmdsPerSecond; unsigned char extValue; @@ -232,6 +233,12 @@ class DivEngine { // get time int getTotalTicks(); + // get repeat pattern + bool getRepeatPattern(); + + // set repeat pattern + void setRepeatPattern(bool value); + // has ext value bool hasExtValue(); @@ -311,6 +318,7 @@ class DivEngine { endOfSong(false), consoleMode(false), extValuePresent(false), + repeatPattern(false), ticks(0), cycles(0), curRow(0), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 0d23e3fa3..f68eefb17 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -5,6 +5,7 @@ void DivEngine::nextOrder() { curRow=0; + if (repeatPattern) return; if (++curOrder>=song.ordersLen) { endOfSong=true; curOrder=0; @@ -385,14 +386,14 @@ void DivEngine::processRow(int i, bool afterDelay) { speed2=effectVal; break; case 0x0b: // change order - if (changeOrd==-1) { + if (changeOrd<0) { changeOrd=effectVal; changePos=0; } break; case 0x0d: // next order - if (changeOrd==-1) { - changeOrd=curOrder+1; + if (changeOrd<0) { + changeOrd=-2; changePos=effectVal; } break; @@ -610,15 +611,21 @@ void DivEngine::nextRow() { if (++curRow>=song.patLen) { nextOrder(); } - if (changeOrd>=0) { - curRow=changePos; - if (changeOrd<=curOrder) endOfSong=true; - curOrder=changeOrd; - if (curOrder>=song.ordersLen) { - curOrder=0; - endOfSong=true; + if (changeOrd!=-1) { + if (repeatPattern) { + curRow=0; + changeOrd=-1; + } else { + curRow=changePos; + if (changeOrd==-2) changeOrd=curOrder+1; + if (changeOrd<=curOrder) endOfSong=true; + curOrder=changeOrd; + if (curOrder>=song.ordersLen) { + curOrder=0; + endOfSong=true; + } + changeOrd=-1; } - changeOrd=-1; } if (song.system==DIV_SYSTEM_YMU759) { diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 8077cba44..2755f6b2b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -269,6 +269,17 @@ void FurnaceGUI::drawEditControls() { if (ImGui::Button(ICON_FA_STOP "##Stop")) { e->stop(); } + + ImGui::Text("Follow"); + ImGui::SameLine(); + ImGui::Checkbox("Orders",&followOrders); + ImGui::SameLine(); + ImGui::Checkbox("Pattern",&followPattern); + + bool repeatPattern=e->getRepeatPattern(); + if (ImGui::Checkbox("Repeat pattern",&repeatPattern)) { + e->setRepeatPattern(repeatPattern); + } } if (ImGui::IsWindowFocused()) curWindow=GUI_WINDOW_EDIT_CONTROLS; ImGui::End(); @@ -365,7 +376,9 @@ void FurnaceGUI::drawOrders() { ImGui::TableSetupScrollFreeze(0,1); float lineHeight=(ImGui::GetTextLineHeight()+4*dpiScale); if (e->isPlaying()) { - ImGui::SetScrollY((e->getOrder()+1)*lineHeight-(ImGui::GetContentRegionAvail().y/2)); + if (followOrders) { + ImGui::SetScrollY((e->getOrder()+1)*lineHeight-(ImGui::GetContentRegionAvail().y/2)); + } } ImGui::TableNextRow(0,lineHeight); ImGui::TableNextColumn(); @@ -954,7 +967,7 @@ void FurnaceGUI::drawPattern() { int curRow=e->getRow(); if (e->isPlaying()) updateScroll(curRow); if (nextScroll>-0.5f) { - ImGui::SetScrollY(nextScroll); + if (followPattern) ImGui::SetScrollY(nextScroll); nextScroll=-1.0f; } ImGui::TableSetupScrollFreeze(1,1); @@ -1652,6 +1665,22 @@ void FurnaceGUI::doPaste() { } void FurnaceGUI::keyDown(SDL_Event& ev) { + // GLOBAL KEYS + switch (ev.key.keysym.sym) { + case SDLK_F5: + if (!e->isPlaying()) e->play(); + break; + case SDLK_F6: + e->play(); + break; + case SDLK_F7: + e->play(); + break; + case SDLK_F8: + e->stop(); + break; + } + // PER-WINDOW KEYS switch (curWindow) { case GUI_WINDOW_PATTERN: { if (ev.key.keysym.mod&KMOD_CTRL) { @@ -1694,6 +1723,13 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { case SDLK_INSERT: doInsert(); break; + case SDLK_RETURN: + if (e->isPlaying()) { + e->stop(); + } else { + e->play(); + } + break; default: if (selStart.xFine==0) { // note try { @@ -2307,6 +2343,8 @@ FurnaceGUI::FurnaceGUI(): selecting(false), curNibble(false), extraChannelButtons(false), + followOrders(true), + followPattern(true), curWindow(GUI_WINDOW_NOTHING), arpMacroScroll(0), macroDragStart(0,0), diff --git a/src/gui/gui.h b/src/gui/gui.h index 6c9e65548..26bade4fe 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -97,7 +97,7 @@ class FurnaceGUI { bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; SelectionPoint selStart, selEnd; - bool selecting, curNibble, extraChannelButtons; + bool selecting, curNibble, extraChannelButtons, followOrders, followPattern; FurnaceGUIWindows curWindow; std::map noteKeys;