From 9bbd673bfafef16654165c4355c480ecb1c73ded Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Wed, 10 Apr 2024 18:37:52 +0000 Subject: [PATCH] Fix another bug in the RLE decompressor, parsing instruments now --- src/engine/fileOps/tfm.cpp | 82 +++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 15 deletions(-) diff --git a/src/engine/fileOps/tfm.cpp b/src/engine/fileOps/tfm.cpp index 7c0e949ef..4680c2f1d 100644 --- a/src/engine/fileOps/tfm.cpp +++ b/src/engine/fileOps/tfm.cpp @@ -45,12 +45,11 @@ class TFMRLEReader { do { rleTag=readC(); tagLenLeft|=(rleTag&0x7F)<len) throw TFMEndOfFileException(this, len); + if (curSeek>len) throw TFMEndOfFileException(this,len); if (inTag) { if (!tagLenLeft) { inTag=false; return readC(); } tagLenLeft--; - logD("one char RLE decompressed, tag left: %d, char: %d", tagLenLeft, tagChar); + logD("one char RLE decompressed, tag left: %d, char: %d",tagLenLeft,tagChar); return tagChar; } @@ -102,16 +101,16 @@ public: } char readCNoRLE() { - if (curSeek+1>len) throw TFMEndOfFileException(this, len); + if (curSeek+1>len) throw TFMEndOfFileException(this,len); return buf[curSeek++]; } void read(unsigned char* b, size_t l) { int i=0; while(l--) { - unsigned char nextChar = readC(); + unsigned char nextChar=readC(); b[i++]=nextChar; - logD("read next char: %x, index: %d", nextChar, i); + logD("read next char: %x, index: %d",nextChar,i); } } @@ -119,7 +118,7 @@ public: int i=0; while (l--) { b[i++]=buf[curSeek++]; - if (curSeek>len) throw TFMEndOfFileException(this, len); + if (curSeek>len) throw TFMEndOfFileException(this,len); } } @@ -128,21 +127,25 @@ public: } short readSNoRLE() { - if (curSeek+2>len) throw TFMEndOfFileException(this, len); + if (curSeek+2>len) throw TFMEndOfFileException(this,len); short ret=buf[curSeek]|buf[curSeek+1]<<8; curSeek+=2; return ret; } + + void skip(size_t l) { + while (l--) readC(); + } }; String TFMparseDate(short date) { - return fmt::sprintf("%02d.%02d.%02d", date>>11, (date>>7)&0xF, date&0x7F); + return fmt::sprintf("%02d.%02d.%02d",date>>11,(date>>7)&0xF,date&0x7F); } bool DivEngine::loadTFM(unsigned char* file, size_t len) { struct InvalidHeaderException {}; bool success=false; - TFMRLEReader reader=TFMRLEReader(file, len); + TFMRLEReader reader=TFMRLEReader(file,len); try { DivSong ds; @@ -219,12 +222,61 @@ bool DivEngine::loadTFM(unsigned char* file, size_t len) { unsigned char orderList[256]; reader.read(orderList,256); - for (int i=0; iordersLen;i++) { + for (int i=0; iordersLen; i++) { for (int j=0; j<6; j++) { ds.subsong[0]->orders.ord[j][i]=orderList[i]; } } + DivInstrument* insMaps[256]; + + // instrument names + logD("parsing instruments"); + unsigned char insName[16]; + int insCount=0; + for (int i=0; i<255; i++) { + reader.read(insName,16); + + if (memcmp(insName,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16)==0) { + logD("instrument unused"); + insMaps[i]=NULL; + continue; + } + + DivInstrument* ins=new DivInstrument; + ins->type=DIV_INS_FM; + ins->name=String((const char*)insName,strnlen((const char*)insName,16)); + ds.ins.push_back(ins); + insCount++; + insMaps[i]=ins; + } + + ds.insLen=insCount; + + // instrument data + for (int i=0; i<255; i++) { + if (!insMaps[i]) { + reader.skip(42); + continue; + } + + insMaps[i]->fm.alg=reader.readC(); + insMaps[i]->fm.fb=reader.readC(); + + for (int j=0; j<4; j++) { + insMaps[i]->fm.op[j].mult=reader.readC(); + insMaps[i]->fm.op[j].dt=reader.readC(); + insMaps[i]->fm.op[j].tl=reader.readC()^0x7F; + insMaps[i]->fm.op[j].rs=reader.readC(); + insMaps[i]->fm.op[j].ar=reader.readC()^0x1F; + insMaps[i]->fm.op[j].dr=reader.readC()^0x1F; + insMaps[i]->fm.op[j].d2r=reader.readC()^0x1F; + insMaps[i]->fm.op[j].rr=reader.readC()^0xF; + insMaps[i]->fm.op[j].sl=reader.readC(); + insMaps[i]->fm.op[j].ssgEnv=reader.readC(); + } + } + ds.notes=notes; BUSY_BEGIN_SOFT; saveLock.lock();