From f0bf58eef28a55045574b9234592c30ff7d4428c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 21 Feb 2024 15:55:15 -0500 Subject: [PATCH] fix crash when changing chip it was somehow possible to exceed the channel limit... --- src/engine/engine.cpp | 72 +++++++++++++++++++++++++++++++++++++++++- src/engine/engine.h | 5 ++- src/gui/gui.cpp | 13 +++++--- src/gui/sysManager.cpp | 21 +++++++++--- 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index eb02287ab..79163b402 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1003,7 +1003,16 @@ void DivEngine::delUnusedSamples() { BUSY_END; } -void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { +bool DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { + if (index<0 || index>=song.systemLen) { + lastError="invalid index"; + return false; + } + if (chans-getChannelCount(song.system[index])+getChannelCount(which)>DIV_MAX_CHANS) { + lastError=fmt::sprintf("max number of total channels is %d",DIV_MAX_CHANS); + return false; + } + int chanCount=chans; quitDispatch(); BUSY_BEGIN; @@ -1045,6 +1054,8 @@ void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { renderSamples(); reset(); BUSY_END; + + return true; } bool DivEngine::addSystem(DivSystem which) { @@ -1097,6 +1108,65 @@ bool DivEngine::addSystem(DivSystem which) { return true; } +bool DivEngine::duplicateSystem(int index, bool pat, bool end) { + if (index<0 || index>=song.systemLen) { + lastError="invalid index"; + return false; + } + if (song.systemLen>DIV_MAX_CHIPS) { + lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS); + return false; + } + if (chans+getChannelCount(song.system[index])>DIV_MAX_CHANS) { + lastError=fmt::sprintf("max number of total channels is %d",DIV_MAX_CHANS); + return false; + } + quitDispatch(); + BUSY_BEGIN; + saveLock.lock(); + song.system[song.systemLen]=song.system[index]; + song.systemVol[song.systemLen]=song.systemVol[index]; + song.systemPan[song.systemLen]=song.systemPan[index]; + song.systemPanFR[song.systemLen]=song.systemPanFR[index]; + song.systemFlags[song.systemLen++]=song.systemFlags[index]; + recalcChans(); + saveLock.unlock(); + BUSY_END; + initDispatch(); + BUSY_BEGIN; + saveLock.lock(); + if (song.patchbayAuto) { + autoPatchbay(); + } else { + int i=song.systemLen-1; + if (disCont[i].dispatch!=NULL) { + unsigned int outs=disCont[i].dispatch->getOutputCount(); + if (outs>16) outs=16; + if (outs<2) { + song.patchbay.reserve(DIV_MAX_OUTPUTS); + for (unsigned int j=0; j0) song.patchbay.reserve(outs); + for (unsigned int j=0; jsong.system[i]),i).c_str())) { DivSystem picked=systemPicker(); if (picked!=DIV_SYSTEM_NULL) { - e->changeSystem(i,picked,preserveChanPos); - MARK_MODIFIED; - if (e->song.autoSystem) { - autoDetectSystem(); + if (e->changeSystem(i,picked,preserveChanPos)) { + MARK_MODIFIED; + if (e->song.autoSystem) { + autoDetectSystem(); + } + updateWindowTitle(); + } else { + showError("cannot change chip! ("+e->getLastError()+")"); } - updateWindowTitle(); ImGui::CloseCurrentPopup(); } ImGui::EndMenu(); diff --git a/src/gui/sysManager.cpp b/src/gui/sysManager.cpp index efe2c29a1..17489c923 100644 --- a/src/gui/sysManager.cpp +++ b/src/gui/sysManager.cpp @@ -83,16 +83,27 @@ void FurnaceGUI::drawSysManager() { ImGui::TreePop(); } ImGui::TableNextColumn(); + if (ImGui::Button("Clone##SysDup")) { + if (!e->duplicateSystem(i)) { + showError("cannot clone chip! ("+e->getLastError()+")"); + } else { + MARK_MODIFIED; + } + } + ImGui::SameLine(); ImGui::Button("Change##SysChange"); if (ImGui::BeginPopupContextItem("SysPickerC",ImGuiPopupFlags_MouseButtonLeft)) { DivSystem picked=systemPicker(); if (picked!=DIV_SYSTEM_NULL) { - e->changeSystem(i,picked,preserveChanPos); - MARK_MODIFIED; - if (e->song.autoSystem) { - autoDetectSystem(); + if (e->changeSystem(i,picked,preserveChanPos)) { + MARK_MODIFIED; + if (e->song.autoSystem) { + autoDetectSystem(); + } + updateWindowTitle(); + } else { + showError("cannot change chip! ("+e->getLastError()+")"); } - updateWindowTitle(); ImGui::CloseCurrentPopup(); } ImGui::EndPopup();