beta 1-3 .dmf loading

i did it
This commit is contained in:
tildearrow 2022-04-11 01:41:45 -05:00
parent 9e0e725802
commit 8a49522e59

View file

@ -53,6 +53,10 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
warnings=""; warnings="";
try { try {
DivSong ds; DivSong ds;
unsigned char historicColIns[DIV_MAX_CHANS];
for (int i=0; i<DIV_MAX_CHANS; i++) {
historicColIns[i]=i;
}
ds.nullWave.len=32; ds.nullWave.len=32;
for (int i=0; i<32; i++) { for (int i=0; i<32; i++) {
@ -172,7 +176,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.timeBase=reader.readC(); ds.timeBase=reader.readC();
ds.speed1=reader.readC(); ds.speed1=reader.readC();
if (ds.version>0x03) { if (ds.version>0x05) {
ds.speed2=reader.readC(); ds.speed2=reader.readC();
ds.pal=reader.readC(); ds.pal=reader.readC();
ds.hz=(ds.pal)?60:50; ds.hz=(ds.pal)?60:50;
@ -258,7 +262,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
addWarning("Yamaha YMU759 emulation is incomplete! please migrate your song to the OPL3 system."); addWarning("Yamaha YMU759 emulation is incomplete! please migrate your song to the OPL3 system.");
} }
logI("reading pattern matrix (%d)...",ds.ordersLen); logV("%x",reader.tell());
logI("reading pattern matrix (%d * %d = %d)...",ds.ordersLen,getChannelCount(ds.system[0]),ds.ordersLen*getChannelCount(ds.system[0]));
for (int i=0; i<getChannelCount(ds.system[0]); i++) { for (int i=0; i<getChannelCount(ds.system[0]); i++) {
for (int j=0; j<ds.ordersLen; j++) { for (int j=0; j<ds.ordersLen; j++) {
ds.orders.ord[i][j]=reader.readC(); ds.orders.ord[i][j]=reader.readC();
@ -272,9 +278,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.pat[i].getPattern(j,true)->name=reader.readString((unsigned char)reader.readC()); ds.pat[i].getPattern(j,true)->name=reader.readString((unsigned char)reader.readC());
} }
} }
if (ds.version>0x03 && ds.version<0x06 && i<16) {
historicColIns[i]=reader.readC();
}
} }
if (ds.version>0x03) { logV("%x",reader.tell());
if (ds.version>0x05) {
ds.insLen=(unsigned char)reader.readC(); ds.insLen=(unsigned char)reader.readC();
} else { } else {
ds.insLen=16; ds.insLen=16;
@ -282,7 +293,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
logI("reading instruments (%d)...",ds.insLen); logI("reading instruments (%d)...",ds.insLen);
for (int i=0; i<ds.insLen; i++) { for (int i=0; i<ds.insLen; i++) {
DivInstrument* ins=new DivInstrument; DivInstrument* ins=new DivInstrument;
if (ds.version>0x03) { if (ds.version>0x05) {
ins->name=reader.readString((unsigned char)reader.readC()); ins->name=reader.readString((unsigned char)reader.readC());
} }
logD("%d name: %s",i,ins->name.c_str()); logD("%d name: %s",i,ins->name.c_str());
@ -319,6 +330,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
if (ins->mode) { // FM if (ins->mode) { // FM
if (ds.version>0x05) {
ins->fm.alg=reader.readC(); ins->fm.alg=reader.readC();
if (ds.version<0x13) { if (ds.version<0x13) {
reader.readC(); reader.readC();
@ -335,13 +347,24 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} else { } else {
ins->fm.ops=4; ins->fm.ops=4;
} }
ins->fm.ams=reader.readC();
} else {
ins->fm.alg=reader.readC();
reader.readC();
ins->fm.fb=reader.readC();
reader.readC(); // apparently an index of sorts starting from 0x59?
ins->fm.fms=reader.readC();
reader.readC(); // 0x59+index?
ins->fm.ops=2+reader.readC()*2;
}
logD("ALG %d FB %d FMS %d AMS %d OPS %d",ins->fm.alg,ins->fm.fb,ins->fm.fms,ins->fm.ams,ins->fm.ops);
if (ins->fm.ops!=2 && ins->fm.ops!=4) { if (ins->fm.ops!=2 && ins->fm.ops!=4) {
logE("invalid op count %d. did we read it wrong?",ins->fm.ops); logE("invalid op count %d. did we read it wrong?",ins->fm.ops);
lastError="file is corrupt or unreadable at operators"; lastError="file is corrupt or unreadable at operators";
delete[] file; delete[] file;
return false; return false;
} }
ins->fm.ams=reader.readC();
for (int j=0; j<ins->fm.ops; j++) { for (int j=0; j<ins->fm.ops; j++) {
ins->fm.op[j].am=reader.readC(); ins->fm.op[j].am=reader.readC();
@ -385,7 +408,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ins->fm.op[j].dt2=reader.readC(); ins->fm.op[j].dt2=reader.readC();
} }
} }
if (ds.version>0x03) { if (ds.version>0x05) {
if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) { if (ds.system[0]==DIV_SYSTEM_SMS_OPLL || ds.system[0]==DIV_SYSTEM_NES_VRC7) {
ins->fm.op[j].ksr=reader.readC(); ins->fm.op[j].ksr=reader.readC();
ins->fm.op[j].vib=reader.readC(); ins->fm.op[j].vib=reader.readC();
@ -588,6 +611,8 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
} }
logV("%x",reader.tell());
logI("reading patterns (%d channels, %d orders)...",getChannelCount(ds.system[0]),ds.ordersLen); logI("reading patterns (%d channels, %d orders)...",getChannelCount(ds.system[0]),ds.ordersLen);
for (int i=0; i<getChannelCount(ds.system[0]); i++) { for (int i=0; i<getChannelCount(ds.system[0]); i++) {
DivChannelData& chan=ds.pat[i]; DivChannelData& chan=ds.pat[i];
@ -595,7 +620,6 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
chan.effectRows=1; chan.effectRows=1;
} else { } else {
chan.effectRows=reader.readC(); chan.effectRows=reader.readC();
} }
logD("%d fx rows: %d",i,chan.effectRows); logD("%d fx rows: %d",i,chan.effectRows);
if (chan.effectRows>4 || chan.effectRows<1) { if (chan.effectRows>4 || chan.effectRows<1) {
@ -606,6 +630,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
for (int j=0; j<ds.ordersLen; j++) { for (int j=0; j<ds.ordersLen; j++) {
DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true); DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true);
if (ds.version>0x05) { // current pattern format
for (int k=0; k<ds.patLen; k++) { for (int k=0; k<ds.patLen; k++) {
// note // note
pat->data[k][0]=reader.readS(); pat->data[k][0]=reader.readS();
@ -672,13 +697,43 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
} }
} }
} else { // historic pattern format
if (i<16) pat->data[0][2]=historicColIns[i];
for (int k=0; k<ds.patLen; k++) {
// note
pat->data[k][0]=reader.readC();
// octave
pat->data[k][1]=reader.readC();
if (pat->data[k][0]!=0) {
// YMU759 is stored 2 octaves lower
pat->data[k][1]+=2;
}
if (pat->data[k][0]==0 && pat->data[k][1]!=0) {
logD("what? %d:%d:%d note %d octave %d",i,j,k,pat->data[k][0],pat->data[k][1]);
pat->data[k][0]=12;
pat->data[k][1]--;
}
// volume and effect
unsigned char vol=reader.readC();
unsigned char fx=reader.readC();
unsigned char fxVal=reader.readC();
pat->data[k][3]=(vol==0x80)?-1:vol;
// effect
pat->data[k][4]=(fx==0x80)?-1:fx;
pat->data[k][5]=(fxVal==0x80)?-1:fxVal;
// instrument wasn't stored back then
}
}
} }
} }
int ymuSampleRate=20;
ds.sampleLen=(unsigned char)reader.readC(); ds.sampleLen=(unsigned char)reader.readC();
logI("reading samples (%d)...",ds.sampleLen); logI("reading samples (%d)...",ds.sampleLen);
if (ds.version<0x0b && ds.sampleLen>0) { // TODO what is this for? if (ds.version<0x0b && ds.sampleLen>0) {
reader.readC(); // it appears this byte stored the YMU759 sample rate
ymuSampleRate=reader.readC();
} }
for (int i=0; i<ds.sampleLen; i++) { for (int i=0; i<ds.sampleLen; i++) {
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
@ -686,6 +741,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
int pitch=5; int pitch=5;
int vol=50; int vol=50;
short* data; short* data;
unsigned char* adpcmData;
if (length<0) { if (length<0) {
logE("invalid sample length %d. are we doing something wrong?",length); logE("invalid sample length %d. are we doing something wrong?",length);
lastError="file is corrupt or unreadable at samples"; lastError="file is corrupt or unreadable at samples";
@ -704,6 +760,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
pitch=reader.readC(); pitch=reader.readC();
vol=reader.readC(); vol=reader.readC();
} }
if (ds.version<=0x05) {
sample->rate=ymuSampleRate*400;
}
if (ds.version>0x15) { if (ds.version>0x15) {
sample->depth=reader.readC(); sample->depth=reader.readC();
if (sample->depth!=8 && sample->depth!=16) { if (sample->depth!=8 && sample->depth!=16) {
@ -711,9 +770,15 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
sample->depth=16; sample->depth=16;
} }
} else { } else {
if (ds.version>0x05) {
sample->depth=16; sample->depth=16;
} else {
// it appears samples were stored as ADPCM back then
sample->depth=6;
}
} }
if (length>0) { if (length>0) {
if (ds.version>0x05) {
if (ds.version<0x0b) { if (ds.version<0x0b) {
data=new short[1+(length/2)]; data=new short[1+(length/2)];
reader.read(data,length); reader.read(data,length);
@ -748,6 +813,22 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
delete[] data; delete[] data;
} else {
// ADPCM?
// it appears to be a slightly modified version of ADPCM-B!
adpcmData=new unsigned char[length];
logV("%x",reader.tell());
reader.read(adpcmData,length);
for (int i=0; i<length; i++) {
adpcmData[i]=(adpcmData[i]<<4)|(adpcmData[i]>>4);
}
if (!sample->init(length*2)) {
logE("%d: error while initializing sample!",i);
}
memcpy(sample->dataB,adpcmData,length);
delete[] adpcmData;
}
} }
ds.sample.push_back(sample); ds.sample.push_back(sample);
} }