From 4ce116ca0aa4a3a07e4749d64b51b6b23a1fab7e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 8 Feb 2022 03:50:42 -0500 Subject: [PATCH] prepare for macro release points issue #142 --- papers/format.md | 36 ++++++++-- src/engine/dispatch.h | 2 + src/engine/engine.h | 4 +- src/engine/instrument.cpp | 63 ++++++++++++++++++ src/engine/instrument.h | 25 ++++++- src/engine/macroInt.cpp | 59 +++++++++------- src/engine/macroInt.h | 3 + src/engine/playback.cpp | 31 ++++++++- src/gui/gui.cpp | 137 +++++++++++++++++++++++--------------- src/gui/gui.h | 8 +-- 10 files changed, 278 insertions(+), 90 deletions(-) diff --git a/papers/format.md b/papers/format.md index 9b43b65cf..6f00d1475 100644 --- a/papers/format.md +++ b/papers/format.md @@ -25,10 +25,12 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: -- 42: Furnace 0.5.5pre1 -- 41: Furnace 0.5.4 -- 40: Furnace 0.5.3 -- 39: Furnace 0.5.2 +- 44: Furnace 0.5.5pre2 +- 43: Furnace 0.5.5pre1 +- 42: Furnace 0.5.4 +- 41: Furnace 0.5.3 +- 40: Furnace 0.5.2 +- 39: Furnace 0.5.2pre3 - 38: Furnace 0.5.2pre2 - 37: Furnace 0.5.2pre1 - 36: Furnace 0.5.1 @@ -353,6 +355,32 @@ size | description 1?? | DT macro 1?? | D2R macro 1?? | SSG-EG macro + --- | **release points** (>=44) + 4 | volume macro release + 4 | arp macro release + 4 | duty macro release + 4 | wave macro release + 4 | pitch macro release + 4 | extra 1 macro release + 4 | extra 2 macro release + 4 | extra 3 macro release + 4 | alg macro release + 4 | fb macro release + 4 | fms macro release + 4 | ams macro release + --- | **operator release points** × 4 (>=44) + 4 | AM macro release + 4 | AR macro release + 4 | DR macro release + 4 | MULT macro release + 4 | RR macro release + 4 | SL macro release + 4 | TL macro release + 4 | DT2 macro release + 4 | RS macro release + 4 | DT macro release + 4 | D2R macro release + 4 | SSG-EG macro release # wavetable diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 134230cbf..840129c3d 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -13,6 +13,8 @@ enum DivDispatchCmds { DIV_CMD_NOTE_ON=0, DIV_CMD_NOTE_OFF, + DIV_CMD_NOTE_OFF_ENV, + DIV_CMD_ENV_RELEASE, DIV_CMD_INSTRUMENT, DIV_CMD_VOLUME, DIV_CMD_GET_VOLUME, diff --git a/src/engine/engine.h b/src/engine/engine.h index 7fa8f7766..04cdd24c3 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -11,8 +11,8 @@ #include #include -#define DIV_VERSION "0.5.5pre1" -#define DIV_ENGINE_VERSION 43 +#define DIV_VERSION "0.5.5pre2" +#define DIV_ENGINE_VERSION 44 enum DivStatusView { DIV_STATUS_NOTHING=0, diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 97739d0a6..482f5ba35 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -253,6 +253,36 @@ void DivInstrument::putInsData(SafeWriter* w) { w->writeC(op.ssgMacro[j]); } } + + // release points + w->writeI(std.volMacroRel); + w->writeI(std.arpMacroRel); + w->writeI(std.dutyMacroRel); + w->writeI(std.waveMacroRel); + w->writeI(std.pitchMacroRel); + w->writeI(std.ex1MacroRel); + w->writeI(std.ex2MacroRel); + w->writeI(std.ex3MacroRel); + w->writeI(std.algMacroRel); + w->writeI(std.fbMacroRel); + w->writeI(std.fmsMacroRel); + w->writeI(std.amsMacroRel); + for (int i=0; i<4; i++) { + DivInstrumentSTD::OpMacro& op=std.opMacros[i]; + + w->writeI(op.amMacroRel); + w->writeI(op.arMacroRel); + w->writeI(op.drMacroRel); + w->writeI(op.multMacroRel); + w->writeI(op.rrMacroRel); + w->writeI(op.slMacroRel); + w->writeI(op.tlMacroRel); + w->writeI(op.dt2MacroRel); + w->writeI(op.rsMacroRel); + w->writeI(op.dtMacroRel); + w->writeI(op.d2rMacroRel); + w->writeI(op.ssgMacroRel); + } } DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { @@ -484,6 +514,39 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { } } + // release points + if (version>=44) { + std.volMacroRel=reader.readI(); + std.arpMacroRel=reader.readI(); + std.dutyMacroRel=reader.readI(); + std.waveMacroRel=reader.readI(); + std.pitchMacroRel=reader.readI(); + std.ex1MacroRel=reader.readI(); + std.ex2MacroRel=reader.readI(); + std.ex3MacroRel=reader.readI(); + std.algMacroRel=reader.readI(); + std.fbMacroRel=reader.readI(); + std.fmsMacroRel=reader.readI(); + std.amsMacroRel=reader.readI(); + + for (int i=0; i<4; i++) { + DivInstrumentSTD::OpMacro& op=std.opMacros[i]; + + op.amMacroRel=reader.readI(); + op.arMacroRel=reader.readI(); + op.drMacroRel=reader.readI(); + op.multMacroRel=reader.readI(); + op.rrMacroRel=reader.readI(); + op.slMacroRel=reader.readI(); + op.tlMacroRel=reader.readI(); + op.dt2MacroRel=reader.readI(); + op.rsMacroRel=reader.readI(); + op.dtMacroRel=reader.readI(); + op.d2rMacroRel=reader.readI(); + op.ssgMacroRel=reader.readI(); + } + } + return DIV_DATA_SUCCESS; } diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 9475a38cd..fa5f6914f 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -123,6 +123,9 @@ struct DivInstrumentSTD { signed char volMacroLoop, arpMacroLoop, dutyMacroLoop, waveMacroLoop; signed char pitchMacroLoop, ex1MacroLoop, ex2MacroLoop, ex3MacroLoop; signed char algMacroLoop, fbMacroLoop, fmsMacroLoop, amsMacroLoop; + signed char volMacroRel, arpMacroRel, dutyMacroRel, waveMacroRel; + signed char pitchMacroRel, ex1MacroRel, ex2MacroRel, ex3MacroRel; + signed char algMacroRel, fbMacroRel, fmsMacroRel, amsMacroRel; struct OpMacro { // ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv; unsigned char amMacro[256]; @@ -146,6 +149,9 @@ struct DivInstrumentSTD { signed char amMacroLoop, arMacroLoop, drMacroLoop, multMacroLoop; signed char rrMacroLoop, slMacroLoop, tlMacroLoop, dt2MacroLoop; signed char rsMacroLoop, dtMacroLoop, d2rMacroLoop, ssgMacroLoop; + signed char amMacroRel, arMacroRel, drMacroRel, multMacroRel; + signed char rrMacroRel, slMacroRel, tlMacroRel, dt2MacroRel; + signed char rsMacroRel, dtMacroRel, d2rMacroRel, ssgMacroRel; OpMacro(): amMacroOpen(false), arMacroOpen(false), drMacroOpen(false), multMacroOpen(false), rrMacroOpen(false), slMacroOpen(false), tlMacroOpen(true), dt2MacroOpen(false), @@ -155,7 +161,10 @@ struct DivInstrumentSTD { rsMacroLen(0), dtMacroLen(0), d2rMacroLen(0), ssgMacroLen(0), amMacroLoop(-1), arMacroLoop(-1), drMacroLoop(-1), multMacroLoop(-1), rrMacroLoop(-1), slMacroLoop(-1), tlMacroLoop(-1), dt2MacroLoop(-1), - rsMacroLoop(-1), dtMacroLoop(-1), d2rMacroLoop(-1), ssgMacroLoop(-1) { + rsMacroLoop(-1), dtMacroLoop(-1), d2rMacroLoop(-1), ssgMacroLoop(-1), + amMacroRel(-1), arMacroRel(-1), drMacroRel(-1), multMacroRel(-1), + rrMacroRel(-1), slMacroRel(-1), tlMacroRel(-1), dt2MacroRel(-1), + rsMacroRel(-1), dtMacroRel(-1), d2rMacroRel(-1), ssgMacroRel(-1) { memset(amMacro,0,256); memset(arMacro,0,256); memset(drMacro,0,256); @@ -210,7 +219,19 @@ struct DivInstrumentSTD { algMacroLoop(-1), fbMacroLoop(-1), fmsMacroLoop(-1), - amsMacroLoop(-1) { + amsMacroLoop(-1), + volMacroRel(-1), + arpMacroRel(-1), + dutyMacroRel(-1), + waveMacroRel(-1), + pitchMacroRel(-1), + ex1MacroRel(-1), + ex2MacroRel(-1), + ex3MacroRel(-1), + algMacroRel(-1), + fbMacroRel(-1), + fmsMacroRel(-1), + amsMacroRel(-1) { memset(volMacro,0,256*sizeof(int)); memset(arpMacro,0,256*sizeof(int)); memset(dutyMacro,0,256*sizeof(int)); diff --git a/src/engine/macroInt.cpp b/src/engine/macroInt.cpp index beb7231de..46c84b8db 100644 --- a/src/engine/macroInt.cpp +++ b/src/engine/macroInt.cpp @@ -1,7 +1,7 @@ #include "macroInt.h" #include "instrument.h" -#define doMacro(finished,had,has,val,pos,source,sourceLen,sourceLoop) \ +#define doMacro(finished,had,has,val,pos,source,sourceLen,sourceLoop,sourceRel) \ if (finished) finished=false; \ if (had!=has) { \ finished=true; \ @@ -9,6 +9,9 @@ had=has; \ if (has) { \ val=source[pos++]; \ + if (pos==sourceRel && !released) { \ + pos--; \ + } \ if (pos>=sourceLen) { \ if (sourceLoop=0) { \ pos=sourceLoop; \ @@ -21,41 +24,45 @@ void DivMacroInt::next() { if (ins==NULL) return; - doMacro(finishedVol,hadVol,hasVol,vol,volPos,ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop); - doMacro(finishedArp,hadArp,hasArp,arp,arpPos,ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop); - doMacro(finishedDuty,hadDuty,hasDuty,duty,dutyPos,ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop); - doMacro(finishedWave,hadWave,hasWave,wave,wavePos,ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop); + doMacro(finishedVol,hadVol,hasVol,vol,volPos,ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel); + doMacro(finishedArp,hadArp,hasArp,arp,arpPos,ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel); + doMacro(finishedDuty,hadDuty,hasDuty,duty,dutyPos,ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel); + doMacro(finishedWave,hadWave,hasWave,wave,wavePos,ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel); - doMacro(finishedPitch,hadPitch,hasPitch,pitch,pitchPos,ins->std.pitchMacro,ins->std.pitchMacroLen,ins->std.pitchMacroLoop); - doMacro(finishedEx1,hadEx1,hasEx1,ex1,ex1Pos,ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop); - doMacro(finishedEx2,hadEx2,hasEx2,ex2,ex2Pos,ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop); - doMacro(finishedEx3,hadEx3,hasEx3,ex3,ex3Pos,ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop); + doMacro(finishedPitch,hadPitch,hasPitch,pitch,pitchPos,ins->std.pitchMacro,ins->std.pitchMacroLen,ins->std.pitchMacroLoop,ins->std.pitchMacroRel); + doMacro(finishedEx1,hadEx1,hasEx1,ex1,ex1Pos,ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel); + doMacro(finishedEx2,hadEx2,hasEx2,ex2,ex2Pos,ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel); + doMacro(finishedEx3,hadEx3,hasEx3,ex3,ex3Pos,ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel); - doMacro(finishedAlg,hadAlg,hasAlg,alg,algPos,ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop); - doMacro(finishedFb,hadFb,hasFb,fb,fbPos,ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop); - doMacro(finishedFms,hadFms,hasFms,fms,fmsPos,ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop); - doMacro(finishedAms,hadAms,hasAms,ams,amsPos,ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop); + doMacro(finishedAlg,hadAlg,hasAlg,alg,algPos,ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel); + doMacro(finishedFb,hadFb,hasFb,fb,fbPos,ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel); + doMacro(finishedFms,hadFms,hasFms,fms,fmsPos,ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel); + doMacro(finishedAms,hadAms,hasAms,ams,amsPos,ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel); for (int i=0; i<4; i++) { DivInstrumentSTD::OpMacro& m=ins->std.opMacros[i]; IntOp& o=op[i]; - doMacro(o.finishedAm,o.hadAm,o.hasAm,o.am,o.amPos,m.amMacro,m.amMacroLen,m.amMacroLoop); - doMacro(o.finishedAr,o.hadAr,o.hasAr,o.ar,o.arPos,m.arMacro,m.arMacroLen,m.arMacroLoop); - doMacro(o.finishedDr,o.hadDr,o.hasDr,o.dr,o.drPos,m.drMacro,m.drMacroLen,m.drMacroLoop); - doMacro(o.finishedMult,o.hadMult,o.hasMult,o.mult,o.multPos,m.multMacro,m.multMacroLen,m.multMacroLoop); + doMacro(o.finishedAm,o.hadAm,o.hasAm,o.am,o.amPos,m.amMacro,m.amMacroLen,m.amMacroLoop,m.amMacroRel); + doMacro(o.finishedAr,o.hadAr,o.hasAr,o.ar,o.arPos,m.arMacro,m.arMacroLen,m.arMacroLoop,m.arMacroRel); + doMacro(o.finishedDr,o.hadDr,o.hasDr,o.dr,o.drPos,m.drMacro,m.drMacroLen,m.drMacroLoop,m.drMacroRel); + doMacro(o.finishedMult,o.hadMult,o.hasMult,o.mult,o.multPos,m.multMacro,m.multMacroLen,m.multMacroLoop,m.multMacroRel); - doMacro(o.finishedRr,o.hadRr,o.hasRr,o.rr,o.rrPos,m.rrMacro,m.rrMacroLen,m.rrMacroLoop); - doMacro(o.finishedSl,o.hadSl,o.hasSl,o.sl,o.slPos,m.slMacro,m.slMacroLen,m.slMacroLoop); - doMacro(o.finishedTl,o.hadTl,o.hasTl,o.tl,o.tlPos,m.tlMacro,m.tlMacroLen,m.tlMacroLoop); - doMacro(o.finishedDt2,o.hadDt2,o.hasDt2,o.dt2,o.dt2Pos,m.dt2Macro,m.dt2MacroLen,m.dt2MacroLoop); + doMacro(o.finishedRr,o.hadRr,o.hasRr,o.rr,o.rrPos,m.rrMacro,m.rrMacroLen,m.rrMacroLoop,m.rrMacroRel); + doMacro(o.finishedSl,o.hadSl,o.hasSl,o.sl,o.slPos,m.slMacro,m.slMacroLen,m.slMacroLoop,m.slMacroRel); + doMacro(o.finishedTl,o.hadTl,o.hasTl,o.tl,o.tlPos,m.tlMacro,m.tlMacroLen,m.tlMacroLoop,m.tlMacroRel); + doMacro(o.finishedDt2,o.hadDt2,o.hasDt2,o.dt2,o.dt2Pos,m.dt2Macro,m.dt2MacroLen,m.dt2MacroLoop,m.dt2MacroRel); - doMacro(o.finishedRs,o.hadRs,o.hasRs,o.rs,o.rsPos,m.rsMacro,m.rsMacroLen,m.rsMacroLoop); - doMacro(o.finishedDt,o.hadDt,o.hasDt,o.dt,o.dtPos,m.dtMacro,m.dtMacroLen,m.dtMacroLoop); - doMacro(o.finishedD2r,o.hadD2r,o.hasD2r,o.d2r,o.d2rPos,m.d2rMacro,m.d2rMacroLen,m.d2rMacroLoop); - doMacro(o.finishedSsg,o.hadSsg,o.hasSsg,o.ssg,o.ssgPos,m.ssgMacro,m.ssgMacroLen,m.ssgMacroLoop); + doMacro(o.finishedRs,o.hadRs,o.hasRs,o.rs,o.rsPos,m.rsMacro,m.rsMacroLen,m.rsMacroLoop,m.rsMacroRel); + doMacro(o.finishedDt,o.hadDt,o.hasDt,o.dt,o.dtPos,m.dtMacro,m.dtMacroLen,m.dtMacroLoop,m.dtMacroRel); + doMacro(o.finishedD2r,o.hadD2r,o.hasD2r,o.d2r,o.d2rPos,m.d2rMacro,m.d2rMacroLen,m.d2rMacroLoop,m.d2rMacroRel); + doMacro(o.finishedSsg,o.hadSsg,o.hasSsg,o.ssg,o.ssgPos,m.ssgMacro,m.ssgMacroLen,m.ssgMacroLoop,m.ssgMacroRel); } } +void DivMacroInt::release() { + released=true; +} + void DivMacroInt::init(DivInstrument* which) { ins=which; volPos=0; @@ -71,6 +78,8 @@ void DivMacroInt::init(DivInstrument* which) { fmsPos=0; amsPos=0; + released=false; + hasVol=false; hasArp=false; hasDuty=false; diff --git a/src/engine/macroInt.h b/src/engine/macroInt.h index dc2153e69..2197ed5eb 100644 --- a/src/engine/macroInt.h +++ b/src/engine/macroInt.h @@ -7,6 +7,7 @@ class DivMacroInt { DivInstrument* ins; int volPos, arpPos, dutyPos, wavePos, pitchPos, ex1Pos, ex2Pos, ex3Pos; int algPos, fbPos, fmsPos, amsPos; + bool released; public: int vol; int arp; @@ -80,6 +81,7 @@ class DivMacroInt { willRr(false), willSl(false), willTl(false), willDt2(false), willRs(false), willDt(false), willD2r(false), willSsg(false) {} } op[4]; + void release(); void next(); void init(DivInstrument* which); void notifyInsDeletion(DivInstrument* which); @@ -97,6 +99,7 @@ class DivMacroInt { fbPos(0), fmsPos(0), amsPos(0), + released(false), vol(0), arp(0), duty(0), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 7721189e2..52f40e391 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -25,6 +25,8 @@ const char* notes[12]={ const char* cmdName[DIV_CMD_MAX]={ "NOTE_ON", "NOTE_OFF", + "NOTE_OFF_ENV", + "ENV_RELEASE", "INSTRUMENT", "VOLUME", "GET_VOLUME", @@ -95,6 +97,10 @@ const char* formatNote(unsigned char note, unsigned char octave) { static char ret[4]; if (note==100) { return "OFF"; + } else if (note==101) { + return "==="; + } else if (note==102) { + return "REL"; } else if (octave==0 && note==0) { return "---"; } @@ -456,7 +462,7 @@ void DivEngine::processRow(int i, bool afterDelay) { dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2])); } // note - if (pat->data[whatRow][0]==100) { + if (pat->data[whatRow][0]==100) { // note off //chan[i].note=-1; chan[i].keyOn=false; chan[i].keyOff=true; @@ -477,6 +483,29 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].scheduledSlideReset=true; } dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); + } else if (pat->data[whatRow][0]==101) { // note off + env release + //chan[i].note=-1; + chan[i].keyOn=false; + chan[i].keyOff=true; + if (chan[i].inPorta) { + if (chan[i].stopOnOff) { + chan[i].portaNote=-1; + chan[i].portaSpeed=-1; + chan[i].stopOnOff=false; + } + if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) { + chan[i].portaNote=-1; + chan[i].portaSpeed=-1; + if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) { + chan[i+1].portaNote=-1; + chan[i+1].portaSpeed=-1; + } + } + chan[i].scheduledSlideReset=true; + } + dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF_ENV,i)); + } else if (pat->data[whatRow][0]==102) { // env release + dispatchCmd(DivCommand(DIV_CMD_ENV_RELEASE,i)); } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) { chan[i].oldNote=chan[i].note; chan[i].note=pat->data[whatRow][0]+((signed char)pat->data[whatRow][1])*12; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 8ac7b23de..443e594ab 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -153,8 +153,12 @@ void FurnaceGUI::bindEngine(DivEngine* eng) { } const char* noteNameNormal(short note, short octave) { - if (note==100) { + if (note==100) { // note cut return "OFF"; + } else if (note==101) { // note off and envelope release + return "==="; + } else if (note==102) { // envelope release only + return "REL"; } else if (octave==0 && note==0) { return "..."; } @@ -168,6 +172,10 @@ const char* noteNameNormal(short note, short octave) { const char* FurnaceGUI::noteName(short note, short octave) { if (note==100) { return "OFF"; + } else if (note==101) { // note off and envelope release + return "==="; + } else if (note==102) { // envelope release only + return "REL"; } else if (octave==0 && note==0) { return "..."; } @@ -211,11 +219,12 @@ bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) { return false; } -void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop) { +void FurnaceGUI::encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel) { target=""; char buf[32]; for (int i=0; i=128) break; } @@ -324,7 +339,7 @@ void FurnaceGUI::decodeMMLStr(String& source, unsigned char* macro, unsigned cha } } -void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax) { +void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel) { int buf=0; bool negaBuf=false; bool hasVal=false; @@ -360,6 +375,11 @@ void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLe macroLoop=macroLen; } break; + case '/': + if (macroRel==-1) { + macroRel=macroLen; + } + break; } if (macroLen>=128) break; } @@ -1381,7 +1401,7 @@ const int orderedOps[4]={ #define PARAMETER modified=true; e->notifyInsChange(curIns); -#define NORMAL_MACRO(macro,macroLen,macroLoop,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax) \ +#define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax) \ ImGui::TableNextRow(); \ ImGui::TableNextColumn(); \ ImGui::Text("%s",displayName); \ @@ -1454,15 +1474,15 @@ const int orderedOps[4]={ } \ ImGui::SetNextItemWidth(availableWidth); \ if (ImGui::InputText("##IMacroMML_" macroName,&mmlStr)) { \ - decodeMMLStr(mmlStr,macro,macroLen,macroLoop,macroAMin,(bitfield)?((1<std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7); - NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7); - NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7); - NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3); + NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7); + NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7); + NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7); + NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3); - NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127); - NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127); - NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255); - NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3); + NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127); + NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127); + NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255); + NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3); MACRO_END; ImGui::EndTabItem(); } @@ -1669,18 +1689,18 @@ void FurnaceGUI::drawInsEdit() { ImGui::PushID(i); MACRO_BEGIN(0); int ordi=orderedOps[i]; - OP_MACRO(ins->std.opMacros[ordi].tlMacro,ins->std.opMacros[ordi].tlMacroLen,ins->std.opMacros[ordi].tlMacroLoop,127,ordi,"tl",FM_NAME(FM_TL),128,ins->std.opMacros[ordi].tlMacroOpen,false,NULL,mmlString[0]); - OP_MACRO(ins->std.opMacros[ordi].arMacro,ins->std.opMacros[ordi].arMacroLen,ins->std.opMacros[ordi].arMacroLoop,31,ordi,"ar",FM_NAME(FM_AR),64,ins->std.opMacros[ordi].arMacroOpen,false,NULL,mmlString[1]); - OP_MACRO(ins->std.opMacros[ordi].drMacro,ins->std.opMacros[ordi].drMacroLen,ins->std.opMacros[ordi].drMacroLoop,31,ordi,"dr",FM_NAME(FM_DR),64,ins->std.opMacros[ordi].drMacroOpen,false,NULL,mmlString[2]); - OP_MACRO(ins->std.opMacros[ordi].d2rMacro,ins->std.opMacros[ordi].d2rMacroLen,ins->std.opMacros[ordi].d2rMacroLoop,31,ordi,"d2r",FM_NAME(FM_D2R),64,ins->std.opMacros[ordi].d2rMacroOpen,false,NULL,mmlString[3]); - OP_MACRO(ins->std.opMacros[ordi].rrMacro,ins->std.opMacros[ordi].rrMacroLen,ins->std.opMacros[ordi].rrMacroLoop,15,ordi,"rr",FM_NAME(FM_RR),64,ins->std.opMacros[ordi].rrMacroOpen,false,NULL,mmlString[4]); - OP_MACRO(ins->std.opMacros[ordi].slMacro,ins->std.opMacros[ordi].slMacroLen,ins->std.opMacros[ordi].slMacroLoop,15,ordi,"sl",FM_NAME(FM_SL),64,ins->std.opMacros[ordi].slMacroOpen,false,NULL,mmlString[5]); - OP_MACRO(ins->std.opMacros[ordi].rsMacro,ins->std.opMacros[ordi].rsMacroLen,ins->std.opMacros[ordi].rsMacroLoop,3,ordi,"rs",FM_NAME(FM_RS),32,ins->std.opMacros[ordi].rsMacroOpen,false,NULL,mmlString[6]); - OP_MACRO(ins->std.opMacros[ordi].multMacro,ins->std.opMacros[ordi].multMacroLen,ins->std.opMacros[ordi].multMacroLoop,15,ordi,"mult",FM_NAME(FM_MULT),64,ins->std.opMacros[ordi].multMacroOpen,false,NULL,mmlString[7]); - OP_MACRO(ins->std.opMacros[ordi].dtMacro,ins->std.opMacros[ordi].dtMacroLen,ins->std.opMacros[ordi].dtMacroLoop,7,ordi,"dt",FM_NAME(FM_DT),64,ins->std.opMacros[ordi].dtMacroOpen,false,NULL,mmlString[8]); - OP_MACRO(ins->std.opMacros[ordi].dt2Macro,ins->std.opMacros[ordi].dt2MacroLen,ins->std.opMacros[ordi].dt2MacroLoop,3,ordi,"dt2",FM_NAME(FM_DT2),32,ins->std.opMacros[ordi].dt2MacroOpen,false,NULL,mmlString[9]); - OP_MACRO(ins->std.opMacros[ordi].amMacro,ins->std.opMacros[ordi].amMacroLen,ins->std.opMacros[ordi].amMacroLoop,1,ordi,"am",FM_NAME(FM_AM),32,ins->std.opMacros[ordi].amMacroOpen,true,NULL,mmlString[10]); - OP_MACRO(ins->std.opMacros[ordi].ssgMacro,ins->std.opMacros[ordi].ssgMacroLen,ins->std.opMacros[ordi].ssgMacroLoop,4,ordi,"ssg",FM_NAME(FM_SSG),64,ins->std.opMacros[ordi].ssgMacroOpen,true,ssgEnvBits,mmlString[11]); + OP_MACRO(ins->std.opMacros[ordi].tlMacro,ins->std.opMacros[ordi].tlMacroLen,ins->std.opMacros[ordi].tlMacroLoop,ins->std.opMacros[ordi].tlMacroRel,127,ordi,"tl",FM_NAME(FM_TL),128,ins->std.opMacros[ordi].tlMacroOpen,false,NULL,mmlString[0]); + OP_MACRO(ins->std.opMacros[ordi].arMacro,ins->std.opMacros[ordi].arMacroLen,ins->std.opMacros[ordi].arMacroLoop,ins->std.opMacros[ordi].arMacroRel,31,ordi,"ar",FM_NAME(FM_AR),64,ins->std.opMacros[ordi].arMacroOpen,false,NULL,mmlString[1]); + OP_MACRO(ins->std.opMacros[ordi].drMacro,ins->std.opMacros[ordi].drMacroLen,ins->std.opMacros[ordi].drMacroLoop,ins->std.opMacros[ordi].drMacroRel,31,ordi,"dr",FM_NAME(FM_DR),64,ins->std.opMacros[ordi].drMacroOpen,false,NULL,mmlString[2]); + OP_MACRO(ins->std.opMacros[ordi].d2rMacro,ins->std.opMacros[ordi].d2rMacroLen,ins->std.opMacros[ordi].d2rMacroLoop,ins->std.opMacros[ordi].d2rMacroRel,31,ordi,"d2r",FM_NAME(FM_D2R),64,ins->std.opMacros[ordi].d2rMacroOpen,false,NULL,mmlString[3]); + OP_MACRO(ins->std.opMacros[ordi].rrMacro,ins->std.opMacros[ordi].rrMacroLen,ins->std.opMacros[ordi].rrMacroLoop,ins->std.opMacros[ordi].rrMacroRel,15,ordi,"rr",FM_NAME(FM_RR),64,ins->std.opMacros[ordi].rrMacroOpen,false,NULL,mmlString[4]); + OP_MACRO(ins->std.opMacros[ordi].slMacro,ins->std.opMacros[ordi].slMacroLen,ins->std.opMacros[ordi].slMacroLoop,ins->std.opMacros[ordi].slMacroRel,15,ordi,"sl",FM_NAME(FM_SL),64,ins->std.opMacros[ordi].slMacroOpen,false,NULL,mmlString[5]); + OP_MACRO(ins->std.opMacros[ordi].rsMacro,ins->std.opMacros[ordi].rsMacroLen,ins->std.opMacros[ordi].rsMacroLoop,ins->std.opMacros[ordi].rsMacroRel,3,ordi,"rs",FM_NAME(FM_RS),32,ins->std.opMacros[ordi].rsMacroOpen,false,NULL,mmlString[6]); + OP_MACRO(ins->std.opMacros[ordi].multMacro,ins->std.opMacros[ordi].multMacroLen,ins->std.opMacros[ordi].multMacroLoop,ins->std.opMacros[ordi].multMacroRel,15,ordi,"mult",FM_NAME(FM_MULT),64,ins->std.opMacros[ordi].multMacroOpen,false,NULL,mmlString[7]); + OP_MACRO(ins->std.opMacros[ordi].dtMacro,ins->std.opMacros[ordi].dtMacroLen,ins->std.opMacros[ordi].dtMacroLoop,ins->std.opMacros[ordi].dtMacroRel,7,ordi,"dt",FM_NAME(FM_DT),64,ins->std.opMacros[ordi].dtMacroOpen,false,NULL,mmlString[8]); + OP_MACRO(ins->std.opMacros[ordi].dt2Macro,ins->std.opMacros[ordi].dt2MacroLen,ins->std.opMacros[ordi].dt2MacroLoop,ins->std.opMacros[ordi].dt2MacroRel,3,ordi,"dt2",FM_NAME(FM_DT2),32,ins->std.opMacros[ordi].dt2MacroOpen,false,NULL,mmlString[9]); + OP_MACRO(ins->std.opMacros[ordi].amMacro,ins->std.opMacros[ordi].amMacroLen,ins->std.opMacros[ordi].amMacroLoop,ins->std.opMacros[ordi].amMacroRel,1,ordi,"am",FM_NAME(FM_AM),32,ins->std.opMacros[ordi].amMacroOpen,true,NULL,mmlString[10]); + OP_MACRO(ins->std.opMacros[ordi].ssgMacro,ins->std.opMacros[ordi].ssgMacroLen,ins->std.opMacros[ordi].ssgMacroLoop,ins->std.opMacros[ordi].ssgMacroRel,4,ordi,"ssg",FM_NAME(FM_SSG),64,ins->std.opMacros[ordi].ssgMacroOpen,true,ssgEnvBits,mmlString[11]); MACRO_END; ImGui::PopID(); ImGui::EndTabItem(); @@ -1881,41 +1901,41 @@ void FurnaceGUI::drawInsEdit() { if (settings.macroView==0) { // modern view MACRO_BEGIN(28*dpiScale); - NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax); - NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94); + NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax); + NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94); if (dutyMax>0) { - NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax); + NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax); } if (waveMax>0) { - NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax); + NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax); } if (ex1Max>0) { if (ins->type==DIV_INS_C64) { - NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); + NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); } else if (ins->type==DIV_INS_SAA1099) { - NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); + NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); } else { - NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); + NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max); } } if (ex2Max>0) { if (ins->type==DIV_INS_C64) { - NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); + NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); } else { - NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); + NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max); } } if (ins->type==DIV_INS_C64) { - NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2); + NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2); } if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) { - NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15); - NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15); + NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15); + NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15); } if (ins->type==DIV_INS_AY8930) { // oh my i am running out of macros - NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8); - NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8); + NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8); + NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8); } MACRO_END; @@ -2295,7 +2315,7 @@ void FurnaceGUI::drawWaveEdit() { decodeMMLStrW(mmlStringW,wave->data,wave->len,wave->max); } if (!ImGui::IsItemActive()) { - encodeMMLStr(mmlStringW,wave->data,wave->len,-1); + encodeMMLStr(mmlStringW,wave->data,wave->len,-1,-1); } ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); @@ -4443,7 +4463,7 @@ void FurnaceGUI::doTranspose(int amount) { if (iFine==0) { int origNote=pat->data[j][0]; int origOctave=(signed char)pat->data[j][1]; - if (origNote!=0 && origNote!=100) { + if (origNote!=0 && origNote!=100 && origNote!=101 && origNote!=102) { origNote+=amount; while (origNote>12) { origNote-=12; @@ -4759,6 +4779,8 @@ void FurnaceGUI::stopPreviewNote(SDL_Scancode scancode) { int num=12*curOctave+key; if (key==100) return; + if (key==101) return; + if (key==102) return; for (size_t i=0; idata[cursor.y][0]=100; pat->data[cursor.y][1]=0; + } else if (key==101) { // note off + env release + pat->data[cursor.y][0]=101; + pat->data[cursor.y][1]=0; + } else if (key==102) { // env release only + pat->data[cursor.y][0]=102; + pat->data[cursor.y][1]=0; } else { pat->data[cursor.y][0]=num%12; pat->data[cursor.y][1]=num/12; @@ -4989,7 +5017,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { editAdvance(); curNibble=false; } else { - if (key!=100) { + if (key!=100 && key!=101 && key!=102) { previewNote(cursor.xCoarse,num); } } @@ -5052,7 +5080,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { try { int key=noteKeys.at(ev.key.keysym.scancode); int num=12*curOctave+key; - if (key!=100) { + if (key!=100 && key!=101 && key!=102) { previewNote(cursor.xCoarse,num); } } catch (std::out_of_range& e) { @@ -5065,7 +5093,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { try { int key=noteKeys.at(ev.key.keysym.scancode); int num=12*curOctave+key; - if (key!=100) { + if (key!=100 && key!=101 && key!=102) { e->previewSample(curSample,num); samplePreviewOn=true; samplePreviewKey=ev.key.keysym.scancode; @@ -5081,7 +5109,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { try { int key=noteKeys.at(ev.key.keysym.scancode); int num=12*curOctave+key; - if (key!=100) { + if (key!=100 && key!=101 && key!=102) { e->previewWave(curWave,num); wavePreviewOn=true; wavePreviewKey=ev.key.keysym.scancode; @@ -6777,10 +6805,15 @@ FurnaceGUI::FurnaceGUI(): noteKeys[SDL_SCANCODE_RIGHTBRACKET]=31; // note off - noteKeys[SDL_SCANCODE_EQUALS]=100; noteKeys[SDL_SCANCODE_TAB]=100; noteKeys[SDL_SCANCODE_1]=100; + // note off + env release + noteKeys[SDL_SCANCODE_EQUALS]=101; + + // env release + noteKeys[SDL_SCANCODE_GRAVE]=102; + // value keys valueKeys[SDLK_0]=0; valueKeys[SDLK_1]=1; diff --git a/src/gui/gui.h b/src/gui/gui.h index 0f63155e5..c4710c386 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -401,10 +401,10 @@ class FurnaceGUI { void applyUISettings(); - void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop); - void encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop); - void decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax); - void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax); + void encodeMMLStr(String& target, int* macro, int macroLen, int macroLoop, int macroRel); + void encodeMMLStr(String& target, unsigned char* macro, unsigned char macroLen, signed char macroLoop, signed char macroRel); + void decodeMMLStr(String& source, unsigned char* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel); + void decodeMMLStr(String& source, int* macro, unsigned char& macroLen, signed char& macroLoop, int macroMin, int macroMax, signed char& macroRel); void decodeMMLStrW(String& source, int* macro, int& macroLen, int macroMax); const char* getSystemName(DivSystem which);