diff --git a/src/engine/defines.h b/src/engine/defines.h index 919ca1f85..5a2fc2a7b 100644 --- a/src/engine/defines.h +++ b/src/engine/defines.h @@ -38,6 +38,10 @@ #define DIV_PAT_FX(_x) (3+((_x)<<1)) #define DIV_PAT_FXVAL(_x) (4+((_x)<<1)) +// column type checks +#define DIV_PAT_IS_EFFECT(_x) ((_x)>DIV_PAT_VOL && (!((_x)&1))) +#define DIV_PAT_IS_EFFECT_VAL(_x) ((_x)>DIV_PAT_VOL && ((_x)&1)) + #define DIV_NOTE_NULL_PAT 252 #define DIV_NOTE_OFF 253 #define DIV_NOTE_REL 254 diff --git a/src/gui/chanOsc.cpp b/src/gui/chanOsc.cpp index cb76baf0a..252b82502 100644 --- a/src/gui/chanOsc.cpp +++ b/src/gui/chanOsc.cpp @@ -902,10 +902,8 @@ void FurnaceGUI::drawChanOsc() { case 'n': { DivChannelState* chanState=e->getChanState(ch); if (chanState==NULL || !(chanState->keyOn)) break; - short tempNote=chanState->note; //all of this conversion is necessary because notes 100-102 are special chars - short noteMod=tempNote%12+12; //also note 0 is a BUG, hence +12 on the note and -1 on the octave - short oct=tempNote/12-1; - text+=fmt::sprintf("%s",noteName(noteMod,oct)); + // no more conversion necessary after the note/octave unification :> + text+=fmt::sprintf("%s",noteName(chanState->note)); break; } case 'l': { diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index a9326016b..8df11453c 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -697,10 +697,10 @@ void FurnaceGUI::doAction(int what) { break; case GUI_ACTION_PAT_LATCH: { DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][cursor.order],true); - latchIns=pat->data[cursor.y][2]; - latchVol=pat->data[cursor.y][3]; - latchEffect=pat->data[cursor.y][4]; - latchEffectVal=pat->data[cursor.y][5]; + latchIns=pat->newData[cursor.y][DIV_PAT_INS]; + latchVol=pat->newData[cursor.y][DIV_PAT_VOL]; + latchEffect=pat->newData[cursor.y][DIV_PAT_FX(0)]; + latchEffectVal=pat->newData[cursor.y][DIV_PAT_FXVAL(0)]; latchTarget=0; latchNibble=false; break; diff --git a/src/gui/editing.cpp b/src/gui/editing.cpp index e94759279..505dd36fb 100644 --- a/src/gui/editing.cpp +++ b/src/gui/editing.cpp @@ -35,21 +35,22 @@ static const char* modPlugFormatHeaders[]={ NULL, }; -const char* FurnaceGUI::noteNameNormal(short note, short octave) { - if (note==100) { // note cut +const char* FurnaceGUI::noteNameNormal(short note) { + if (note==DIV_NOTE_OFF) { // note cut return "OFF"; - } else if (note==101) { // note off and envelope release + } else if (note==DIV_NOTE_REL) { // note off and envelope release return "==="; - } else if (note==102) { // envelope release only + } else if (note==DIV_MACRO_REL) { // envelope release only return "REL"; - } else if (octave==0 && note==0) { + } else if (note==-1) { return "..."; + } else if (note==DIV_NOTE_NULL_PAT) { + return "BUG"; } - int seek=(note+(signed char)octave*12)+60; - if (seek<0 || seek>=180) { + if (note<0 || note>=180) { return "???"; } - return noteNames[seek]; + return noteNames[note]; } void FurnaceGUI::prepareUndo(ActionType action, UndoRegion region) { @@ -222,16 +223,16 @@ void FurnaceGUI::makeUndo(ActionType action, UndoRegion region) { for (int j=jBegin; j<=jEnd; j++) { for (int k=0; kdata[j][k]!=op->data[j][k]) { - s.pat.push_back(UndoPatternData(subSong,i,e->curOrders->ord[i][h],j,k,op->data[j][k],p->data[j][k])); + if (p->newData[j][k]!=op->newData[j][k]) { + s.pat.push_back(UndoPatternData(subSong,i,e->curOrders->ord[i][h],j,k,op->newData[j][k],p->newData[j][k])); - if (k>=4) { - if (op->data[j][k&(~1)]==0x0b || - p->data[j][k&(~1)]==0x0b || - op->data[j][k&(~1)]==0x0d || - p->data[j][k&(~1)]==0x0d || - op->data[j][k&(~1)]==0xff || - p->data[j][k&(~1)]==0xff) { + if (k>=DIV_PAT_FX(0)) { + if (op->newData[j][k&(~1)]==0x0b || + p->newData[j][k&(~1)]==0x0b || + op->newData[j][k&(~1)]==0x0d || + p->newData[j][k&(~1)]==0x0d || + op->newData[j][k&(~1)]==0xff || + p->newData[j][k&(~1)]==0xff) { shallWalk=true; } } @@ -366,13 +367,12 @@ void FurnaceGUI::doDelete() { for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][iFine]=0; - if (selStart.y==selEnd.y && selStart.order==selEnd.order) pat->data[j][2]=-1; + if (selStart.y==selEnd.y && selStart.order==selEnd.order) pat->newData[j][DIV_PAT_VOL]=-1; } - pat->data[j][iFine+1]=(iFine<1)?0:-1; + pat->newData[j][iFine]=-1; - if (selStart.y==selEnd.y && selStart.order==selEnd.order && iFine>2 && iFine&1 && settings.effectDeletionAltersValue) { - pat->data[j][iFine+2]=-1; + if (selStart.y==selEnd.y && selStart.order==selEnd.order && DIV_PAT_IS_EFFECT(iFine) && settings.effectDeletionAltersValue) { + pat->newData[j][iFine+1]=-1; } } j=0; @@ -439,16 +439,12 @@ void FurnaceGUI::doPullDelete() { for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarsecurSubSong->patLen; j++) { + // TODO: we've got a problem here. this should pull from the next row if the selection spans + // more than one order. if (jcurSubSong->patLen-1) { - if (iFine==0) { - pat->data[j][iFine]=pat->data[j+1][iFine]; - } - pat->data[j][iFine+1]=pat->data[j+1][iFine+1]; + pat->newData[j][iFine]=pat->newData[j+1][iFine]; } else { - if (iFine==0) { - pat->data[j][iFine]=0; - } - pat->data[j][iFine+1]=(iFine<1)?0:-1; + pat->newData[j][iFine]=-1; } } } @@ -486,15 +482,9 @@ void FurnaceGUI::doInsert() { maskOut(opMaskInsert,iFine); for (int j=e->curSubSong->patLen-1; j>=sStart.y; j--) { if (j==sStart.y) { - if (iFine==0) { - pat->data[j][iFine]=0; - } - pat->data[j][iFine+1]=(iFine<1)?0:-1; + pat->newData[j][iFine]=-1; } else { - if (iFine==0) { - pat->data[j][iFine]=pat->data[j-1][iFine]; - } - pat->data[j][iFine+1]=pat->data[j-1][iFine+1]; + pat->newData[j][iFine]=pat->newData[j-1][iFine]; } } } @@ -522,45 +512,22 @@ void FurnaceGUI::doTranspose(int amount, OperationMask& mask) { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][0]; - int origOctave=(signed char)pat->data[j][1]; - if (origNote!=0 && origNote!=100 && origNote!=101 && origNote!=102) { - origNote+=amount; - while (origNote>12) { - origNote-=12; - origOctave++; - } - while (origNote<1) { - origNote+=12; - origOctave--; - } - if (origOctave==9 && origNote>11) { - origNote=11; - origOctave=9; - } - if (origOctave>9) { - origNote=11; - origOctave=9; - } - if (origOctave<-5) { - origNote=1; - origOctave=-5; - } - pat->data[j][0]=origNote; - pat->data[j][1]=(unsigned char)origOctave; - } - } else { - int top=255; - if (iFine==1) { - if (e->song.ins.empty()) continue; - top=e->song.ins.size()-1; - } else if (iFine==2) { // volume - top=e->getMaxVolumeChan(iCoarse); - } - if (pat->data[j][iFine+1]==-1) continue; - pat->data[j][iFine+1]=MIN(top,MAX(0,pat->data[j][iFine+1]+amount)); + int top=255; + if (iFine==DIV_PAT_NOTE) { + top=179; + // don't transpose special notes + if (pat->newData[j][iFine]==DIV_NOTE_OFF) continue; + if (pat->newData[j][iFine]==DIV_NOTE_REL) continue; + if (pat->newData[j][iFine]==DIV_MACRO_REL) continue; + if (pat->newData[j][iFine]==DIV_NOTE_NULL_PAT) continue; + } else if (iFine==DIV_PAT_INS) { + if (e->song.ins.empty()) continue; + top=e->song.ins.size()-1; + } else if (iFine==DIV_PAT_VOL) { // volume + top=e->getMaxVolumeChan(iCoarse); } + if (pat->newData[j][iFine]==-1) continue; + pat->newData[j][iFine]=MIN(top,MAX(0,pat->newData[j][iFine]+amount)); } j=0; } @@ -596,19 +563,18 @@ String FurnaceGUI::doCopy(bool cut, bool writeClipboard, const SelectionPoint& s DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarsedata[j][0],pat->data[j][1]); + clipb+=noteNameNormal(pat->newData[j][DIV_PAT_NOTE]); if (cut) { - pat->data[j][0]=0; - pat->data[j][1]=0; + pat->newData[j][DIV_PAT_NOTE]=-1; } } else { - if (pat->data[j][iFine+1]==-1) { + if (pat->newData[j][iFine]==-1) { clipb+=".."; } else { - clipb+=fmt::sprintf("%.2X",pat->data[j][iFine+1]); + clipb+=fmt::sprintf("%.2X",pat->newData[j][iFine]); } if (cut) { - pat->data[j][iFine+1]=-1; + pat->newData[j][iFine]=-1; } } } @@ -685,12 +651,12 @@ void FurnaceGUI::doPasteFurnace(PasteMode mode, int arg, bool readClipboard, Str mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) && strcmp(note,"...")==0) { // do nothing. } else { - if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->data[j][0]==0 && pat->data[j][1]==0)) { - if (!decodeNote(note,pat->data[j][0],pat->data[j][1])) { + if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->newData[j][DIV_PAT_NOTE]==-1)) { + if (!decodeNote(note,pat->newData[j][DIV_PAT_NOTE])) { invalidData=true; break; } - if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->data[j][2]=arg; + if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->newData[j][DIV_PAT_INS]=arg; } } } else { @@ -706,12 +672,12 @@ void FurnaceGUI::doPasteFurnace(PasteMode mode, int arg, bool readClipboard, Str note[1]=line[charPos++]; note[2]=0; - if (iFine==1) { + if (iFine==DIV_PAT_INS) { if (!opMaskPaste.ins || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) { iFine++; continue; } - } else if (iFine==2) { + } else if (iFine==DIV_PAT_VOL) { if (!opMaskPaste.vol) { iFine++; continue; @@ -731,7 +697,7 @@ void FurnaceGUI::doPasteFurnace(PasteMode mode, int arg, bool readClipboard, Str if (strcmp(note,"..")==0) { if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) { - pat->data[j][iFine+1]=-1; + pat->newData[j][iFine]=-1; } } else { unsigned int val=0; @@ -739,8 +705,8 @@ void FurnaceGUI::doPasteFurnace(PasteMode mode, int arg, bool readClipboard, Str invalidData=true; break; } - if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->data[j][iFine+1]==-1) { - if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val; + if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->newData[j][iFine]==-1) { + if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->newData[j][iFine]=val; } } } @@ -1024,7 +990,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String charPos++; continue; } - if (iFine==0) { // note + if (iFine==DIV_PAT_NOTE) { // note if (charPos>=line.size()) { invalidData=true; break; @@ -1050,25 +1016,28 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String if (strcmp(note,"...")==0 || strcmp(note," ")==0) { // do nothing. } else { - if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->data[j][0]==0 && pat->data[j][1]==0)) { - if (!decodeNote(note,pat->data[j][0],pat->data[j][1])) { + if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->newData[j][DIV_PAT_NOTE]==-1)) { + if (!decodeNote(note,pat->newData[j][DIV_PAT_NOTE])) { if (strcmp(note, "^^^")==0) { - pat->data[j][0]=100; - pat->data[j][1]=0; + pat->newData[j][0]=DIV_NOTE_OFF; } else if (strcmp(note, "~~~")==0 || strcmp(note,"===")==0) { - pat->data[j][0]=101; - pat->data[j][1]=0; + pat->newData[j][0]=DIV_NOTE_REL; } else { invalidData=true; } break; } else { - pat->data[j][1]--; // MPT is one octave higher... + // MPT is one octave higher... + if (pat->newData[j][DIV_PAT_NOTE]<12) { + pat->newData[j][DIV_PAT_NOTE]=0; + } else { + pat->newData[j][DIV_PAT_NOTE]-=12; + } } - if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->data[j][2]=arg; + if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->newData[j][DIV_PAT_INS]=arg; } } - } else if (iFine==1) { // instrument + } else if (iFine==DIV_PAT_INS) { // instrument if (charPos>=line.size()) { invalidData=true; break; @@ -1081,7 +1050,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String note[1]=line[charPos++]; note[2]=0; - if (iFine==1) { + if (iFine==DIV_PAT_INS) { if (!opMaskPaste.ins || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) { iFine++; continue; @@ -1091,7 +1060,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String if (strcmp(note,"..")==0 || strcmp(note," ")==0) { if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) { - pat->data[j][iFine+1]=-1; + pat->newData[j][iFine]=-1; } } else { unsigned int val=0; @@ -1100,8 +1069,8 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String break; } - if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->data[j][iFine+1]==-1) { - pat->data[j][iFine+1]=val-1; + if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->newData[j][iFine]==-1) { + pat->newData[j][iFine]=val-1; } } } else { // volume and effects @@ -1122,14 +1091,12 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String note[2]=line[charPos++]; note[3]=0; - if (iFine==2) { + if (iFine==DIV_PAT_VOL) { if (!opMaskPaste.vol) { iFine++; continue; } - } - - else if ((iFine&1)==0) { + } else if ((iFine&1)==0) { // FUCKING HELL WITH THE INDENTATION?!?! if (!opMaskPaste.effectVal) { iFine++; continue; @@ -1143,9 +1110,8 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String if (strcmp(note,"...")==0 || strcmp(note," ")==0) { if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG || - mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) - { - pat->data[j][iFine+1]=-1; + mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) { + pat->newData[j][iFine]=-1; } } else { unsigned int val=0; @@ -1153,19 +1119,19 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String symbol=note[0]; - if (iFine==2) { + if (iFine==DIV_PAT_VOL) { sscanf(¬e[1],"%2d",&val); } else { sscanf(¬e[1],"%2X",&val); } - if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->data[j][iFine+1]==-1) { - // if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val; - if (iFine==2) { // volume + if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->newData[j][iFine]==-1) { + // if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->newData[j][iFine]=val; + if (iFine==DIV_PAT_VOL) { // volume switch(symbol) { case 'v': { - pat->data[j][iFine+1]=val; + pat->newData[j][iFine]=val; break; } default: @@ -1176,7 +1142,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String if (mptFormat==0) { eff=convertEffectMPT_MOD(symbol, val); // up to 4 effects stored in one variable if (((eff&0x0f00)>>8)==0x0C) { // set volume - pat->data[j][iFine]=eff&0xff; + pat->newData[j][iFine-1]=eff&0xff; } } @@ -1189,7 +1155,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String if (((eff&0x0f00)>>8)==0x0C) { - pat->data[j][iFine]=eff&0xff; + pat->newData[j][iFine-1]=eff&0xff; } } @@ -1201,12 +1167,12 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String eff=convertEffectMPT_MPTM(symbol, val); } - pat->data[j][iFine+1]=((eff&0xff00)>>8); - pat->data[j][iFine+2]=(eff&0xff); + pat->newData[j][iFine]=((eff&0xff00)>>8); + pat->newData[j][iFine+1]=(eff&0xff); if (eff>0xffff) { - pat->data[j][iFine+3]=((eff&0xff000000)>>24); - pat->data[j][iFine+4]=((eff&0xff0000)>>16); + pat->newData[j][iFine+2]=((eff&0xff000000)>>24); + pat->newData[j][iFine+3]=((eff&0xff0000)>>16); } } } @@ -1346,8 +1312,8 @@ void FurnaceGUI::doChangeIns(int ins) { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][2]!=-1 || !((pat->data[j][0]==0 || pat->data[j][0]==100 || pat->data[j][0]==101 || pat->data[j][0]==102) && pat->data[j][1]==0)) { - pat->data[j][2]=ins; + if (pat->newData[j][DIV_PAT_INS]!=-1 || !(pat->newData[j][DIV_PAT_NOTE]==-1 || pat->newData[j][DIV_PAT_NOTE]==DIV_NOTE_OFF || pat->newData[j][DIV_PAT_NOTE]==DIV_NOTE_REL || pat->newData[j][DIV_PAT_NOTE]==DIV_MACRO_REL)) { + pat->newData[j][DIV_PAT_INS]=ins; } } j=0; @@ -1372,15 +1338,15 @@ void FurnaceGUI::doInterpolate() { maskOut(opMaskInterpolate,iFine); points.clear(); resetTouches; - if (iFine!=0) { + if (iFine!=DIV_PAT_NOTE) { int jOrder=selStart.order; int j=selStart.y; for (; jOrder<=selEnd.order; jOrder++) { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][iFine+1]!=-1) { - points.emplace(points.end(),j|(jOrder<<8),pat->data[j][iFine+1]); + if (pat->newData[j][iFine]!=-1) { + points.emplace(points.end(),j|(jOrder<<8),pat->newData[j][iFine]); } } j=0; @@ -1395,7 +1361,7 @@ void FurnaceGUI::doInterpolate() { ); for (int k=0, k_p=curPoint.first; kcurPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][(k_p>>8)&0xff],true); - pat->data[k_p&0xff][iFine+1]=curPoint.second+((nextPoint.second-curPoint.second)*(double)k/(double)distance); + pat->newData[k_p&0xff][iFine]=curPoint.second+((nextPoint.second-curPoint.second)*(double)k/(double)distance); k_p++; if ((k_p&0xff)>=e->curSubSong->patLen) { k_p&=~0xff; @@ -1410,9 +1376,9 @@ void FurnaceGUI::doInterpolate() { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][0]!=0 || pat->data[j][1]!=0) { - if (pat->data[j][0]!=100 && pat->data[j][0]!=101 && pat->data[j][0]!=102) { - points.emplace(points.end(),j|(jOrder<<8),pat->data[j][0]+(signed char)pat->data[j][1]*12); + if (pat->newData[j][DIV_PAT_NOTE]!=-1) { + if (pat->newData[j][DIV_PAT_NOTE]!=DIV_NOTE_OFF && pat->newData[j][DIV_PAT_NOTE]!=DIV_NOTE_REL && pat->newData[j][DIV_PAT_NOTE]!=DIV_MACRO_REL) { + points.emplace(points.end(),j|(jOrder<<8),pat->newData[j][DIV_PAT_NOTE]); } } } @@ -1429,13 +1395,7 @@ void FurnaceGUI::doInterpolate() { for (int k=0, k_p=curPoint.first; kcurPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][(k_p>>8)&0xff],true); int val=curPoint.second+((nextPoint.second-curPoint.second)*(double)k/(double)distance); - pat->data[k_p&0xff][0]=val%12; - pat->data[k_p&0xff][1]=val/12; - if (pat->data[k_p&0xff][0]==0) { - pat->data[k_p&0xff][0]=12; - pat->data[k_p&0xff][1]--; - } - pat->data[k_p&0xff][1]&=255; + pat->newData[k_p&0xff][DIV_PAT_NOTE]=val%12; k_p++; if ((k_p&0xff)>=e->curSubSong->patLen) { k_p&=~0xff; @@ -1469,12 +1429,12 @@ void FurnaceGUI::doFade(int p0, int p1, bool mode) { int j_p=0; maskOut(opMaskFade,iFine); resetTouches; - if (iFine!=0) { + if (iFine!=DIV_PAT_NOTE) { int absoluteTop=255; - if (iFine==1) { + if (iFine==DIV_PAT_INS) { if (e->song.ins.empty()) continue; absoluteTop=e->song.ins.size()-1; - } else if (iFine==2) { // volume + } else if (iFine==DIV_PAT_VOL) { // volume absoluteTop=e->getMaxVolumeChan(iCoarse); } if (distance<1) continue; @@ -1485,9 +1445,9 @@ void FurnaceGUI::doFade(int p0, int p1, bool mode) { int value=p0+double(p1-p0)*fraction; if (mode) { // nibble value&=15; - pat->data[j][iFine+1]=MIN(absoluteTop,value|(value<<4)); + pat->newData[j][iFine]=MIN(absoluteTop,value|(value<<4)); } else { // byte - pat->data[j][iFine+1]=MIN(absoluteTop,value); + pat->newData[j][iFine]=MIN(absoluteTop,value); } j_p++; } @@ -1514,20 +1474,20 @@ void FurnaceGUI::doInvertValues() { int j=selStart.y; maskOut(opMaskInvertVal,iFine); resetTouches; - if (iFine!=0) { + if (iFine!=DIV_PAT_NOTE) { int top=255; - if (iFine==1) { + if (iFine==DIV_PAT_INS) { if (e->song.ins.empty()) continue; top=e->song.ins.size()-1; - } else if (iFine==2) { // volume + } else if (iFine==DIV_PAT_VOL) { // volume top=e->getMaxVolumeChan(iCoarse); } for (; jOrder<=selEnd.order; jOrder++) { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][iFine+1]==-1) continue; - pat->data[j][iFine+1]=top-pat->data[j][iFine+1]; + if (pat->newData[j][iFine]==-1) continue; + pat->newData[j][iFine]=top-pat->newData[j][iFine]; } j=0; } @@ -1552,20 +1512,20 @@ void FurnaceGUI::doScale(float top) { int j=selStart.y; maskOut(opMaskScale,iFine); resetTouches; - if (iFine!=0) { + if (iFine!=DIV_PAT_NOTE) { int absoluteTop=255; - if (iFine==1) { + if (iFine==DIV_PAT_INS) { if (e->song.ins.empty()) continue; absoluteTop=e->song.ins.size()-1; - } else if (iFine==2) { // volume + } else if (iFine==DIV_PAT_VOL) { // volume absoluteTop=e->getMaxVolumeChan(iCoarse); } for (; jOrder<=selEnd.order; jOrder++) { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][iFine+1]==-1) continue; - pat->data[j][iFine+1]=MIN(absoluteTop,(double)pat->data[j][iFine+1]*(top/100.0f)); + if (pat->newData[j][iFine]==-1) continue; + pat->newData[j][iFine]=MIN(absoluteTop,(double)pat->newData[j][iFine]*(top/100.0f)); } j=0; } @@ -1590,63 +1550,40 @@ void FurnaceGUI::doRandomize(int bottom, int top, bool mode, bool eff, int effVa int j=selStart.y; maskOut(opMaskRandomize,iFine); resetTouches; - if (iFine!=0) { - int absoluteTop=255; - if (iFine==1) { - if (e->song.ins.empty()) continue; - absoluteTop=e->song.ins.size()-1; - } else if (iFine==2) { // volume - absoluteTop=e->getMaxVolumeChan(iCoarse); - } - for (; jOrder<=selEnd.order; jOrder++) { - DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); - for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][iFine+1]=value|(value2<<4); - } else { - pat->data[j][iFine+1]=value; - } - if (eff && iFine>2 && (iFine&1)) { - pat->data[j][iFine+1]=effVal; - } + int absoluteTop=255; + if (iFine==DIV_PAT_NOTE) { + absoluteTop=179; + } else if (iFine==DIV_PAT_INS) { + if (e->song.ins.empty()) continue; + absoluteTop=e->song.ins.size()-1; + } else if (iFine==DIV_PAT_VOL) { // volume + absoluteTop=e->getMaxVolumeChan(iCoarse); + } + for (; jOrder<=selEnd.order; jOrder++) { + DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); + for (; jcurSubSong->patLen && (j<=selEnd.y || jOrdercurPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); - for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][0]=value%12; - pat->data[j][1]=(value-60)/12; - if (pat->data[j][0]==0) { - pat->data[j][0]=12; - pat->data[j][1]--; - } - pat->data[j][1]=(unsigned char)pat->data[j][1]; + if (mode) { + value&=15; + value2&=15; + pat->newData[j][iFine]=value|(value2<<4); + } else { + pat->newData[j][iFine]=value; + } + if (eff && iFine>2 && (iFine&1)) { + pat->newData[j][iFine]=effVal; } - j=0; } + j=0; } } iFine=0; @@ -1678,7 +1615,7 @@ void FurnaceGUI::doFlip() { DivPattern* pat=e->curPat[iCoarse].getPattern(e->curOrders->ord[iCoarse][jOrder],true); for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j],DIV_MAX_COLS*sizeof(short)); + memcpy(put.data,pat->newData[j],DIV_MAX_COLS*sizeof(short)); patBuffer.push_back(put); } j=0; @@ -1697,10 +1634,7 @@ void FurnaceGUI::doFlip() { for (; jcurSubSong->patLen && (j<=selEnd.y || jOrderdata[j][0]=patBuffer[j_i].data[0]; - } - pat->data[j][iFine+1]=patBuffer[j_i].data[iFine+1]; + pat->newData[j][iFine]=patBuffer[j_i].data[iFine]; } j=0; } @@ -1734,38 +1668,18 @@ void FurnaceGUI::doCollapse(int divider, const SelectionPoint& sStart, const Sel for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarsedata[j][0]; - } - patBuffer.data[j][iFine+1]=pat->data[j][iFine+1]; + patBuffer.newData[j][iFine]=pat->newData[j][iFine]; } for (int j=0; j<=sEnd.y-sStart.y; j++) { if (j*divider>=sEnd.y-sStart.y) { - if (iFine==0) { - pat->data[j+sStart.y][0]=0; - pat->data[j+sStart.y][1]=0; - } else { - pat->data[j+sStart.y][iFine+1]=-1; - } + pat->newData[j+sStart.y][iFine]=-1; } else { - if (iFine==0) { - pat->data[j+sStart.y][0]=patBuffer.data[j*divider+sStart.y][0]; - } - pat->data[j+sStart.y][iFine+1]=patBuffer.data[j*divider+sStart.y][iFine+1]; + pat->newData[j+sStart.y][iFine+1]=patBuffer.newData[j*divider+sStart.y][iFine]; - if (iFine==0) { - for (int k=1; k=sEnd.y-sStart.y) break; - if (!(pat->data[j+sStart.y][0]==0 && pat->data[j+sStart.y][1]==0)) break; - pat->data[j+sStart.y][0]=patBuffer.data[j*divider+sStart.y+k][0]; - pat->data[j+sStart.y][1]=patBuffer.data[j*divider+sStart.y+k][1]; - } - } else { - for (int k=1; k=sEnd.y-sStart.y) break; - if (pat->data[j+sStart.y][iFine+1]!=-1) break; - pat->data[j+sStart.y][iFine+1]=patBuffer.data[j*divider+sStart.y+k][iFine+1]; - } + for (int k=1; k=sEnd.y-sStart.y) break; + if (pat->newData[j+sStart.y][iFine]!=-1) break; + pat->newData[j+sStart.y][iFine]=patBuffer.newData[j*divider+sStart.y+k][iFine]; } } } @@ -1795,26 +1709,15 @@ void FurnaceGUI::doExpand(int multiplier, const SelectionPoint& sStart, const Se for (; iFine<3+e->curPat[iCoarse].effectCols*2 && (iCoarsedata[j][0]; - } - patBuffer.data[j][iFine+1]=pat->data[j][iFine+1]; + patBuffer.newData[j][iFine]=pat->newData[j][iFine]; } for (int j=0; j<=(sEnd.y-sStart.y)*multiplier; j++) { if ((j+sStart.y)>=e->curSubSong->patLen) break; if ((j%multiplier)!=0) { - if (iFine==0) { - pat->data[j+sStart.y][0]=0; - pat->data[j+sStart.y][1]=0; - } else { - pat->data[j+sStart.y][iFine+1]=-1; - } + pat->newData[j+sStart.y][iFine]=-1; continue; } - if (iFine==0) { - pat->data[j+sStart.y][0]=patBuffer.data[j/multiplier+sStart.y][0]; - } - pat->data[j+sStart.y][iFine+1]=patBuffer.data[j/multiplier+sStart.y][iFine+1]; + pat->newData[j+sStart.y][iFine]=patBuffer.newData[j/multiplier+sStart.y][iFine]; } } iFine=0; @@ -1846,24 +1749,17 @@ void FurnaceGUI::doCollapseSong(int divider) { pat->clear(); for (int k=0; kdata[k/divider][0]==0 && pat->data[k/divider][1]==0)) continue; - } else { - if (pat->data[k/divider][l+1]!=-1) continue; - } + if (pat->newData[k/divider][l]!=-1) continue; - if (l==0) { - pat->data[k/divider][l]=patCopy.data[k][l]; - } - pat->data[k/divider][l+1]=patCopy.data[k][l+1]; + pat->newData[k/divider][l]=patCopy.newData[k][l]; - if (l>3 && !(l&1)) { // scale effects as needed - switch (pat->data[k/divider][l]) { + if (DIV_PAT_IS_EFFECT(l)) { // scale effects as needed + switch (pat->newData[k/divider][l]) { case 0x0d: - pat->data[k/divider][l+1]/=divider; + pat->newData[k/divider][l+1]/=divider; break; case 0x0f: - pat->data[k/divider][l+1]=CLAMP(pat->data[k/divider][l+1]*divider,1,255); + pat->newData[k/divider][l+1]=CLAMP(pat->newData[k/divider][l+1]*divider,1,255); break; } } @@ -1873,8 +1769,8 @@ void FurnaceGUI::doCollapseSong(int divider) { // put undo for (int k=0; kdata[k][l]!=patCopy.data[k][l]) { - us.pat.push_back(UndoPatternData(subSong,i,j,k,l,patCopy.data[k][l],pat->data[k][l])); + if (pat->newData[k][l]!=patCopy.newData[k][l]) { + us.pat.push_back(UndoPatternData(subSong,i,j,k,l,patCopy.newData[k][l],pat->newData[k][l])); } } } @@ -1929,24 +1825,17 @@ void FurnaceGUI::doExpandSong(int multiplier) { pat->clear(); for (int k=0; k<(256/multiplier); k++) { for (int l=0; ldata[k*multiplier][0]==0 && pat->data[k*multiplier][1]==0)) continue; - } else { - if (pat->data[k*multiplier][l+1]!=-1) continue; - } + if (pat->newData[k*multiplier][l]!=-1) continue; - if (l==0) { - pat->data[k*multiplier][l]=patCopy.data[k][l]; - } - pat->data[k*multiplier][l+1]=patCopy.data[k][l+1]; + pat->newData[k*multiplier][l]=patCopy.newData[k][l]; - if (l>3 && !(l&1)) { // scale effects as needed - switch (pat->data[k*multiplier][l]) { + if (DIV_PAT_IS_EFFECT(l)) { // scale effects as needed + switch (pat->newData[k*multiplier][l]) { case 0x0d: - pat->data[k*multiplier][l+1]/=multiplier; + pat->newData[k*multiplier][l+1]/=multiplier; break; case 0x0f: - pat->data[k*multiplier][l+1]=CLAMP(pat->data[k*multiplier][l+1]/multiplier,1,255); + pat->newData[k*multiplier][l+1]=CLAMP(pat->newData[k*multiplier][l+1]/multiplier,1,255); break; } } @@ -1956,8 +1845,8 @@ void FurnaceGUI::doExpandSong(int multiplier) { // put undo for (int k=0; kdata[k][l]!=patCopy.data[k][l]) { - us.pat.push_back(UndoPatternData(subSong,i,j,k,l,patCopy.data[k][l],pat->data[k][l])); + if (pat->newData[k][l]!=patCopy.newData[k][l]) { + us.pat.push_back(UndoPatternData(subSong,i,j,k,l,patCopy.newData[k][l],pat->newData[k][l])); } } } @@ -2006,28 +1895,23 @@ void FurnaceGUI::doAbsorbInstrument() { for (int i=searchStartRow; i>=0 && !foundAll(); i--) { // absorb most recent instrument - if (!foundIns && pat->data[i][2] >= 0) { + if (!foundIns && pat->newData[i][DIV_PAT_INS] >= 0) { foundIns=true; - curIns=pat->data[i][2]; + curIns=pat->newData[i][DIV_PAT_INS]; } // absorb most recent octave (i.e. set curOctave such that the "main row" (QWERTY) of // notes will result in an octave number equal to the previous note). make sure to // skip "special note values" like OFF/REL/=== and "none", since there won't be valid // octave values - unsigned char note=pat->data[i][0]; - if (!foundOctave && note!=0 && note!=100 && note!=101 && note!=102) { + short note=pat->newData[i][DIV_PAT_NOTE]; + if (!foundOctave && note!=-1 && note!=DIV_NOTE_OFF && note!=DIV_NOTE_REL && note!=DIV_MACRO_REL) { foundOctave=true; - // decode octave data (was signed cast to unsigned char) - int octave=pat->data[i][1]; - if (octave>128) octave-=256; + // decode octave data + int octave=(pat->newData[i][DIV_PAT_NOTE]-60)/12; - // @NOTE the special handling when note==12, which is really an octave above what's - // stored in the octave data. without this handling, if you press Q, then - // "ABSORB_INSTRUMENT", then Q again, you'd get a different octave! - if (pat->data[i][0]==12) octave++; - curOctave=CLAMP(octave-1, GUI_EDIT_OCTAVE_MIN, GUI_EDIT_OCTAVE_MAX); + curOctave=CLAMP(octave-1,GUI_EDIT_OCTAVE_MIN,GUI_EDIT_OCTAVE_MAX); } } } @@ -2221,7 +2105,7 @@ void FurnaceGUI::doUndo() { for (UndoPatternData& i: us.pat) { e->changeSongP(i.subSong); DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true); - p->data[i.row][i.col]=i.oldVal; + p->newData[i.row][i.col]=i.oldVal; } if (us.type!=GUI_UNDO_REPLACE) { if (!e->isPlaying() || !followPattern) { @@ -2299,7 +2183,7 @@ void FurnaceGUI::doRedo() { for (UndoPatternData& i: us.pat) { e->changeSongP(i.subSong); DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true); - p->data[i.row][i.col]=i.newVal; + p->newData[i.row][i.col]=i.newVal; } if (us.type!=GUI_UNDO_REPLACE) { if (!e->isPlaying() || !followPattern) { diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 296465668..890bbad21 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -97,66 +97,54 @@ void FurnaceGUI::enableSafeMode() { safeMode=true; } -const char* FurnaceGUI::noteName(short note, short octave) { - if (note==100) { +const char* FurnaceGUI::noteName(short note) { + if (note==DIV_NOTE_OFF) { return noteOffLabel; - } else if (note==101) { // note off and envelope release + } else if (note==DIV_NOTE_REL) { // note off and envelope release return noteRelLabel; - } else if (note==102) { // envelope release only + } else if (note==DIV_MACRO_REL) { // envelope release only return macroRelLabel; - } else if (octave==0 && note==0) { + } else if (note==-1) { return emptyLabel; - } else if (note==0 && octave!=0) { + } else if (note==DIV_NOTE_NULL_PAT) { return "BUG"; } - int seek=(note+(signed char)octave*12)+60; - if (seek<0 || seek>=180) { + if (note<0 || note>=180) { return "???"; } if (settings.flatNotes) { - if (settings.germanNotation) return noteNamesGF[seek]; - return noteNamesF[seek]; + if (settings.germanNotation) return noteNamesGF[note]; + return noteNamesF[note]; } - if (settings.germanNotation) return noteNamesG[seek]; - return noteNames[seek]; + if (settings.germanNotation) return noteNamesG[note]; + return noteNames[note]; } -bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) { +bool FurnaceGUI::decodeNote(const char* what, short& note) { if (strlen(what)!=3) return false; if (strcmp(what,"...")==0) { - note=0; - octave=0; + note=-1; return true; } if (strcmp(what,"???")==0) { - note=0; - octave=0; + note=DIV_NOTE_NULL_PAT; return true; } if (strcmp(what,"OFF")==0) { - note=100; - octave=0; + note=DIV_NOTE_OFF; return true; } if (strcmp(what,"===")==0) { - note=101; - octave=0; + note=DIV_NOTE_REL; return true; } if (strcmp(what,"REL")==0) { - note=102; - octave=0; + note=DIV_MACRO_REL; return true; } for (int i=0; i<180; i++) { if (strcmp(what,noteNames[i])==0) { - if ((i%12)==0) { - note=12; - octave=(unsigned char)((i/12)-6); - } else { - note=i%12; - octave=(unsigned char)((i/12)-5); - } + note=i; return true; } } diff --git a/src/gui/gui.h b/src/gui/gui.h index 3041f310f..86acdda56 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -3142,9 +3142,9 @@ class FurnaceGUI { void showWarning(String what, FurnaceGUIWarnings type); void showError(String what); String getLastError(); - const char* noteNameNormal(short note, short octave); - const char* noteName(short note, short octave); - bool decodeNote(const char* what, short& note, short& octave); + const char* noteNameNormal(short note); + const char* noteName(short note); + bool decodeNote(const char* what, short& note); void bindEngine(DivEngine* eng); void enableSafeMode(); void updateScroll(int amount);