diff --git a/CMakeLists.txt b/CMakeLists.txt index 695206ff..f2b7cb70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_CXX_STANDARD 14) set(CMAKE_PROJECT_VERSION_MAJOR 0) set(CMAKE_PROJECT_VERSION_MINOR 5) -set(CMAKE_PROJECT_VERSION_PATCH 6) +set(CMAKE_PROJECT_VERSION_PATCH 7) if (ANDROID) set(BUILD_GUI_DEFAULT OFF) diff --git a/papers/format.md b/papers/format.md index aab764fd..d3add4f1 100644 --- a/papers/format.md +++ b/papers/format.md @@ -150,6 +150,8 @@ size | description | - 0xa5: OPL3 4-op (YMF262) - 12 channels | - 0xa6: OPL3 4-op + drums (YMF262) - 14 channels | - 0xa7: OPLL drums (YM2413) - 11 channels + | - 0xa8: Atari Lynx - 4 channels + | - 0xe0: QSound - 16 channels 32 | sound chip volumes | - signed char, 64=1.0, 127=~2.0 32 | sound chip panning diff --git a/res/Info.plist b/res/Info.plist index 73daa246..d6f1c4a0 100644 --- a/res/Info.plist +++ b/res/Info.plist @@ -15,17 +15,17 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - 0.5.6 + 0.5.7 CFBundleName Furnace CFBundlePackageType APPL CFBundleShortVersionString - 0.5.6 + 0.5.7 CFBundleSignature ???? CFBundleVersion - 0.5.6 + 0.5.7 NSHumanReadableCopyright NSHighResolutionCapable diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 3069f919..21d6789b 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -743,6 +743,7 @@ void DivEngine::getCommandStream(std::vector& where) { } void DivEngine::playSub(bool preserveDrift, int goalRow) { + for (int i=0; isetSkipRegisterWrites(false); reset(); if (preserveDrift && curOrder==0) return; bool oldRepeatPattern=repeatPattern; @@ -767,11 +768,11 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) { playing=true; for (int i=0; isetSkipRegisterWrites(true); while (playing && curOrdersetSkipRegisterWrites(false); @@ -804,8 +805,8 @@ int DivEngine::calcBaseFreq(double clock, double divider, int note, bool period) int DivEngine::calcFreq(int base, int pitch, bool period, int octave) { if (song.linearPitch) { return period? - round(base*pow(2,-(double)pitch/(12.0*128.0))/(98.0+globalPitch*6.0)*98.0): - (round(base*pow(2,(double)pitch/(12.0*128.0))*(98+globalPitch*6))/98); + base*pow(2,-(double)pitch/(12.0*128.0))/(98.0+globalPitch*6.0)*98.0: + (base*pow(2,(double)pitch/(12.0*128.0))*(98+globalPitch*6))/98; } return period? base-pitch: @@ -1195,8 +1196,24 @@ int DivEngine::addInstrument(int refChan) { return insCount; } +enum DivInsFormats { + DIV_INSFORMAT_DMP, + DIV_INSFORMAT_TFI, + DIV_INSFORMAT_VGI, + DIV_INSFORMAT_FTI, + DIV_INSFORMAT_BTI +}; + bool DivEngine::addInstrumentFromFile(const char *path) { warnings=""; + + const char* pathRedux=strrchr(path,DIR_SEPARATOR); + if (pathRedux==NULL) { + pathRedux="Instrument"; + } else { + pathRedux++; + } + FILE* f=ps_fopen(path,"rb"); if (f==NULL) { lastError=strerror(errno); @@ -1273,251 +1290,356 @@ bool DivEngine::addInstrumentFromFile(const char *path) { delete[] buf; return false; } - } else { // read as .dmp - // this is a ridiculous mess - unsigned char version=0; - unsigned char sys=0; - try { - reader.seek(0,SEEK_SET); - version=reader.readC(); - } catch (EndOfFileException e) { - lastError="premature end of file"; - logE("premature end of file!\n"); - delete ins; - delete[] buf; - return false; + } else { // read as a different format + const char* ext=strrchr(path,'.'); + DivInsFormats format=DIV_INSFORMAT_DMP; + if (ext!=NULL) { + String extS; + for (; *ext; ext++) { + char i=*ext; + if (i>='A' && i<='Z') { + i+='a'-'A'; + } + extS+=i; + } + if (extS==String(".dmp")) { + format=DIV_INSFORMAT_DMP; + } else if (extS==String(".tfi")) { + format=DIV_INSFORMAT_TFI; + } else if (extS==String(".vgi")) { + format=DIV_INSFORMAT_VGI; + } else if (extS==String(".fti")) { + format=DIV_INSFORMAT_FTI; + } else if (extS==String(".bti")) { + format=DIV_INSFORMAT_BTI; + } } + switch (format) { + case DIV_INSFORMAT_DMP: { + // this is a ridiculous mess + unsigned char version=0; + unsigned char sys=0; + try { + reader.seek(0,SEEK_SET); + version=reader.readC(); + } catch (EndOfFileException e) { + lastError="premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; + } - if (version>11) { - lastError="unknown instrument version!"; - delete ins; - delete[] buf; - return false; - } + if (version>11) { + lastError="unknown instrument version!"; + delete ins; + delete[] buf; + return false; + } - if (version>=11) { // 1.0 - try { - sys=reader.readC(); - - switch (sys) { - case 1: // YMU759 - ins->type=DIV_INS_FM; - break; - case 2: // Genesis - ins->type=DIV_INS_FM; - break; - case 3: // SMS - ins->type=DIV_INS_STD; - break; - case 4: // Game Boy - ins->type=DIV_INS_GB; - break; - case 5: // PC Engine - ins->type=DIV_INS_PCE; - break; - case 6: // NES - ins->type=DIV_INS_STD; - break; - case 7: case 0x17: // C64 - ins->type=DIV_INS_C64; - break; - case 8: // Arcade - ins->type=DIV_INS_FM; - break; - default: - lastError="unknown instrument type!"; + ins->name=pathRedux; + + if (version>=11) { // 1.0 + try { + sys=reader.readC(); + + switch (sys) { + case 1: // YMU759 + ins->type=DIV_INS_FM; + break; + case 2: // Genesis + ins->type=DIV_INS_FM; + break; + case 3: // SMS + ins->type=DIV_INS_STD; + break; + case 4: // Game Boy + ins->type=DIV_INS_GB; + break; + case 5: // PC Engine + ins->type=DIV_INS_PCE; + break; + case 6: // NES + ins->type=DIV_INS_STD; + break; + case 7: case 0x17: // C64 + ins->type=DIV_INS_C64; + break; + case 8: // Arcade + ins->type=DIV_INS_FM; + break; + default: + lastError="unknown instrument type!"; + delete ins; + delete[] buf; + return false; + break; + } + } catch (EndOfFileException e) { + lastError="premature end of file"; + logE("premature end of file!\n"); delete ins; delete[] buf; return false; - break; - } - } catch (EndOfFileException e) { - lastError="premature end of file"; - logE("premature end of file!\n"); - delete ins; - delete[] buf; - return false; - } - } - - try { - bool mode=true; - if (version>1) { - mode=reader.readC(); - if (mode==0) { - if (version<11) { - ins->type=DIV_INS_STD; } - } else { - ins->type=DIV_INS_FM; } - } else { - ins->type=DIV_INS_FM; - } - if (mode) { // FM - if (version<10) { + try { + bool mode=true; if (version>1) { - ins->fm.ops=reader.readC()?4:2; - } else { - ins->fm.ops=reader.readC()?2:4; - } - } - if (version>1) { // HELP! in which version of the format did we start storing FMS! - ins->fm.fms=reader.readC(); - } - ins->fm.fb=reader.readC(); - ins->fm.alg=reader.readC(); - // DITTO - if (sys!=1) ins->fm.ams=reader.readC(); - - for (int j=0; jfm.ops; j++) { - ins->fm.op[j].mult=reader.readC(); - ins->fm.op[j].tl=reader.readC(); - ins->fm.op[j].ar=reader.readC(); - ins->fm.op[j].dr=reader.readC(); - ins->fm.op[j].sl=reader.readC(); - ins->fm.op[j].rr=reader.readC(); - ins->fm.op[j].am=reader.readC(); - // what the hell how do I tell! - if (sys==1) { // YMU759 - ins->fm.op[j].ws=reader.readC(); - ins->fm.op[j].ksl=reader.readC(); - ins->fm.op[j].vib=reader.readC(); - ins->fm.op[j].egt=reader.readC(); - ins->fm.op[j].sus=reader.readC(); - ins->fm.op[j].ksr=reader.readC(); - ins->fm.op[j].dvb=reader.readC(); - ins->fm.op[j].dam=reader.readC(); - } else { - ins->fm.op[j].rs=reader.readC(); - ins->fm.op[j].dt=reader.readC(); - ins->fm.op[j].dt2=ins->fm.op[j].dt>>4; - ins->fm.op[j].dt&=15; - ins->fm.op[j].d2r=reader.readC(); - ins->fm.op[j].ssgEnv=reader.readC(); - } - } - } else { // STD - if (ins->type!=DIV_INS_GB) { - ins->std.volMacroLen=reader.readC(); - if (version>5) { - for (int i=0; istd.volMacroLen; i++) { - ins->std.volMacro[i]=reader.readI(); + mode=reader.readC(); + if (mode==0) { + if (version<11) { + ins->type=DIV_INS_STD; + } + } else { + ins->type=DIV_INS_FM; } } else { - for (int i=0; istd.volMacroLen; i++) { - ins->std.volMacro[i]=reader.readC(); + ins->type=DIV_INS_FM; + } + + if (mode) { // FM + if (version<10) { + if (version>1) { + ins->fm.ops=reader.readC()?4:2; + } else { + ins->fm.ops=reader.readC()?2:4; + } + } + if (version>1) { // HELP! in which version of the format did we start storing FMS! + ins->fm.fms=reader.readC(); + } + ins->fm.fb=reader.readC(); + ins->fm.alg=reader.readC(); + // DITTO + if (sys!=1) ins->fm.ams=reader.readC(); + + for (int j=0; jfm.ops; j++) { + ins->fm.op[j].mult=reader.readC(); + ins->fm.op[j].tl=reader.readC(); + ins->fm.op[j].ar=reader.readC(); + ins->fm.op[j].dr=reader.readC(); + ins->fm.op[j].sl=reader.readC(); + ins->fm.op[j].rr=reader.readC(); + ins->fm.op[j].am=reader.readC(); + // what the hell how do I tell! + if (sys==1) { // YMU759 + ins->fm.op[j].ws=reader.readC(); + ins->fm.op[j].ksl=reader.readC(); + ins->fm.op[j].vib=reader.readC(); + ins->fm.op[j].egt=reader.readC(); + ins->fm.op[j].sus=reader.readC(); + ins->fm.op[j].ksr=reader.readC(); + ins->fm.op[j].dvb=reader.readC(); + ins->fm.op[j].dam=reader.readC(); + } else { + ins->fm.op[j].rs=reader.readC(); + ins->fm.op[j].dt=reader.readC(); + ins->fm.op[j].dt2=ins->fm.op[j].dt>>4; + ins->fm.op[j].dt&=15; + ins->fm.op[j].d2r=reader.readC(); + ins->fm.op[j].ssgEnv=reader.readC(); + } + } + } else { // STD + if (ins->type!=DIV_INS_GB) { + ins->std.volMacroLen=reader.readC(); + if (version>5) { + for (int i=0; istd.volMacroLen; i++) { + ins->std.volMacro[i]=reader.readI(); + } + } else { + for (int i=0; istd.volMacroLen; i++) { + ins->std.volMacro[i]=reader.readC(); + } + } + if (version<11) for (int i=0; istd.volMacroLen; i++) { + if (ins->std.volMacro[i]>15 && ins->type==DIV_INS_STD) ins->type=DIV_INS_PCE; + } + if (ins->std.volMacroLen>0) { + ins->std.volMacroOpen=true; + ins->std.volMacroLoop=reader.readC(); + } else { + ins->std.volMacroOpen=false; + } + } + + ins->std.arpMacroLen=reader.readC(); + if (version>5) { + for (int i=0; istd.arpMacroLen; i++) { + ins->std.arpMacro[i]=reader.readI(); + } + } else { + for (int i=0; istd.arpMacroLen; i++) { + ins->std.arpMacro[i]=reader.readC(); + } + } + if (ins->std.arpMacroLen>0) { + ins->std.arpMacroOpen=true; + ins->std.arpMacroLoop=reader.readC(); + } else { + ins->std.arpMacroOpen=false; + } + if (version>8) { // TODO: when? + ins->std.arpMacroMode=reader.readC(); + } + + ins->std.dutyMacroLen=reader.readC(); + if (version>5) { + for (int i=0; istd.dutyMacroLen; i++) { + ins->std.dutyMacro[i]=reader.readI(); + } + } else { + for (int i=0; istd.dutyMacroLen; i++) { + ins->std.dutyMacro[i]=reader.readC(); + } + } + if (ins->std.dutyMacroLen>0) { + ins->std.dutyMacroOpen=true; + ins->std.dutyMacroLoop=reader.readC(); + } else { + ins->std.dutyMacroOpen=false; + } + + ins->std.waveMacroLen=reader.readC(); + if (version>5) { + for (int i=0; istd.waveMacroLen; i++) { + ins->std.waveMacro[i]=reader.readI(); + } + } else { + for (int i=0; istd.waveMacroLen; i++) { + ins->std.waveMacro[i]=reader.readC(); + } + } + if (ins->std.waveMacroLen>0) { + ins->std.waveMacroOpen=true; + ins->std.waveMacroLoop=reader.readC(); + } else { + ins->std.waveMacroOpen=false; + } + + if (ins->type==DIV_INS_C64) { + ins->c64.triOn=reader.readC(); + ins->c64.sawOn=reader.readC(); + ins->c64.pulseOn=reader.readC(); + ins->c64.noiseOn=reader.readC(); + + ins->c64.a=reader.readC(); + ins->c64.d=reader.readC(); + ins->c64.s=reader.readC(); + ins->c64.r=reader.readC(); + + ins->c64.duty=(reader.readC()*4095)/100; + + ins->c64.ringMod=reader.readC(); + ins->c64.oscSync=reader.readC(); + ins->c64.toFilter=reader.readC(); + if (version<0x07) { // TODO: UNSURE + ins->c64.volIsCutoff=reader.readI(); + } else { + ins->c64.volIsCutoff=reader.readC(); + } + ins->c64.initFilter=reader.readC(); + + ins->c64.res=reader.readC(); + ins->c64.cut=(reader.readC()*2047)/100; + ins->c64.hp=reader.readC(); + ins->c64.bp=reader.readC(); + ins->c64.lp=reader.readC(); + ins->c64.ch3off=reader.readC(); + } + if (ins->type==DIV_INS_GB) { + ins->gb.envVol=reader.readC(); + ins->gb.envDir=reader.readC(); + ins->gb.envLen=reader.readC(); + ins->gb.soundLen=reader.readC(); } } - if (version<11) for (int i=0; istd.volMacroLen; i++) { - if (ins->std.volMacro[i]>15 && ins->type==DIV_INS_STD) ins->type=DIV_INS_PCE; - } - if (ins->std.volMacroLen>0) { - ins->std.volMacroOpen=true; - ins->std.volMacroLoop=reader.readC(); - } else { - ins->std.volMacroOpen=false; - } - } - - ins->std.arpMacroLen=reader.readC(); - if (version>5) { - for (int i=0; istd.arpMacroLen; i++) { - ins->std.arpMacro[i]=reader.readI(); - } - } else { - for (int i=0; istd.arpMacroLen; i++) { - ins->std.arpMacro[i]=reader.readC(); - } - } - if (ins->std.arpMacroLen>0) { - ins->std.arpMacroOpen=true; - ins->std.arpMacroLoop=reader.readC(); - } else { - ins->std.arpMacroOpen=false; - } - if (version>8) { // TODO: when? - ins->std.arpMacroMode=reader.readC(); - } - - ins->std.dutyMacroLen=reader.readC(); - if (version>5) { - for (int i=0; istd.dutyMacroLen; i++) { - ins->std.dutyMacro[i]=reader.readI(); - } - } else { - for (int i=0; istd.dutyMacroLen; i++) { - ins->std.dutyMacro[i]=reader.readC(); - } - } - if (ins->std.dutyMacroLen>0) { - ins->std.dutyMacroOpen=true; - ins->std.dutyMacroLoop=reader.readC(); - } else { - ins->std.dutyMacroOpen=false; - } - - ins->std.waveMacroLen=reader.readC(); - if (version>5) { - for (int i=0; istd.waveMacroLen; i++) { - ins->std.waveMacro[i]=reader.readI(); - } - } else { - for (int i=0; istd.waveMacroLen; i++) { - ins->std.waveMacro[i]=reader.readC(); - } - } - if (ins->std.waveMacroLen>0) { - ins->std.waveMacroOpen=true; - ins->std.waveMacroLoop=reader.readC(); - } else { - ins->std.waveMacroOpen=false; - } - - if (ins->type==DIV_INS_C64) { - ins->c64.triOn=reader.readC(); - ins->c64.sawOn=reader.readC(); - ins->c64.pulseOn=reader.readC(); - ins->c64.noiseOn=reader.readC(); - - ins->c64.a=reader.readC(); - ins->c64.d=reader.readC(); - ins->c64.s=reader.readC(); - ins->c64.r=reader.readC(); - - ins->c64.duty=(reader.readC()*4095)/100; - - ins->c64.ringMod=reader.readC(); - ins->c64.oscSync=reader.readC(); - ins->c64.toFilter=reader.readC(); - if (version<0x07) { // TODO: UNSURE - ins->c64.volIsCutoff=reader.readI(); - } else { - ins->c64.volIsCutoff=reader.readC(); - } - ins->c64.initFilter=reader.readC(); - - ins->c64.res=reader.readC(); - ins->c64.cut=(reader.readC()*2047)/100; - ins->c64.hp=reader.readC(); - ins->c64.bp=reader.readC(); - ins->c64.lp=reader.readC(); - ins->c64.ch3off=reader.readC(); - } - if (ins->type==DIV_INS_GB) { - ins->gb.envVol=reader.readC(); - ins->gb.envDir=reader.readC(); - ins->gb.envLen=reader.readC(); - ins->gb.soundLen=reader.readC(); + } catch (EndOfFileException e) { + lastError="premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; } + break; } - } catch (EndOfFileException e) { - lastError="premature end of file"; - logE("premature end of file!\n"); - delete ins; - delete[] buf; - return false; + case DIV_INSFORMAT_TFI: + try { + reader.seek(0,SEEK_SET); + + ins->type=DIV_INS_FM; + ins->name=pathRedux; + + ins->fm.alg=reader.readC(); + ins->fm.fb=reader.readC(); + + for (int i=0; i<4; i++) { + DivInstrumentFM::Operator& op=ins->fm.op[i]; + + op.mult=reader.readC(); + op.dt=reader.readC(); + op.tl=reader.readC(); + op.rs=reader.readC(); + op.ar=reader.readC(); + op.dr=reader.readC(); + op.d2r=reader.readC(); + op.rr=reader.readC(); + op.sl=reader.readC(); + op.ssgEnv=reader.readC(); + } + } catch (EndOfFileException e) { + lastError="premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; + } + break; + case DIV_INSFORMAT_VGI: + try { + reader.seek(0,SEEK_SET); + + ins->type=DIV_INS_FM; + ins->name=pathRedux; + + ins->fm.alg=reader.readC(); + ins->fm.fb=reader.readC(); + unsigned char fmsams=reader.readC(); + ins->fm.fms=fmsams&7; + ins->fm.ams=fmsams>>4; + + for (int i=0; i<4; i++) { + DivInstrumentFM::Operator& op=ins->fm.op[i]; + + op.mult=reader.readC(); + op.dt=reader.readC(); + op.tl=reader.readC(); + op.rs=reader.readC(); + op.ar=reader.readC(); + op.dr=reader.readC(); + if (op.dr&0x80) { + op.am=1; + op.dr&=0x7f; + } + op.d2r=reader.readC(); + op.rr=reader.readC(); + op.sl=reader.readC(); + op.ssgEnv=reader.readC(); + } + } catch (EndOfFileException e) { + lastError="premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; + } + break; + case DIV_INSFORMAT_FTI: + break; + case DIV_INSFORMAT_BTI: + break; } if (reader.tell()data,oldPat->data,256*32*sizeof(short)); + logD("found at %d\n",j); + didNotFind=false; break; } } - if (order[i]==song.orders.ord[i][curOrder]) { + if (didNotFind) { addWarning(fmt::sprintf("no free patterns in channel %d!",i)); } } diff --git a/src/engine/engine.h b/src/engine/engine.h index ddf9f581..d3be5ae9 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -37,8 +37,8 @@ warnings+=(String("\n")+x); \ } -#define DIV_VERSION "0.5.7pre3" -#define DIV_ENGINE_VERSION 51 +#define DIV_VERSION "0.5.7pre4" +#define DIV_ENGINE_VERSION 52 enum DivStatusView { DIV_STATUS_NOTHING=0, diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index af31845c..0214d5f2 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -171,7 +171,7 @@ void DivPlatformC64::tick() { if (!chan[i].resetMask && !isMuted[i]) { rWrite(i*7+5,0); rWrite(i*7+6,0); - rWrite(i*7+4,(isMuted[i]?0:(chan[i].wave<<4))|8|(chan[i].ring<<2)|(chan[i].sync<<1)); + rWrite(i*7+4,(isMuted[i]?8:(chan[i].wave<<4))|8|(chan[i].ring<<2)|(chan[i].sync<<1)); } } } @@ -246,8 +246,8 @@ int DivPlatformC64::dispatch(DivCommand c) { filtCut=ins->c64.cut; filtRes=ins->c64.res; filtControl=ins->c64.lp|(ins->c64.bp<<1)|(ins->c64.hp<<2)|(ins->c64.ch3off<<3); - updateFilter(); } + updateFilter(); } if (chan[c.chan].insChanged) { chan[c.chan].insChanged=false; diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 84c673e5..aa9e2249 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -977,7 +977,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) { writeLoop=true; } } - if (nextTick()) { + if (nextTick() || !playing) { done=true; if (!loop) { for (int i=0; iwriteC(i); loopSample[i]=-1; } + + if (!playing) { + writeLoop=false; + loopPos=-1; + } } // get register dumps for (int i=0; iwriteI(gd3Off-0x14); w->writeI(tickCount); if (loop) { - w->writeI(loopPos-0x1c); - w->writeI(tickCount-loopTick-1); + if (loopPos==-1) { + w->writeI(0); + w->writeI(0); + } else { + w->writeI(loopPos-0x1c); + w->writeI(tickCount-loopTick-1); + } } else { w->writeI(0); w->writeI(0); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 953f6f0d..e18d3a79 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3820,7 +3820,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { ImGuiFileDialog::Instance()->OpenModal("FileDialog","Save File","DefleMask 1.0/legacy module{.dmf}",workingDir,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite); break; case GUI_FILE_INS_OPEN: - ImGuiFileDialog::Instance()->OpenModal("FileDialog","Load Instrument","compatible files{.fui,.dmp},.*",workingDir); + ImGuiFileDialog::Instance()->OpenModal("FileDialog","Load Instrument","compatible files{.fui,.dmp,.tfi,.vgi},.*",workingDir); break; case GUI_FILE_INS_SAVE: ImGuiFileDialog::Instance()->OpenModal("FileDialog","Save Instrument","Furnace instrument{.fui}",workingDir,1,nullptr,ImGuiFileDialogFlags_ConfirmOverwrite); @@ -5486,6 +5486,11 @@ bool FurnaceGUI::init() { ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".otf",ImVec4(0.3f,1.0f,0.6f,1.0f),ICON_FA_FONT); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".ttc",ImVec4(0.3f,1.0f,0.6f,1.0f),ICON_FA_FONT); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".tfi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".vgi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".fti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".bti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + updateWindowTitle(); for (int i=0; i #define _USE_MATH_DEFINES #include "gui.h" #include "imgui_internal.h" #include "IconsFontAwesome4.h" +#include "misc/cpp/imgui_stdlib.h" #include "guiConst.h" #include @@ -376,8 +378,8 @@ void FurnaceGUI::drawPattern() { } ImGui::TableNextRow(); ImGui::TableNextColumn(); - if (ImGui::Selectable(extraChannelButtons?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { - extraChannelButtons=!extraChannelButtons; + if (ImGui::Selectable((extraChannelButtons==2)?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { + if (++extraChannelButtons>2) extraChannelButtons=0; } if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { fancyPattern=!fancyPattern; @@ -448,7 +450,34 @@ void FurnaceGUI::drawPattern() { if (settings.soloAction!=2) if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { e->toggleSolo(i); } - if (extraChannelButtons) { + if (extraChannelButtons==2) { + DivPattern* pat=e->song.pat[i].getPattern(e->song.orders.ord[i][ord],true); + ImGui::PushFont(mainFont); + if (patNameTarget==i) { + snprintf(chanID,2048,"##PatNameI%d_%d",i,ord); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(8.0f*dpiScale)); + ImGui::SetCursorPosX(ImGui::GetCursorPosX()+4.0f*dpiScale); + ImGui::InputText(chanID,&pat->name); + if (wantPatName) { + wantPatName=false; + ImGui::SetItemDefaultFocus(); + ImGui::SetKeyboardFocusHere(-1); + } else { + if (!ImGui::IsItemActive()) { + patNameTarget=-1; + } + } + } else { + snprintf(chanID,2048," %s##PatName%d",pat->name.c_str(),i); + if (ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { + patNameTarget=i; + wantPatName=true; + snprintf(chanID,2048,"##PatNameI%d_%d",i,ord); + ImGui::SetActiveID(ImGui::GetID(chanID),ImGui::GetCurrentWindow()); + } + } + ImGui::PopFont(); + } else if (extraChannelButtons==1) { snprintf(chanID,2048,"%c##_HCH%d",e->song.chanCollapse[i]?'+':'-',i); ImGui::SetCursorPosX(ImGui::GetCursorPosX()+4.0f*dpiScale); if (ImGui::SmallButton(chanID)) {