mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-15 17:25:06 +00:00
Instrument File Import support for 2op SBI, 4op SBI, and Freq Monster 801 SBI format (4op portion only).
This commit is contained in:
parent
e032580639
commit
b1a0aa86ef
1 changed files with 100 additions and 44 deletions
|
@ -1347,6 +1347,8 @@ bool DivEngine::addInstrumentFromFile(const char* path) {
|
||||||
format = DIV_INSFORMAT_SBI;
|
format = DIV_INSFORMAT_SBI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TDOO these really should be refactored to separate functions/cpp files per instrument file type.
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case DIV_INSFORMAT_DMP: {
|
case DIV_INSFORMAT_DMP: {
|
||||||
// this is a ridiculous mess
|
// this is a ridiculous mess
|
||||||
|
@ -1679,12 +1681,11 @@ bool DivEngine::addInstrumentFromFile(const char* path) {
|
||||||
ins->type = DIV_INS_OPL;
|
ins->type = DIV_INS_OPL;
|
||||||
|
|
||||||
int sbi_header = reader.readI();
|
int sbi_header = reader.readI();
|
||||||
// TODO check header == "SBI\x1A" (0x1A494253)
|
// SBI header determines format
|
||||||
|
bool is_2op = (sbi_header == 0x1A494253); // SBI\x1A
|
||||||
|
bool is_4op = (sbi_header == 0x1A504F34); // 4OP\x1A
|
||||||
|
bool is_6op = (sbi_header == 0x1A504F36); // 6OP\x1A - Freq Monster 801-specific
|
||||||
|
|
||||||
// 60 bytes = 4op SBI
|
|
||||||
// 52 bytes = 2op SBI (assumed)
|
|
||||||
bool is4op = (reader.size() >= 60);
|
|
||||||
|
|
||||||
// 32-byte null terminated instrument name
|
// 32-byte null terminated instrument name
|
||||||
ins->name = reader.readString(32);
|
ins->name = reader.readString(32);
|
||||||
|
|
||||||
|
@ -1713,73 +1714,128 @@ bool DivEngine::addInstrumentFromFile(const char* path) {
|
||||||
uint8_t sbi_M4wave;
|
uint8_t sbi_M4wave;
|
||||||
uint8_t sbi_C4wave;
|
uint8_t sbi_C4wave;
|
||||||
uint8_t sbi_4opConnect;
|
uint8_t sbi_4opConnect;
|
||||||
for (int j = 0; j < 6 && reader.tell() < reader.size(); ++j) {
|
|
||||||
reader.readC();
|
if (is_2op) {
|
||||||
|
DivInstrumentFM::Operator& opM = ins->fm.op[0];
|
||||||
|
DivInstrumentFM::Operator& opC = ins->fm.op[1];
|
||||||
|
ins->fm.ops = 2;
|
||||||
|
opM.mult = sbi_Mcharacteristics & 0xF;
|
||||||
|
opM.ksr = ((sbi_Mcharacteristics >> 4) & 0x1);
|
||||||
|
opM.sus = ((sbi_Mcharacteristics >> 5) & 0x1);
|
||||||
|
opM.vib = ((sbi_Mcharacteristics >> 6) & 0x1);
|
||||||
|
opM.am = ((sbi_Mcharacteristics >> 7) & 0x1);
|
||||||
|
opM.tl = sbi_Mscaling_output & 0x3F;
|
||||||
|
opM.ksl = ((sbi_Mscaling_output >> 6) & 0x3);
|
||||||
|
opM.ar = ((sbi_Meg_AD >> 4) & 0xF);
|
||||||
|
opM.dr = (sbi_Meg_AD & 0xF);
|
||||||
|
opM.rr = (sbi_Meg_SR & 0xF);
|
||||||
|
opM.sl = ((sbi_Meg_SR >> 4) & 0xF);
|
||||||
|
opM.ws = sbi_Mwave;
|
||||||
|
|
||||||
|
ins->fm.alg = (sbi_FeedConnect & 0x1);
|
||||||
|
ins->fm.fb = ((sbi_FeedConnect >> 1) & 0x7);
|
||||||
|
|
||||||
|
opC.mult = sbi_Ccharacteristics & 0xF;
|
||||||
|
opC.ksr = ((sbi_Ccharacteristics >> 4) & 0x1);
|
||||||
|
opC.sus = ((sbi_Ccharacteristics >> 5) & 0x1);
|
||||||
|
opC.vib = ((sbi_Ccharacteristics >> 6) & 0x1);
|
||||||
|
opC.am = ((sbi_Ccharacteristics >> 7) & 0x1);
|
||||||
|
opC.tl = sbi_Cscaling_output & 0x3F;
|
||||||
|
opC.ksl = ((sbi_Cscaling_output >> 6) & 0x3);
|
||||||
|
opC.ar = ((sbi_Ceg_AD >> 4) & 0xF);
|
||||||
|
opC.dr = (sbi_Ceg_AD & 0xF);
|
||||||
|
opC.rr = (sbi_Ceg_SR & 0xF);
|
||||||
|
opC.sl = ((sbi_Ceg_SR >> 4) & 0xF);
|
||||||
|
opC.ws = sbi_Cwave;
|
||||||
|
|
||||||
|
// Ignore rest of file - rest is 'reserved padding'.
|
||||||
|
if (is_2op) {
|
||||||
|
reader.seek(0, SEEK_END);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DivInstrumentFM::Operator& opM = ins->fm.op[0];
|
|
||||||
DivInstrumentFM::Operator& opC = ins->fm.op[1];
|
|
||||||
|
|
||||||
opM.mult = sbi_Mcharacteristics & 0xF;
|
if (is_4op || is_6op) {
|
||||||
opM.tl = sbi_Mscaling_output & 0x3F;
|
// Operator placement is different so need to place in correct registers.
|
||||||
//opM.rs = reader.readC();
|
// Note: 6op is an unofficial extension of 4op SBIs by Darron Broad (Freq Monster 801).
|
||||||
opM.ar = ((sbi_Meg_AD >> 4) & 0xF);
|
// We'll only use the 4op portion here for pure OPL3.
|
||||||
opM.dr = (sbi_Meg_AD & 0xF);
|
DivInstrumentFM::Operator& opM = ins->fm.op[0];
|
||||||
opM.rr = (sbi_Meg_SR & 0xF);
|
DivInstrumentFM::Operator& opC = ins->fm.op[2];
|
||||||
opM.sl = ((sbi_Meg_SR >> 4) & 0xF);
|
DivInstrumentFM::Operator& opM4 = ins->fm.op[1];
|
||||||
//opM.ssgEnv = reader.readC();
|
DivInstrumentFM::Operator& opC4 = ins->fm.op[3];
|
||||||
|
ins->fm.ops = 4;
|
||||||
|
|
||||||
ins->fm.alg = (sbi_FeedConnect & 0x1);
|
|
||||||
ins->fm.fb = (sbi_FeedConnect >> 1) & 0x7;
|
|
||||||
|
|
||||||
opC.mult = sbi_Ccharacteristics & 0xF;
|
|
||||||
opC.tl = sbi_Cscaling_output & 0x3F;
|
|
||||||
//opC.rs = ???;
|
|
||||||
opC.ar = ((sbi_Ceg_AD >> 4) & 0xF);
|
|
||||||
opC.dr = (sbi_Ceg_AD & 0xF);
|
|
||||||
opC.rr = (sbi_Ceg_SR & 0xF);
|
|
||||||
opC.sl = ((sbi_Ceg_SR >> 4) & 0xF);
|
|
||||||
//opC.ssgEnv = ???;
|
|
||||||
|
|
||||||
if (is4op) {
|
|
||||||
sbi_M4characteristics = reader.readC();
|
sbi_M4characteristics = reader.readC();
|
||||||
sbi_C4characteristics = reader.readC();
|
sbi_C4characteristics = reader.readC();
|
||||||
sbi_M4scaling_output = reader.readC();
|
sbi_M4scaling_output = reader.readC();
|
||||||
sbi_C4scaling_output = reader.readC();
|
sbi_C4scaling_output = reader.readC();
|
||||||
sbi_M4eg_AD = reader.readC();
|
sbi_M4eg_AD = reader.readC();
|
||||||
|
sbi_C4eg_AD = reader.readC();
|
||||||
sbi_M4eg_SR = reader.readC();
|
sbi_M4eg_SR = reader.readC();
|
||||||
|
sbi_C4eg_SR = reader.readC();
|
||||||
sbi_M4wave = reader.readC();
|
sbi_M4wave = reader.readC();
|
||||||
sbi_C4wave = reader.readC();
|
sbi_C4wave = reader.readC();
|
||||||
sbi_4opConnect = reader.readC();
|
sbi_4opConnect = reader.readC();
|
||||||
for (int j = 0; j < 6 && reader.tell() < reader.size(); ++j) {
|
|
||||||
reader.readC();
|
ins->fm.alg = (sbi_FeedConnect & 0x1) | ((sbi_4opConnect & 0x1) << 1);
|
||||||
}
|
|
||||||
|
|
||||||
|
opM.mult = sbi_Mcharacteristics & 0xF;
|
||||||
|
opM.ksr = ((sbi_Mcharacteristics >> 4) & 0x1);
|
||||||
|
opM.sus = ((sbi_Mcharacteristics >> 5) & 0x1);
|
||||||
|
opM.vib = ((sbi_Mcharacteristics >> 6) & 0x1);
|
||||||
|
opM.am = ((sbi_Mcharacteristics >> 7) & 0x1);
|
||||||
|
opM.tl = sbi_Mscaling_output & 0x3F;
|
||||||
|
opM.ksl = ((sbi_Mscaling_output >> 6) & 0x3);
|
||||||
|
opM.ar = ((sbi_Meg_AD >> 4) & 0xF);
|
||||||
|
opM.dr = (sbi_Meg_AD & 0xF);
|
||||||
|
opM.rr = (sbi_Meg_SR & 0xF);
|
||||||
|
opM.sl = ((sbi_Meg_SR >> 4) & 0xF);
|
||||||
|
opM.ws = sbi_Mwave;
|
||||||
|
|
||||||
ins->fm.alg |= (sbi_4opConnect & 0x1);
|
opC.mult = sbi_Ccharacteristics & 0xF;
|
||||||
DivInstrumentFM::Operator& opM4 = ins->fm.op[2];
|
opC.ksr = ((sbi_Ccharacteristics >> 4) & 0x1);
|
||||||
DivInstrumentFM::Operator& opC4 = ins->fm.op[3];
|
opC.sus = ((sbi_Ccharacteristics >> 5) & 0x1);
|
||||||
|
opC.vib = ((sbi_Ccharacteristics >> 6) & 0x1);
|
||||||
|
opC.am = ((sbi_Ccharacteristics >> 7) & 0x1);
|
||||||
|
opC.tl = sbi_Cscaling_output & 0x3F;
|
||||||
|
opC.ksl = ((sbi_Cscaling_output >> 6) & 0x3);
|
||||||
|
opC.ar = ((sbi_Ceg_AD >> 4) & 0xF);
|
||||||
|
opC.dr = (sbi_Ceg_AD & 0xF);
|
||||||
|
opC.rr = (sbi_Ceg_SR & 0xF);
|
||||||
|
opC.sl = ((sbi_Ceg_SR >> 4) & 0xF);
|
||||||
|
opC.ws = sbi_Cwave;
|
||||||
|
|
||||||
opM4.mult = sbi_M4characteristics & 0xF;
|
opM4.mult = sbi_M4characteristics & 0xF;
|
||||||
|
opM4.ksr = ((sbi_M4characteristics >> 4) & 0x1);
|
||||||
|
opM4.sus = ((sbi_M4characteristics >> 5) & 0x1);
|
||||||
|
opM4.vib = ((sbi_M4characteristics >> 6) & 0x1);
|
||||||
|
opM4.am = ((sbi_M4characteristics >> 7) & 0x1);
|
||||||
opM4.tl = sbi_M4scaling_output & 0x3F;
|
opM4.tl = sbi_M4scaling_output & 0x3F;
|
||||||
//opM4.rs = reader.readC();
|
opM4.ksl = ((sbi_M4scaling_output >> 6) & 0x3);
|
||||||
opM4.ar = ((sbi_M4eg_AD >> 4) & 0xF);
|
opM4.ar = ((sbi_M4eg_AD >> 4) & 0xF);
|
||||||
opM4.dr = (sbi_M4eg_AD & 0xF);
|
opM4.dr = (sbi_M4eg_AD & 0xF);
|
||||||
opM4.rr = (sbi_M4eg_SR & 0xF);
|
opM4.rr = (sbi_M4eg_SR & 0xF);
|
||||||
opM4.sl = ((sbi_M4eg_SR >> 4) & 0xF);
|
opM4.sl = ((sbi_M4eg_SR >> 4) & 0xF);
|
||||||
//opM4.ssgEnv = reader.readC();
|
opM4.ws = sbi_M4wave;
|
||||||
|
|
||||||
opC4.mult = sbi_C4characteristics & 0xF;
|
opC4.mult = sbi_C4characteristics & 0xF;
|
||||||
|
opC4.ksr = ((sbi_C4characteristics >> 4) & 0x1);
|
||||||
|
opC4.sus = ((sbi_C4characteristics >> 5) & 0x1);
|
||||||
|
opC4.vib = ((sbi_C4characteristics >> 6) & 0x1);
|
||||||
|
opC4.am = ((sbi_C4characteristics >> 7) & 0x1);
|
||||||
opC4.tl = sbi_C4scaling_output & 0x3F;
|
opC4.tl = sbi_C4scaling_output & 0x3F;
|
||||||
//opC4.rs = ???;
|
opC4.ksl = ((sbi_C4scaling_output >> 6) & 0x3);
|
||||||
opC4.ar = ((sbi_C4eg_AD >> 4) & 0xF);
|
opC4.ar = ((sbi_C4eg_AD >> 4) & 0xF);
|
||||||
opC4.dr = (sbi_C4eg_AD & 0xF);
|
opC4.dr = (sbi_C4eg_AD & 0xF);
|
||||||
opC4.rr = (sbi_C4eg_SR & 0xF);
|
opC4.rr = (sbi_C4eg_SR & 0xF);
|
||||||
opC4.sl = ((sbi_C4eg_SR >> 4) & 0xF);
|
opC4.sl = ((sbi_C4eg_SR >> 4) & 0xF);
|
||||||
//opC4.ssgEnv = ???;
|
opC4.ws = sbi_C4wave;
|
||||||
|
|
||||||
|
// Ignore rest of file once we've read in all we need.
|
||||||
|
// Note: Freq Monster 801 adds a ton of other additional fields irrelevant to chip registers.
|
||||||
|
reader.seek(0, SEEK_END);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (EndOfFileException& e) {
|
} catch (EndOfFileException& e) {
|
||||||
lastError = "premature end of file";
|
lastError = "premature end of file";
|
||||||
logE("premature end of file!\n");
|
logE("premature end of file!\n");
|
||||||
delete ins;
|
delete ins;
|
||||||
|
|
Loading…
Reference in a new issue