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; 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; int chanCount=chans;
quitDispatch(); quitDispatch();
BUSY_BEGIN; BUSY_BEGIN;
@ -1045,6 +1054,8 @@ void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) {
renderSamples(); renderSamples();
reset(); reset();
BUSY_END; BUSY_END;
return true;
} }
bool DivEngine::addSystem(DivSystem which) { bool DivEngine::addSystem(DivSystem which) {
@ -1097,6 +1108,65 @@ bool DivEngine::addSystem(DivSystem which) {
return true; 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? // TODO: maybe issue with subsongs?
bool DivEngine::removeSystem(int index, bool preserveOrder) { bool DivEngine::removeSystem(int index, bool preserveOrder) {
if (song.systemLen<=1) { if (song.systemLen<=1) {

View file

@ -1155,11 +1155,14 @@ class DivEngine {
void delUnusedSamples(); void delUnusedSamples();
// change system // change system
void changeSystem(int index, DivSystem which, bool preserveOrder=true); bool changeSystem(int index, DivSystem which, bool preserveOrder=true);
// add system // add system
bool addSystem(DivSystem which); bool addSystem(DivSystem which);
// duplicate system
bool duplicateSystem(int index, bool pat=true, bool end=false);
// remove system // remove system
bool removeSystem(int index, bool preserveOrder=true); 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())) { if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
DivSystem picked=systemPicker(); DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) { if (picked!=DIV_SYSTEM_NULL) {
e->changeSystem(i,picked,preserveChanPos); if (e->changeSystem(i,picked,preserveChanPos)) {
MARK_MODIFIED; MARK_MODIFIED;
if (e->song.autoSystem) { if (e->song.autoSystem) {
autoDetectSystem(); autoDetectSystem();
} }
updateWindowTitle(); updateWindowTitle();
} else {
showError("cannot change chip! ("+e->getLastError()+")");
}
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::EndMenu(); ImGui::EndMenu();

View file

@ -83,16 +83,27 @@ void FurnaceGUI::drawSysManager() {
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::TableNextColumn(); 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"); ImGui::Button("Change##SysChange");
if (ImGui::BeginPopupContextItem("SysPickerC",ImGuiPopupFlags_MouseButtonLeft)) { if (ImGui::BeginPopupContextItem("SysPickerC",ImGuiPopupFlags_MouseButtonLeft)) {
DivSystem picked=systemPicker(); DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) { if (picked!=DIV_SYSTEM_NULL) {
e->changeSystem(i,picked,preserveChanPos); if (e->changeSystem(i,picked,preserveChanPos)) {
MARK_MODIFIED; MARK_MODIFIED;
if (e->song.autoSystem) { if (e->song.autoSystem) {
autoDetectSystem(); autoDetectSystem();
} }
updateWindowTitle(); updateWindowTitle();
} else {
showError("cannot change chip! ("+e->getLastError()+")");
}
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::EndPopup(); ImGui::EndPopup();