Implement looping in TFM import

This commit is contained in:
techmetx11 2025-02-19 14:01:11 +01:00 committed by tildearrow
parent c02e80a269
commit 308aacc1e6

View file

@ -193,6 +193,7 @@ struct TFMParsePatternInfo {
DivSong* ds; DivSong* ds;
int* insNumMaps; int* insNumMaps;
bool v2; bool v2;
unsigned char loop_pos;
}; };
void TFMParsePattern(struct TFMParsePatternInfo info) { void TFMParsePattern(struct TFMParsePatternInfo info) {
@ -366,7 +367,7 @@ void TFMParsePattern(struct TFMParsePatternInfo info) {
pat->data[k][5+(l*2)]=effectVal[k]; pat->data[k][5+(l*2)]=effectVal[k];
break; break;
case 13: case 13:
// modify TL of operator 2 // modify TL of operator 4
pat->data[k][4+(l*2)]=0x15; pat->data[k][4+(l*2)]=0x15;
pat->data[k][5+(l*2)]=effectVal[k]; pat->data[k][5+(l*2)]=effectVal[k];
break; break;
@ -459,17 +460,21 @@ void TFMParsePattern(struct TFMParsePatternInfo info) {
bool chVibrato[6]={false}; bool chVibrato[6]={false};
bool chPorta[6]={false}; bool chPorta[6]={false};
bool chVolumeSlide[6]={false}; bool chVolumeSlide[6]={false};
int lastPatSeen=0;
for (int i=0; i<info.ds->subsong[0]->ordersLen; i++) { for (int i=0; i<info.ds->subsong[0]->ordersLen; i++) {
// this is if the last pattern is used more than once
if (info.orderList[i] == info.orderList[info.ds->subsong[0]->ordersLen - 1]) {
lastPatSeen++;
}
for (int j=0; j<6; j++) { for (int j=0; j<6; j++) {
for (int l=0; l<usedEffectsCol; l++) { for (int l=0; l<usedEffectsCol; l++) {
DivPattern* pat = info.ds->subsong[0]->pat[j].data[info.orderList[i]]; DivPattern* pat = info.ds->subsong[0]->pat[j].data[info.orderList[i]];
unsigned char truePatLen=(info.patLens[info.orderList[i]]<info.ds->subsong[0]->patLen) ? info.patLens[info.orderList[i]] : info.ds->subsong[0]->patLen;
// default instrument // default instrument
if (i==0 && pat->data[0][2]==-1) pat->data[0][2]=0; if (i==0 && pat->data[0][2]==-1) pat->data[0][2]=0;
unsigned char truePatLen=(info.patLens[info.orderList[i]]<info.ds->subsong[0]->patLen) ? info.patLens[info.orderList[i]] : info.ds->subsong[0]->patLen;
for (int k=0; k<truePatLen; k++) { for (int k=0; k<truePatLen; k++) {
if (chArpeggio[j] && pat->data[k][4+(l*2)]!=0x00 && pat->data[k][0]!=-1) { if (chArpeggio[j] && pat->data[k][4+(l*2)]!=0x00 && pat->data[k][0]!=-1) {
pat->data[k][4+usedEffectsCol*2+(l*2)]=0x00; pat->data[k][4+usedEffectsCol*2+(l*2)]=0x00;
@ -505,12 +510,35 @@ void TFMParsePattern(struct TFMParsePatternInfo info) {
chVolumeSlide[j]=true; chVolumeSlide[j]=true;
break; break;
default: default:
break; break;
} }
} }
} }
} }
} }
if (lastPatSeen>1) {
// clone the last pattern
info.maxPat++;
for (int i=0;i<6;i++) {
int last_pat_num = info.ds->subsong[0]->orders.ord[i][info.ds->subsong[0]->ordersLen - 1];
DivPattern* new_pat = new DivPattern;
DivPattern* last_pat = info.ds->subsong[0]->pat[i].data[last_pat_num];
last_pat->copyOn(new_pat);
info.ds->subsong[0]->orders.ord[i][info.ds->subsong[0]->ordersLen - 1] = info.maxPat;
new_pat->data[info.patLens[last_pat_num]-1][4+(usedEffectsCol*4)] = 0x0B;
new_pat->data[info.patLens[last_pat_num]-1][5+(usedEffectsCol*4)] = info.loop_pos;
info.ds->subsong[0]->pat[i].data[info.maxPat] = new_pat;
}
} else {
for (int i=0;i<6;i++) {
int last_pat_num = info.ds->subsong[0]->orders.ord[i][info.ds->subsong[0]->ordersLen - 1];
DivPattern* last_pat = info.ds->subsong[0]->pat[i].data[last_pat_num];
last_pat->data[info.patLens[last_pat_num]-1][4+(usedEffectsCol*4)] = 0x0B;
last_pat->data[info.patLens[last_pat_num]-1][5+(usedEffectsCol*4)] = info.loop_pos;
}
}
} }
bool DivEngine::loadTFMv1(unsigned char* file, size_t len) { bool DivEngine::loadTFMv1(unsigned char* file, size_t len) {
@ -551,7 +579,7 @@ bool DivEngine::loadTFMv1(unsigned char* file, size_t len) {
ds.subsong[0]->ordersLen=reader.readCNoRLE(); ds.subsong[0]->ordersLen=reader.readCNoRLE();
// order loop position, unused // order loop position, unused
(void)reader.readCNoRLE(); unsigned char loop_pos = reader.readCNoRLE();
ds.createdDate=TFMparseDate(reader.readSNoRLE()); ds.createdDate=TFMparseDate(reader.readSNoRLE());
ds.revisionDate=TFMparseDate(reader.readSNoRLE()); ds.revisionDate=TFMparseDate(reader.readSNoRLE());
@ -677,6 +705,7 @@ bool DivEngine::loadTFMv1(unsigned char* file, size_t len) {
info.patLens=patLens; info.patLens=patLens;
info.reader=&reader; info.reader=&reader;
info.v2=false; info.v2=false;
info.loop_pos=loop_pos;
TFMParsePattern(info); TFMParsePattern(info);
if (active) quitDispatch(); if (active) quitDispatch();
@ -750,7 +779,7 @@ bool DivEngine::loadTFMv2(unsigned char* file, size_t len) {
ds.subsong[0]->ordersLen=reader.readCNoRLE(); ds.subsong[0]->ordersLen=reader.readCNoRLE();
// order loop position, unused // order loop position, unused
(void)reader.readCNoRLE(); unsigned char loop_pos = reader.readCNoRLE();
ds.createdDate=TFMparseDate(reader.readSNoRLE()); ds.createdDate=TFMparseDate(reader.readSNoRLE());
ds.revisionDate=TFMparseDate(reader.readSNoRLE()); ds.revisionDate=TFMparseDate(reader.readSNoRLE());
@ -876,6 +905,7 @@ bool DivEngine::loadTFMv2(unsigned char* file, size_t len) {
info.patLens=patLens; info.patLens=patLens;
info.reader=&reader; info.reader=&reader;
info.v2=true; info.v2=true;
info.loop_pos=loop_pos;
TFMParsePattern(info); TFMParsePattern(info);
if (active) quitDispatch(); if (active) quitDispatch();