fix crash when changing chip

it was somehow possible to exceed the channel limit...
This commit is contained in:
tildearrow 2024-02-21 15:55:15 -05:00
parent 9dbb1f7371
commit f0bf58eef2
4 changed files with 99 additions and 12 deletions

View file

@ -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; j<DIV_MAX_OUTPUTS; j++) {
song.patchbay.push_back((i<<20)|j);
}
} else {
if (outs>0) song.patchbay.reserve(outs);
for (unsigned int j=0; j<outs; j++) {
song.patchbay.push_back((i<<20)|(j<<16)|j);
}
}
}
}
// duplicate patterns
if (pat) {
}
saveLock.unlock();
renderSamples();
reset();
BUSY_END;
return true;
}
// TODO: maybe issue with subsongs?
bool DivEngine::removeSystem(int index, bool preserveOrder) {
if (song.systemLen<=1) {

View file

@ -1155,11 +1155,14 @@ class DivEngine {
void delUnusedSamples();
// change system
void changeSystem(int index, DivSystem which, bool preserveOrder=true);
bool changeSystem(int index, DivSystem which, bool preserveOrder=true);
// add system
bool addSystem(DivSystem which);
// duplicate system
bool duplicateSystem(int index, bool pat=true, bool end=false);
// remove system
bool removeSystem(int index, bool preserveOrder=true);

View file

@ -4284,12 +4284,15 @@ bool FurnaceGUI::loop() {
if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.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();

View file

@ -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();