From 5ec4f2d1f0fd068d0c35a9971f1ae0fa17ad2d64 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 20 Nov 2022 14:28:43 -0500 Subject: [PATCH] new ins format, part 7 FM instruments now loadable --- papers/newIns.md | 2 +- src/engine/engine.h | 4 +-- src/engine/fileOpsIns.cpp | 31 +++++++++++++----- src/engine/instrument.cpp | 66 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 10 deletions(-) diff --git a/papers/newIns.md b/papers/newIns.md index 6f420de0b..4baab71e1 100644 --- a/papers/newIns.md +++ b/papers/newIns.md @@ -1,4 +1,4 @@ -# possible new Furnace instrument format +# new Furnace instrument format the main issue with Furnace instrument files is that they are too big, even if the instrument is nothing more than the FM setup... diff --git a/src/engine/engine.h b/src/engine/engine.h index 4a36b27d7..0c2782050 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -47,8 +47,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev125" -#define DIV_ENGINE_VERSION 125 +#define DIV_VERSION "dev126" +#define DIV_ENGINE_VERSION 126 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/engine/fileOpsIns.cpp b/src/engine/fileOpsIns.cpp index 83361130b..c002efea2 100644 --- a/src/engine/fileOpsIns.cpp +++ b/src/engine/fileOpsIns.cpp @@ -1880,10 +1880,19 @@ std::vector DivEngine::instrumentFromFile(const char* path) { unsigned char magic[16]; bool isFurnaceInstr=false; + bool isOldFurnaceIns=false; try { - reader.read(magic,16); - if (memcmp("-Furnace instr.-",magic,16)==0) { + reader.read(magic,4); + if (memcmp("FINS",magic,4)==0) { isFurnaceInstr=true; + logV("found a new Furnace ins"); + } else { + reader.read(&magic[4],12); + if (memcmp("-Furnace instr.-",magic,16)==0) { + logV("found an old Furnace ins"); + isFurnaceInstr=true; + isOldFurnaceIns=true; + } } } catch (EndOfFileException& e) { reader.seek(0,SEEK_SET); @@ -1892,17 +1901,25 @@ std::vector DivEngine::instrumentFromFile(const char* path) { if (isFurnaceInstr) { DivInstrument* ins=new DivInstrument; try { - short version=reader.readS(); - reader.readS(); // reserved + short version=0; + if (isOldFurnaceIns) { + version=reader.readS(); + reader.readS(); // reserved + } else { + version=reader.readS(); + reader.seek(0,SEEK_SET); + } if (version>DIV_ENGINE_VERSION) { warnings="this instrument is made with a more recent version of Furnace!"; } - unsigned int dataPtr=reader.readI(); - reader.seek(dataPtr,SEEK_SET); + if (isOldFurnaceIns) { + unsigned int dataPtr=reader.readI(); + reader.seek(dataPtr,SEEK_SET); + } - if (ins->readInsData(reader,version)!=DIV_DATA_SUCCESS) { + if (ins->readInsData(reader,version,&song)!=DIV_DATA_SUCCESS) { lastError="invalid instrument header/data!"; delete ins; delete[] buf; diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 622c9b60f..9f9482d9d 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -1738,6 +1738,71 @@ void DivInstrument::readFeatureNA(SafeReader& reader) { void DivInstrument::readFeatureFM(SafeReader& reader) { READ_FEAT_BEGIN; + unsigned char opCount=reader.readC(); + + fm.op[0].enable=(opCount&16); + fm.op[1].enable=(opCount&32); + fm.op[2].enable=(opCount&64); + fm.op[3].enable=(opCount&128); + + opCount&=15; + + unsigned char next=reader.readC(); + fm.alg=(next>>4)&7; + fm.fb=next&7; + + next=reader.readC(); + fm.fms2=(next>>5)&7; + fm.ams=(next>>3)&3; + fm.fms=next&7; + + next=reader.readC(); + fm.ams2=(next>>6)&3; + fm.ops=(next&32)?4:2; + fm.opllPreset=next&31; + + // read operators + for (int i=0; i>4)&7; + op.mult=next&15; + + next=reader.readC(); + op.sus=(next&128)?1:0; + op.tl=next&127; + + next=reader.readC(); + op.rs=(next>>6)&3; + op.vib=(next&32)?1:0; + op.ar=next&31; + + next=reader.readC(); + op.am=(next&128)?1:0; + op.ksl=(next>>5)&3; + op.dr=next&31; + + next=reader.readC(); + op.egt=(next&128)?1:0; + op.kvs=(next>>5)&3; + op.d2r=next&31; + + next=reader.readC(); + op.sl=(next>>4)&15; + op.rr=next&15; + + next=reader.readC(); + op.dvb=(next>>4)&15; + op.ssgEnv=next&15; + + next=reader.readC(); + op.dam=(next>>5)&7; + op.dt2=(next>>3)&3; + op.ws=next&7; + } + READ_FEAT_END; } @@ -2644,6 +2709,7 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version, DivS } if (type==1 || type==2) { + logV("reading new instrument data..."); return readInsDataNew(reader,version,type==2,song); } return readInsDataOld(reader,version);