From d4ecf4045b4b72201b00b45d7f9e283f35564a18 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 14 Oct 2025 05:07:35 -0500 Subject: [PATCH] pattern data refactor, part 1 this first stage changes the way notes are encoded instead of note/octave, it is just note --- src/engine/engine.cpp | 57 +++++++++ src/engine/engine.h | 6 +- src/engine/fileOps/dmf.cpp | 72 +++++------ src/engine/fileOps/fc.cpp | 73 +++++------ src/engine/fileOps/ftm.cpp | 139 ++++++++++----------- src/engine/fileOps/fur.cpp | 247 ++++++++++++++++--------------------- src/engine/fileOps/it.cpp | 208 +++++++++++++++---------------- src/engine/fileOps/mod.cpp | 32 ++--- src/engine/fileOps/s3m.cpp | 68 +++++----- src/engine/pattern.cpp | 10 +- 10 files changed, 447 insertions(+), 465 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 3dd9d85c1..66de17439 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -2293,6 +2293,63 @@ int DivEngine::getEffectiveSampleRate(int rate) { return rate; } +short DivEngine::splitNoteToNote(short note, short octave) { + if (note==100) { + return DIV_NOTE_OFF; + } else if (note==101) { + return DIV_NOTE_REL; + } else if (note==102) { + return DIV_MACRO_REL; + } else if (note==0 && octave!=0) { + // "BUG" note! + return DIV_NOTE_NULL_PAT; + } else if (note==0 && octave==0) { + return -1; + } else { + int seek=(note+(signed char)octave*12)+60; + if (seek<0 || seek>=180) { + return DIV_NOTE_NULL_PAT; + } else { + return seek; + } + } + + return -1; +} + +void DivEngine::noteToSplitNote(short note, short& outNote, short& outOctave) { + switch (note) { + case DIV_NOTE_OFF: + outNote=100; + outOctave=0; + break; + case DIV_NOTE_REL: + outNote=101; + outOctave=0; + break; + case DIV_MACRO_REL: + outNote=102; + outOctave=0; + break; + case DIV_NOTE_NULL_PAT: + // "BUG" note! + outNote=0; + outOctave=1; + break; + case -1: + outNote=0; + outOctave=0; + default: + outNote=note%12; + outOctave=(unsigned char)(note-60)/12; + if (outNote==0) { + outNote=12; + outOctave--; + } + break; + } +} + void DivEngine::previewSample(int sample, int note, int pStart, int pEnd) { BUSY_BEGIN; previewSampleNoLock(sample,note,pStart,pEnd); diff --git a/src/engine/engine.h b/src/engine/engine.h index 231acba77..674fffffb 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -721,7 +721,7 @@ class DivEngine { SafeWriter* saveDMF(unsigned char version); // save as .fur. // if notPrimary is true then the song will not be altered - SafeWriter* saveFur(bool notPrimary=false, bool newPatternFormat=true); + SafeWriter* saveFur(bool notPrimary=false); // return a ROM exporter. DivROMExport* buildROM(DivROMExportOptions sys); // dump to VGM. @@ -927,6 +927,10 @@ class DivEngine { // get effective sample rate int getEffectiveSampleRate(int rate); + // convert between old and new note/octave format + short splitNoteToNote(short note, short octave); + void noteToSplitNote(short note, short& outNote, short& outOctave); + // is FM system bool isFMSystem(DivSystem sys); diff --git a/src/engine/fileOps/dmf.cpp b/src/engine/fileOps/dmf.cpp index 0c10aafec..2b43ce275 100644 --- a/src/engine/fileOps/dmf.cpp +++ b/src/engine/fileOps/dmf.cpp @@ -811,25 +811,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { octave--; } - if (note==100) { - pat->newData[k][DIV_PAT_NOTE]=DIV_NOTE_OFF; - } else if (note==101) { - pat->newData[k][DIV_PAT_NOTE]=DIV_NOTE_REL; - } else if (note==102) { - pat->newData[k][DIV_PAT_NOTE]=DIV_MACRO_REL; - } else if (note==0 && octave!=0) { - // "BUG" note! - pat->newData[k][DIV_PAT_NOTE]=DIV_NOTE_NULL_PAT; - } else if (note==0 && octave==0) { - pat->newData[k][DIV_PAT_NOTE]=-1; - } else { - int seek=(note+(signed char)octave*12)+60; - if (seek<0 || seek>=180) { - pat->newData[k][DIV_PAT_NOTE]=DIV_NOTE_NULL_PAT; - } else { - pat->newData[k][DIV_PAT_NOTE]=seek; - } - } + pat->newData[k][DIV_PAT_NOTE]=splitNoteToNote(note,octave); // volume pat->newData[k][DIV_PAT_VOL]=reader.readS(); @@ -844,7 +826,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { if (ds.version<0x12) { if (ds.system[0]==DIV_SYSTEM_GB && i==2 && pat->newData[k][DIV_PAT_VOL]>0) { // volume range of GB wave channel was 0-3 rather than 0-F - pat->newData[k][DIV_PAT_VOL]=(pat->data[k][DIV_PAT_VOL]&3)*5; + pat->newData[k][DIV_PAT_VOL]=(pat->newData[k][DIV_PAT_VOL]&3)*5; } } for (int l=0; ldata[0][2]=historicColIns[i]; + if (i<16) pat->newData[0][DIV_PAT_INS]=historicColIns[i]; for (int k=0; kpatLen; k++) { - // note - pat->data[k][0]=reader.readC(); - // octave - pat->data[k][1]=reader.readC(); - if (pat->data[k][0]!=0) { + short note=reader.readC(); + short octave=reader.readC(); + + if (note!=0) { // YMU759 is stored 2 octaves lower - pat->data[k][1]+=2; + octave+=2; } - if (pat->data[k][0]==0 && pat->data[k][1]!=0) { - logD("what? %d:%d:%d note %d octave %d",i,j,k,pat->data[k][0],pat->data[k][1]); - pat->data[k][0]=12; - pat->data[k][1]--; + if (note==0 && octave!=0) { + logD("what? %d:%d:%d note %d octave %d",i,j,k,note,octave); + note=12; + octave--; } + + pat->newData[k][DIV_PAT_NOTE]=splitNoteToNote(note,octave); + // volume and effect unsigned char vol=reader.readC(); unsigned char fx=reader.readC(); unsigned char fxVal=reader.readC(); - pat->data[k][3]=(vol==0x80 || vol==0xff)?-1:vol; + pat->newData[k][DIV_PAT_VOL]=(vol==0x80 || vol==0xff)?-1:vol; // effect - pat->data[k][4]=(fx==0x80 || fx==0xff)?-1:fx; - pat->data[k][5]=(fxVal==0x80 || fx==0xff)?-1:fxVal; + pat->newData[k][DIV_PAT_FX(0)]=(fx==0x80 || fx==0xff)?-1:fx; + pat->newData[k][DIV_PAT_FXVAL(0)]=(fxVal==0x80 || fx==0xff)?-1:fxVal; // instrument if (ds.version>0x05) { - pat->data[k][2]=reader.readC(); - if (pat->data[k][2]==0x80 || pat->data[k][2]==0xff) pat->data[k][2]=-1; + pat->newData[k][DIV_PAT_INS]=reader.readC(); + if (pat->newData[k][DIV_PAT_INS]==0x80 || pat->newData[k][DIV_PAT_INS]==0xff) pat->newData[k][DIV_PAT_INS]=-1; } } } @@ -1650,12 +1634,13 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) { bool relWarning=false; for (int i=0; iwriteC(curPat[i].effectCols); for (int j=0; jordersLen; j++) { DivPattern* pat=curPat[i].getPattern(curOrders->ord[i][j],false); for (int k=0; kpatLen; k++) { - if ((pat->data[k][0]==101 || pat->data[k][0]==102) && pat->data[k][1]==0) { + if (pat->newData[k][DIV_PAT_NOTE]==DIV_NOTE_REL || pat->newData[k][DIV_PAT_NOTE]==DIV_MACRO_REL) { w->writeS(100); w->writeS(0); if (!relWarning) { @@ -1663,18 +1648,19 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) { addWarning("note/macro release will be converted to note off!"); } } else { - w->writeS(pat->data[k][0]); // note - w->writeS(pat->data[k][1]); // octave + noteToSplitNote(pat->newData[k][DIV_PAT_NOTE],note,octave); + w->writeS(note); // note + w->writeS(octave); // octave } - w->writeS(pat->data[k][3]); // volume + w->writeS(pat->newData[k][DIV_PAT_VOL]); // volume #ifdef TA_BIG_ENDIAN for (int l=0; lwriteS(pat->data[k][4+l]); + w->writeS(pat->newData[k][DIV_PAT_FX(0)+l]); } #else - w->write(&pat->data[k][4],2*curPat[i].effectCols*2); // effects + w->write(&pat->newData[k][DIV_PAT_FX(0)],2*curPat[i].effectCols*2); // effects #endif - w->writeS(pat->data[k][2]); // instrument + w->writeS(pat->newData[k][DIV_PAT_INS]); // instrument } } } diff --git a/src/engine/fileOps/fc.cpp b/src/engine/fileOps/fc.cpp index da57fad69..f138adfd0 100644 --- a/src/engine/fileOps/fc.cpp +++ b/src/engine/fileOps/fc.cpp @@ -418,8 +418,8 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { ds.subsong[0]->orders.ord[j][i]=i; DivPattern* p=ds.subsong[0]->pat[j].getPattern(i,true); if (j==3 && seq[i].speed) { - p->data[0][6]=0x0f; - p->data[0][7]=seq[i].speed; + p->newData[0][DIV_PAT_FX(1)]=0x0f; + p->newData[0][DIV_PAT_FXVAL(1)]=seq[i].speed; } bool ignoreNext=false; @@ -428,80 +428,65 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { FCPattern& fp=pat[seq[i].pat[j]]; if (fp.note[k]>0 && fp.note[k]<0x49) { lastNote[j]=fp.note[k]; - short note=(fp.note[k]+seq[i].transpose[j])%12; - short octave=2+((fp.note[k]+seq[i].transpose[j])/12); - if (fp.note[k]>=0x3d) octave-=6; - if (note==0) { - note=12; - octave--; - } - octave&=0xff; - p->data[k][0]=note; - p->data[k][1]=octave; + p->newData[k][DIV_PAT_NOTE]=fp.note[k]+seq[i].transpose[j]+60; + // wrap-around if the note is too high + if (fp.note[k]>=0x3d) p->newData[k][DIV_PAT_NOTE]-=6*12; if (isSliding[j]) { isSliding[j]=false; - p->data[k][4]=2; - p->data[k][5]=0; + p->newData[k][DIV_PAT_FX(0)]=2; + p->newData[k][DIV_PAT_FXVAL(0)]=0; } } else if (fp.note[k]==0x49) { if (k>0) { - p->data[k-1][4]=0x0d; - p->data[k-1][5]=0; + p->newData[k-1][DIV_PAT_FX(0)]=0x0d; + p->newData[k-1][DIV_PAT_FXVAL(0)]=0; } } else if (k==0 && lastTranspose[j]!=seq[i].transpose[j]) { - p->data[0][2]=lastIns[j]; - p->data[0][4]=0x03; - p->data[0][5]=0xff; + p->newData[0][DIV_PAT_INS]=lastIns[j]; + p->newData[0][DIV_PAT_FX(0)]=0x03; + p->newData[0][DIV_PAT_FXVAL(0)]=0xff; lastTranspose[j]=seq[i].transpose[j]; - short note=(lastNote[j]+seq[i].transpose[j])%12; - short octave=2+((lastNote[j]+seq[i].transpose[j])/12); - if (lastNote[j]>=0x3d) octave-=6; - if (note==0) { - note=12; - octave--; - } - octave&=0xff; - p->data[k][0]=note; - p->data[k][1]=octave; + p->newData[k][DIV_PAT_NOTE]=lastNote[j]+seq[i].transpose[j]+60; + // wrap-around if the note is too high + if (lastNote[j]>=0x3d) p->newData[k][DIV_PAT_NOTE]-=6*12; } if (fp.val[k]) { if (ignoreNext) { ignoreNext=false; } else { if (fp.val[k]==0xf0) { - p->data[k][0]=100; - p->data[k][1]=0; - p->data[k][2]=-1; + p->newData[k][DIV_PAT_NOTE]=DIV_NOTE_OFF; + p->newData[k][DIV_PAT_INS]=-1; } else if (fp.val[k]&0xe0) { if (fp.val[k]&0x40) { - p->data[k][4]=2; - p->data[k][5]=0; + p->newData[k][DIV_PAT_FX(0)]=2; + p->newData[k][DIV_PAT_FXVAL(0)]=0; isSliding[j]=false; } else if (fp.val[k]&0x80) { isSliding[j]=true; if (k<31) { if (fp.val[k+1]&0x20) { - p->data[k][4]=2; - p->data[k][5]=fp.val[k+1]&0x1f; + p->newData[k][DIV_PAT_FX(0)]=2; + p->newData[k][DIV_PAT_FXVAL(0)]=fp.val[k+1]&0x1f; } else { - p->data[k][4]=1; - p->data[k][5]=fp.val[k+1]&0x1f; + p->newData[k][DIV_PAT_FX(0)]=1; + p->newData[k][DIV_PAT_FXVAL(0)]=fp.val[k+1]&0x1f; } ignoreNext=true; } else { - p->data[k][4]=2; - p->data[k][5]=0; + p->newData[k][DIV_PAT_FX(0)]=2; + p->newData[k][DIV_PAT_FXVAL(0)]=0; } } } else { - p->data[k][2]=(fp.val[k]+seq[i].offsetIns[j])&0x3f; - lastIns[j]=p->data[k][2]; + p->newData[k][DIV_PAT_INS]=(fp.val[k]+seq[i].offsetIns[j])&0x3f; + lastIns[j]=p->newData[k][DIV_PAT_INS]; } } } else if (fp.note[k]>0 && fp.note[k]<0x49) { - p->data[k][2]=seq[i].offsetIns[j]; - lastIns[j]=p->data[k][2]; + p->newData[k][DIV_PAT_INS]=seq[i].offsetIns[j]; + lastIns[j]=p->newData[k][DIV_PAT_INS]; } } } diff --git a/src/engine/fileOps/ftm.cpp b/src/engine/fileOps/ftm.cpp index b471959d6..6a7643ae4 100644 --- a/src/engine/fileOps/ftm.cpp +++ b/src/engine/fileOps/ftm.cpp @@ -270,7 +270,7 @@ int convert_vrc6_duties[4] = {1, 3, 7, 3}; int findEmptyFx(short* data) { for (int i=0; i<7; i++) { - if (data[4+i*2]==-1) return i; + if (data[DIV_PAT_FX(i)]==-1) return i; } return -1; } @@ -1752,17 +1752,13 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (map_channels[ch] != 0xff) { if (nextNote == 0x0d) { - pat->data[row][0] = 101; + pat->newData[row][DIV_PAT_NOTE] = DIV_NOTE_REL; } else if (nextNote == 0x0e) { - pat->data[row][0] = 100; - } else if (nextNote == 0x01) { - pat->data[row][0] = 12; - pat->data[row][1] = nextOctave - 1; + pat->newData[row][DIV_PAT_NOTE] = DIV_NOTE_OFF; } else if (nextNote == 0) { - pat->data[row][0] = 0; + pat->newData[row][DIV_PAT_NOTE] = -1; } else if (nextNote < 0x0d) { - pat->data[row][0] = nextNote - 1; - pat->data[row][1] = nextOctave; + pat->newData[row][DIV_PAT_NOTE] = nextOctave*12 + (nextNote - 1); } } @@ -1770,27 +1766,27 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si // TODO: you sure about 0xff? if (map_channels[ch] != 0xff) { if (nextIns < 0x40 && nextNote != 0x0d && nextNote != 0x0e) { - pat->data[row][2] = nextIns; + pat->newData[row][DIV_PAT_INS] = nextIns; } else { - pat->data[row][2] = -1; + pat->newData[row][DIV_PAT_INS] = -1; } } unsigned char nextVol = reader.readC(); if (map_channels[ch] != 0xff) { if (nextVol < 0x10) { - pat->data[row][3] = nextVol; + pat->newData[row][DIV_PAT_VOL] = nextVol; if (map_channels[ch] == vrc6_saw_chan) // scale volume { // TODO: shouldn't it be 32? - pat->data[row][3] = (pat->data[row][3] * 42) / 15; + pat->newData[row][DIV_PAT_VOL] = (pat->newData[row][DIV_PAT_VOL] * 42) / 15; } if (map_channels[ch] == fds_chan) { - pat->data[row][3] = (pat->data[row][3] * 31) / 15; + pat->newData[row][DIV_PAT_VOL] = (pat->newData[row][DIV_PAT_VOL] * 31) / 15; } } else { - pat->data[row][3] = -1; + pat->newData[row][DIV_PAT_VOL] = -1; } } @@ -1829,15 +1825,15 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (nextEffect == FT_EF_SPEED && nextEffectVal < 20) nextEffectVal++; - if (pat->data[row][3] == 0) - pat->data[row][3] = 0xf; + if (pat->newData[row][DIV_PAT_VOL] == 0) + pat->newData[row][DIV_PAT_VOL] = 0xf; else { - pat->data[row][3]--; - pat->data[row][3] &= 0x0F; + pat->newData[row][DIV_PAT_VOL]--; + pat->newData[row][DIV_PAT_VOL] &= 0x0F; } - if (pat->data[row][0] == 0) - pat->data[row][2] = -1; + if (pat->newData[row][DIV_PAT_NOTE] == -1) + pat->newData[row][DIV_PAT_INS] = -1; } if (blockVersion == 3) { @@ -1902,43 +1898,43 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (map_channels[ch] != 0xff) { if (nextEffect == 0 && nextEffectVal == 0) { - pat->data[row][4 + (j * 2)] = -1; - pat->data[row][5 + (j * 2)] = -1; + pat->newData[row][DIV_PAT_FX(j)] = -1; + pat->newData[row][DIV_PAT_FXVAL(j)] = -1; } else { if ((eft && nextEffectdata[row][4 + (j * 2)] = eftEffectMap[nextEffect]; - pat->data[row][5 + (j * 2)] = eftEffectMap[nextEffect] == -1 ? -1 : nextEffectVal; + pat->newData[row][DIV_PAT_FX(j)] = eftEffectMap[nextEffect]; + pat->newData[row][DIV_PAT_FXVAL(j)] = eftEffectMap[nextEffect] == -1 ? -1 : nextEffectVal; - if (pat->data[row][4 + (j * 2)] == 0x100) { - pat->data[row][3] += pat->data[row][5 + (j * 2)] ? 0x10 : 0; // extra volume bit for AY8930 - pat->data[row][4 + (j * 2)] = -1; - pat->data[row][5 + (j * 2)] = -1; + if (pat->newData[row][DIV_PAT_FX(j)] == 0x100) { + pat->newData[row][DIV_PAT_VOL] += pat->newData[row][DIV_PAT_FXVAL(j)] ? 0x10 : 0; // extra volume bit for AY8930 + pat->newData[row][DIV_PAT_FX(j)] = -1; + pat->newData[row][DIV_PAT_FXVAL(j)] = -1; } if (eftEffectMap[nextEffect] == 0x0f && nextEffectVal > 0x1f) { - pat->data[row][4 + (j * 2)] = 0xfd; // BPM speed change! + pat->newData[row][DIV_PAT_FX(j)] = 0xfd; // BPM speed change! } if ((eftEffectMap[nextEffect] == 0xe1 || eftEffectMap[nextEffect] == 0xe2) && (nextEffectVal & 0xf0) == 0) { - pat->data[row][5 + (j * 2)] |= 0x10; // in FamiTracker if e1/e2 commands speed is 0 the portamento still has some speed! + pat->newData[row][DIV_PAT_FXVAL(j)] |= 0x10; // in FamiTracker if e1/e2 commands speed is 0 the portamento still has some speed! } } else { - pat->data[row][4 + (j * 2)] = ftEffectMap[nextEffect]; - pat->data[row][5 + (j * 2)] = ftEffectMap[nextEffect] == -1 ? -1 : nextEffectVal; + pat->newData[row][DIV_PAT_FX(j)] = ftEffectMap[nextEffect]; + pat->newData[row][DIV_PAT_FXVAL(j)] = ftEffectMap[nextEffect] == -1 ? -1 : nextEffectVal; if (ftEffectMap[nextEffect] == 0x0f && nextEffectVal > 0x1f) { - pat->data[row][4 + (j * 2)] = 0xfd; // BPM speed change! + pat->newData[row][DIV_PAT_FX(j)] = 0xfd; // BPM speed change! } if ((ftEffectMap[nextEffect] == 0xe1 || ftEffectMap[nextEffect] == 0xe2) && (nextEffectVal & 0xf0) == 0) { - pat->data[row][5 + (j * 2)] |= 0x10; // in FamiTracker if e1/e2 commands speed is 0 the portamento still has some speed! + pat->newData[row][DIV_PAT_FXVAL(j)] |= 0x10; // in FamiTracker if e1/e2 commands speed is 0 the portamento still has some speed! } } for (int v = 0; v < 8; v++) { if (map_channels[ch] == n163_chans[v]) { - if (pat->data[row][4 + (j * 2)] == 0x12) { - pat->data[row][4 + (j * 2)] = 0x110; // N163 wave change (we'll map this later) + if (pat->newData[row][DIV_PAT_FX(j)] == 0x12) { + pat->newData[row][DIV_PAT_FX(j)] = 0x110; // N163 wave change (we'll map this later) } } } @@ -1947,23 +1943,24 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si { if (map_channels[ch] == vrc7_chans[vrr]) { - if (pat->data[row][4 + (j * 2)] == 0x12) + if (pat->newData[row][DIV_PAT_FX(j)] == 0x12) { - pat->data[row][4 + (j * 2)] = 0x10; // set VRC7 patch + pat->newData[row][DIV_PAT_FX(j)] = 0x10; // set VRC7 patch } } } for (int v = 0; v < 3; v++) { if (map_channels[ch] == s5b_chans[v] || map_channels[ch] == ay8930_chans[v]) { - if (pat->data[row][4 + (j * 2)] == 0x22 && (pat->data[row][5 + (j * 2)] & 0xf0) != 0) { - pat->data[row][4 + (7 * 2)] = -666; //marker + if (pat->newData[row][DIV_PAT_FX(j)] == 0x22 && (pat->newData[row][DIV_PAT_FXVAL(j)] & 0xf0) != 0) { + // TODO: in the second stage of pattern refactor this will have to change. + pat->newData[row][DIV_PAT_FX(7)] = -666; //marker } } } } else { - pat->data[row][4 + (j * 2)] = -1; - pat->data[row][5 + (j * 2)] = -1; + pat->newData[row][DIV_PAT_FX(j)] = -1; + pat->newData[row][DIV_PAT_FXVAL(j)] = -1; } } } @@ -2438,8 +2435,8 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (ds.subsong[j]->pat[ii].data[k] == NULL) continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] > index) { - ds.subsong[j]->pat[ii].data[k]->data[l][2]--; + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] > index) { + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS]--; } } } @@ -2456,12 +2453,12 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (ds.subsong[j]->pat[ii].data[k] == NULL) continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { - if (ds.subsong[j]->pat[ii].data[k]->data[l][4 + 7*2] == -666) { + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FX(7)] == -666) { bool converted = false; // for()? if()? THESE ARE NOT FUNCTIONS! for (int hh = 0; hh < 7; hh++) { // oh and now you 1TBS up. oh man... - if (ds.subsong[j]->pat[ii].data[k]->data[l][4 + hh*2] == 0x22 && !converted) { - int slot = findEmptyFx(ds.subsong[j]->pat[ii].data[k]->data[l]); + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FX(hh)] == 0x22 && !converted) { + int slot = findEmptyFx(ds.subsong[j]->pat[ii].data[k]->newData[l]); if (slot != -1) { // space your comments damn it! // Hxy - Envelope automatic pitch @@ -2469,7 +2466,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si // Sets envelope period to the note period shifted by x and envelope type y. // Approximate envelope frequency is note frequency * (2^|x - 8|) / 32. - int ftAutoEnv = (ds.subsong[j]->pat[ii].data[k]->data[l][5 + hh*2] >> 4) & 15; + int ftAutoEnv = (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FXVAL(hh)] >> 4) & 15; int autoEnvDen = 16; // ???? with 32 it's an octave lower... int autoEnvNum = (1 << (abs(ftAutoEnv - 8))); @@ -2479,18 +2476,18 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si } if (autoEnvDen < 16 && autoEnvNum < 16) { - ds.subsong[j]->pat[ii].data[k]->data[l][4 + slot*2] = 0x29; - ds.subsong[j]->pat[ii].data[k]->data[l][5 + slot*2] = (autoEnvNum << 4) | autoEnvDen; + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FX(slot)] = 0x29; + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FXVAL(slot)] = (autoEnvNum << 4) | autoEnvDen; } - ds.subsong[j]->pat[ii].data[k]->data[l][5 + hh*2] = (ds.subsong[j]->pat[ii].data[k]->data[l][5 + hh*2] & 0xf) << 4; + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FXVAL(hh)] = (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FXVAL(hh)] & 0xf) << 4; converted = true; } } } - ds.subsong[j]->pat[ii].data[k]->data[l][4 + (7 * 2)] = -1; //delete marker + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_FX(7)] = -1; //delete marker } } } @@ -2506,10 +2503,10 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si for (int p = 0; p < s->ordersLen; p++) { for (int r = 0; r < s->patLen; r++) { DivPattern* pat = s->pat[c].getPattern(s->orders.ord[c][p], true); - short* s_row_data = pat->data[r]; + short* s_row_data = pat->newData[r]; for (int eff = 0; eff < DIV_MAX_EFFECTS - 1; eff++) { - if (s_row_data[4 + 2 * eff] != -1 && eff + 1 > num_fx) { + if (s_row_data[DIV_PAT_FX(eff)] != -1 && eff + 1 > num_fx) { num_fx = eff + 1; } } @@ -2556,7 +2553,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { // 1TBS > GNU - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == i) { // instrument + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == i) { // instrument DivInstrument* ins = ds.ins[i]; bool go_to_end = false; @@ -2606,7 +2603,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (ds.subsong[j]->pat[ii].data[k] == NULL) continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == i) // instrument + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == i) // instrument { DivInstrument* ins = ds.ins[i]; bool go_to_end = false; @@ -2658,7 +2655,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (ds.subsong[j]->pat[ii].data[k] == NULL) continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == i) // instrument + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == i) // instrument { DivInstrument* ins = ds.ins[i]; bool go_to_end = false; @@ -2729,17 +2726,17 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si if (ds.subsong[j]->pat[ii].data[k] == NULL) continue; for (int l = 0; l < ds.subsong[j]->patLen; l++) { - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == ins_vrc6_conv[i][0] && (ii == vrc6_chans[0] || ii == vrc6_chans[1])) // change ins index + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == ins_vrc6_conv[i][0] && (ii == vrc6_chans[0] || ii == vrc6_chans[1])) // change ins index { - ds.subsong[j]->pat[ii].data[k]->data[l][2] = ins_vrc6_conv[i][1]; + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] = ins_vrc6_conv[i][1]; } - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == ins_vrc6_saw_conv[i][0] && ii == vrc6_saw_chan) { - ds.subsong[j]->pat[ii].data[k]->data[l][2] = ins_vrc6_saw_conv[i][1]; + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == ins_vrc6_saw_conv[i][0] && ii == vrc6_saw_chan) { + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] = ins_vrc6_saw_conv[i][1]; } - if (ds.subsong[j]->pat[ii].data[k]->data[l][2] == ins_nes_conv[i][0] && (ii == mmc5_chans[0] || ii == mmc5_chans[1] || ii < 5)) { - ds.subsong[j]->pat[ii].data[k]->data[l][2] = ins_nes_conv[i][1]; + if (ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] == ins_nes_conv[i][0] && (ii == mmc5_chans[0] || ii == mmc5_chans[1] || ii < 5)) { + ds.subsong[j]->pat[ii].data[k]->newData[l][DIV_PAT_INS] = ins_nes_conv[i][1]; } } } @@ -2785,19 +2782,19 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si DivPattern* p=i->pat[j].getPattern(i->orders.ord[j][k],true); for (int l=0; lpatLen; l++) { // check for instrument change - if (p->data[l][2]!=-1) { - curWaveOff=n163WaveOff[p->data[l][2]&127]; + if (p->newData[l][DIV_PAT_INS]!=-1) { + curWaveOff=n163WaveOff[p->newData[l][DIV_PAT_INS]&127]; } // check effect columns for 0x110 (dummy wave change) for (int m=0; mpat[j].effectCols; m++) { - if (p->data[l][4+(m<<1)]==0x110) { + if (p->newData[l][DIV_PAT_FX(m)]==0x110) { // map wave - p->data[l][4+(m<<1)]=0x10; - if (p->data[l][5+(m<<1)]==-1) { - p->data[l][5+(m<<1)]=curWaveOff&0xff; + p->newData[l][DIV_PAT_FX(m)]=0x10; + if (p->newData[l][DIV_PAT_FXVAL(m)]==-1) { + p->newData[l][DIV_PAT_FXVAL(m)]=curWaveOff&0xff; } else { - p->data[l][5+(m<<1)]=(p->data[l][5+(m<<1)]+curWaveOff)&0xff; + p->newData[l][DIV_PAT_FXVAL(m)]=(p->newData[l][DIV_PAT_FXVAL(m)]+curWaveOff)&0xff; } } } diff --git a/src/engine/fileOps/fur.cpp b/src/engine/fileOps/fur.cpp index e67360108..f7ff5b3be 100644 --- a/src/engine/fileOps/fur.cpp +++ b/src/engine/fileOps/fur.cpp @@ -1778,32 +1778,28 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { if (mask&1) { // note unsigned char note=reader.readC(); + // TODO: PAT2 format with new off/===/rel values! if (note==180) { - pat->data[j][0]=100; - pat->data[j][1]=0; + pat->newData[j][0]=DIV_NOTE_OFF; } else if (note==181) { - pat->data[j][0]=101; - pat->data[j][1]=0; + pat->newData[j][0]=DIV_NOTE_REL; } else if (note==182) { - pat->data[j][0]=102; - pat->data[j][1]=0; + pat->newData[j][0]=DIV_MACRO_REL; } else if (note<180) { - pat->data[j][0]=newFormatNotes[note]; - pat->data[j][1]=newFormatOctaves[note]; + pat->newData[j][DIV_PAT_NOTE]=note; } else { - pat->data[j][0]=0; - pat->data[j][1]=0; + pat->newData[j][0]=-1; } } if (mask&2) { // instrument - pat->data[j][2]=(unsigned char)reader.readC(); + pat->newData[j][DIV_PAT_INS]=(unsigned char)reader.readC(); } if (mask&4) { // volume - pat->data[j][3]=(unsigned char)reader.readC(); + pat->newData[j][DIV_PAT_VOL]=(unsigned char)reader.readC(); } for (unsigned char k=0; k<16; k++) { if (effectMask&(1<data[j][4+k]=(unsigned char)reader.readC(); + pat->newData[j][DIV_PAT_FX(0)+k]=(unsigned char)reader.readC(); } } } @@ -1844,18 +1840,20 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { DivPattern* pat=ds.subsong[subs]->pat[chan].getPattern(index,true); for (int j=0; jpatLen; j++) { - pat->data[j][0]=reader.readS(); - pat->data[j][1]=reader.readS(); - pat->data[j][2]=reader.readS(); - pat->data[j][3]=reader.readS(); - for (int k=0; kpat[chan].effectCols; k++) { - pat->data[j][4+(k<<1)]=reader.readS(); - pat->data[j][5+(k<<1)]=reader.readS(); + short note=reader.readS(); + short octave=reader.readS(); + if (note==0 && octave!=0) { + logD("what? %d:%d:%d note %d octave %d",chan,i,j,note,octave); + note=12; + octave--; } - if (pat->data[j][0]==0 && pat->data[j][1]!=0) { - logD("what? %d:%d:%d note %d octave %d",chan,i,j,pat->data[j][0],pat->data[j][1]); - pat->data[j][0]=12; - pat->data[j][1]--; + pat->newData[j][DIV_PAT_NOTE]=splitNoteToNote(note,octave); + + pat->newData[j][DIV_PAT_INS]=reader.readS(); + pat->newData[j][DIV_PAT_VOL]=reader.readS(); + for (int k=0; kpat[chan].effectCols; k++) { + pat->newData[j][DIV_PAT_FX(k)]=reader.readS(); + pat->newData[j][DIV_PAT_FXVAL(k)]=reader.readS(); } } @@ -2171,7 +2169,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len, int variantID) { return true; } -SafeWriter* DivEngine::saveFur(bool notPrimary, bool newPatternFormat) { +SafeWriter* DivEngine::saveFur(bool notPrimary) { saveLock.lock(); std::vector subSongPtr; std::vector sysFlagsPtr; @@ -2622,133 +2620,100 @@ SafeWriter* DivEngine::saveFur(bool notPrimary, bool newPatternFormat) { DivPattern* pat=song.subsong[i.subsong]->pat[i.chan].getPattern(i.pat,false); patPtr.push_back(w->tell()); - if (newPatternFormat) { - w->write("PATN",4); - blockStartSeek=w->tell(); - w->writeI(0); + w->write("PATN",4); + blockStartSeek=w->tell(); + w->writeI(0); - w->writeC(i.subsong); - w->writeC(i.chan); - w->writeS(i.pat); - w->writeString(pat->name,false); + w->writeC(i.subsong); + w->writeC(i.chan); + w->writeS(i.pat); + w->writeString(pat->name,false); - unsigned char emptyRows=0; + unsigned char emptyRows=0; - for (int j=0; jpatLen; j++) { - unsigned char mask=0; - unsigned char finalNote=255; - unsigned short effectMask=0; + for (int j=0; jpatLen; j++) { + unsigned char mask=0; + unsigned char finalNote=255; + unsigned short effectMask=0; - if (pat->data[j][0]==100) { - finalNote=180; - } else if (pat->data[j][0]==101) { // note release - finalNote=181; - } else if (pat->data[j][0]==102) { // macro release - finalNote=182; - } else if (pat->data[j][1]==0 && pat->data[j][0]==0) { - finalNote=255; - } else { - int seek=(pat->data[j][0]+(signed char)pat->data[j][1]*12)+60; - if (seek<0 || seek>=180) { - finalNote=255; - } else { - finalNote=seek; - } - } - - if (finalNote!=255) mask|=1; // note - if (pat->data[j][2]!=-1) mask|=2; // instrument - if (pat->data[j][3]!=-1) mask|=4; // volume - for (int k=0; kpat[i.chan].effectCols*2; k+=2) { - if (k==0) { - if (pat->data[j][4+k]!=-1) mask|=8; - if (pat->data[j][5+k]!=-1) mask|=16; - } else if (k<8) { - if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=32; - } else { - if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=64; - } - - if (pat->data[j][4+k]!=-1) effectMask|=(1<data[j][5+k]!=-1) effectMask|=(2<127) { - w->writeC(128|(emptyRows-2)); - emptyRows=0; - } - } else { - if (emptyRows>1) { - w->writeC(128|(emptyRows-2)); - emptyRows=0; - } else if (emptyRows) { - w->writeC(0); - emptyRows=0; - } - - w->writeC(mask); - - if (mask&32) w->writeC(effectMask&0xff); - if (mask&64) w->writeC((effectMask>>8)&0xff); - - if (mask&1) w->writeC(finalNote); - if (mask&2) w->writeC(pat->data[j][2]); - if (mask&4) w->writeC(pat->data[j][3]); - if (mask&8) w->writeC(pat->data[j][4]); - if (mask&16) w->writeC(pat->data[j][5]); - if (mask&32) { - if (effectMask&4) w->writeC(pat->data[j][6]); - if (effectMask&8) w->writeC(pat->data[j][7]); - if (effectMask&16) w->writeC(pat->data[j][8]); - if (effectMask&32) w->writeC(pat->data[j][9]); - if (effectMask&64) w->writeC(pat->data[j][10]); - if (effectMask&128) w->writeC(pat->data[j][11]); - } - if (mask&64) { - if (effectMask&256) w->writeC(pat->data[j][12]); - if (effectMask&512) w->writeC(pat->data[j][13]); - if (effectMask&1024) w->writeC(pat->data[j][14]); - if (effectMask&2048) w->writeC(pat->data[j][15]); - if (effectMask&4096) w->writeC(pat->data[j][16]); - if (effectMask&8192) w->writeC(pat->data[j][17]); - if (effectMask&16384) w->writeC(pat->data[j][18]); - if (effectMask&32768) w->writeC(pat->data[j][19]); - } - } + if (pat->newData[j][DIV_PAT_NOTE]==DIV_NOTE_OFF) { // note off + finalNote=180; + } else if (pat->newData[j][DIV_PAT_NOTE]==DIV_NOTE_REL) { // note release + finalNote=181; + } else if (pat->newData[j][DIV_PAT_NOTE]==DIV_MACRO_REL) { // macro release + finalNote=182; + } else if (pat->newData[j][DIV_PAT_NOTE]==-1) { // empty + finalNote=255; + } else { + finalNote=pat->newData[j][DIV_PAT_NOTE]; } - // stop - w->writeC(0xff); - } else { - w->write("PATR",4); - blockStartSeek=w->tell(); - w->writeI(0); - - w->writeS(i.chan); - w->writeS(i.pat); - w->writeS(i.subsong); - - w->writeS(0); // reserved - - for (int j=0; jpatLen; j++) { - w->writeS(pat->data[j][0]); // note - w->writeS(pat->data[j][1]); // octave - w->writeS(pat->data[j][2]); // instrument - w->writeS(pat->data[j][3]); // volume -#ifdef TA_BIG_ENDIAN - for (int k=0; kpat[i.chan].effectCols*2; k++) { - w->writeS(pat->data[j][4+k]); + if (finalNote!=255) mask|=1; // note + if (pat->newData[j][DIV_PAT_INS]!=-1) mask|=2; // instrument + if (pat->newData[j][DIV_PAT_VOL]!=-1) mask|=4; // volume + for (int k=0; kpat[i.chan].effectCols*2; k+=2) { + if (k==0) { + if (pat->newData[j][DIV_PAT_FX(0)+k]!=-1) mask|=8; + if (pat->newData[j][DIV_PAT_FXVAL(1)+k]!=-1) mask|=16; + } else if (k<8) { + if (pat->newData[j][DIV_PAT_FX(0)+k]!=-1 || pat->newData[j][DIV_PAT_FXVAL(1)+k]!=-1) mask|=32; + } else { + if (pat->newData[j][DIV_PAT_FX(0)+k]!=-1 || pat->newData[j][DIV_PAT_FXVAL(1)+k]!=-1) mask|=64; } -#else - w->write(&pat->data[j][4],2*song.subsong[i.subsong]->pat[i.chan].effectCols*2); // effects -#endif + + if (pat->newData[j][DIV_PAT_FX(0)+k]!=-1) effectMask|=(1<newData[j][DIV_PAT_FXVAL(1)+k]!=-1) effectMask|=(2<writeString(pat->name,false); + if (mask==0) { + emptyRows++; + if (emptyRows>127) { + w->writeC(128|(emptyRows-2)); + emptyRows=0; + } + } else { + if (emptyRows>1) { + w->writeC(128|(emptyRows-2)); + emptyRows=0; + } else if (emptyRows) { + w->writeC(0); + emptyRows=0; + } + + w->writeC(mask); + + if (mask&32) w->writeC(effectMask&0xff); + if (mask&64) w->writeC((effectMask>>8)&0xff); + + if (mask&1) w->writeC(finalNote); + if (mask&2) w->writeC(pat->newData[j][DIV_PAT_INS]); + if (mask&4) w->writeC(pat->newData[j][DIV_PAT_VOL]); + if (mask&8) w->writeC(pat->newData[j][DIV_PAT_FX(0)]); + if (mask&16) w->writeC(pat->newData[j][DIV_PAT_FXVAL(0)]); + if (mask&32) { + if (effectMask&4) w->writeC(pat->newData[j][DIV_PAT_FX(1)]); + if (effectMask&8) w->writeC(pat->newData[j][DIV_PAT_FXVAL(1)]); + if (effectMask&16) w->writeC(pat->newData[j][DIV_PAT_FX(2)]); + if (effectMask&32) w->writeC(pat->newData[j][DIV_PAT_FXVAL(2)]); + if (effectMask&64) w->writeC(pat->newData[j][DIV_PAT_FX(3)]); + if (effectMask&128) w->writeC(pat->newData[j][DIV_PAT_FXVAL(3)]); + } + if (mask&64) { + if (effectMask&256) w->writeC(pat->newData[j][DIV_PAT_FX(4)]); + if (effectMask&512) w->writeC(pat->newData[j][DIV_PAT_FXVAL(4)]); + if (effectMask&1024) w->writeC(pat->newData[j][DIV_PAT_FX(5)]); + if (effectMask&2048) w->writeC(pat->newData[j][DIV_PAT_FXVAL(5)]); + if (effectMask&4096) w->writeC(pat->newData[j][DIV_PAT_FX(6)]); + if (effectMask&8192) w->writeC(pat->newData[j][DIV_PAT_FXVAL(6)]); + if (effectMask&16384) w->writeC(pat->newData[j][DIV_PAT_FX(7)]); + if (effectMask&32768) w->writeC(pat->newData[j][DIV_PAT_FXVAL(7)]); + } + } } + // stop + w->writeC(0xff); + blockEndSeek=w->tell(); w->seek(blockStartSeek,SEEK_SET); w->writeI(blockEndSeek-blockStartSeek-4); diff --git a/src/engine/fileOps/it.cpp b/src/engine/fileOps/it.cpp index e31d78180..78ec218a4 100644 --- a/src/engine/fileOps/it.cpp +++ b/src/engine/fileOps/it.cpp @@ -1139,82 +1139,82 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { for (int j=0; j<64; j++) { DivPattern* p=ds.subsong[0]->pat[j].getPattern(i,true); if (vibing[j]!=vibingOld[j] || vibStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x04; - p->data[readRow][effectCol[j]++]=vibing[j]?vibStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=vibing[j]?vibStatus[j]:0; doesVibrato[j]=true; } else if (doesVibrato[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x04; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (volSliding[j]!=volSlidingOld[j] || volSlideStatusChanged[j]) { if (volSlideStatus[j]>=0xf1 && volSliding[j]) { - p->data[readRow][effectCol[j]++]=0xf9; - p->data[readRow][effectCol[j]++]=volSlideStatus[j]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xf9; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSlideStatus[j]&15; volSliding[j]=false; } else if ((volSlideStatus[j]&15)==15 && volSlideStatus[j]>=0x10 && volSliding[j]) { - p->data[readRow][effectCol[j]++]=0xf8; - p->data[readRow][effectCol[j]++]=volSlideStatus[j]>>4; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xf8; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSlideStatus[j]>>4; volSliding[j]=false; } else { - p->data[readRow][effectCol[j]++]=0xfa; - p->data[readRow][effectCol[j]++]=volSliding[j]?volSlideStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xfa; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSliding[j]?volSlideStatus[j]:0; } doesVolSlide[j]=true; } else if (doesVolSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0xfa; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xfa; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (porting[j]!=portingOld[j] || portaStatusChanged[j]) { if (portaStatus[j]>=0xe0 && portaType[j]!=3 && porting[j]) { - p->data[readRow][effectCol[j]++]=portaType[j]|0xf0; - p->data[readRow][effectCol[j]++]=(portaStatus[j]&15)*((portaStatus[j]>=0xf0)?1:1); + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=portaType[j]|0xf0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=(portaStatus[j]&15)*((portaStatus[j]>=0xf0)?1:1); porting[j]=false; } else { - p->data[readRow][effectCol[j]++]=portaType[j]; - p->data[readRow][effectCol[j]++]=porting[j]?portaStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=portaType[j]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=porting[j]?portaStatus[j]:0; } doesPitchSlide[j]=true; } else if (doesPitchSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x01; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x01; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (arping[j]!=arpingOld[j] || arpStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x00; - p->data[readRow][effectCol[j]++]=arping[j]?arpStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=arping[j]?arpStatus[j]:0; doesArp[j]=true; } else if (doesArp[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x00; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (treming[j]!=tremingOld[j] || tremStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x07; - p->data[readRow][effectCol[j]++]=treming[j]?tremStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x07; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=treming[j]?tremStatus[j]:0; doesTremolo[j]=true; } else if (doesTremolo[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x07; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x07; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (panning[j]!=panningOld[j] || panStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x84; - p->data[readRow][effectCol[j]++]=panning[j]?panStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x84; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=panning[j]?panStatus[j]:0; doesPanbrello[j]=true; } else if (doesPanbrello[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x84; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x84; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (panSliding[j]!=panSlidingOld[j] || panSlideStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x83; - p->data[readRow][effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x83; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0; doesPanSlide[j]=true; } else if (doesPanSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x83; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x83; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if ((effectCol[j]>>1)-2>ds.subsong[0]->pat[j].effectCols) { @@ -1250,8 +1250,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { if (readRow>0) { // place end of pattern marker DivPattern* p=ds.subsong[0]->pat[0].getPattern(i,true); - p->data[readRow-1][effectCol[0]++]=0x0d; - p->data[readRow-1][effectCol[0]++]=0; + p->newData[readRow-1][DIV_PAT_FX(0)+effectCol[0]++]=0x0d; + p->newData[readRow-1][DIV_PAT_FX(0)+effectCol[0]++]=0; if ((effectCol[0]>>1)-2>ds.subsong[0]->pat[0].effectCols) { ds.subsong[0]->pat[0].effectCols=(effectCol[0]>>1)-1; @@ -1302,25 +1302,17 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { if (hasNote) { if (note[chan]==255) { // note release - p->data[readRow][0]=101; - p->data[readRow][1]=0; + p->newData[readRow][DIV_PAT_NOTE]=DIV_NOTE_REL; } else if (note[chan]==254) { // note off - p->data[readRow][0]=100; - p->data[readRow][1]=0; + p->newData[readRow][DIV_PAT_NOTE]=DIV_NOTE_OFF; } else if (note[chan]<120) { - p->data[readRow][0]=note[chan]%12; - p->data[readRow][1]=note[chan]/12; - if (p->data[readRow][0]==0) { - p->data[readRow][0]=12; - p->data[readRow][1]--; - } + p->newData[readRow][DIV_PAT_NOTE]=note[chan]+60; } else { // note fade, but Furnace does not support that - p->data[readRow][0]=102; - p->data[readRow][1]=0; + p->newData[readRow][DIV_PAT_NOTE]=DIV_MACRO_REL; } } if (hasIns) { - p->data[readRow][2]=ins[chan]-1; + p->newData[readRow][DIV_PAT_INS]=ins[chan]-1; if ((note[chan]<120 || ds.insLen==0) && ins[chan]>0) { unsigned char targetPan=0; if (ds.insLen==0) { @@ -1332,26 +1324,26 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { } } if (targetPan&128) { - p->data[readRow][effectCol[chan]++]=0x80; - p->data[readRow][effectCol[chan]++]=CLAMP((targetPan&127)<<2,0,255); + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x80; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=CLAMP((targetPan&127)<<2,0,255); } } if (hasNote && (note[chan]<120 || ds.insLen==0) && ins[chan]>0) { if (ds.insLen==0) { - p->data[readRow][3]=defVol[(ins[chan]-1)&255]; + p->newData[readRow][DIV_PAT_VOL]=defVol[(ins[chan]-1)&255]; } else { - p->data[readRow][3]=defVol[noteMap[(ins[chan]-1)&255][note[chan]]]; + p->newData[readRow][DIV_PAT_VOL]=defVol[noteMap[(ins[chan]-1)&255][note[chan]]]; } } } if (hasVol) { if (vol[chan]<=64) { - p->data[readRow][3]=vol[chan]; + p->newData[readRow][DIV_PAT_VOL]=vol[chan]; } else { // effects in volume column if (vol[chan]>=128 && vol[chan]<=192) { // panning - p->data[readRow][effectCol[chan]++]=0x80; - p->data[readRow][effectCol[chan]++]=CLAMP((vol[chan]-128)<<2,0,255); + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x80; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=CLAMP((vol[chan]-128)<<2,0,255); } else if (vol[chan]>=65 && vol[chan]<=74) { // fine vol up } else if (vol[chan]>=75 && vol[chan]<=84) { // fine vol down } else if (vol[chan]>=85 && vol[chan]<=94) { // vol slide up @@ -1398,16 +1390,16 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { if (hasEffect) { switch (effect[chan]+'A'-1) { case 'A': // speed - p->data[readRow][effectCol[chan]++]=0x0f; - p->data[readRow][effectCol[chan]++]=effectVal[chan]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0f; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]; break; case 'B': // go to order - p->data[readRow][effectCol[chan]++]=0x0b; - p->data[readRow][effectCol[chan]++]=orders[effectVal[chan]]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0b; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=orders[effectVal[chan]]; break; case 'C': // next order - p->data[readRow][effectCol[chan]++]=0x0d; - p->data[readRow][effectCol[chan]++]=effectVal[chan]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0d; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]; break; case 'D': // vol slide if (effectVal[chan]!=0) { @@ -1490,8 +1482,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { case 'N': // channel vol slide break; case 'O': // offset - p->data[readRow][effectCol[chan]++]=0x91; - p->data[readRow][effectCol[chan]++]=effectVal[chan]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x91; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]; break; case 'P': // pan slide if (effectVal[chan]!=0) { @@ -1504,8 +1496,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { if (effectVal[chan]!=0) { lastRetrig[chan]=effectVal[chan]; } - p->data[readRow][effectCol[chan]++]=0x0c; - p->data[readRow][effectCol[chan]++]=lastRetrig[chan]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0c; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=lastRetrig[chan]&15; break; case 'R': // tremolo if (effectVal[chan]!=0) { @@ -1519,77 +1511,77 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { case 0x3: // vibrato waveform switch (effectVal[chan]&3) { case 0x0: // sine - p->data[readRow][effectCol[chan]++]=0xe3; - p->data[readRow][effectCol[chan]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xe3; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x00; break; case 0x1: // ramp down - p->data[readRow][effectCol[chan]++]=0xe3; - p->data[readRow][effectCol[chan]++]=0x05; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xe3; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x05; break; case 0x2: // square - p->data[readRow][effectCol[chan]++]=0xe3; - p->data[readRow][effectCol[chan]++]=0x06; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xe3; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x06; break; case 0x3: // random - p->data[readRow][effectCol[chan]++]=0xe3; - p->data[readRow][effectCol[chan]++]=0x07; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xe3; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x07; break; } break; case 0x7: switch (effectVal[chan]&15) { case 0x7: // volume envelope off - p->data[readRow][effectCol[chan]++]=0xf5; - p->data[readRow][effectCol[chan]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf5; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x00; break; case 0x8: // volume envelope on - p->data[readRow][effectCol[chan]++]=0xf6; - p->data[readRow][effectCol[chan]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf6; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x00; break; case 0x9: // panning envelope off - p->data[readRow][effectCol[chan]++]=0xf5; - p->data[readRow][effectCol[chan]++]=0x0c; - p->data[readRow][effectCol[chan]++]=0xf5; - p->data[readRow][effectCol[chan]++]=0x0d; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf5; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0c; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf5; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0d; break; case 0xa: // panning envelope on - p->data[readRow][effectCol[chan]++]=0xf6; - p->data[readRow][effectCol[chan]++]=0x0c; - p->data[readRow][effectCol[chan]++]=0xf6; - p->data[readRow][effectCol[chan]++]=0x0d; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf6; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0c; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf6; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x0d; break; case 0xb: // pitch envelope off - p->data[readRow][effectCol[chan]++]=0xf5; - p->data[readRow][effectCol[chan]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf5; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x04; break; case 0xc: //pitch envelope on - p->data[readRow][effectCol[chan]++]=0xf6; - p->data[readRow][effectCol[chan]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf6; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x04; break; } break; case 0x8: // panning - p->data[readRow][effectCol[chan]++]=0x80; - p->data[readRow][effectCol[chan]++]=(effectVal[chan]&15)<<4; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x80; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=(effectVal[chan]&15)<<4; break; case 0xa: // offset (high nibble) - p->data[readRow][effectCol[chan]++]=0x92; - p->data[readRow][effectCol[chan]++]=effectVal[chan]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x92; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]&15; break; case 0xc: // note cut - p->data[readRow][effectCol[chan]++]=0xec; - p->data[readRow][effectCol[chan]++]=effectVal[chan]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xec; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]&15; break; case 0xd: // note delay - p->data[readRow][effectCol[chan]++]=0xed; - p->data[readRow][effectCol[chan]++]=effectVal[chan]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xed; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]&15; break; } break; case 'T': // tempo if (effectVal[chan]>=0x20) { - p->data[readRow][effectCol[chan]++]=0xf0; - p->data[readRow][effectCol[chan]++]=effectVal[chan]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0xf0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]; } break; case 'U': // fine vibrato @@ -1604,8 +1596,8 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { case 'W': // global volume slide (!) break; case 'X': // panning - p->data[readRow][effectCol[chan]++]=0x80; - p->data[readRow][effectCol[chan]++]=effectVal[chan]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=0x80; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[chan]++]=effectVal[chan]; break; case 'Y': // panbrello if (effectVal[chan]!=0) { @@ -1690,18 +1682,18 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) { for (int j=0; jpat[j].getPattern(ds.subsong[i]->orders.ord[j][0],true); for (int k=0; kdata[0][4+(k<<1)]==0x80) { + if (p->newData[0][DIV_PAT_FX(k)]==0x80) { // give up if there's a panning effect already break; } - if (p->data[0][4+(k<<1)]==-1) { + if (p->newData[0][DIV_PAT_FX(k)]==-1) { if ((chanPan[j]&127)==100) { // should be surround... - p->data[0][4+(k<<1)]=0x80; - p->data[0][5+(k<<1)]=0x80; + p->newData[0][DIV_PAT_FX(k)]=0x80; + p->newData[0][DIV_PAT_FXVAL(k)]=0x80; } else { - p->data[0][4+(k<<1)]=0x80; - p->data[0][5+(k<<1)]=CLAMP((chanPan[j]&127)<<2,0,255); + p->newData[0][DIV_PAT_FX(k)]=0x80; + p->newData[0][DIV_PAT_FXVAL(k)]=CLAMP((chanPan[j]&127)<<2,0,255); } if (ds.subsong[i]->pat[j].effectCols<=k) ds.subsong[i]->pat[j].effectCols=k+1; break; diff --git a/src/engine/fileOps/mod.cpp b/src/engine/fileOps/mod.cpp index 8cdd4a61f..55e8d8b9e 100644 --- a/src/engine/fileOps/mod.cpp +++ b/src/engine/fileOps/mod.cpp @@ -185,21 +185,21 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { } for (int row=0; row<64; row++) { for (int ch=0; chdata[row]; + short* dstrowN=chpats[ch]->newData[row]; unsigned char data[4]; reader.read(&data,4); // instrument short ins=(data[0]&0xf0)|(data[2]>>4); if (ins>0) { - dstrow[2]=ins-1; - dstrow[3]=defaultVols[ins-1]; + dstrowN[DIV_PAT_INS]=ins-1; + dstrowN[DIV_PAT_VOL]=defaultVols[ins-1]; } // note int period=data[1]+((data[0]&0x0f)<<8); if (period>0 && period<0x0fff) { short note=(short)round(log2(3424.0/period)*12); - dstrow[0]=((note+11)%12)+1; - dstrow[1]=(note-1)/12+1; + // TODO: refactor test + dstrowN[DIV_PAT_NOTE]=note+60; if (period<114) { bypassLimits=true; } @@ -207,8 +207,8 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { // effects are done later short fxtyp=data[2]&0x0f; short fxval=data[3]; - dstrow[4]=fxtyp; - dstrow[5]=fxval; + dstrowN[DIV_PAT_FX(0)]=fxtyp; + dstrowN[DIV_PAT_FXVAL(0)]=fxval; switch (fxtyp) { case 0: if (fxval!=0) fxUsage[ch][0]=true; @@ -256,7 +256,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { for (int ch=0; ch<=chCount; ch++) { unsigned char fxCols=1; for (int pat=0; pat<=patMax; pat++) { - auto* data=ds.subsong[0]->pat[ch].getPattern(pat,true)->data; + auto* newData=ds.subsong[0]->pat[ch].getPattern(pat,true)->newData; short lastPitchEffect=-1; short lastEffectState[5]={-1,-1,-1,-1,-1}; short setEffectState[5]={-1,-1,-1,-1,-1}; @@ -264,11 +264,11 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { const short fxUsageTyp[5]={0x00,0x01,0x04,0x07,0xFA}; short effectState[5]={0,0,0,0,0}; unsigned char curFxCol=0; - short fxTyp=data[row][4]; - short fxVal=data[row][5]; - auto writeFxCol=[data,row,&curFxCol](short typ, short val) { - data[row][4+curFxCol*2]=typ; - data[row][5+curFxCol*2]=val; + short fxTyp=newData[row][DIV_PAT_FX(0)]; + short fxVal=newData[row][DIV_PAT_FXVAL(0)]; + auto writeFxCol=[newData,row,&curFxCol](short typ, short val) { + newData[row][DIV_PAT_FX(curFxCol)]=typ; + newData[row][DIV_PAT_FXVAL(curFxCol)]=val; curFxCol++; }; writeFxCol(-1,-1); @@ -293,7 +293,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { effectState[1]=fxVal; if ((effectState[1]!=lastEffectState[1]) || (fxTyp!=lastPitchEffect) || - (effectState[1]!=0 && data[row][0]>0)) { + (effectState[1]!=0 && newData[row][DIV_PAT_NOTE]>-1)) { writeFxCol(fxTyp,fxVal); } lastPitchEffect=fxTyp; @@ -331,7 +331,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { writeFxCol(fxTyp,fxVal); break; case 12: // set vol - data[row][3]=MIN(0x40,fxVal); + newData[row][DIV_PAT_VOL]=MIN(0x40,fxVal); break; case 13: // break to row (BCD) writeFxCol(fxTyp,((fxVal>>4)*10)+(fxVal&15)); @@ -387,7 +387,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { for (int i=0; i<5; i++) { // pitch slide and volume slide needs to be kept active on new note // even after target/max is reached - if (fxUsage[ch][i] && (effectState[i]!=lastEffectState[i] || (effectState[i]!=0 && i==4 && data[row][3]>=0))) { + if (fxUsage[ch][i] && (effectState[i]!=lastEffectState[i] || (effectState[i]!=0 && i==4 && newData[row][DIV_PAT_VOL]>=0))) { writeFxCol(fxUsageTyp[i],effectState[i]); } } diff --git a/src/engine/fileOps/s3m.cpp b/src/engine/fileOps/s3m.cpp index 2aaf6f757..575734ca7 100644 --- a/src/engine/fileOps/s3m.cpp +++ b/src/engine/fileOps/s3m.cpp @@ -811,82 +811,82 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { for (int j=0; j<32; j++) { DivPattern* p=ds.subsong[0]->pat[chanMap[j]].getPattern(i,true); if (vibing[j]!=vibingOld[j] || vibStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x04; - p->data[readRow][effectCol[j]++]=vibing[j]?vibStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=vibing[j]?vibStatus[j]:0; doesVibrato[j]=true; } else if (doesVibrato[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x04; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x04; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (volSliding[j]!=volSlidingOld[j] || volSlideStatusChanged[j]) { if (volSlideStatus[j]>=0xf1 && volSliding[j]) { - p->data[readRow][effectCol[j]++]=0xf9; - p->data[readRow][effectCol[j]++]=volSlideStatus[j]&15; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xf9; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSlideStatus[j]&15; volSliding[j]=false; } else if ((volSlideStatus[j]&15)==15 && volSlideStatus[j]>=0x10 && volSliding[j]) { - p->data[readRow][effectCol[j]++]=0xf8; - p->data[readRow][effectCol[j]++]=volSlideStatus[j]>>4; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xf8; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSlideStatus[j]>>4; volSliding[j]=false; } else { - p->data[readRow][effectCol[j]++]=0xfa; - p->data[readRow][effectCol[j]++]=volSliding[j]?volSlideStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xfa; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=volSliding[j]?volSlideStatus[j]:0; } doesVolSlide[j]=true; } else if (doesVolSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0xfa; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0xfa; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (porting[j]!=portingOld[j] || portaStatusChanged[j]) { if (portaStatus[j]>=0xe0 && portaType[j]!=3 && porting[j]) { - p->data[readRow][effectCol[j]++]=portaType[j]|0xf0; - p->data[readRow][effectCol[j]++]=(portaStatus[j]&15)*((portaStatus[j]>=0xf0)?1:1); + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=portaType[j]|0xf0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=(portaStatus[j]&15)*((portaStatus[j]>=0xf0)?1:1); porting[j]=false; } else { - p->data[readRow][effectCol[j]++]=portaType[j]; - p->data[readRow][effectCol[j]++]=porting[j]?portaStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=portaType[j]; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=porting[j]?portaStatus[j]:0; } doesPitchSlide[j]=true; } else if (doesPitchSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x01; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x01; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (arping[j]!=arpingOld[j] || arpStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x00; - p->data[readRow][effectCol[j]++]=arping[j]?arpStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=arping[j]?arpStatus[j]:0; doesArp[j]=true; } else if (doesArp[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x00; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x00; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (treming[j]!=tremingOld[j] || tremStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x07; - p->data[readRow][effectCol[j]++]=treming[j]?tremStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x07; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=treming[j]?tremStatus[j]:0; doesTremolo[j]=true; } else if (doesTremolo[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x07; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x07; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (panning[j]!=panningOld[j] || panStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x84; - p->data[readRow][effectCol[j]++]=panning[j]?panStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x84; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=panning[j]?panStatus[j]:0; doesPanbrello[j]=true; } else if (doesPanbrello[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x84; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x84; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (panSliding[j]!=panSlidingOld[j] || panSlideStatusChanged[j]) { - p->data[readRow][effectCol[j]++]=0x83; - p->data[readRow][effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x83; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0; doesPanSlide[j]=true; } else if (doesPanSlide[j] && mustCommitInitial) { - p->data[readRow][effectCol[j]++]=0x83; - p->data[readRow][effectCol[j]++]=0; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0x83; + p->newData[readRow][DIV_PAT_FX(0)+effectCol[j]++]=0; } if (effectCol[j]>=4+8*2) { diff --git a/src/engine/pattern.cpp b/src/engine/pattern.cpp index 49e66665c..cce45e65c 100644 --- a/src/engine/pattern.cpp +++ b/src/engine/pattern.cpp @@ -45,7 +45,7 @@ std::vector> DivChannelData::optimize() { for (int j=0; jdata,data[j]->data,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short))==0) { + if (memcmp(data[i]->newData,data[j]->newData,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short))==0) { delete data[j]; data[j]=NULL; logV("%d == %d",i,j); @@ -86,15 +86,11 @@ void DivChannelData::wipePatterns() { void DivPattern::copyOn(DivPattern* dest) { dest->name=name; - memcpy(dest->data,data,sizeof(data)); + memcpy(dest->newData,newData,sizeof(newData)); } void DivPattern::clear() { - memset(data,-1,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short)); - for (int i=0; i