diff --git a/src/engine/engine.h b/src/engine/engine.h index 6d18c728f..fe604a61a 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -54,8 +54,8 @@ class DivWorkPool; #define DIV_UNSTABLE -#define DIV_VERSION "dev182" -#define DIV_ENGINE_VERSION 182 +#define DIV_VERSION "dev183" +#define DIV_ENGINE_VERSION 183 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 80a5a6bf1..1786ffb86 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -719,6 +719,21 @@ void DivInstrument::writeFeatureX1(SafeWriter* w) { FEATURE_END; } +void DivInstrument::writeFeatureNE(SafeWriter* w) { + FEATURE_BEGIN("NE"); + + w->writeC(amiga.useNoteMap?1:0); + + if (amiga.useNoteMap) { + for (int note=0; note<120; note++) { + w->writeC(amiga.noteMap[note].dpcmFreq); + w->writeC(amiga.noteMap[note].dpcmDelta); + } + } + + FEATURE_END; +} + void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bool insName) { size_t blockStartSeek=0; size_t blockEndSeek=0; @@ -761,6 +776,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo bool featureSU=false; bool featureES=false; bool featureX1=false; + bool featureNE=false; bool checkForWL=false; @@ -904,6 +920,8 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo featureFM=true; break; case DIV_INS_NES: + featureSM=true; + featureNE=true; break; case DIV_INS_MSM6258: featureSM=true; @@ -993,6 +1011,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo } if (amiga!=defaultIns.amiga) { featureSM=true; + featureNE=true; } if (snes!=defaultIns.snes) { featureSN=true; @@ -1157,6 +1176,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo if (featureX1) { writeFeatureX1(w); } + if (featureNE) { + writeFeatureNE(w); + } if (fui && (featureSL || featureWL)) { w->write("EN",2); @@ -2541,6 +2563,21 @@ void DivInstrument::readFeatureX1(SafeReader& reader, short version) { READ_FEAT_END; } +void DivInstrument::readFeatureNE(SafeReader& reader, short version) { + READ_FEAT_BEGIN; + + amiga.useNoteMap=reader.readC(); + + if (amiga.useNoteMap) { + for (int note=0; note<120; note++) { + amiga.noteMap[note].dpcmFreq=reader.readC(); + amiga.noteMap[note].dpcmDelta=reader.readC(); + } + } + + READ_FEAT_END; +} + DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song) { unsigned char featCode[2]; @@ -2606,6 +2643,8 @@ DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, b readFeatureES(reader,version); } else if (memcmp(featCode,"X1",2)==0) { // X1-010 readFeatureX1(reader,version); + } else if (memcmp(featCode,"NE",2)==0) { // NES (DPCM) + readFeatureNE(reader,version); } else { if (song==NULL && (memcmp(featCode,"SL",2)==0 || (memcmp(featCode,"WL",2)==0))) { // nothing diff --git a/src/engine/instrument.h b/src/engine/instrument.h index a4024addf..41b61ae48 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -452,9 +452,13 @@ struct DivInstrumentAmiga { struct SampleMap { int freq; short map; - SampleMap(int f=0, short m=-1): + signed char dpcmFreq; + signed char dpcmDelta; + SampleMap(int f=0, short m=-1, signed char df=15, signed char dd=-1): freq(f), - map(m) {} + map(m), + dpcmFreq(df), + dpcmDelta(dd) {} }; short initSample; bool useNoteMap; @@ -759,6 +763,7 @@ struct DivInstrument { void writeFeatureSU(SafeWriter* w); void writeFeatureES(SafeWriter* w); void writeFeatureX1(SafeWriter* w); + void writeFeatureNE(SafeWriter* w); void readFeatureNA(SafeReader& reader, short version); void readFeatureFM(SafeReader& reader, short version); @@ -778,6 +783,7 @@ struct DivInstrument { void readFeatureSU(SafeReader& reader, short version); void readFeatureES(SafeReader& reader, short version); void readFeatureX1(SafeReader& reader, short version); + void readFeatureNE(SafeReader& reader, short version); DivDataErrors readInsDataOld(SafeReader& reader, short version); DivDataErrors readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song); diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index de1798d11..aee338493 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -695,8 +695,8 @@ void DivEngine::registerSystems() { {"Pulse 1", "Pulse 2", "Triangle", "Noise", "DPCM"}, {"S1", "S2", "TR", "NO", "DMC"}, {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE, DIV_CH_PCM}, - {DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_AMIGA}, - {}, + {DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES, DIV_INS_NES}, + {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA}, { {0x11, {DIV_CMD_NES_DMC, "11xx: Write to delta modulation counter (0 to 7F)"}}, {0x12, {DIV_CMD_STD_NOISE_MODE, "12xx: Set duty cycle/noise mode (pulse: 0 to 3; noise: 0 or 1)"}}, diff --git a/src/gui/gui.h b/src/gui/gui.h index ccb81d400..7835161e8 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -2260,6 +2260,8 @@ class FurnaceGUI { void drawMacros(std::vector& macros, FurnaceGUIMacroEditState& state); void alterSampleMap(bool isNote, int val); + void insTabSample(DivInstrument* ins); + void drawOrderButtons(); void actualWaveList(); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 491b1659e..ff800c195 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2272,6 +2272,410 @@ void FurnaceGUI::alterSampleMap(bool isNote, int val) { ImGui::EndDragDropTarget(); \ } +void FurnaceGUI::insTabSample(DivInstrument* ins) { + const char* sampleTabName="Sample"; + if (ins->type==DIV_INS_SU) sampleTabName="Sound Unit"; + if (ins->type==DIV_INS_NES) sampleTabName="DPCM"; + if (ImGui::BeginTabItem(sampleTabName)) { + String sName; + bool wannaOpenSMPopup=false; + if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) { + sName="none selected"; + } else { + sName=e->song.sample[ins->amiga.initSample]->name; + } + if (ins->type==DIV_INS_PCE || + ins->type==DIV_INS_MIKEY || + ins->type==DIV_INS_X1_010 || + ins->type==DIV_INS_SWAN || + ins->type==DIV_INS_AY || + ins->type==DIV_INS_AY8930 || + ins->type==DIV_INS_VRC6 || + ins->type==DIV_INS_SU) { + P(ImGui::Checkbox("Use sample",&ins->amiga.useSample)); + if (ins->type==DIV_INS_SU) { + P(ImGui::Checkbox("Switch roles of frequency and phase reset timer",&ins->su.switchRoles)); + } + if (ins->type==DIV_INS_X1_010) { + if (ImGui::InputInt("Sample bank slot##BANKSLOT",&ins->x1_010.bankSlot,1,4)) { PARAMETER + if (ins->x1_010.bankSlot<0) ins->x1_010.bankSlot=0; + if (ins->x1_010.bankSlot>=7) ins->x1_010.bankSlot=7; + } + } + } + ImGui::AlignTextToFramePadding(); + ImGui::Text("Sample"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##ISample",sName.c_str())) { + String id; + for (int i=0; isong.sampleLen; i++) { + id=fmt::sprintf("%d: %s",i,e->song.sample[i]->name); + if (ImGui::Selectable(id.c_str(),ins->amiga.initSample==i)) { PARAMETER + ins->amiga.initSample=i; + } + } + ImGui::EndCombo(); + } + // Wavetable + if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SNES) { + ImGui::BeginDisabled(ins->amiga.useNoteMap); + P(ImGui::Checkbox("Use wavetable (Amiga/SNES/Generic DAC only)",&ins->amiga.useWave)); + if (ins->amiga.useWave) { + int len=ins->amiga.waveLen+1; + int origLen=len; + if (ImGui::InputInt("Width",&len,2,16)) { + if (ins->type==DIV_INS_SNES) { + if (len<16) len=16; + if (len>256) len=256; + if (len>origLen) { + ins->amiga.waveLen=((len+15)&(~15))-1; + } else { + ins->amiga.waveLen=(len&(~15))-1; + } + } else { + if (len<2) len=2; + if (len>256) len=256; + ins->amiga.waveLen=(len&(~1))-1; + } + PARAMETER + } + } + ImGui::EndDisabled(); + } + // Note map + ImGui::BeginDisabled(ins->amiga.useWave); + P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap)); + if (ins->amiga.useNoteMap) { + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) sampleMapFocused=false; + if (curWindowLast!=GUI_WINDOW_INS_EDIT) sampleMapFocused=false; + if (!sampleMapFocused) sampleMapDigit=0; + if (ImGui::BeginTable("NoteMap",(ins->type==DIV_INS_NES)?5:4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); + if (ins->type==DIV_INS_NES) ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch); + + ImGui::TableSetupScrollFreeze(0,1); + + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + ImGui::Text("#"); + if (ins->type==DIV_INS_NES) { + ImGui::TableNextColumn(); + ImGui::Text("freq"); + ImGui::TableNextColumn(); + ImGui::Text("delta"); + } else { + ImGui::TableNextColumn(); + ImGui::Text("note"); + } + ImGui::TableNextColumn(); + ImGui::Text("sample name"); + int sampleMapMin=sampleMapSelStart; + int sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + + ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(ImGuiCol_HeaderHovered)); + ImGui::PushStyleColor(ImGuiCol_HeaderActive,ImGui::GetColorU32(ImGuiCol_HeaderHovered)); + for (int i=0; i<120; i++) { + DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i]; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(ImGuiCol_TableHeaderBg)); + ImGui::AlignTextToFramePadding(); + ImGui::Text("%s",noteNames[60+i]); + ImGui::TableNextColumn(); + if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { + sName=fmt::sprintf("---##SM%d",i); + sampleMap.map=-1; + } else { + sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i); + } + ImGui::PushFont(patFont); + ImGui::AlignTextToFramePadding(); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); + ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=0; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + ImGui::InhibitInertialScroll(); + } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + if (sampleMapSelStart==sampleMapSelEnd) { + sampleMapFocused=true; + sampleMapColumn=0; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + } + if (sampleMapFocused) { + wannaOpenSMPopup=true; + } + } + ImGui::PopFont(); + + if (ins->type==DIV_INS_NES) { + // pitch + ImGui::TableNextColumn(); + ImGui::PushFont(patFont); + ImGui::AlignTextToFramePadding(); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("0000").x); + ImGui::Selectable(" TO ",(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax)); + + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=1; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + ImGui::InhibitInertialScroll(); + } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + if (sampleMapSelStart==sampleMapSelEnd) { + sampleMapFocused=true; + sampleMapColumn=1; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + } + if (sampleMapFocused) { + wannaOpenSMPopup=true; + } + } + + ImGui::PopFont(); + + // delta + ImGui::TableNextColumn(); + ImGui::PushFont(patFont); + ImGui::AlignTextToFramePadding(); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("0000").x); + ImGui::Selectable(" DO ",(sampleMapWaitingInput && sampleMapColumn==2 && i>=sampleMapMin && i<=sampleMapMax)); + + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=2; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + ImGui::InhibitInertialScroll(); + } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + if (sampleMapSelStart==sampleMapSelEnd) { + sampleMapFocused=true; + sampleMapColumn=2; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + } + if (sampleMapFocused) { + wannaOpenSMPopup=true; + } + } + + ImGui::PopFont(); + } else { + ImGui::TableNextColumn(); + sName="???"; + if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) { + sName=noteNames[sampleMap.freq+60]; + } + sName+=fmt::sprintf("##SN%d",i); + ImGui::PushFont(patFont); + ImGui::AlignTextToFramePadding(); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); + ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=1; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + ImGui::InhibitInertialScroll(); + } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + if (sampleMapSelStart==sampleMapSelEnd) { + sampleMapFocused=true; + sampleMapColumn=1; + sampleMapDigit=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + + sampleMapMin=sampleMapSelStart; + sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + } + if (sampleMapFocused) { + wannaOpenSMPopup=true; + } + } + ImGui::PopFont(); + } + + ImGui::TableNextColumn(); + String prevName="---"; + if (sampleMap.map>=0 && sampleMap.mapsong.sampleLen) { + prevName=e->song.sample[sampleMap.map]->name; + } + ImGui::PushID(i+2); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##SMSample",prevName.c_str())) { + if (ImGui::Selectable("---")) { + sampleMap.map=-1; + } + for (int k=0; ksong.sampleLen; k++) { + String itemName=fmt::sprintf("%d: %s",k,e->song.sample[k]->name); + if (ImGui::Selectable(itemName.c_str())) { + sampleMap.map=k; + } + } + ImGui::EndCombo(); + } + ImGui::PopID(); + } + ImGui::PopStyleColor(2); + ImGui::EndTable(); + } + } else { + sampleMapFocused=false; + } + ImGui::EndDisabled(); + if (wannaOpenSMPopup) { + ImGui::OpenPopup("SampleMapUtils"); + } + if (ImGui::BeginPopup("SampleMapUtils",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) { + if (sampleMapSelStart==sampleMapSelEnd && sampleMapSelStart>=0 && sampleMapSelStart<120) { + if (ins->type==DIV_INS_NES) { + if (ImGui::MenuItem("set entire map to this frequency")) { + } + if (ImGui::MenuItem("set entire map to this delta counter value")) { + } + } else { + if (ImGui::MenuItem("set entire map to this note")) { + if (sampleMapSelStart>=0 && sampleMapSelStart<120) { + for (int i=0; i<120; i++) { + if (i==sampleMapSelStart) continue; + ins->amiga.noteMap[i].freq=ins->amiga.noteMap[sampleMapSelStart].freq; + } + } + } + } + if (ImGui::MenuItem("set entire map to this sample")) { + if (sampleMapSelStart>=0 && sampleMapSelStart<120) { + for (int i=0; i<120; i++) { + if (i==sampleMapSelStart) continue; + ins->amiga.noteMap[i].map=ins->amiga.noteMap[sampleMapSelStart].map; + } + } + } + } + if (ins->type==DIV_INS_NES) { + if (ImGui::MenuItem("clear frequencies")) { + } + if (ImGui::MenuItem("clear delta counter values")) { + } + } else { + if (ImGui::MenuItem("reset notes")) { + for (int i=0; i<120; i++) { + ins->amiga.noteMap[i].freq=i; + } + } + } + if (ImGui::MenuItem("clear map samples")) { + for (int i=0; i<120; i++) { + ins->amiga.noteMap[i].map=-1; + } + } + ImGui::EndPopup(); + } + ImGui::EndTabItem(); + } else { + sampleMapFocused=false; + } +} + void FurnaceGUI::drawInsEdit() { if (nextWindow==GUI_WINDOW_INS_EDIT) { insEditOpen=true; @@ -4547,278 +4951,7 @@ void FurnaceGUI::drawInsEdit() { ins->type==DIV_INS_K053260 || ins->type==DIV_INS_C140 || ins->type==DIV_INS_C219) { - if (ImGui::BeginTabItem((ins->type==DIV_INS_SU)?"Sound Unit":"Sample")) { - String sName; - bool wannaOpenSMPopup=false; - if (ins->amiga.initSample<0 || ins->amiga.initSample>=e->song.sampleLen) { - sName="none selected"; - } else { - sName=e->song.sample[ins->amiga.initSample]->name; - } - if (ins->type==DIV_INS_PCE || - ins->type==DIV_INS_MIKEY || - ins->type==DIV_INS_X1_010 || - ins->type==DIV_INS_SWAN || - ins->type==DIV_INS_AY || - ins->type==DIV_INS_AY8930 || - ins->type==DIV_INS_VRC6 || - ins->type==DIV_INS_SU) { - P(ImGui::Checkbox("Use sample",&ins->amiga.useSample)); - if (ins->type==DIV_INS_SU) { - P(ImGui::Checkbox("Switch roles of frequency and phase reset timer",&ins->su.switchRoles)); - } - if (ins->type==DIV_INS_X1_010) { - if (ImGui::InputInt("Sample bank slot##BANKSLOT",&ins->x1_010.bankSlot,1,4)) { PARAMETER - if (ins->x1_010.bankSlot<0) ins->x1_010.bankSlot=0; - if (ins->x1_010.bankSlot>=7) ins->x1_010.bankSlot=7; - } - } - } - if (ImGui::BeginCombo("Initial Sample",sName.c_str())) { - String id; - for (int i=0; isong.sampleLen; i++) { - id=fmt::sprintf("%d: %s",i,e->song.sample[i]->name); - if (ImGui::Selectable(id.c_str(),ins->amiga.initSample==i)) { PARAMETER - ins->amiga.initSample=i; - } - } - ImGui::EndCombo(); - } - // Wavetable - if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SNES) { - ImGui::BeginDisabled(ins->amiga.useNoteMap); - P(ImGui::Checkbox("Use wavetable (Amiga/SNES/Generic DAC only)",&ins->amiga.useWave)); - if (ins->amiga.useWave) { - int len=ins->amiga.waveLen+1; - int origLen=len; - if (ImGui::InputInt("Width",&len,2,16)) { - if (ins->type==DIV_INS_SNES) { - if (len<16) len=16; - if (len>256) len=256; - if (len>origLen) { - ins->amiga.waveLen=((len+15)&(~15))-1; - } else { - ins->amiga.waveLen=(len&(~15))-1; - } - } else { - if (len<2) len=2; - if (len>256) len=256; - ins->amiga.waveLen=(len&(~1))-1; - } - PARAMETER - } - } - ImGui::EndDisabled(); - } - // Note map - ImGui::BeginDisabled(ins->amiga.useWave); - P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap)); - if (ins->amiga.useNoteMap) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows)) sampleMapFocused=false; - if (curWindowLast!=GUI_WINDOW_INS_EDIT) sampleMapFocused=false; - if (!sampleMapFocused) sampleMapDigit=0; - if (ImGui::BeginTable("NoteMap",4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch); - - ImGui::TableSetupScrollFreeze(0,1); - - ImGui::TableNextRow(ImGuiTableRowFlags_Headers); - ImGui::TableNextColumn(); - ImGui::TableNextColumn(); - ImGui::Text("#"); - ImGui::TableNextColumn(); - ImGui::Text("note"); - ImGui::TableNextColumn(); - ImGui::Text("sample name"); - int sampleMapMin=sampleMapSelStart; - int sampleMapMax=sampleMapSelEnd; - if (sampleMapMin>sampleMapMax) { - sampleMapMin^=sampleMapMax; - sampleMapMax^=sampleMapMin; - sampleMapMin^=sampleMapMax; - } - - ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(ImGuiCol_HeaderHovered)); - ImGui::PushStyleColor(ImGuiCol_HeaderActive,ImGui::GetColorU32(ImGuiCol_HeaderHovered)); - for (int i=0; i<120; i++) { - DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i]; - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(ImGuiCol_TableHeaderBg)); - ImGui::AlignTextToFramePadding(); - ImGui::Text("%s",noteNames[60+i]); - ImGui::TableNextColumn(); - if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { - sName=fmt::sprintf("---##SM%d",i); - sampleMap.map=-1; - } else { - sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i); - } - ImGui::PushFont(patFont); - ImGui::AlignTextToFramePadding(); - ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); - ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - sampleMapFocused=true; - sampleMapColumn=0; - sampleMapDigit=0; - sampleMapSelStart=i; - sampleMapSelEnd=i; - - sampleMapMin=sampleMapSelStart; - sampleMapMax=sampleMapSelEnd; - if (sampleMapMin>sampleMapMax) { - sampleMapMin^=sampleMapMax; - sampleMapMax^=sampleMapMin; - sampleMapMin^=sampleMapMax; - } - ImGui::InhibitInertialScroll(); - } - if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - sampleMapSelEnd=i; - } - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { - if (sampleMapSelStart==sampleMapSelEnd) { - sampleMapFocused=true; - sampleMapColumn=0; - sampleMapDigit=0; - sampleMapSelStart=i; - sampleMapSelEnd=i; - - sampleMapMin=sampleMapSelStart; - sampleMapMax=sampleMapSelEnd; - if (sampleMapMin>sampleMapMax) { - sampleMapMin^=sampleMapMax; - sampleMapMax^=sampleMapMin; - sampleMapMin^=sampleMapMax; - } - } - if (sampleMapFocused) { - wannaOpenSMPopup=true; - } - } - ImGui::PopFont(); - - ImGui::TableNextColumn(); - sName="???"; - if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) { - sName=noteNames[sampleMap.freq+60]; - } - sName+=fmt::sprintf("##SN%d",i); - ImGui::PushFont(patFont); - ImGui::AlignTextToFramePadding(); - ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); - ImGui::Selectable(sName.c_str(),(sampleMapWaitingInput && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax)); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - sampleMapFocused=true; - sampleMapColumn=1; - sampleMapDigit=0; - sampleMapSelStart=i; - sampleMapSelEnd=i; - - sampleMapMin=sampleMapSelStart; - sampleMapMax=sampleMapSelEnd; - if (sampleMapMin>sampleMapMax) { - sampleMapMin^=sampleMapMax; - sampleMapMax^=sampleMapMin; - sampleMapMin^=sampleMapMax; - } - ImGui::InhibitInertialScroll(); - } - if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - sampleMapSelEnd=i; - } - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { - if (sampleMapSelStart==sampleMapSelEnd) { - sampleMapFocused=true; - sampleMapColumn=1; - sampleMapDigit=0; - sampleMapSelStart=i; - sampleMapSelEnd=i; - - sampleMapMin=sampleMapSelStart; - sampleMapMax=sampleMapSelEnd; - if (sampleMapMin>sampleMapMax) { - sampleMapMin^=sampleMapMax; - sampleMapMax^=sampleMapMin; - sampleMapMin^=sampleMapMax; - } - } - if (sampleMapFocused) { - wannaOpenSMPopup=true; - } - } - ImGui::PopFont(); - - ImGui::TableNextColumn(); - String prevName="---"; - if (sampleMap.map>=0 && sampleMap.mapsong.sampleLen) { - prevName=e->song.sample[sampleMap.map]->name; - } - ImGui::PushID(i+2); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("##SMSample",prevName.c_str())) { - if (ImGui::Selectable("---")) { - sampleMap.map=-1; - } - for (int k=0; ksong.sampleLen; k++) { - String itemName=fmt::sprintf("%d: %s",k,e->song.sample[k]->name); - if (ImGui::Selectable(itemName.c_str())) { - sampleMap.map=k; - } - } - ImGui::EndCombo(); - } - ImGui::PopID(); - } - ImGui::PopStyleColor(2); - ImGui::EndTable(); - } - } else { - sampleMapFocused=false; - } - ImGui::EndDisabled(); - if (wannaOpenSMPopup) { - ImGui::OpenPopup("SampleMapUtils"); - } - if (ImGui::BeginPopup("SampleMapUtils",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) { - if (sampleMapSelStart==sampleMapSelEnd && sampleMapSelStart>=0 && sampleMapSelStart<120) { - if (ImGui::MenuItem("set entire map to this note")) { - if (sampleMapSelStart>=0 && sampleMapSelStart<120) { - for (int i=0; i<120; i++) { - if (i==sampleMapSelStart) continue; - ins->amiga.noteMap[i].freq=ins->amiga.noteMap[sampleMapSelStart].freq; - } - } - } - if (ImGui::MenuItem("set entire map to this sample")) { - if (sampleMapSelStart>=0 && sampleMapSelStart<120) { - for (int i=0; i<120; i++) { - if (i==sampleMapSelStart) continue; - ins->amiga.noteMap[i].map=ins->amiga.noteMap[sampleMapSelStart].map; - } - } - } - } - if (ImGui::MenuItem("reset notes")) { - for (int i=0; i<120; i++) { - ins->amiga.noteMap[i].freq=i; - } - } - if (ImGui::MenuItem("clear map samples")) { - for (int i=0; i<120; i++) { - ins->amiga.noteMap[i].map=-1; - } - } - ImGui::EndPopup(); - } - ImGui::EndTabItem(); - } else { - sampleMapFocused=false; - } + insTabSample(ins); } if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem("Namco 163")) { bool preLoad=ins->n163.waveMode&0x1; @@ -6059,6 +6192,9 @@ void FurnaceGUI::drawInsEdit() { drawMacros(macroList,macroEditStateMacros); ImGui::EndTabItem(); } + if (ins->type==DIV_INS_NES) { + insTabSample(ins); + } ImGui::EndTabBar(); } if (settings.insEditColorize) {