Merge branch 'master' of https://github.com/tildearrow/furnace into command-palette

This commit is contained in:
YohananDiamond 2023-09-04 19:32:24 -03:00
commit 5a5090f711
168 changed files with 5101 additions and 1926 deletions

View file

@ -417,6 +417,7 @@ void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLe
}
bool FurnaceGUI::CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) {
flags^=ImGuiSliderFlags_AlwaysClamp;
if (ImGui::SliderScalar(label,data_type,p_data,p_min,p_max,format,flags)) {
return true;
}
@ -453,6 +454,7 @@ bool FurnaceGUI::CWSliderScalar(const char* label, ImGuiDataType data_type, void
}
bool FurnaceGUI::CWVSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) {
flags^=ImGuiSliderFlags_AlwaysClamp;
if (ImGui::VSliderScalar(label,size,data_type,p_data,p_min,p_max,format,flags)) {
return true;
}
@ -1103,10 +1105,21 @@ void FurnaceGUI::setOrder(unsigned char order, bool forced) {
}
void FurnaceGUI::stop() {
bool wasPlaying=e->isPlaying();
e->walkSong(loopOrder,loopRow,loopEnd);
e->stop();
curNibble=false;
orderNibble=false;
if (followPattern && wasPlaying) {
nextScroll=-1.0f;
nextAddScroll=0.0f;
cursor.y=e->getRow();
if (selStart.xCoarse==selEnd.xCoarse && selStart.xFine==selEnd.xFine && selStart.y==selEnd.y && !selecting) {
selStart=cursor;
selEnd=cursor;
}
updateScroll(cursor.y);
}
}
void FurnaceGUI::previewNote(int refChan, int note, bool autoNote) {
@ -1554,7 +1567,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Open File",
{"compatible files", "*.fur *.dmf *.mod *.fc13 *.fc14 *.smod *.fc",
"all files", "*"},
"compatible files{.fur,.dmf,.mod,.fc13,.fc14,.smod,.fc},.*",
workingDirSong,
dpiScale
);
@ -1567,7 +1579,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Restore Backup",
{"Furnace song", "*.fur"},
"Furnace song{.fur}",
backupPath+String(DIR_SEPARATOR_STR),
dpiScale
);
@ -1577,7 +1588,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save File",
{"Furnace song", "*.fur"},
"Furnace song{.fur}",
workingDirSong,
dpiScale
);
@ -1587,7 +1597,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save File",
{"DefleMask 1.1.3 module", "*.dmf"},
"DefleMask 1.1.3 module{.dmf}",
workingDirSong,
dpiScale
);
@ -1597,7 +1606,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save File",
{"DefleMask 1.0/legacy module", "*.dmf"},
"DefleMask 1.0/legacy module{.dmf}",
workingDirSong,
dpiScale
);
@ -1614,8 +1622,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
if (!dirExists(workingDirIns)) workingDirIns=getHomeDir();
hasOpened=fileDialog->openLoad(
"Load Instrument",
// TODO supply loadable formats in a dynamic, scalable, "DRY" way.
// thank the author of IGFD for making things impossible
{"all compatible files", "*.fui *.dmp *.tfi *.vgi *.s3i *.sbi *.opli *.opni *.y12 *.bnk *.ff *.gyb *.opm *.wopl *.wopn",
"Furnace instrument", "*.fui",
"DefleMask preset", "*.dmp",
@ -1633,7 +1639,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Wohlstand WOPL bank", "*.wopl",
"Wohlstand WOPN bank", "*.wopn",
"all files", "*"},
"all compatible files{.fui,.dmp,.tfi,.vgi,.s3i,.sbi,.opli,.opni,.y12,.bnk,.ff,.gyb,.opm,.wopl,.wopn},.*",
workingDirIns,
dpiScale,
[this](const char* path) {
@ -1668,7 +1673,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Instrument",
{"Furnace instrument", "*.fui"},
"Furnace instrument{.fui}",
workingDirIns,
dpiScale
);
@ -1678,7 +1682,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Instrument",
{"DefleMask preset", "*.dmp"},
"DefleMask preset{.dmp}",
workingDirIns,
dpiScale
);
@ -1690,7 +1693,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Load Wavetable",
{"compatible files", "*.fuw *.dmw",
"all files", "*"},
"compatible files{.fuw,.dmw},.*",
workingDirWave,
dpiScale,
NULL, // TODO
@ -1702,7 +1704,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Wavetable",
{"Furnace wavetable", ".fuw"},
"Furnace wavetable{.fuw}",
workingDirWave,
dpiScale
);
@ -1712,7 +1713,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Wavetable",
{"DefleMask wavetable", ".dmw"},
"DefleMask wavetable{.dmw}",
workingDirWave,
dpiScale
);
@ -1722,7 +1722,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Wavetable",
{"raw data", ".raw"},
"raw data{.raw}",
workingDirWave,
dpiScale
);
@ -1734,7 +1733,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Load Sample",
{"compatible files", "*.wav *.dmc *.brr",
"all files", "*"},
"compatible files{.wav,.dmc,.brr},.*",
workingDirSample,
dpiScale,
NULL, // TODO
@ -1747,7 +1745,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Load Raw Sample",
{"all files", "*"},
".*",
workingDirSample,
dpiScale
);
@ -1757,7 +1754,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Save Sample",
{"Wave file", "*.wav"},
"Wave file{.wav}",
workingDirSample,
dpiScale
);
@ -1765,9 +1761,8 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
case GUI_FILE_SAMPLE_SAVE_RAW:
if (!dirExists(workingDirSample)) workingDirSample=getHomeDir();
hasOpened=fileDialog->openSave(
"Load Raw Sample",
"Save Raw Sample",
{"all files", "*"},
".*",
workingDirSample,
dpiScale
);
@ -1777,7 +1772,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Audio",
{"Wave file", "*.wav"},
"Wave file{.wav}",
workingDirAudioExport,
dpiScale
);
@ -1787,7 +1781,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Audio",
{"Wave file", "*.wav"},
"Wave file{.wav}",
workingDirAudioExport,
dpiScale
);
@ -1797,7 +1790,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Audio",
{"Wave file", "*.wav"},
"Wave file{.wav}",
workingDirAudioExport,
dpiScale
);
@ -1807,7 +1799,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export VGM",
{"VGM file", "*.vgm"},
"VGM file{.vgm}",
workingDirVGMExport,
dpiScale
);
@ -1817,7 +1808,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export ZSM",
{"ZSM file", "*.zsm"},
"ZSM file{.zsm}",
workingDirZSMExport,
dpiScale
);
@ -1827,7 +1817,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Command Stream",
{"text file", "*.txt"},
"text file{.txt}",
workingDirROMExport,
dpiScale
);
@ -1837,7 +1826,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Command Stream",
{"binary file", "*.bin"},
"binary file{.bin}",
workingDirROMExport,
dpiScale
);
@ -1850,7 +1838,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Font",
{"compatible files", "*.ttf *.otf *.ttc"},
"compatible files{.ttf,.otf,.ttc}",
workingDirFont,
dpiScale
);
@ -1860,7 +1847,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Font",
{"compatible files", "*.ttf *.otf *.ttc"},
"compatible files{.ttf,.otf,.ttc}",
workingDirFont,
dpiScale
);
@ -1870,7 +1856,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Font",
{"compatible files", "*.ttf *.otf *.ttc"},
"compatible files{.ttf,.otf,.ttc}",
workingDirFont,
dpiScale
);
@ -1880,7 +1865,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Color File",
{"configuration files", "*.cfgc"},
"configuration files{.cfgc}",
workingDirColors,
dpiScale
);
@ -1890,7 +1874,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Keybind File",
{"configuration files", "*.cfgk"},
"configuration files{.cfgk}",
workingDirKeybinds,
dpiScale
);
@ -1900,7 +1883,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openLoad(
"Select Layout File",
{".ini files", "*.ini"},
".ini files{.ini}",
workingDirKeybinds,
dpiScale
);
@ -1910,7 +1892,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Colors",
{"configuration files", "*.cfgc"},
"configuration files{.cfgc}",
workingDirColors,
dpiScale
);
@ -1920,7 +1901,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Keybinds",
{"configuration files", "*.cfgk"},
"configuration files{.cfgk}",
workingDirKeybinds,
dpiScale
);
@ -1930,7 +1910,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
hasOpened=fileDialog->openSave(
"Export Layout",
{".ini files", "*.ini"},
".ini files{.ini}",
workingDirKeybinds,
dpiScale
);
@ -1943,7 +1922,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Load ROM",
{"compatible files", "*.rom *.bin",
"all files", "*"},
"compatible files{.rom,.bin},.*",
workingDirROM,
dpiScale
);
@ -1954,7 +1932,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Play Command Stream",
{"command stream", "*.bin",
"all files", "*"},
"command stream{.bin},.*",
workingDirROM,
dpiScale
);
@ -1966,7 +1943,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
{"compatible files", "*.fur *.dmf *.mod",
"another option", "*.wav *.ttf",
"all files", "*"},
"compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*",
workingDirTest,
dpiScale,
[](const char* path) {
@ -1985,7 +1961,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
{"compatible files", "*.fur *.dmf *.mod",
"another option", "*.wav *.ttf",
"all files", "*"},
"compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*",
workingDirTest,
dpiScale,
[](const char* path) {
@ -2004,7 +1979,6 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
"Save Test",
{"Furnace song", "*.fur",
"DefleMask module", "*.dmf"},
"Furnace song{.fur},DefleMask module{.dmf}",
workingDirTest,
dpiScale
);
@ -3491,6 +3465,7 @@ bool FurnaceGUI::loop() {
scrX=ev.window.data1;
scrY=ev.window.data2;
updateWindow=true;
shallDetectScale=2;
logV("window moved to %dx%d",scrX,scrY);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
@ -3628,6 +3603,8 @@ bool FurnaceGUI::loop() {
if (prevScrW!=scrW || prevScrH!=scrH) {
logV("size change 2: %dx%d (from %dx%d)",scrW,scrH,prevScrW,prevScrH);
}
ImGui::GetIO().InputScale=(float)canvasW/(float)scrW;
}
wantCaptureKeyboard=ImGui::GetIO().WantTextInput;
@ -4176,70 +4153,76 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
ImGui::Separator();
if (ImGui::BeginMenu("add chip...")) {
exitDisabledTimer=1;
DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) {
if (!e->addSystem(picked)) {
showError("cannot add chip! ("+e->getLastError()+")");
} else {
MARK_MODIFIED;
}
ImGui::CloseCurrentPopup();
if (e->song.autoSystem) {
autoDetectSystem();
}
updateWindowTitle();
if (!settings.classicChipOptions) {
if (ImGui::MenuItem("manage chips")) {
nextWindow=GUI_WINDOW_SYS_MANAGER;
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("configure chip...")) {
exitDisabledTimer=1;
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())) {
drawSysConf(i,e->song.system[i],e->song.systemFlags[i],true,true);
ImGui::TreePop();
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("change chip...")) {
exitDisabledTimer=1;
ImGui::Checkbox("Preserve channel positions",&preserveChanPos);
for (int i=0; i<e->song.systemLen; i++) {
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();
}
updateWindowTitle();
ImGui::CloseCurrentPopup();
}
ImGui::EndMenu();
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("remove chip...")) {
exitDisabledTimer=1;
ImGui::Checkbox("Preserve channel positions",&preserveChanPos);
for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
if (!e->removeSystem(i,preserveChanPos)) {
showError("cannot remove chip! ("+e->getLastError()+")");
} else {
if (ImGui::BeginMenu("add chip...")) {
exitDisabledTimer=1;
DivSystem picked=systemPicker();
if (picked!=DIV_SYSTEM_NULL) {
if (!e->addSystem(picked)) {
showError("cannot add chip! ("+e->getLastError()+")");
} else {
MARK_MODIFIED;
}
ImGui::CloseCurrentPopup();
if (e->song.autoSystem) {
autoDetectSystem();
updateWindowTitle();
}
updateWindowTitle();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("configure chip...")) {
exitDisabledTimer=1;
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())) {
drawSysConf(i,e->song.system[i],e->song.systemFlags[i],true,true);
ImGui::TreePop();
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("change chip...")) {
exitDisabledTimer=1;
ImGui::Checkbox("Preserve channel positions",&preserveChanPos);
for (int i=0; i<e->song.systemLen; i++) {
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();
}
updateWindowTitle();
ImGui::CloseCurrentPopup();
}
ImGui::EndMenu();
}
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("remove chip...")) {
exitDisabledTimer=1;
ImGui::Checkbox("Preserve channel positions",&preserveChanPos);
for (int i=0; i<e->song.systemLen; i++) {
if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) {
if (!e->removeSystem(i,preserveChanPos)) {
showError("cannot remove chip! ("+e->getLastError()+")");
} else {
MARK_MODIFIED;
}
if (e->song.autoSystem) {
autoDetectSystem();
updateWindowTitle();
}
}
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
ImGui::BeginDisabled(exitDisabledTimer);
ImGui::Separator();
@ -4355,7 +4338,7 @@ bool FurnaceGUI::loop() {
if (ImGui::BeginMenu(settings.capitalMenuBar?"Help":"help")) {
if (ImGui::MenuItem("effect list",BIND_FOR(GUI_ACTION_WINDOW_EFFECT_LIST),effectListOpen)) effectListOpen=!effectListOpen;
if (ImGui::MenuItem("debug menu",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) debugOpen=!debugOpen;
if (ImGui::MenuItem("inspector",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) inspectorOpen=!inspectorOpen;
if (ImGui::MenuItem("inspector")) inspectorOpen=!inspectorOpen;
if (ImGui::MenuItem("panic",BIND_FOR(GUI_ACTION_PANIC))) e->syncReset();
if (ImGui::MenuItem("about...",BIND_FOR(GUI_ACTION_WINDOW_ABOUT))) {
aboutOpen=true;
@ -4515,6 +4498,7 @@ bool FurnaceGUI::loop() {
MEASURE(compatFlags,drawCompatFlags());
MEASURE(stats,drawStats());
MEASURE(chanOsc,drawChanOsc());
MEASURE(regView,drawRegView());
} else {
globalWinFlags=0;
ImGui::DockSpaceOverViewport(NULL,lockLayout?(ImGuiDockNodeFlags_NoWindowMenuButton|ImGuiDockNodeFlags_NoMove|ImGuiDockNodeFlags_NoResize|ImGuiDockNodeFlags_NoCloseButton|ImGuiDockNodeFlags_NoDocking|ImGuiDockNodeFlags_NoDockingSplitMe|ImGuiDockNodeFlags_NoDockingSplitOther):0);
@ -6146,7 +6130,38 @@ bool FurnaceGUI::loop() {
if (shallDetectScale) {
if (--shallDetectScale<1) {
if (settings.dpiScale<0.5f) {
applyUISettings();
const char* videoBackend=SDL_GetCurrentVideoDriver();
double newScale=getScaleFactor(videoBackend,sdlWin);
if (newScale<0.1f) {
logW("scale what?");
newScale=1.0f;
}
if (newScale!=dpiScale) {
logD("auto UI scale changed (%f != %f) - applying settings...",newScale,dpiScale);
ImGui::GetIO().Fonts->Clear();
applyUISettings();
if (rend) rend->destroyFontsTexture();
if (!ImGui::GetIO().Fonts->Build()) {
logE("error while building font atlas!");
showError("error while loading fonts! please check your settings.");
ImGui::GetIO().Fonts->Clear();
mainFont=ImGui::GetIO().Fonts->AddFontDefault();
patFont=mainFont;
bigFont=mainFont;
headFont=mainFont;
if (rend) rend->destroyFontsTexture();
if (!ImGui::GetIO().Fonts->Build()) {
logE("error again while building font atlas!");
} else {
rend->createFontsTexture();
}
} else {
rend->createFontsTexture();
}
}
}
}
}
@ -6374,7 +6389,7 @@ bool FurnaceGUI::init() {
dpiScale=settings.dpiScale;
} else {
logD("auto-detecting UI scale factor.");
dpiScale=getScaleFactor(videoBackend);
dpiScale=getScaleFactor(videoBackend,sdlWin);
logD("scale factor: %f",dpiScale);
if (dpiScale<0.1f) {
logW("scale what?");
@ -6539,10 +6554,12 @@ bool FurnaceGUI::init() {
logW("could not list render drivers! %s",SDL_GetError());
} else {
SDL_RendererInfo ri;
logV("available render drivers:");
for (int i=0; i<numDrivers; i++) {
int r=SDL_GetRenderDriverInfo(i,&ri);
if (r!=0) continue;
availRenderDrivers.push_back(String(ri.name));
logV("- %s",ri.name);
}
}
@ -6552,6 +6569,7 @@ bool FurnaceGUI::init() {
logD("starting render backend...");
if (!rend->init(sdlWin)) {
logE("it failed...");
if (settings.renderBackend!="SDL") {
settings.renderBackend="SDL";
e->setConf("renderBackend","SDL");
@ -6568,6 +6586,7 @@ bool FurnaceGUI::init() {
}
return false;
}
logV("render backend started");
// try acquiring the canvas size
if (!rend->getOutputSize(canvasW,canvasH)) {
@ -6917,6 +6936,9 @@ FurnaceGUI::FurnaceGUI():
displayEditString(false),
mobileEdit(false),
killGraphics(false),
audioEngineChanged(false),
settingsChanged(false),
debugFFT(false),
vgmExportVersion(0x171),
vgmExportTrailingTicks(-1),
drawHalt(10),