diff --git a/src/engine/fileOps/xm.cpp b/src/engine/fileOps/xm.cpp index e42362046..c7ca9f51d 100644 --- a/src/engine/fileOps/xm.cpp +++ b/src/engine/fileOps/xm.cpp @@ -57,6 +57,158 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) { // 0x1a reader.readC(); + String trackerName=reader.readString(20); + unsigned short trackerVer=reader.readS(); + + if (trackerName!="") logV("made with %s",trackerName); + logV("version %x",trackerVer); + + unsigned int headerSeek=reader.tell(); + headerSeek+=reader.readI(); + + ds.subsong[0]->ordersLen=(unsigned short)reader.readS(); + ds.subsong[0]->patLen=1; + unsigned short loopPos=reader.readS(); + unsigned short totalChans=reader.readS(); + unsigned short patCount=reader.readS(); + ds.insLen=(unsigned short)reader.readS(); + ds.linearPitch=(reader.readS()&1)?2:0; + ds.subsong[0]->speeds.val[0]=reader.readS(); + ds.subsong[0]->speeds.len=1; + double bpm=(unsigned short)reader.readS(); + ds.subsong[0]->hz=(double)bpm/2.5; + + logV("channels: %d",totalChans); + + logV("repeat pos: %d",loopPos); + + logV("reading orders..."); + for (int i=0; i<256; i++) { + unsigned char val=reader.readC(); + for (int j=0; jorders.ord[j][i]=val; + } + } + + logV("seeking to %x...",headerSeek); + + if (!reader.seek(headerSeek,SEEK_SET)) { + logE("premature end of file!"); + lastError="incomplete file"; + delete[] file; + return false; + } + + // read patterns + logD("reading patterns..."); + for (unsigned short i=0; ids.subsong[0]->patLen) ds.subsong[0]->patLen=totalRows; + + unsigned int packedSeek=headerSeek+(unsigned short)reader.readS(); + + logV("seeking to %x...",headerSeek); + if (!reader.seek(headerSeek,SEEK_SET)) { + logE("premature end of file!"); + lastError="incomplete file"; + delete[] file; + return false; + } + + // read data + for (int j=0; jpat[k].getPattern(i,true); + + unsigned char note=reader.readC(); + unsigned char ins=0; + unsigned char vol=0; + unsigned char effect=0; + unsigned char effectVal=0; + bool hasNote=false; + bool hasIns=false; + bool hasVol=false; + bool hasEffect=false; + bool hasEffectVal=false; + + if (note&0x80) { // packed + hasNote=note&1; + hasIns=note&2; + hasVol=note&4; + hasEffect=note&8; + hasEffectVal=note&16; + if (hasNote) { + note=reader.readC(); + } + } else { // unpacked + hasNote=true; + hasIns=true; + hasVol=true; + hasEffect=true; + hasEffectVal=true; + } + + if (hasNote) { + if (note>=96) { + p->data[j][0]=100; + p->data[j][1]=0; + } else { + p->data[j][0]=note%12; + p->data[j][1]=note/12; + if (p->data[j][0]==0) { + p->data[j][0]=12; + p->data[j][1]=(unsigned char)(p->data[j][1]-1); + } + } + } + if (hasIns) { + ins=reader.readC(); + p->data[j][2]=((int)ins)-1; + } + if (hasVol) { + vol=reader.readC(); + p->data[j][3]=vol; + } + if (hasEffect) { + effect=reader.readC(); + p->data[j][4]=effect; + } + if (hasEffectVal) { + effectVal=reader.readC(); + p->data[j][5]=effectVal; + } + } + } + + logV("seeking to %x...",packedSeek); + if (!reader.seek(packedSeek,SEEK_SET)) { + logE("premature end of file!"); + lastError="incomplete file"; + delete[] file; + return false; + } + } + + // read instruments + for (int i=0; i