GUI: add ability to customize startup system

This commit is contained in:
tildearrow 2022-04-30 01:37:37 -05:00
parent d79e5d77a7
commit 52c0044bd9
7 changed files with 361 additions and 160 deletions

View file

@ -13,12 +13,10 @@
- maybe YMU759 ADPCM channel - maybe YMU759 ADPCM channel
- ADPCM chips - ADPCM chips
- more effects for FM param control - more effects for FM param control
- ability to customize startup system
- store system presets in new file - store system presets in new file
- Game Boy envelope macro/sequence - Game Boy envelope macro/sequence
- option to display chip names instead of "multi-system" on title bar - option to display chip names instead of "multi-system" on title bar
- rewrite the system name detection function anyway - rewrite the system name detection function anyway
- add nightly.link
- scroll instrument/wave/sample list when selecting item - scroll instrument/wave/sample list when selecting item
- unified data view - unified data view
- volume commands should work on Game Boy - volume commands should work on Game Boy

View file

@ -620,6 +620,98 @@ void DivEngine::renderSamples() {
x1_010MemLen=memPos+256; x1_010MemLen=memPos+256;
} }
String DivEngine::encodeSysDesc(std::vector<int>& desc) {
String ret;
if (desc[0]!=0) {
int index=0;
for (size_t i=0; i<desc.size(); i+=4) {
ret+=fmt::sprintf("%d %d %d %d ",systemToFileFur((DivSystem)desc[i]),desc[i+1],desc[i+2],desc[i+3]);
index++;
if (index>=32) break;
}
}
return ret;
}
std::vector<int> DivEngine::decodeSysDesc(String desc) {
std::vector<int> ret;
bool hasVal=false;
bool negative=false;
int val=0;
int curStage=0;
int sysID, sysVol, sysPan, sysFlags;
desc+=' '; // ha
for (char i: desc) {
switch (i) {
case ' ':
if (hasVal) {
if (negative) val=-val;
switch (curStage) {
case 0:
sysID=val;
curStage++;
break;
case 1:
sysVol=val;
curStage++;
break;
case 2:
sysPan=val;
curStage++;
break;
case 3:
sysFlags=val;
if (systemFromFileFur(sysID)!=0) {
if (sysVol<-128) sysVol=-128;
if (sysVol>127) sysVol=127;
if (sysPan<-128) sysPan=-128;
if (sysPan>127) sysPan=127;
ret.push_back(systemFromFileFur(sysID));
ret.push_back(sysVol);
ret.push_back(sysPan);
ret.push_back(sysFlags);
}
curStage=0;
break;
}
hasVal=false;
negative=false;
val=0;
}
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
val=(val*10)+(i-'0');
hasVal=true;
break;
case '-':
if (!hasVal) negative=true;
break;
}
}
return ret;
}
void DivEngine::initSongWithDesc(const int* description) {
int chanCount=0;
if (description[0]!=0) {
int index=0;
for (int i=0; description[i]; i+=4) {
song.system[index]=(DivSystem)description[i];
song.systemVol[index]=description[i+1];
song.systemPan[index]=description[i+2];
song.systemFlags[index]=description[i+3];
index++;
chanCount+=getChannelCount(song.system[index]);
if (chanCount>=63) break;
if (index>=32) break;
}
song.systemLen=index;
}
}
void DivEngine::createNew(const int* description) { void DivEngine::createNew(const int* description) {
quitDispatch(); quitDispatch();
BUSY_BEGIN; BUSY_BEGIN;
@ -627,18 +719,7 @@ void DivEngine::createNew(const int* description) {
song.unload(); song.unload();
song=DivSong(); song=DivSong();
if (description!=NULL) { if (description!=NULL) {
if (description[0]!=0) { initSongWithDesc(description);
int index=0;
for (int i=0; description[i]; i+=4) {
song.system[index]=(DivSystem)description[i];
song.systemVol[index]=description[i+1];
song.systemPan[index]=description[i+2];
song.systemFlags[index]=description[i+3];
index++;
if (index>=32) break;
}
song.systemLen=index;
}
} }
recalcChans(); recalcChans();
renderSamples(); renderSamples();
@ -1207,6 +1288,8 @@ void DivEngine::recalcChans() {
for (int i=0; i<DIV_INS_MAX; i++) { for (int i=0; i<DIV_INS_MAX; i++) {
if (isInsTypePossible[i]) possibleInsTypes.push_back((DivInstrumentType)i); if (isInsTypePossible[i]) possibleInsTypes.push_back((DivInstrumentType)i);
} }
hasLoadedSomething=true;
} }
void DivEngine::reset() { void DivEngine::reset() {
@ -2666,6 +2749,18 @@ bool DivEngine::init() {
loadConf(); loadConf();
// set default system preset
if (!hasLoadedSomething) {
logI("setting");
std::vector<int> preset=decodeSysDesc(getConfString("initialSys",""));
logI("preset size %ld",preset.size());
if (preset.size()>0 && (preset.size()&3)==0) {
preset.push_back(0);
initSongWithDesc(preset.data());
}
hasLoadedSomething=true;
}
// init the rest of engine // init the rest of engine
bool haveAudio=false; bool haveAudio=false;
if (!initAudioBackend()) { if (!initAudioBackend()) {

View file

@ -298,6 +298,7 @@ class DivEngine {
bool midiIsDirect; bool midiIsDirect;
bool lowLatency; bool lowLatency;
bool systemsRegistered; bool systemsRegistered;
bool hasLoadedSomething;
int softLockCount; int softLockCount;
int subticks, ticks, curRow, curOrder, remainingLoops, nextSpeed; int subticks, ticks, curRow, curOrder, remainingLoops, nextSpeed;
double divider; double divider;
@ -398,6 +399,7 @@ class DivEngine {
bool deinitAudioBackend(); bool deinitAudioBackend();
void registerSystems(); void registerSystems();
void initSongWithDesc(const int* description);
void exchangeIns(int one, int two); void exchangeIns(int one, int two);
void swapChannels(int src, int dest); void swapChannels(int src, int dest);
@ -420,6 +422,9 @@ class DivEngine {
DivInstrument* getIns(int index, DivInstrumentType fallbackType=DIV_INS_FM); DivInstrument* getIns(int index, DivInstrumentType fallbackType=DIV_INS_FM);
DivWavetable* getWave(int index); DivWavetable* getWave(int index);
DivSample* getSample(int index); DivSample* getSample(int index);
// parse system setup description
String encodeSysDesc(std::vector<int>& desc);
std::vector<int> decodeSysDesc(String desc);
// start fresh // start fresh
void createNew(const int* description); void createNew(const int* description);
// load a file. // load a file.
@ -876,6 +881,7 @@ class DivEngine {
midiIsDirect(false), midiIsDirect(false),
lowLatency(false), lowLatency(false),
systemsRegistered(false), systemsRegistered(false),
hasLoadedSomething(false),
softLockCount(0), softLockCount(0),
subticks(0), subticks(0),
ticks(0), ticks(0),

View file

@ -2662,7 +2662,7 @@ bool FurnaceGUI::loop() {
if (ImGui::BeginMenu("configure system...")) { if (ImGui::BeginMenu("configure system...")) {
for (int i=0; i<e->song.systemLen; i++) { for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::TreeNode(fmt::sprintf("%d. %s##_SYSP%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { if (ImGui::TreeNode(fmt::sprintf("%d. %s##_SYSP%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
drawSysConf(i); drawSysConf(i,e->song.system[i],e->song.systemFlags[i],true);
ImGui::TreePop(); ImGui::TreePop();
} }
} }

View file

@ -857,6 +857,7 @@ class FurnaceGUI {
String audioDevice; String audioDevice;
String midiInDevice; String midiInDevice;
String midiOutDevice; String midiOutDevice;
std::vector<int> initialSys;
Settings(): Settings():
mainFontSize(18), mainFontSize(18),
@ -1114,7 +1115,7 @@ class FurnaceGUI {
void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size); void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size);
void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, const ImVec2& size, unsigned short instType); void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, const ImVec2& size, unsigned short instType);
void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size); void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size);
void drawSysConf(int i); void drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange);
// these ones offer ctrl-wheel fine value changes. // these ones offer ctrl-wheel fine value changes.
bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0); bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0);

View file

@ -23,6 +23,7 @@
#include "../fileutils.h" #include "../fileutils.h"
#include "util.h" #include "util.h"
#include "guiConst.h" #include "guiConst.h"
#include "intConst.h"
#include "ImGuiFileDialog.h" #include "ImGuiFileDialog.h"
#include "IconsFontAwesome4.h" #include "IconsFontAwesome4.h"
#include "misc/cpp/imgui_stdlib.h" #include "misc/cpp/imgui_stdlib.h"
@ -219,7 +220,8 @@ void FurnaceGUI::drawSettings() {
} }
if (ImGui::BeginTabBar("settingsTab")) { if (ImGui::BeginTabBar("settingsTab")) {
if (ImGui::BeginTabItem("General")) { if (ImGui::BeginTabItem("General")) {
ImGui::Text("Workspace layout"); ImGui::Text("Workspace layout:");
ImGui::SameLine();
if (ImGui::Button("Import")) { if (ImGui::Button("Import")) {
openFileDialog(GUI_FILE_IMPORT_LAYOUT); openFileDialog(GUI_FILE_IMPORT_LAYOUT);
} }
@ -231,7 +233,108 @@ void FurnaceGUI::drawSettings() {
if (ImGui::Button("Reset")) { if (ImGui::Button("Reset")) {
showWarning("Are you sure you want to reset the workspace layout?",GUI_WARN_RESET_LAYOUT); showWarning("Are you sure you want to reset the workspace layout?",GUI_WARN_RESET_LAYOUT);
} }
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Initial system/chips:");
ImGui::SameLine();
if (ImGui::Button("Current systems")) {
settings.initialSys.clear();
for (int i=0; i<e->song.systemLen; i++) {
settings.initialSys.push_back(e->song.system[i]);
settings.initialSys.push_back(e->song.systemVol[i]);
settings.initialSys.push_back(e->song.systemPan[i]);
settings.initialSys.push_back(e->song.systemFlags[i]);
}
}
ImGui::SameLine();
if (ImGui::Button("Randomize")) {
settings.initialSys.clear();
int howMany=1+rand()%3;
int totalAvailSys=0;
for (totalAvailSys=0; availableSystems[totalAvailSys]; totalAvailSys++);
if (totalAvailSys>0) {
for (int i=0; i<howMany; i++) {
settings.initialSys.push_back(availableSystems[rand()%totalAvailSys]);
settings.initialSys.push_back(64);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
}
} else {
settings.initialSys.push_back(DIV_SYSTEM_DUMMY);
settings.initialSys.push_back(64);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
}
}
ImGui::SameLine();
if (ImGui::Button("Reset to defaults")) {
settings.initialSys.clear();
settings.initialSys.push_back(DIV_SYSTEM_YM2612);
settings.initialSys.push_back(64);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
settings.initialSys.push_back(DIV_SYSTEM_SMS);
settings.initialSys.push_back(32);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
}
for (size_t i=0; i<settings.initialSys.size(); i+=4) {
bool doRemove=false;
bool doInvert=settings.initialSys[i+1]&128;
signed char vol=settings.initialSys[i+1]&127;
ImGui::PushID(i);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-ImGui::CalcTextSize("Invert").x-ImGui::GetFrameHeightWithSpacing()*2.0-ImGui::GetStyle().ItemSpacing.x);
if (ImGui::BeginCombo("##System",getSystemName((DivSystem)settings.initialSys[i]))) {
for (int j=0; availableSystems[j]; j++) {
if (ImGui::Selectable(getSystemName((DivSystem)availableSystems[j]),settings.initialSys[i]==availableSystems[j])) {
settings.initialSys[i]=availableSystems[j];
settings.initialSys[i+3]=0;
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
if (ImGui::Checkbox("Invert",&doInvert)) {
settings.initialSys[i+1]^=128;
}
ImGui::SameLine();
ImGui::BeginDisabled(settings.initialSys.size()<=4);
if (ImGui::Button(ICON_FA_MINUS "##InitSysRemove")) {
doRemove=true;
}
ImGui::EndDisabled();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale));
if (CWSliderScalar("Volume",ImGuiDataType_S8,&vol,&_ZERO,&_ONE_HUNDRED_TWENTY_SEVEN)) {
settings.initialSys[i+1]=(settings.initialSys[i+1]&128)|vol;
} rightClickable
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale));
CWSliderScalar("Panning",ImGuiDataType_S8,&settings.initialSys[i+2],&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN); rightClickable
// oh please MSVC don't cry
if (ImGui::TreeNode("Configure")) {
drawSysConf(-1,(DivSystem)settings.initialSys[i],(unsigned int&)settings.initialSys[i+3],false);
ImGui::TreePop();
}
ImGui::PopID();
if (doRemove && settings.initialSys.size()>=8) {
settings.initialSys.erase(settings.initialSys.begin()+i,settings.initialSys.begin()+i+4);
i-=4;
}
}
if (ImGui::Button(ICON_FA_PLUS "##InitSysAdd")) {
settings.initialSys.push_back(DIV_SYSTEM_YM2612);
settings.initialSys.push_back(64);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
}
ImGui::Separator();
ImGui::Text("Toggle channel solo on:"); ImGui::Text("Toggle channel solo on:");
if (ImGui::RadioButton("Right-click or double-click##soloA",settings.soloAction==0)) { if (ImGui::RadioButton("Right-click or double-click##soloA",settings.soloAction==0)) {
settings.soloAction=0; settings.soloAction=0;
@ -1755,6 +1858,19 @@ void FurnaceGUI::syncSettings() {
clampSetting(settings.moveWindowTitle,0,1); clampSetting(settings.moveWindowTitle,0,1);
clampSetting(settings.hiddenSystems,0,1); clampSetting(settings.hiddenSystems,0,1);
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
if (settings.initialSys.size()<4) {
settings.initialSys.clear();
settings.initialSys.push_back(DIV_SYSTEM_YM2612);
settings.initialSys.push_back(64);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
settings.initialSys.push_back(DIV_SYSTEM_SMS);
settings.initialSys.push_back(32);
settings.initialSys.push_back(0);
settings.initialSys.push_back(0);
}
// keybinds // keybinds
for (int i=0; i<GUI_ACTION_MAX; i++) { for (int i=0; i<GUI_ACTION_MAX; i++) {
if (guiActions[i].defaultBind==-1) continue; // not a bind if (guiActions[i].defaultBind==-1) continue; // not a bind
@ -1849,6 +1965,7 @@ void FurnaceGUI::commitSettings() {
e->setConf("eventDelay",settings.eventDelay); e->setConf("eventDelay",settings.eventDelay);
e->setConf("moveWindowTitle",settings.moveWindowTitle); e->setConf("moveWindowTitle",settings.moveWindowTitle);
e->setConf("hiddenSystems",settings.hiddenSystems); e->setConf("hiddenSystems",settings.hiddenSystems);
e->setConf("initialSys",e->encodeSysDesc(settings.initialSys));
// colors // colors
for (int i=0; i<GUI_COLOR_MAX; i++) { for (int i=0; i<GUI_COLOR_MAX; i++) {

View file

@ -19,75 +19,70 @@
#include "gui.h" #include "gui.h"
void FurnaceGUI::drawSysConf(int i) { void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange) {
unsigned int flags=e->song.systemFlags[i]; bool restart=settings.restartOnFlagChange && modifyOnChange;
bool restart=settings.restartOnFlagChange;
bool sysPal=flags&1; bool sysPal=flags&1;
switch (e->song.system[i]) { unsigned int copyOfFlags=flags;
switch (type) {
case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612:
case DIV_SYSTEM_YM2612_EXT: { case DIV_SYSTEM_YM2612_EXT: {
if (ImGui::RadioButton("NTSC (7.67MHz)",(flags&3)==0)) { if (ImGui::RadioButton("NTSC (7.67MHz)",(flags&3)==0)) {
e->setSysFlags(i,(flags&0x80000000)|0,restart); copyOfFlags=(flags&0x80000000)|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (7.61MHz)",(flags&3)==1)) { if (ImGui::RadioButton("PAL (7.61MHz)",(flags&3)==1)) {
e->setSysFlags(i,(flags&0x80000000)|1,restart); copyOfFlags=(flags&0x80000000)|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("FM Towns (8MHz)",(flags&3)==2)) { if (ImGui::RadioButton("FM Towns (8MHz)",(flags&3)==2)) {
e->setSysFlags(i,(flags&0x80000000)|2,restart); copyOfFlags=(flags&0x80000000)|2;
updateWindowTitle();
} }
if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",(flags&3)==3)) { if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",(flags&3)==3)) {
e->setSysFlags(i,(flags&0x80000000)|3,restart); copyOfFlags=(flags&0x80000000)|3;
updateWindowTitle();
} }
bool ladder=flags&0x80000000; bool ladder=flags&0x80000000;
if (ImGui::Checkbox("Enable DAC distortion",&ladder)) { if (ImGui::Checkbox("Enable DAC distortion",&ladder)) {
e->setSysFlags(i,(flags&(~0x80000000))|(ladder?0x80000000:0),restart); copyOfFlags=(flags&(~0x80000000))|(ladder?0x80000000:0);
updateWindowTitle();
} }
break; break;
} }
case DIV_SYSTEM_SMS: { case DIV_SYSTEM_SMS: {
ImGui::Text("Clock rate:"); ImGui::Text("Clock rate:");
if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&3)==0)) { if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&3)==0)) {
e->setSysFlags(i,(flags&(~3))|0,restart); copyOfFlags=(flags&(~3))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (3.55MHz)",(flags&3)==1)) { if (ImGui::RadioButton("PAL (3.55MHz)",(flags&3)==1)) {
e->setSysFlags(i,(flags&(~3))|1,restart); copyOfFlags=(flags&(~3))|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&3)==2)) { if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&3)==2)) {
e->setSysFlags(i,(flags&(~3))|2,restart); copyOfFlags=(flags&(~3))|2;
updateWindowTitle();
} }
if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&3)==3)) { if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&3)==3)) {
e->setSysFlags(i,(flags&(~3))|3,restart); copyOfFlags=(flags&(~3))|3;
updateWindowTitle();
} }
ImGui::Text("Chip type:"); ImGui::Text("Chip type:");
if (ImGui::RadioButton("Sega VDP/Master System",((flags>>2)&3)==0)) { if (ImGui::RadioButton("Sega VDP/Master System",((flags>>2)&3)==0)) {
e->setSysFlags(i,(flags&(~12))|0,restart); copyOfFlags=(flags&(~12))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("TI SN76489",((flags>>2)&3)==1)) { if (ImGui::RadioButton("TI SN76489",((flags>>2)&3)==1)) {
e->setSysFlags(i,(flags&(~12))|4,restart); copyOfFlags=(flags&(~12))|4;
updateWindowTitle();
} }
if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",((flags>>2)&3)==2)) { if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",((flags>>2)&3)==2)) {
e->setSysFlags(i,(flags&(~12))|8,restart); copyOfFlags=(flags&(~12))|8;
updateWindowTitle();
} }
/*if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) { /*if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) {
e->setSysFlags(i,(flags&3)|12); copyOfFlags=(flags&3)|12);
}*/ }*/
bool noPhaseReset=flags&16; bool noPhaseReset=flags&16;
if (ImGui::Checkbox("Disable noise period change phase reset",&noPhaseReset)) { if (ImGui::Checkbox("Disable noise period change phase reset",&noPhaseReset)) {
e->setSysFlags(i,(flags&(~16))|(noPhaseReset<<4),restart); copyOfFlags=(flags&(~16))|(noPhaseReset<<4);
updateWindowTitle();
} }
break; break;
} }
@ -96,54 +91,54 @@ void FurnaceGUI::drawSysConf(int i) {
case DIV_SYSTEM_VRC7: { case DIV_SYSTEM_VRC7: {
ImGui::Text("Clock rate:"); ImGui::Text("Clock rate:");
if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&15)==0)) { if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&15)==0)) {
e->setSysFlags(i,(flags&(~15))|0,restart); copyOfFlags=(flags&(~15))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) { if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) {
e->setSysFlags(i,(flags&(~15))|1,restart); copyOfFlags=(flags&(~15))|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&15)==2)) { if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&15)==2)) {
e->setSysFlags(i,(flags&(~15))|2,restart); copyOfFlags=(flags&(~15))|2;
updateWindowTitle();
} }
if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) { if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) {
e->setSysFlags(i,(flags&(~15))|3,restart); copyOfFlags=(flags&(~15))|3;
updateWindowTitle();
} }
if (e->song.system[i]!=DIV_SYSTEM_VRC7) { if (type!=DIV_SYSTEM_VRC7) {
ImGui::Text("Patch set:"); ImGui::Text("Patch set:");
if (ImGui::RadioButton("Yamaha YM2413",((flags>>4)&15)==0)) { if (ImGui::RadioButton("Yamaha YM2413",((flags>>4)&15)==0)) {
e->setSysFlags(i,(flags&(~0xf0))|0,restart); copyOfFlags=(flags&(~0xf0))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("Yamaha YMF281",((flags>>4)&15)==1)) { if (ImGui::RadioButton("Yamaha YMF281",((flags>>4)&15)==1)) {
e->setSysFlags(i,(flags&(~0xf0))|0x10,restart); copyOfFlags=(flags&(~0xf0))|0x10;
updateWindowTitle();
} }
if (ImGui::RadioButton("Yamaha YM2423",((flags>>4)&15)==2)) { if (ImGui::RadioButton("Yamaha YM2423",((flags>>4)&15)==2)) {
e->setSysFlags(i,(flags&(~0xf0))|0x20,restart); copyOfFlags=(flags&(~0xf0))|0x20;
updateWindowTitle();
} }
if (ImGui::RadioButton("Konami VRC7",((flags>>4)&15)==3)) { if (ImGui::RadioButton("Konami VRC7",((flags>>4)&15)==3)) {
e->setSysFlags(i,(flags&(~0xf0))|0x30,restart); copyOfFlags=(flags&(~0xf0))|0x30;
updateWindowTitle();
} }
} }
break; break;
} }
case DIV_SYSTEM_YM2151: case DIV_SYSTEM_YM2151:
if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",flags==0)) { if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",flags==0)) {
e->setSysFlags(i,0,restart); copyOfFlags=0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (3.55MHz)",flags==1)) { if (ImGui::RadioButton("PAL (3.55MHz)",flags==1)) {
e->setSysFlags(i,1,restart); copyOfFlags=1;
updateWindowTitle();
} }
if (ImGui::RadioButton("X1/X68000 (4MHz)",flags==2)) { if (ImGui::RadioButton("X1/X68000 (4MHz)",flags==2)) {
e->setSysFlags(i,2,restart); copyOfFlags=2;
updateWindowTitle();
} }
break; break;
case DIV_SYSTEM_NES: case DIV_SYSTEM_NES:
@ -151,120 +146,117 @@ void FurnaceGUI::drawSysConf(int i) {
case DIV_SYSTEM_FDS: case DIV_SYSTEM_FDS:
case DIV_SYSTEM_MMC5: case DIV_SYSTEM_MMC5:
if (ImGui::RadioButton("NTSC (1.79MHz)",flags==0)) { if (ImGui::RadioButton("NTSC (1.79MHz)",flags==0)) {
e->setSysFlags(i,0,restart); copyOfFlags=0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (1.67MHz)",flags==1)) { if (ImGui::RadioButton("PAL (1.67MHz)",flags==1)) {
e->setSysFlags(i,1,restart); copyOfFlags=1;
updateWindowTitle();
} }
if (ImGui::RadioButton("Dendy (1.77MHz)",flags==2)) { if (ImGui::RadioButton("Dendy (1.77MHz)",flags==2)) {
e->setSysFlags(i,2,restart); copyOfFlags=2;
updateWindowTitle();
} }
break; break;
case DIV_SYSTEM_C64_8580: case DIV_SYSTEM_C64_8580:
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_6581:
if (ImGui::RadioButton("NTSC (1.02MHz)",flags==0)) { if (ImGui::RadioButton("NTSC (1.02MHz)",flags==0)) {
e->setSysFlags(i,0,restart); copyOfFlags=0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (0.99MHz)",flags==1)) { if (ImGui::RadioButton("PAL (0.99MHz)",flags==1)) {
e->setSysFlags(i,1,restart); copyOfFlags=1;
updateWindowTitle();
} }
if (ImGui::RadioButton("SSI 2001 (0.89MHz)",flags==2)) { if (ImGui::RadioButton("SSI 2001 (0.89MHz)",flags==2)) {
e->setSysFlags(i,2,restart); copyOfFlags=2;
updateWindowTitle();
} }
break; break;
case DIV_SYSTEM_AY8910: case DIV_SYSTEM_AY8910:
case DIV_SYSTEM_AY8930: { case DIV_SYSTEM_AY8930: {
ImGui::Text("Clock rate:"); ImGui::Text("Clock rate:");
if (ImGui::RadioButton("1.79MHz (ZX Spectrum NTSC/MSX)",(flags&15)==0)) { if (ImGui::RadioButton("1.79MHz (ZX Spectrum NTSC/MSX)",(flags&15)==0)) {
e->setSysFlags(i,(flags&(~15))|0,restart); copyOfFlags=(flags&(~15))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("1.77MHz (ZX Spectrum)",(flags&15)==1)) { if (ImGui::RadioButton("1.77MHz (ZX Spectrum)",(flags&15)==1)) {
e->setSysFlags(i,(flags&(~15))|1,restart); copyOfFlags=(flags&(~15))|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("1.75MHz (ZX Spectrum)",(flags&15)==2)) { if (ImGui::RadioButton("1.75MHz (ZX Spectrum)",(flags&15)==2)) {
e->setSysFlags(i,(flags&(~15))|2,restart); copyOfFlags=(flags&(~15))|2;
updateWindowTitle();
} }
if (ImGui::RadioButton("2MHz (Atari ST/Sharp X1)",(flags&15)==3)) { if (ImGui::RadioButton("2MHz (Atari ST/Sharp X1)",(flags&15)==3)) {
e->setSysFlags(i,(flags&(~15))|3,restart); copyOfFlags=(flags&(~15))|3;
updateWindowTitle();
} }
if (ImGui::RadioButton("1.5MHz (Vectrex)",(flags&15)==4)) { if (ImGui::RadioButton("1.5MHz (Vectrex)",(flags&15)==4)) {
e->setSysFlags(i,(flags&(~15))|4,restart); copyOfFlags=(flags&(~15))|4;
updateWindowTitle();
} }
if (ImGui::RadioButton("1MHz (Amstrad CPC)",(flags&15)==5)) { if (ImGui::RadioButton("1MHz (Amstrad CPC)",(flags&15)==5)) {
e->setSysFlags(i,(flags&(~15))|5,restart); copyOfFlags=(flags&(~15))|5;
updateWindowTitle();
} }
if (ImGui::RadioButton("0.89MHz (Sunsoft 5B)",(flags&15)==6)) { if (ImGui::RadioButton("0.89MHz (Sunsoft 5B)",(flags&15)==6)) {
e->setSysFlags(i,(flags&(~15))|6,restart); copyOfFlags=(flags&(~15))|6;
updateWindowTitle();
} }
if (ImGui::RadioButton("1.67MHz (?)",(flags&15)==7)) { if (ImGui::RadioButton("1.67MHz (?)",(flags&15)==7)) {
e->setSysFlags(i,(flags&(~15))|7,restart); copyOfFlags=(flags&(~15))|7;
updateWindowTitle();
} }
if (ImGui::RadioButton("0.83MHz (Sunsoft 5B on PAL)",(flags&15)==8)) { if (ImGui::RadioButton("0.83MHz (Sunsoft 5B on PAL)",(flags&15)==8)) {
e->setSysFlags(i,(flags&(~15))|8,restart); copyOfFlags=(flags&(~15))|8;
updateWindowTitle();
} }
if (ImGui::RadioButton("1.10MHz (Gamate/VIC-20 PAL)",(flags&15)==9)) { if (ImGui::RadioButton("1.10MHz (Gamate/VIC-20 PAL)",(flags&15)==9)) {
e->setSysFlags(i,(flags&(~15))|9,restart); copyOfFlags=(flags&(~15))|9;
updateWindowTitle();
} }
if (ImGui::RadioButton("2^21Hz (Game Boy)",(flags&15)==10)) { if (ImGui::RadioButton("2^21Hz (Game Boy)",(flags&15)==10)) {
e->setSysFlags(i,(flags&(~15))|10,restart); copyOfFlags=(flags&(~15))|10;
updateWindowTitle();
} }
if (e->song.system[i]==DIV_SYSTEM_AY8910) { if (type==DIV_SYSTEM_AY8910) {
ImGui::Text("Chip type:"); ImGui::Text("Chip type:");
if (ImGui::RadioButton("AY-3-8910",(flags&0x30)==0)) { if (ImGui::RadioButton("AY-3-8910",(flags&0x30)==0)) {
e->setSysFlags(i,(flags&(~0x30))|0,restart); copyOfFlags=(flags&(~0x30))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("YM2149(F)",(flags&0x30)==16)) { if (ImGui::RadioButton("YM2149(F)",(flags&0x30)==16)) {
e->setSysFlags(i,(flags&(~0x30))|16,restart); copyOfFlags=(flags&(~0x30))|16;
updateWindowTitle();
} }
if (ImGui::RadioButton("Sunsoft 5B",(flags&0x30)==32)) { if (ImGui::RadioButton("Sunsoft 5B",(flags&0x30)==32)) {
e->setSysFlags(i,(flags&(~0x30))|32,restart); copyOfFlags=(flags&(~0x30))|32;
updateWindowTitle();
} }
if (ImGui::RadioButton("AY-3-8914",(flags&0x30)==48)) { if (ImGui::RadioButton("AY-3-8914",(flags&0x30)==48)) {
e->setSysFlags(i,(flags&(~0x30))|48,restart); copyOfFlags=(flags&(~0x30))|48;
updateWindowTitle();
} }
} }
bool stereo=flags&0x40; bool stereo=flags&0x40;
ImGui::BeginDisabled((flags&0x30)==32); ImGui::BeginDisabled((flags&0x30)==32);
if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) { if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) {
e->setSysFlags(i,(flags&(~0x40))|(stereo?0x40:0),restart); copyOfFlags=(flags&(~0x40))|(stereo?0x40:0);
updateWindowTitle();
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
break; break;
} }
case DIV_SYSTEM_SAA1099: case DIV_SYSTEM_SAA1099:
if (ImGui::RadioButton("SAM Coupé (8MHz)",flags==0)) { if (ImGui::RadioButton("SAM Coupé (8MHz)",flags==0)) {
e->setSysFlags(i,0,restart); copyOfFlags=0;
updateWindowTitle();
} }
if (ImGui::RadioButton("NTSC (7.15MHz)",flags==1)) { if (ImGui::RadioButton("NTSC (7.15MHz)",flags==1)) {
e->setSysFlags(i,1,restart); copyOfFlags=1;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (7.09MHz)",flags==2)) { if (ImGui::RadioButton("PAL (7.09MHz)",flags==2)) {
e->setSysFlags(i,2,restart); copyOfFlags=2;
updateWindowTitle();
} }
break; break;
case DIV_SYSTEM_AMIGA: { case DIV_SYSTEM_AMIGA: {
@ -273,44 +265,37 @@ void FurnaceGUI::drawSysConf(int i) {
if (CWSliderInt("##StereoSep",&stereoSep,0,127)) { if (CWSliderInt("##StereoSep",&stereoSep,0,127)) {
if (stereoSep<0) stereoSep=0; if (stereoSep<0) stereoSep=0;
if (stereoSep>127) stereoSep=127; if (stereoSep>127) stereoSep=127;
e->setSysFlags(i,(flags&(~0x7f00))|((stereoSep&127)<<8),restart); copyOfFlags=(flags&(~0x7f00))|((stereoSep&127)<<8);
updateWindowTitle();
} rightClickable } rightClickable
if (ImGui::RadioButton("Amiga 500 (OCS)",(flags&2)==0)) { if (ImGui::RadioButton("Amiga 500 (OCS)",(flags&2)==0)) {
e->setSysFlags(i,flags&(~2),restart); copyOfFlags=flags&(~2);
} }
if (ImGui::RadioButton("Amiga 1200 (AGA)",(flags&2)==2)) { if (ImGui::RadioButton("Amiga 1200 (AGA)",(flags&2)==2)) {
e->setSysFlags(i,(flags&(~2))|2,restart); copyOfFlags=(flags&(~2))|2;
} }
sysPal=flags&1; sysPal=flags&1;
if (ImGui::Checkbox("PAL",&sysPal)) { if (ImGui::Checkbox("PAL",&sysPal)) {
e->setSysFlags(i,(flags&(~1))|(unsigned int)sysPal,restart); copyOfFlags=(flags&(~1))|(unsigned int)sysPal;
updateWindowTitle();
} }
bool bypassLimits=flags&4; bool bypassLimits=flags&4;
if (ImGui::Checkbox("Bypass frequency limits",&bypassLimits)) { if (ImGui::Checkbox("Bypass frequency limits",&bypassLimits)) {
e->setSysFlags(i,(flags&(~4))|(bypassLimits<<2),restart); copyOfFlags=(flags&(~4))|(bypassLimits<<2);
updateWindowTitle();
} }
break; break;
} }
case DIV_SYSTEM_PCSPKR: { case DIV_SYSTEM_PCSPKR: {
ImGui::Text("Speaker type:"); ImGui::Text("Speaker type:");
if (ImGui::RadioButton("Unfiltered",(flags&3)==0)) { if (ImGui::RadioButton("Unfiltered",(flags&3)==0)) {
e->setSysFlags(i,(flags&(~3))|0,restart); copyOfFlags=(flags&(~3))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("Cone",(flags&3)==1)) { if (ImGui::RadioButton("Cone",(flags&3)==1)) {
e->setSysFlags(i,(flags&(~3))|1,restart); copyOfFlags=(flags&(~3))|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("Piezo",(flags&3)==2)) { if (ImGui::RadioButton("Piezo",(flags&3)==2)) {
e->setSysFlags(i,(flags&(~3))|2,restart); copyOfFlags=(flags&(~3))|2;
updateWindowTitle();
} }
if (ImGui::RadioButton("Use system beeper (Linux only!)",(flags&3)==3)) { if (ImGui::RadioButton("Use system beeper (Linux only!)",(flags&3)==3)) {
e->setSysFlags(i,(flags&(~3))|3,restart); copyOfFlags=(flags&(~3))|3;
updateWindowTitle();
} }
break; break;
} }
@ -320,62 +305,53 @@ void FurnaceGUI::drawSysConf(int i) {
if (CWSliderInt("##EchoBufSize",&echoBufSize,0,2725)) { if (CWSliderInt("##EchoBufSize",&echoBufSize,0,2725)) {
if (echoBufSize<0) echoBufSize=0; if (echoBufSize<0) echoBufSize=0;
if (echoBufSize>2725) echoBufSize=2725; if (echoBufSize>2725) echoBufSize=2725;
e->setSysFlags(i,(flags & ~4095) | ((2725 - echoBufSize) & 4095),restart); copyOfFlags=(flags & ~4095) | ((2725 - echoBufSize) & 4095);
updateWindowTitle();
} rightClickable } rightClickable
ImGui::Text("Echo feedback:"); ImGui::Text("Echo feedback:");
int echoFeedback=(flags>>12)&255; int echoFeedback=(flags>>12)&255;
if (CWSliderInt("##EchoFeedback",&echoFeedback,0,255)) { if (CWSliderInt("##EchoFeedback",&echoFeedback,0,255)) {
if (echoFeedback<0) echoFeedback=0; if (echoFeedback<0) echoFeedback=0;
if (echoFeedback>255) echoFeedback=255; if (echoFeedback>255) echoFeedback=255;
e->setSysFlags(i,(flags & ~(255 << 12)) | ((echoFeedback & 255) << 12),restart); copyOfFlags=(flags & ~(255 << 12)) | ((echoFeedback & 255) << 12);
updateWindowTitle();
} rightClickable } rightClickable
break; break;
} }
case DIV_SYSTEM_X1_010: { case DIV_SYSTEM_X1_010: {
ImGui::Text("Clock rate:"); ImGui::Text("Clock rate:");
if (ImGui::RadioButton("16MHz (Seta 1)",(flags&15)==0)) { if (ImGui::RadioButton("16MHz (Seta 1)",(flags&15)==0)) {
e->setSysFlags(i,(flags&(~15))|0,restart); copyOfFlags=(flags&(~15))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("16.67MHz (Seta 2)",(flags&15)==1)) { if (ImGui::RadioButton("16.67MHz (Seta 2)",(flags&15)==1)) {
e->setSysFlags(i,(flags&(~15))|1,restart); copyOfFlags=(flags&(~15))|1;
updateWindowTitle();
} }
bool x1_010Stereo=flags&16; bool x1_010Stereo=flags&16;
if (ImGui::Checkbox("Stereo",&x1_010Stereo)) { if (ImGui::Checkbox("Stereo",&x1_010Stereo)) {
e->setSysFlags(i,(flags&(~16))|(x1_010Stereo<<4),restart); copyOfFlags=(flags&(~16))|(x1_010Stereo<<4);
updateWindowTitle();
} }
break; break;
} }
case DIV_SYSTEM_N163: { case DIV_SYSTEM_N163: {
ImGui::Text("Clock rate:"); ImGui::Text("Clock rate:");
if (ImGui::RadioButton("NTSC (1.79MHz)",(flags&15)==0)) { if (ImGui::RadioButton("NTSC (1.79MHz)",(flags&15)==0)) {
e->setSysFlags(i,(flags&(~15))|0,restart); copyOfFlags=(flags&(~15))|0;
updateWindowTitle();
} }
if (ImGui::RadioButton("PAL (1.67MHz)",(flags&15)==1)) { if (ImGui::RadioButton("PAL (1.67MHz)",(flags&15)==1)) {
e->setSysFlags(i,(flags&(~15))|1,restart); copyOfFlags=(flags&(~15))|1;
updateWindowTitle();
} }
if (ImGui::RadioButton("Dendy (1.77MHz)",(flags&15)==2)) { if (ImGui::RadioButton("Dendy (1.77MHz)",(flags&15)==2)) {
e->setSysFlags(i,(flags&(~15))|2,restart); copyOfFlags=(flags&(~15))|2;
updateWindowTitle();
} }
ImGui::Text("Initial channel limit:"); ImGui::Text("Initial channel limit:");
int initialChannelLimit=((flags>>4)&7)+1; int initialChannelLimit=((flags>>4)&7)+1;
if (CWSliderInt("##InitialChannelLimit",&initialChannelLimit,1,8)) { if (CWSliderInt("##InitialChannelLimit",&initialChannelLimit,1,8)) {
if (initialChannelLimit<1) initialChannelLimit=1; if (initialChannelLimit<1) initialChannelLimit=1;
if (initialChannelLimit>8) initialChannelLimit=8; if (initialChannelLimit>8) initialChannelLimit=8;
e->setSysFlags(i,(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4),restart); copyOfFlags=(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4);
updateWindowTitle();
} rightClickable } rightClickable
bool n163Multiplex=flags&128; bool n163Multiplex=flags&128;
if (ImGui::Checkbox("Disable hissing",&n163Multiplex)) { if (ImGui::Checkbox("Disable hissing",&n163Multiplex)) {
e->setSysFlags(i,(flags&(~128))|(n163Multiplex<<7),restart); copyOfFlags=(flags&(~128))|(n163Multiplex<<7);
updateWindowTitle();
} }
break; break;
} }
@ -395,9 +371,17 @@ void FurnaceGUI::drawSysConf(int i) {
break; break;
default: default:
if (ImGui::Checkbox("PAL",&sysPal)) { if (ImGui::Checkbox("PAL",&sysPal)) {
e->setSysFlags(i,sysPal,restart); copyOfFlags=sysPal;
updateWindowTitle();
} }
break; break;
} }
if (copyOfFlags!=flags) {
if (chan>=0) {
e->setSysFlags(chan,copyOfFlags,restart);
updateWindowTitle();
} else {
flags=copyOfFlags;
}
}
} }