From 308aacc1e6511ec8ed19a62e056f298b1be0c9d9 Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Wed, 19 Feb 2025 14:01:11 +0100 Subject: [PATCH] Implement looping in TFM import --- src/engine/fileOps/tfm.cpp | 42 ++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/engine/fileOps/tfm.cpp b/src/engine/fileOps/tfm.cpp index 919e7f52f..6b0365346 100644 --- a/src/engine/fileOps/tfm.cpp +++ b/src/engine/fileOps/tfm.cpp @@ -193,6 +193,7 @@ struct TFMParsePatternInfo { DivSong* ds; int* insNumMaps; bool v2; + unsigned char loop_pos; }; void TFMParsePattern(struct TFMParsePatternInfo info) { @@ -366,7 +367,7 @@ void TFMParsePattern(struct TFMParsePatternInfo info) { pat->data[k][5+(l*2)]=effectVal[k]; break; case 13: - // modify TL of operator 2 + // modify TL of operator 4 pat->data[k][4+(l*2)]=0x15; pat->data[k][5+(l*2)]=effectVal[k]; break; @@ -459,17 +460,21 @@ void TFMParsePattern(struct TFMParsePatternInfo info) { bool chVibrato[6]={false}; bool chPorta[6]={false}; bool chVolumeSlide[6]={false}; + int lastPatSeen=0; for (int i=0; isubsong[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 l=0; lsubsong[0]->pat[j].data[info.orderList[i]]; + unsigned char truePatLen=(info.patLens[info.orderList[i]]subsong[0]->patLen) ? info.patLens[info.orderList[i]] : info.ds->subsong[0]->patLen; // default instrument if (i==0 && pat->data[0][2]==-1) pat->data[0][2]=0; - unsigned char truePatLen=(info.patLens[info.orderList[i]]subsong[0]->patLen) ? info.patLens[info.orderList[i]] : info.ds->subsong[0]->patLen; - for (int k=0; kdata[k][4+(l*2)]!=0x00 && pat->data[k][0]!=-1) { pat->data[k][4+usedEffectsCol*2+(l*2)]=0x00; @@ -505,12 +510,35 @@ void TFMParsePattern(struct TFMParsePatternInfo info) { chVolumeSlide[j]=true; break; 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) { @@ -551,7 +579,7 @@ bool DivEngine::loadTFMv1(unsigned char* file, size_t len) { ds.subsong[0]->ordersLen=reader.readCNoRLE(); // order loop position, unused - (void)reader.readCNoRLE(); + unsigned char loop_pos = reader.readCNoRLE(); ds.createdDate=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.reader=&reader; info.v2=false; + info.loop_pos=loop_pos; TFMParsePattern(info); if (active) quitDispatch(); @@ -750,7 +779,7 @@ bool DivEngine::loadTFMv2(unsigned char* file, size_t len) { ds.subsong[0]->ordersLen=reader.readCNoRLE(); // order loop position, unused - (void)reader.readCNoRLE(); + unsigned char loop_pos = reader.readCNoRLE(); ds.createdDate=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.reader=&reader; info.v2=true; + info.loop_pos=loop_pos; TFMParsePattern(info); if (active) quitDispatch();