new ins format, part 7

FM instruments now loadable
This commit is contained in:
tildearrow 2022-11-20 14:28:43 -05:00
parent badf91d447
commit 5ec4f2d1f0
4 changed files with 93 additions and 10 deletions

View file

@ -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... the main issue with Furnace instrument files is that they are too big, even if the instrument is nothing more than the FM setup...

View file

@ -47,8 +47,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false; #define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev125" #define DIV_VERSION "dev126"
#define DIV_ENGINE_VERSION 125 #define DIV_ENGINE_VERSION 126
// for imports // for imports
#define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02 #define DIV_VERSION_FC 0xff02

View file

@ -1880,10 +1880,19 @@ std::vector<DivInstrument*> DivEngine::instrumentFromFile(const char* path) {
unsigned char magic[16]; unsigned char magic[16];
bool isFurnaceInstr=false; bool isFurnaceInstr=false;
bool isOldFurnaceIns=false;
try { try {
reader.read(magic,16); reader.read(magic,4);
if (memcmp("-Furnace instr.-",magic,16)==0) { if (memcmp("FINS",magic,4)==0) {
isFurnaceInstr=true; 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) { } catch (EndOfFileException& e) {
reader.seek(0,SEEK_SET); reader.seek(0,SEEK_SET);
@ -1892,17 +1901,25 @@ std::vector<DivInstrument*> DivEngine::instrumentFromFile(const char* path) {
if (isFurnaceInstr) { if (isFurnaceInstr) {
DivInstrument* ins=new DivInstrument; DivInstrument* ins=new DivInstrument;
try { try {
short version=reader.readS(); short version=0;
reader.readS(); // reserved if (isOldFurnaceIns) {
version=reader.readS();
reader.readS(); // reserved
} else {
version=reader.readS();
reader.seek(0,SEEK_SET);
}
if (version>DIV_ENGINE_VERSION) { if (version>DIV_ENGINE_VERSION) {
warnings="this instrument is made with a more recent version of Furnace!"; warnings="this instrument is made with a more recent version of Furnace!";
} }
unsigned int dataPtr=reader.readI(); if (isOldFurnaceIns) {
reader.seek(dataPtr,SEEK_SET); 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!"; lastError="invalid instrument header/data!";
delete ins; delete ins;
delete[] buf; delete[] buf;

View file

@ -1738,6 +1738,71 @@ void DivInstrument::readFeatureNA(SafeReader& reader) {
void DivInstrument::readFeatureFM(SafeReader& reader) { void DivInstrument::readFeatureFM(SafeReader& reader) {
READ_FEAT_BEGIN; 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<opCount; i++) {
DivInstrumentFM::Operator& op=fm.op[i];
next=reader.readC();
op.ksr=(next&128)?1:0;
op.dt=(next>>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; READ_FEAT_END;
} }
@ -2644,6 +2709,7 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version, DivS
} }
if (type==1 || type==2) { if (type==1 || type==2) {
logV("reading new instrument data...");
return readInsDataNew(reader,version,type==2,song); return readInsDataNew(reader,version,type==2,song);
} }
return readInsDataOld(reader,version); return readInsDataOld(reader,version);