Fix another bug in the RLE decompressor, parsing instruments now

This commit is contained in:
techmetx11 2024-04-10 18:37:52 +00:00
parent 9f26257364
commit 9bbd673bfa
No known key found for this signature in database
GPG key ID: 20E0C88A0E7E5AF2

View file

@ -45,12 +45,11 @@ class TFMRLEReader {
do { do {
rleTag=readC(); rleTag=readC();
tagLenLeft|=(rleTag&0x7F)<<lenShift; tagLenLeft|=(rleTag&0x7F)<<lenShift;
lenShift += 7; lenShift+=7;
logD("RLE tag: %X, len shift: %d, len left: %d", rleTag, lenShift, tagLenLeft); logD("RLE tag: %X, len shift: %d, len left: %d",rleTag,lenShift,tagLenLeft);
// sync back since we've already read one character
tagLenLeft--;
} while (!(rleTag&0x80)); } while (!(rleTag&0x80));
// sync back since we've already read one character
tagLenLeft--;
inTag=true; inTag=true;
tagChar=prevChar; tagChar=prevChar;
} }
@ -66,14 +65,14 @@ public:
// these functions may throw TFMEndOfFileException // these functions may throw TFMEndOfFileException
unsigned char readC() { unsigned char readC() {
if (curSeek>len) throw TFMEndOfFileException(this, len); if (curSeek>len) throw TFMEndOfFileException(this,len);
if (inTag) { if (inTag) {
if (!tagLenLeft) { if (!tagLenLeft) {
inTag=false; inTag=false;
return readC(); return readC();
} }
tagLenLeft--; 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; return tagChar;
} }
@ -102,16 +101,16 @@ public:
} }
char readCNoRLE() { char readCNoRLE() {
if (curSeek+1>len) throw TFMEndOfFileException(this, len); if (curSeek+1>len) throw TFMEndOfFileException(this,len);
return buf[curSeek++]; return buf[curSeek++];
} }
void read(unsigned char* b, size_t l) { void read(unsigned char* b, size_t l) {
int i=0; int i=0;
while(l--) { while(l--) {
unsigned char nextChar = readC(); unsigned char nextChar=readC();
b[i++]=nextChar; 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; int i=0;
while (l--) { while (l--) {
b[i++]=buf[curSeek++]; 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() { 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; short ret=buf[curSeek]|buf[curSeek+1]<<8;
curSeek+=2; curSeek+=2;
return ret; return ret;
} }
void skip(size_t l) {
while (l--) readC();
}
}; };
String TFMparseDate(short date) { 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) { bool DivEngine::loadTFM(unsigned char* file, size_t len) {
struct InvalidHeaderException {}; struct InvalidHeaderException {};
bool success=false; bool success=false;
TFMRLEReader reader=TFMRLEReader(file, len); TFMRLEReader reader=TFMRLEReader(file,len);
try { try {
DivSong ds; DivSong ds;
@ -219,12 +222,61 @@ bool DivEngine::loadTFM(unsigned char* file, size_t len) {
unsigned char orderList[256]; unsigned char orderList[256];
reader.read(orderList,256); reader.read(orderList,256);
for (int i=0; i<ds.subsong[0]->ordersLen;i++) { for (int i=0; i<ds.subsong[0]->ordersLen; i++) {
for (int j=0; j<6; j++) { for (int j=0; j<6; j++) {
ds.subsong[0]->orders.ord[j][i]=orderList[i]; 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; ds.notes=notes;
BUSY_BEGIN_SOFT; BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();