From 72ef39db6067bb9d4b4ac9445c1d20e38daba821 Mon Sep 17 00:00:00 2001 From: YohananDiamond Date: Mon, 3 Apr 2023 00:05:25 -0300 Subject: [PATCH 01/22] New song dialog: auto focus on pop up + reset search box --- src/gui/gui.cpp | 1 + src/gui/newSong.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 6213bdfde..2f96b8977 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4840,6 +4840,7 @@ bool FurnaceGUI::loop() { } if (displayNew) { + newSongQuery = ""; displayNew=false; ImGui::OpenPopup("New Song"); } diff --git a/src/gui/newSong.cpp b/src/gui/newSong.cpp index 8fdafeb9b..081554121 100644 --- a/src/gui/newSong.cpp +++ b/src/gui/newSong.cpp @@ -23,6 +23,9 @@ #include void FurnaceGUI::drawNewSong() { + // Be sure to reset this to true when the popup is closed + static bool firstFrame = true; + bool accepted=false; ImGui::PushFont(bigFont); @@ -34,6 +37,10 @@ void FurnaceGUI::drawNewSong() { avail.y-=ImGui::GetFrameHeightWithSpacing(); if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) { + if (firstFrame) { + ImGui::SetKeyboardFocusHere(); + firstFrame = false; + } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::InputTextWithHint("##SysSearch","Search...",&newSongQuery)) { String lowerCase=newSongQuery; @@ -122,10 +129,12 @@ void FurnaceGUI::drawNewSong() { if (ImGui::Button("I'm feeling lucky")) { if (sysCategories.size()==0) { + firstFrame = true; ImGui::CloseCurrentPopup(); } else { FurnaceGUISysCategory* newSystemCat=&sysCategories[rand()%sysCategories.size()]; if (newSystemCat->systems.size()==0) { + firstFrame = true; ImGui::CloseCurrentPopup(); } else { unsigned int selection=rand()%newSystemCat->systems.size(); @@ -139,6 +148,7 @@ void FurnaceGUI::drawNewSong() { ImGui::SameLine(); if (ImGui::Button("Cancel")) { + firstFrame = true; ImGui::CloseCurrentPopup(); } @@ -157,6 +167,7 @@ void FurnaceGUI::drawNewSong() { selEnd=SelectionPoint(); cursor=SelectionPoint(); updateWindowTitle(); + firstFrame = true; ImGui::CloseCurrentPopup(); } } From c3654a4d525ad40bfa1c158a7fab25a853c002b6 Mon Sep 17 00:00:00 2001 From: YohananDiamond Date: Mon, 3 Apr 2023 11:11:26 -0300 Subject: [PATCH 02/22] Applying corrections --- src/gui/gui.cpp | 3 ++- src/gui/gui.h | 1 + src/gui/newSong.cpp | 13 +++---------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 2f96b8977..66e57df08 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4840,7 +4840,8 @@ bool FurnaceGUI::loop() { } if (displayNew) { - newSongQuery = ""; + newSongQuery=""; + newSongFirstFrame=true; displayNew=false; ImGui::OpenPopup("New Song"); } diff --git a/src/gui/gui.h b/src/gui/gui.h index cf18f7e8a..e75ee91bd 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1564,6 +1564,7 @@ class FurnaceGUI { double exportFadeOut; + bool newSongFirstFrame; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; diff --git a/src/gui/newSong.cpp b/src/gui/newSong.cpp index 081554121..735f8bfb0 100644 --- a/src/gui/newSong.cpp +++ b/src/gui/newSong.cpp @@ -23,9 +23,6 @@ #include void FurnaceGUI::drawNewSong() { - // Be sure to reset this to true when the popup is closed - static bool firstFrame = true; - bool accepted=false; ImGui::PushFont(bigFont); @@ -37,10 +34,8 @@ void FurnaceGUI::drawNewSong() { avail.y-=ImGui::GetFrameHeightWithSpacing(); if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) { - if (firstFrame) { + if (newSongFirstFrame) ImGui::SetKeyboardFocusHere(); - firstFrame = false; - } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::InputTextWithHint("##SysSearch","Search...",&newSongQuery)) { String lowerCase=newSongQuery; @@ -129,12 +124,10 @@ void FurnaceGUI::drawNewSong() { if (ImGui::Button("I'm feeling lucky")) { if (sysCategories.size()==0) { - firstFrame = true; ImGui::CloseCurrentPopup(); } else { FurnaceGUISysCategory* newSystemCat=&sysCategories[rand()%sysCategories.size()]; if (newSystemCat->systems.size()==0) { - firstFrame = true; ImGui::CloseCurrentPopup(); } else { unsigned int selection=rand()%newSystemCat->systems.size(); @@ -148,7 +141,6 @@ void FurnaceGUI::drawNewSong() { ImGui::SameLine(); if (ImGui::Button("Cancel")) { - firstFrame = true; ImGui::CloseCurrentPopup(); } @@ -167,7 +159,8 @@ void FurnaceGUI::drawNewSong() { selEnd=SelectionPoint(); cursor=SelectionPoint(); updateWindowTitle(); - firstFrame = true; ImGui::CloseCurrentPopup(); } + + newSongFirstFrame=false; } From a8d1f0ca166205cefb83a4c81beb4a6b961d566b Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 8 Apr 2023 20:45:58 +0900 Subject: [PATCH 03/22] Possibly fix k007232 stereo setting --- src/engine/platform/k007232.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/platform/k007232.cpp b/src/engine/platform/k007232.cpp index 04e1bde5e..0b11d45f6 100644 --- a/src/engine/platform/k007232.cpp +++ b/src/engine/platform/k007232.cpp @@ -34,7 +34,7 @@ const char* regCheatSheetK007232[]={ "CHX_StartM", "X*6+3", "CHX_StartH", "X*6+4", "CHX_Keyon", "X*6+5", - "SLEV", "C", // external IO + "SLEV", "C", // external IO (Volume for Mono speaker) "Loop", "D", // off-chip "CHX_Volume", "X*2+10", @@ -157,8 +157,7 @@ void DivPlatformK007232::tick(bool sysTick) { rWrite(0x10+i,(chan[i].lvol&0xf)|((chan[i].rvol&0xf)<<4)); chan[i].prevPan=newPan; } - } - else { + } else { const unsigned char prevVolume=lastVolume; lastVolume=(lastVolume&~(0xf<<(i<<2)))|((chan[i].resVol&0xf)<<(i<<2)); if (prevVolume!=lastVolume) { @@ -480,6 +479,7 @@ void DivPlatformK007232::setFlags(const DivConfig& flags) { rate=chipClock/4; stereo=flags.getBool("stereo",false); for (int i=0; i<2; i++) { + chan[i].volumeChanged=true; oscBuf[i]->rate=rate; } } From 84eadd7aacacd1c4bd21009c4cfddeb45907a5f1 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 8 Apr 2023 14:23:44 -0500 Subject: [PATCH 04/22] dev152 - sample map notes, part 2 Sound Unit --- src/engine/platform/su.cpp | 10 +++++++--- src/engine/platform/su.h | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index 7367f50ce..728d7a91a 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -138,9 +138,7 @@ void DivPlatformSoundUnit::tick(bool sysTick) { //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,chan[i].switchRoles,2,chan[i].pitch2,chipClock,chan[i].switchRoles?CHIP_DIVIDER:CHIP_FREQBASE); if (chan[i].pcm) { - DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SU); - // TODO: sample map? - DivSample* sample=parent->getSample(ins->amiga.getSample(chan[i].note)); + DivSample* sample=parent->getSample(chan[i].sample); if (sample!=NULL) { double off=0.25; if (sample->centerRate<1) { @@ -209,6 +207,12 @@ int DivPlatformSoundUnit::dispatch(DivCommand c) { writeControlUpper(c.chan); } chan[c.chan].pcm=(ins->type==DIV_INS_AMIGA || ins->amiga.useSample); + if (chan[c.chan].pcm) { + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].sample=ins->amiga.getSample(c.value); + c.value=ins->amiga.getFreq(c.value); + } + } if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_SU(c.chan,c.value); chan[c.chan].freqChanged=true; diff --git a/src/engine/platform/su.h b/src/engine/platform/su.h index 13b4d4bba..de67c2faf 100644 --- a/src/engine/platform/su.h +++ b/src/engine/platform/su.h @@ -26,7 +26,7 @@ class DivPlatformSoundUnit: public DivDispatch { struct Channel: public SharedChannel { - int cutoff, baseCutoff, res, control, hasOffset; + int cutoff, baseCutoff, res, control, hasOffset, sample; signed char pan; unsigned char duty; bool noise, pcm, phaseReset, filterPhaseReset, switchRoles; @@ -43,6 +43,7 @@ class DivPlatformSoundUnit: public DivDispatch { res(0), control(0), hasOffset(0), + sample(-1), pan(0), duty(63), noise(false), From 385f7af664d58725cb69479d22f0a734ed8b0b30 Mon Sep 17 00:00:00 2001 From: cam900 Date: Sun, 9 Apr 2023 10:29:51 +0900 Subject: [PATCH 05/22] ES5506: Fix frequency for note map --- src/engine/platform/es5506.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/engine/platform/es5506.cpp b/src/engine/platform/es5506.cpp index 28ad45eb2..5f6e28292 100644 --- a/src/engine/platform/es5506.cpp +++ b/src/engine/platform/es5506.cpp @@ -433,7 +433,6 @@ void DivPlatformES5506::tick(bool sysTick) { off=(double)center/8363.0; } if (ins->amiga.useNoteMap) { - off*=(double)noteMapind.freq/((double)MAX(1,center)*pow(2.0,((double)next-48.0)/12.0)); chan[i].pcm.note=next; } // get loop mode @@ -618,10 +617,6 @@ void DivPlatformES5506::tick(bool sysTick) { } else { off=(double)center/8363.0; } - if (ins->amiga.useNoteMap) { - DivInstrumentAmiga::SampleMap& noteMapind=ins->amiga.noteMap[chan[i].pcm.note]; - off*=(double)noteMapind.freq/((double)MAX(1,center)*pow(2.0,((double)chan[i].pcm.note-48.0)/12.0)); - } chan[i].pcm.loopStart=(chan[i].pcm.start+(s->loopStart<<11))&0xfffff800; chan[i].pcm.loopEnd=(chan[i].pcm.start+((s->loopEnd-1)<<11))&0xffffff80; chan[i].pcm.freqOffs=PITCH_OFFSET*off; From 90829a8a9554d18484d0a1e054ea1cffcc64aebf Mon Sep 17 00:00:00 2001 From: freq-mod <32672779+freq-mod@users.noreply.github.com> Date: Sat, 8 Apr 2023 14:44:02 +0200 Subject: [PATCH 06/22] add c15+bubsys wsg + k007232 demo song --- demos/multichip/MegaMari-Cirno.fur | Bin 0 -> 34728 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/multichip/MegaMari-Cirno.fur diff --git a/demos/multichip/MegaMari-Cirno.fur b/demos/multichip/MegaMari-Cirno.fur new file mode 100644 index 0000000000000000000000000000000000000000..2781a795f8a8253d08c300aab1e0d3b665de60a7 GIT binary patch literal 34728 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 K<0H2X$NmIG*v}{c literal 0 HcmV?d00001 From 5466b26c75caafa3bfde2fefe528db3048b861a1 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 9 Apr 2023 01:13:45 -0500 Subject: [PATCH 07/22] GUI: fix osc out of bounds mode --- src/gui/osc.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/osc.cpp b/src/gui/osc.cpp index f04587c8b..e5bc09e4b 100644 --- a/src/gui/osc.cpp +++ b/src/gui/osc.cpp @@ -221,8 +221,9 @@ void FurnaceGUI::drawOsc() { waveform[i]=ImLerp(inRect.Min,inRect.Max,ImVec2(x,0.5f-y)); } if (settings.oscEscapesBoundary) { - ImDrawList* dlf=ImGui::GetForegroundDrawList(); - dlf->AddPolyline(waveform,512,color,ImDrawFlags_None,dpiScale); + dl->PushClipRectFullScreen(); + dl->AddPolyline(waveform,512,color,ImDrawFlags_None,dpiScale); + dl->PopClipRect(); } else { dl->AddPolyline(waveform,512,color,ImDrawFlags_None,dpiScale); } From 8dfe0bc0210051adc61b81f21ca233dddfa76082 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 9 Apr 2023 13:20:28 -0500 Subject: [PATCH 08/22] OPN: fix ExtCh muting --- src/engine/platform/genesisext.cpp | 7 +------ src/engine/platform/ym2203ext.cpp | 7 +------ src/engine/platform/ym2608ext.cpp | 7 +------ src/engine/platform/ym2610bext.cpp | 7 +------ src/engine/platform/ym2610ext.cpp | 7 +------ 5 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 3ab6cec4e..08b7a65cc 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -433,13 +433,8 @@ void DivPlatformGenesisExt::muteChannel(int ch, bool mute) { DivInstrumentFM::Operator op=chan[2].state.op[ordch]; if (isOpMuted[ch-2] || !op.enable) { rWrite(baseAddr+0x40,127); - immWrite(baseAddr+0x40,127); - } else if (KVS(2,ordch)) { - rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); - immWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } else { - rWrite(baseAddr+0x40,op.tl); - immWrite(baseAddr+0x40,op.tl); + rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-2].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); diff --git a/src/engine/platform/ym2203ext.cpp b/src/engine/platform/ym2203ext.cpp index ae6eacd3e..6398ba7f1 100644 --- a/src/engine/platform/ym2203ext.cpp +++ b/src/engine/platform/ym2203ext.cpp @@ -542,13 +542,8 @@ void DivPlatformYM2203Ext::muteChannel(int ch, bool mute) { DivInstrumentFM::Operator op=chan[2].state.op[ordch]; if (isOpMuted[ch-2] || !op.enable) { rWrite(baseAddr+0x40,127); - immWrite(baseAddr+0x40,127); - } else if (KVS(2,ordch)) { - rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); - immWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } else { - rWrite(baseAddr+0x40,op.tl); - immWrite(baseAddr+0x40,op.tl); + rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } } diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index 387ba110e..120261c0c 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -564,13 +564,8 @@ void DivPlatformYM2608Ext::muteChannel(int ch, bool mute) { DivInstrumentFM::Operator op=chan[2].state.op[ordch]; if (isOpMuted[ch-2] || !op.enable) { rWrite(baseAddr+0x40,127); - immWrite(baseAddr+0x40,127); - } else if (KVS(2,ordch)) { - rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); - immWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } else { - rWrite(baseAddr+0x40,op.tl); - immWrite(baseAddr+0x40,op.tl); + rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-2].outVol&0x7f,127)); } rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-2].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index 97f5c0d61..5ab45ecbe 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -560,13 +560,8 @@ void DivPlatformYM2610BExt::muteChannel(int ch, bool mute) { DivInstrumentFM::Operator op=chan[extChanOffs].state.op[ordch]; if (isOpMuted[ch-extChanOffs] || !op.enable) { rWrite(baseAddr+0x40,127); - immWrite(baseAddr+0x40,127); - } else if (KVS(2,ordch)) { - rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); - immWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); } else { - rWrite(baseAddr+0x40,op.tl); - immWrite(baseAddr+0x40,op.tl); + rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); } rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-extChanOffs].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index 09347443a..620973503 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -560,13 +560,8 @@ void DivPlatformYM2610Ext::muteChannel(int ch, bool mute) { DivInstrumentFM::Operator op=chan[extChanOffs].state.op[ordch]; if (isOpMuted[ch-extChanOffs] || !op.enable) { rWrite(baseAddr+0x40,127); - immWrite(baseAddr+0x40,127); - } else if (KVS(2,ordch)) { - rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); - immWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); } else { - rWrite(baseAddr+0x40,op.tl); - immWrite(baseAddr+0x40,op.tl); + rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch-extChanOffs].outVol&0x7f,127)); } rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-extChanOffs].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); From 7a137fcdd1f38a0571e1667919e9042b82bdd301 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 9 Apr 2023 13:44:47 -0500 Subject: [PATCH 09/22] QuadTone: fix PCM muting --- src/engine/platform/zxbeeperquadtone.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/engine/platform/zxbeeperquadtone.cpp b/src/engine/platform/zxbeeperquadtone.cpp index 8bfce1701..3be196ad0 100644 --- a/src/engine/platform/zxbeeperquadtone.cpp +++ b/src/engine/platform/zxbeeperquadtone.cpp @@ -32,11 +32,11 @@ const char** DivPlatformZXBeeperQuadTone::getRegisterSheet() { void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) { bool o=false; for (size_t h=0; h=0 && curSamplesong.sampleLen) { + if (curSample>=0 && curSamplesong.sampleLen && !isMuted[4]) { while (curSamplePeriod>=chan[4].freq) { DivSample* s=parent->getSample(curSample); if (s->samples>0) { - o=(!isMuted[4]&&s->data8[curSamplePos++]>0); + if (!isMuted[4]) o=(s->data8[curSamplePos++]>0); if (curSamplePos>=s->samples) curSample=-1; // (theoretical) 32KiB limit if (curSamplePos>=32768*8) curSample=-1; @@ -59,6 +59,7 @@ void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) { if ((outputClock&1)==0) { chan[ch].sPosition+=(regPool[1+b]<<8)|regPool[0+b]; chan[ch].out=regPool[3+b]+((((chan[ch].sPosition>>8)&0xff)data[oscBuf[4]->needle++]=0; @@ -66,6 +67,22 @@ void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) { o=chan[ch].out&0x10; oscBuf[ch]->data[oscBuf[ch]->needle++]=o?32767:0; chan[ch].out<<=1; + + // if muted, ztill run sample + if (curSample>=0 && curSamplesong.sampleLen && isMuted[4]) { + while (curSamplePeriod>=chan[4].freq) { + DivSample* s=parent->getSample(curSample); + if (s->samples>0) { + if (curSamplePos>=s->samples) curSample=-1; + // (theoretical) 32KiB limit + if (curSamplePos>=32768*8) curSample=-1; + } else { + curSample=-1; + } + curSamplePeriod-=chan[4].freq; + } + curSamplePeriod+=40; + } } outputClock=(outputClock+1)&7; buf[0][h]=o?32767:0; @@ -283,7 +300,7 @@ int DivPlatformZXBeeperQuadTone::dispatch(DivCommand c) { void DivPlatformZXBeeperQuadTone::writeOutVol(int ch) { if (ch>=4) return; unsigned char val=(chan[ch].outVol>=1)?((chan[ch].outVol>=2)?31:7):0; - rWrite(3+ch*4,(!isMuted[ch]&&chan[ch].active)?val:0); + rWrite(3+ch*4,(chan[ch].active)?val:0); } void DivPlatformZXBeeperQuadTone::muteChannel(int ch, bool mute) { From e755f1bbd0cfe19c39bd22239e364648bc0a7adc Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 9 Apr 2023 15:27:17 -0500 Subject: [PATCH 10/22] GUI: possibly fix MIDI note hang issue #815 --- src/gui/gui.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 8947d566e..058be1d14 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -5564,6 +5564,52 @@ bool FurnaceGUI::loop() { curWindowThreadSafe=curWindow; + if (curWindow!=curWindowLast) { + int curWindowCat=0; + int lastWindowCat=0; + + switch (curWindow) { + case GUI_WINDOW_WAVE_LIST: + case GUI_WINDOW_WAVE_EDIT: + curWindowCat=1; + break; + case GUI_WINDOW_SAMPLE_LIST: + case GUI_WINDOW_SAMPLE_EDIT: + curWindowCat=2; + break; + default: + curWindowCat=0; + break; + } + switch (curWindowLast) { + case GUI_WINDOW_WAVE_LIST: + case GUI_WINDOW_WAVE_EDIT: + lastWindowCat=1; + break; + case GUI_WINDOW_SAMPLE_LIST: + case GUI_WINDOW_SAMPLE_EDIT: + lastWindowCat=2; + break; + default: + lastWindowCat=0; + break; + } + + if (curWindowCat!=lastWindowCat) { + switch (lastWindowCat) { + case 0: + e->autoNoteOffAll(); + break; + case 1: + e->stopWavePreview(); + break; + case 2: + e->stopSamplePreview(); + break; + } + } + } + SDL_SetRenderDrawColor(sdlRend,uiColors[GUI_COLOR_BACKGROUND].x*255, uiColors[GUI_COLOR_BACKGROUND].y*255, uiColors[GUI_COLOR_BACKGROUND].z*255, From 8375256ff735c94ac8279647bff9dbe816f8abb2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 10 Apr 2023 00:31:55 -0500 Subject: [PATCH 11/22] debug dmf not loading again --- src/engine/fileOps.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index c9e51bf0b..a6a737431 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -928,15 +928,17 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { data=newData; } + logV("length: %d. scaledLen: %d.",length,scaledLen); + if (ds.version>=0x1b) { if (cutStart<0 || cutStart>scaledLen) { - logE("cutStart is out of range! (%d)",cutStart); + logE("cutStart is out of range! (%d, scaledLen: %d)",cutStart,scaledLen); lastError="file is corrupt or unreadable at samples"; delete[] file; return false; } if (cutEnd<0 || cutEnd>scaledLen) { - logE("cutEnd is out of range! (%d)",cutEnd); + logE("cutEnd is out of range! (%d, scaledLen: %d)",cutEnd,scaledLen); lastError="file is corrupt or unreadable at samples"; delete[] file; return false; From 9e615bb3aabfdb44346c4a7478fc4fae04f55011 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 10 Apr 2023 01:09:58 -0500 Subject: [PATCH 12/22] fix .dmf loading..... again (I think) --- src/engine/fileOps.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index a6a737431..0ca5dff69 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -902,13 +902,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { } #endif - int scaledLen=(double)length/samplePitches[pitch]; + int scaledLen=ceil((double)length/samplePitches[pitch]); if (scaledLen>0) { // resample logD("%d: scaling from %d...",i,pitch); short* newData=new short[scaledLen]; + memset(newData,0,scaledLen*sizeof(short)); int k=0; float mult=(float)(vol)/50.0f; for (double j=0; j Date: Mon, 10 Apr 2023 03:10:44 -0500 Subject: [PATCH 13/22] two demo songs by TheDuccinator --- demos/arcade/Maximum_Overdrive_NamcoWSG.fur | Bin 0 -> 3905 bytes demos/ay8910/Second_Addition.fur | Bin 0 -> 2814 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/arcade/Maximum_Overdrive_NamcoWSG.fur create mode 100644 demos/ay8910/Second_Addition.fur diff --git a/demos/arcade/Maximum_Overdrive_NamcoWSG.fur b/demos/arcade/Maximum_Overdrive_NamcoWSG.fur new file mode 100644 index 0000000000000000000000000000000000000000..0fdbc113d40122aaea9ae4b00d9a11be6ca9a056 GIT binary patch literal 3905 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 P;t`K{y?Flz+gwTW6V9?b literal 0 HcmV?d00001 diff --git a/demos/ay8910/Second_Addition.fur b/demos/ay8910/Second_Addition.fur new file mode 100644 index 0000000000000000000000000000000000000000..0ba3f5ed8bbae426e8eaf20a33381686826971e5 GIT binary patch literal 2814 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 Q`9pam@b*ss2LV1@MfBE>vj6}9 literal 0 HcmV?d00001 From 40da2c52344bcd07fd16143d28a204ac00df231a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 10 Apr 2023 03:12:22 -0500 Subject: [PATCH 14/22] correct two demo songs corrections by Yuzu4K --- demos/misc/TimeMan_SharpX68k.fur | Bin 4082 -> 4084 bytes demos/msx/Nemesis2AirBattle.fur | Bin 2668 -> 2659 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/demos/misc/TimeMan_SharpX68k.fur b/demos/misc/TimeMan_SharpX68k.fur index 0b51a2835af8f63d589f2770b2af0022090cb992..ae09890af94138efe69d80f9fbc1693d15ce1c85 100644 GIT binary patch literal 4084 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 literal 2668 zcmaiyYdF&lAIC8pQEY9_Vd-F$Q{-%8NaW1OJ%=LXFuReQZHe2dNJQl@LR2bugqk^% z5Gv;-=8zosN6a$Z?(4a(=f(5pdGmYw{e3>yCnA5v)hbZxgGk&?o13!v?pV4s-j8|&6<8m~_YOzs<&f5hAG~#+X z`n1m6sHUM&k*Z|rk$Ya`y$WJ|HMMQ7VNNJqA*=h6ts+@y@^coqK35aWH7uy0vW4Y4bvCHAA@)r?nJt zSN_|jyFMlFox;^R=mA4?9IL%MqmdEkyCYARR|_WP@wtsW6t>!+`HkzJ-jdG7a!+Zd z61W@E*AI2$q^3?}`=)X=VcDQ=jBTGTSJMTy_*~#2j4@lU`_Z{(729-2uJ0Gvzr~yR zP_kA$oF!y4Nf>lT7Nos*iu_f%^EZxsCIeK7r2T+%VMs@(K1q-#F(6>Inv03y14f8E zoKVpzj0)GC0>15aFj-zKI9~JHg%!I57wc{t0_TutvF09AyHdCAk@%(va6+xeMm zo8{x1e%?)ewCOKDgvm=5i4iFNlr$`7)(c(L7mmvr^Z060|J|u6h1A-TAb1x)louB6 z7guK5>VI!qLbE~7Lp zU>!yZ#o2a>C@<6u3XbBEUG+!lrrz>=g0MY{kSa@_F3Ps;Mu}vrWd~;;LXbtbh*$Uj z-|>yzy<+)dqxn+%m)z&JS00~sicc4V<@ZOmR7WiT{JgMm5A0qO&JemTwZAm&WyTI{UyIb8 zsx~Yo!?iVZ+#j7gOfd|XdEXhD2+(EvRfT;Yd8FezQ`)`q3zj7D6W5M7h1)s5Z65NP zc=c-VbrNXTHTt*sH@rt*oTRqi@JisG=am1WcaOK=i`v?qrcRen>$M6TGWZ&5nHExi z^v{Pm!4ZncVEeA1XQ-FC*0VipUFw?RX5x&y6RqE1F%ZQ;{iwjxjsex4!)wXF`7Jp*ca zIrgJcHMNa0+)9a?Um!!XMXz~_lDvx|=!dRYfk)FcM$+CchVjNG+{)2^1+#QZXNQp4 z7ZIV)qUf;#M#8GLQcQgrhn`u9^HJW8soHRxEH1ZXzF0}4a`B2eF-MgggK0FplW;P5 zXK}gCgL5iCW}fo*nQo!(*zZ2`dZ_vF-G&Y6>Cl^T(sPo;rjC9oPK1@AOk4UZp?pI1O6WQw)lLnJ6kRoof3j>h7Uvzo_is5&e-6Uk<^mA{S$!kb3n z&Muzy7Ele?%tJA)WN~0vg?j+yPX2EfKu(!7MpVCHZg%#s@Z5N$n%U)vK6#=bDfMTL?mf! zFZ}Y~-g%4c=54GfA2*N4S&J`BbVu0$wY2q_sU+37Vk~L`=#1#1ETy zXTuZs6Tdu<-<saES?$zZ_JJC@w}m>g*0U8A?QiI~*1>Ha z5>_R`m++=eU6Ega()yV{)(I|us8Q?YL{mjcRGDV7j%u=IaFVL7fZR=n8d>wwqPXbT z?JbttNnvd5j+%eQG4tt=i*t$-4GQMoO}9xn|fDDNvbT75|^7YJ}qsMhe`&t-|9qh?v}S3*PrKvmi0R$(TZbYNKBcutu9+5? z@;-i0_{U(`NBl24|LhGSJhJ4MBl_!TIYR|uQeRQ%Pb38y*6<`T-;!r<3AF`qf1KpG zNTKNO?=l3zFy-goV72_$-Zz$JUb&V4fBeOYO5kLguWAX&zjGI%ycszc6=r;?%I`kz z;BA_Vqh5=or+lW$q6@VlV+5+0He0#;pXRrG> Date: Mon, 10 Apr 2023 03:14:18 -0500 Subject: [PATCH 15/22] add two demo songs by TakuikaNinja --- demos/misc/BlueBolt_VIC20.fur | Bin 0 -> 1432 bytes demos/misc/GreenIdeas_PET.fur | Bin 0 -> 1655 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/misc/BlueBolt_VIC20.fur create mode 100644 demos/misc/GreenIdeas_PET.fur diff --git a/demos/misc/BlueBolt_VIC20.fur b/demos/misc/BlueBolt_VIC20.fur new file mode 100644 index 0000000000000000000000000000000000000000..51458e7fd73fd8d723787fa00238b967725999a9 GIT binary patch literal 1432 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 Date: Mon, 10 Apr 2023 05:31:08 -0500 Subject: [PATCH 16/22] crash --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 20e267370..e85c4de77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: RelWithDebInfo + BUILD_TYPE: Debug jobs: build: From ad2af793ba0e171c0535d2f6100f571135e17afa Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 10 Apr 2023 13:12:01 -0500 Subject: [PATCH 17/22] work around NFD crash --- extern/nfd-modified/src/nfd_win.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extern/nfd-modified/src/nfd_win.cpp b/extern/nfd-modified/src/nfd_win.cpp index e4342243c..9c12c3485 100644 --- a/extern/nfd-modified/src/nfd_win.cpp +++ b/extern/nfd-modified/src/nfd_win.cpp @@ -204,7 +204,9 @@ static void CopyNFDCharToWChar( const nfdchar_t *inStr, wchar_t **outStr ) #ifdef _DEBUG int inStrCharacterCount = static_cast(NFDi_UTF8_Strlen(inStr)); - assert( ret == inStrCharacterCount ); + if (ret!=inStrCharacterCount) { + logW("length does not match! %d != %d",ret,inStrCharacterCount); + } #else _NFD_UNUSED(ret); #endif From 8d4fa6e0cc97c568562590af6a1db13e13b31aed Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 10 Apr 2023 19:49:14 -0500 Subject: [PATCH 18/22] prepare for new sample map UI --- src/gui/gui.cpp | 7 +++++-- src/gui/gui.h | 7 +++++-- src/gui/insEdit.cpp | 1 + 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 058be1d14..23d96cd1f 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6472,8 +6472,11 @@ FurnaceGUI::FurnaceGUI(): samplePreviewOn(false), samplePreviewKey((SDL_Scancode)0), samplePreviewNote(0), - arpMacroScroll(-12), - pitchMacroScroll(-80), + sampleMapSelStart(-1), + sampleMapSelEnd(-1), + sampleMapDigit(0), + sampleMapColumn(0), + sampleMapFocused(false), macroDragStart(0,0), macroDragAreaSize(0,0), macroDragCTarget(NULL), diff --git a/src/gui/gui.h b/src/gui/gui.h index 87fb79702..4dcb78ee1 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1679,8 +1679,11 @@ class FurnaceGUI { std::vector pressedPoints; std::vector releasedPoints; - int arpMacroScroll; - int pitchMacroScroll; + int sampleMapSelStart; + int sampleMapSelEnd; + int sampleMapDigit; + int sampleMapColumn; + bool sampleMapFocused; ImVec2 macroDragStart; ImVec2 macroDragAreaSize; diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index f2d97ac04..b6fcd7bc9 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4425,6 +4425,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); ImGui::Text("%s",noteNames[60+i]); ImGui::TableNextColumn(); + // TODO: new style sample map if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { sName="-- empty --"; sampleMap.map=-1; From f90ca2410fad998c4e5f9fd91d99f0d8c85bfb01 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 11 Apr 2023 18:17:30 -0500 Subject: [PATCH 19/22] GUI: new sample map UI, part 1 keyboard/MIDI missing --- src/gui/insEdit.cpp | 93 ++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index b6fcd7bc9..349376c26 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4405,66 +4405,89 @@ void FurnaceGUI::drawInsEdit() { ImGui::BeginDisabled(ins->amiga.useWave); P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap)); if (ins->amiga.useNoteMap) { - if (ImGui::BeginTable("NoteMap",3,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) { + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=false; + } + if (ImGui::BeginTable("NoteMap",4,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); + 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("Sample"); + ImGui::Text("#"); ImGui::TableNextColumn(); - ImGui::Text("Note"); + ImGui::Text("note"); + ImGui::TableNextColumn(); + if (sampleMapFocused) { + ImGui::Text("FOCUSED"); + } else { + ImGui::Text("sample name"); + } + int sampleMapMin=sampleMapSelStart; + int sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + for (int i=0; i<120; i++) { DivInstrumentAmiga::SampleMap& sampleMap=ins->amiga.noteMap[i]; ImGui::TableNextRow(); - ImGui::PushID(fmt::sprintf("NM_%d",i).c_str()); ImGui::TableNextColumn(); ImGui::Text("%s",noteNames[60+i]); ImGui::TableNextColumn(); - // TODO: new style sample map if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { - sName="-- empty --"; + sName=fmt::sprintf("---##SM%d",i); sampleMap.map=-1; } else { - sName=e->song.sample[sampleMap.map]->name; + sName=fmt::sprintf("%3d##SM%d",sampleMap.map,i); } - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("##SM",sName.c_str())) { - String id; - if (ImGui::Selectable("-- empty --",sampleMap.map==-1)) { PARAMETER - sampleMap.map=-1; - } - for (int j=0; jsong.sampleLen; j++) { - id=fmt::sprintf("%d: %s",j,e->song.sample[j]->name); - if (ImGui::Selectable(id.c_str(),sampleMap.map==j)) { PARAMETER - sampleMap.map=j; - } - } - ImGui::EndCombo(); + ImGui::PushFont(patFont); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); + ImGui::Selectable(sName.c_str(),(sampleMapFocused && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=0; + sampleMapSelStart=i; + sampleMapSelEnd=i; + ImGui::InhibitInertialScroll(); } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + ImGui::PopFont(); ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - const char* nName="???"; + sName="???"; if ((sampleMap.freq+60)>0 && (sampleMap.freq+60)<180) { - nName=noteNames[sampleMap.freq+60]; + sName=noteNames[sampleMap.freq+60]; } - if (ImGui::BeginCombo("##SN",nName)) { - for (int j=0; j<180; j++) { - const char* nName2="???"; - nName2=noteNames[j]; - if (ImGui::Selectable(nName2,(sampleMap.freq+60)==j)) { - sampleMap.freq=j-60; - } - } - ImGui::EndCombo(); + sName+=fmt::sprintf("##SN%d",i); + ImGui::PushFont(patFont); + ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); + ImGui::Selectable(sName.c_str(),(sampleMapFocused && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax)); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + sampleMapFocused=true; + sampleMapColumn=1; + sampleMapSelStart=i; + sampleMapSelEnd=i; + ImGui::InhibitInertialScroll(); } + if (sampleMapFocused && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + sampleMapSelEnd=i; + } + ImGui::PopFont(); - ImGui::PopID(); + ImGui::TableNextColumn(); + if (sampleMap.map>=0 && sampleMap.mapsong.sampleLen) { + ImGui::TextUnformatted(e->song.sample[sampleMap.map]->name.c_str()); + } } ImGui::EndTable(); } From 7af514a658ba975b656d81dd81472a0a013d08b5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 11 Apr 2023 19:41:20 -0500 Subject: [PATCH 20/22] GUI: new sample map UI, part 2 next commit will introduce keyboard input --- src/gui/gui.cpp | 4 ++- src/gui/gui.h | 3 ++- src/gui/insEdit.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++--- src/gui/piano.cpp | 12 ++++++--- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 23d96cd1f..13a380b41 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2905,7 +2905,7 @@ int FurnaceGUI::processEvent(SDL_Event* ev) { } #endif if (ev->type==SDL_KEYDOWN) { - if (!ev->key.repeat && latchTarget==0 && !wantCaptureKeyboard && (ev->key.keysym.mod&(~(KMOD_NUM|KMOD_CAPS|KMOD_SCROLL)))==0) { + if (!ev->key.repeat && latchTarget==0 && !wantCaptureKeyboard && !sampleMapWaitingInput && (ev->key.keysym.mod&(~(KMOD_NUM|KMOD_CAPS|KMOD_SCROLL)))==0) { if (settings.notePreviewBehavior==0) return 1; switch (curWindow) { case GUI_WINDOW_SAMPLE_EDIT: @@ -5561,6 +5561,8 @@ bool FurnaceGUI::loop() { } } } + + sampleMapWaitingInput=(curWindow==GUI_WINDOW_INS_EDIT && sampleMapFocused); curWindowThreadSafe=curWindow; diff --git a/src/gui/gui.h b/src/gui/gui.h index 4dcb78ee1..fb193c20a 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1683,7 +1683,7 @@ class FurnaceGUI { int sampleMapSelEnd; int sampleMapDigit; int sampleMapColumn; - bool sampleMapFocused; + bool sampleMapFocused, sampleMapWaitingInput; ImVec2 macroDragStart; ImVec2 macroDragAreaSize; @@ -1938,6 +1938,7 @@ class FurnaceGUI { void drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float availableWidth, int index); void drawMacros(std::vector& macros, FurnaceGUIMacroEditState& state); + void alterSampleMap(bool isNote, int val); void drawOrderButtons(); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 349376c26..9ec9da044 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2023,6 +2023,57 @@ void FurnaceGUI::drawMacros(std::vector& macros, FurnaceGUI } } +void FurnaceGUI::alterSampleMap(bool isNote, int val) { + if (curIns<0 || curIns>=(int)e->song.ins.size()) return; + DivInstrument* ins=e->song.ins[curIns]; + int sampleMapMin=sampleMapSelStart; + int sampleMapMax=sampleMapSelEnd; + if (sampleMapMin>sampleMapMax) { + sampleMapMin^=sampleMapMax; + sampleMapMax^=sampleMapMin; + sampleMapMin^=sampleMapMax; + } + + for (int i=sampleMapMin; i<=sampleMapMax; i++) { + if (i<0 || i>=120) continue; + + if (sampleMapColumn==1 && isNote) { + ins->amiga.noteMap[i].freq=val; + } else if (sampleMapColumn==0 && !isNote) { + if (val<0) { + ins->amiga.noteMap[i].map=-1; + } else if (sampleMapDigit>0) { + ins->amiga.noteMap[i].map*=10; + ins->amiga.noteMap[i].map+=val; + } else { + ins->amiga.noteMap[i].map=val; + } + if (ins->amiga.noteMap[i].map>=(int)e->song.sample.size()) { + ins->amiga.noteMap[i].map=((int)e->song.sample.size())-1; + } + } + } + + bool advance=false; + if (sampleMapColumn==1 && isNote) { + advance=true; + } else if (sampleMapColumn==0 && !isNote) { + int digits=1; + if (e->song.sample.size()>=10) digits=2; + if (e->song.sample.size()>=100) digits=3; + if (++sampleMapDigit>=digits) { + sampleMapDigit=0; + advance=true; + } + } + + if (advance && sampleMapMin==sampleMapMax) { + sampleMapSelStart++; + if (sampleMapSelStart>119) sampleMapSelStart=119; + sampleMapSelEnd=sampleMapSelStart; + } +} + #define DRUM_FREQ(name,db,df,prop) \ ImGui::TableNextRow(); \ ImGui::TableNextColumn(); \ @@ -4405,9 +4456,9 @@ void FurnaceGUI::drawInsEdit() { ImGui::BeginDisabled(ins->amiga.useWave); P(ImGui::Checkbox("Use sample map",&ins->amiga.useNoteMap)); if (ins->amiga.useNoteMap) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { - sampleMapFocused=false; - } + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered()) 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); @@ -4454,6 +4505,7 @@ void FurnaceGUI::drawInsEdit() { if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { sampleMapFocused=true; sampleMapColumn=0; + sampleMapDigit=0; sampleMapSelStart=i; sampleMapSelEnd=i; ImGui::InhibitInertialScroll(); @@ -4475,6 +4527,7 @@ void FurnaceGUI::drawInsEdit() { if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { sampleMapFocused=true; sampleMapColumn=1; + sampleMapDigit=0; sampleMapSelStart=i; sampleMapSelEnd=i; ImGui::InhibitInertialScroll(); diff --git a/src/gui/piano.cpp b/src/gui/piano.cpp index fe451c3f7..baae316d1 100644 --- a/src/gui/piano.cpp +++ b/src/gui/piano.cpp @@ -415,10 +415,14 @@ void FurnaceGUI::drawPiano() { e->previewSample(curSample,note); break; default: - e->synchronized([this,note]() { - e->autoNoteOn(-1,curIns,note); - }); - if (edit && curWindow!=GUI_WINDOW_INS_LIST && curWindow!=GUI_WINDOW_INS_EDIT) noteInput(note,0); + if (sampleMapWaitingInput) { + alterSampleMap(true,note); + } else { + e->synchronized([this,note]() { + e->autoNoteOn(-1,curIns,note); + }); + if (edit && curWindow!=GUI_WINDOW_INS_LIST && curWindow!=GUI_WINDOW_INS_EDIT) noteInput(note,0); + } break; } } From e4bfcd985094fdd5978b69fe93e836f271529fe3 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Apr 2023 00:50:31 -0500 Subject: [PATCH 21/22] GUI: new sample map UI, part 3 keyboard input --- src/gui/gui.cpp | 35 +++++++++++++++++++++++++++++++++++ src/gui/insEdit.cpp | 32 +++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 13a380b41..aa23ef07c 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1327,6 +1327,41 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { return; } + if (sampleMapWaitingInput) { + if (sampleMapColumn==1) { + // TODO: map? + if (ev.key.keysym.scancode==SDL_SCANCODE_DELETE) { + alterSampleMap(true,-1); + return; + } + try { + int key=noteKeys.at(ev.key.keysym.scancode); + int num=12*curOctave+key; + + if (num<-60) num=-60; // C-(-5) + if (num>119) num=119; // B-9 + + alterSampleMap(true,num); + return; + } catch (std::out_of_range& e) { + } + } else { + // TODO: map? + if (ev.key.keysym.scancode==SDL_SCANCODE_DELETE) { + alterSampleMap(false,-1); + return; + } + try { + int num=valueKeys.at(ev.key.keysym.sym); + if (num<10) { + alterSampleMap(false,num); + return; + } + } catch (std::out_of_range& e) { + } + } + } + // PER-WINDOW KEYS switch (curWindow) { case GUI_WINDOW_PATTERN: diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 9ec9da044..2b73c7ae1 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2072,6 +2072,8 @@ void FurnaceGUI::alterSampleMap(bool isNote, int val) { if (sampleMapSelStart>119) sampleMapSelStart=119; sampleMapSelEnd=sampleMapSelStart; } + + MARK_MODIFIED; } #define DRUM_FREQ(name,db,df,prop) \ @@ -4456,7 +4458,7 @@ void FurnaceGUI::drawInsEdit() { 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()) sampleMapFocused=false; + 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)) { @@ -4487,10 +4489,13 @@ void FurnaceGUI::drawInsEdit() { 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::Text("%s",noteNames[60+i]); ImGui::TableNextColumn(); if (sampleMap.map<0 || sampleMap.map>=e->song.sampleLen) { @@ -4501,13 +4506,21 @@ void FurnaceGUI::drawInsEdit() { } ImGui::PushFont(patFont); ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); - ImGui::Selectable(sName.c_str(),(sampleMapFocused && sampleMapColumn==0 && i>=sampleMapMin && i<=sampleMapMax)); + 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)) { @@ -4523,13 +4536,21 @@ void FurnaceGUI::drawInsEdit() { sName+=fmt::sprintf("##SN%d",i); ImGui::PushFont(patFont); ImGui::SetNextItemWidth(ImGui::CalcTextSize("00000").x); - ImGui::Selectable(sName.c_str(),(sampleMapFocused && sampleMapColumn==1 && i>=sampleMapMin && i<=sampleMapMax)); + 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)) { @@ -4542,11 +4563,16 @@ void FurnaceGUI::drawInsEdit() { ImGui::TextUnformatted(e->song.sample[sampleMap.map]->name.c_str()); } } + ImGui::PopStyleColor(2); ImGui::EndTable(); } + } else { + sampleMapFocused=false; } ImGui::EndDisabled(); ImGui::EndTabItem(); + } else { + sampleMapFocused=false; } } if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem(settings.c163Name.c_str())) { From b9b121efdfd3fec823f76f05b83af65a18ffe550 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Apr 2023 01:38:44 -0500 Subject: [PATCH 22/22] GUI: new sample map UI, part 4 right click menu --- src/gui/gui.cpp | 1 + src/gui/insEdit.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index aa23ef07c..8fdbaf755 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6514,6 +6514,7 @@ FurnaceGUI::FurnaceGUI(): sampleMapDigit(0), sampleMapColumn(0), sampleMapFocused(false), + sampleMapWaitingInput(false), macroDragStart(0,0), macroDragAreaSize(0,0), macroDragCTarget(NULL), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 2b73c7ae1..6ab5b23cb 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4394,6 +4394,7 @@ void FurnaceGUI::drawInsEdit() { ins->type==DIV_INS_GA20) { 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 { @@ -4476,11 +4477,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); ImGui::Text("note"); ImGui::TableNextColumn(); - if (sampleMapFocused) { - ImGui::Text("FOCUSED"); - } else { - ImGui::Text("sample name"); - } + ImGui::Text("sample name"); int sampleMapMin=sampleMapSelStart; int sampleMapMax=sampleMapSelEnd; if (sampleMapMin>sampleMapMax) { @@ -4526,6 +4523,26 @@ void FurnaceGUI::drawInsEdit() { 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(); @@ -4556,6 +4573,26 @@ void FurnaceGUI::drawInsEdit() { 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(); @@ -4570,6 +4607,40 @@ void FurnaceGUI::drawInsEdit() { 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;