SBI fixes:
- Support 2OP\x1A header (used in some third party implementations) - Include 2op pair for Freq Monster 801 6op (4+2op) patches. - Fall back to filename if no internal patch name found.
This commit is contained in:
parent
96715ed88c
commit
ee14f0fa8c
|
@ -447,6 +447,8 @@ void DivEngine::loadS3I(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
logE("S3I PCM samples currently not supported.");
|
logE("S3I PCM samples currently not supported.");
|
||||||
}
|
}
|
||||||
ins->name = reader.readString(28);
|
ins->name = reader.readString(28);
|
||||||
|
ins->name = (ins->name[0] == '\0') ? stripPath : ins->name;
|
||||||
|
|
||||||
int s3i_signature = reader.readI();
|
int s3i_signature = reader.readI();
|
||||||
|
|
||||||
if (s3i_signature != 0x49524353) {
|
if (s3i_signature != 0x49524353) {
|
||||||
|
@ -470,12 +472,13 @@ void DivEngine::loadSBI(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
|
|
||||||
int sbi_header = reader.readI();
|
int sbi_header = reader.readI();
|
||||||
// SBI header determines format
|
// SBI header determines format
|
||||||
bool is_2op = (sbi_header == 0x1A494253); // SBI\x1A
|
bool is_2op = (sbi_header == 0x1A494253 || sbi_header == 0x1A504F32); // SBI\x1A or 2OP\x1A
|
||||||
bool is_4op = (sbi_header == 0x1A504F34); // 4OP\x1A
|
bool is_4op = (sbi_header == 0x1A504F34); // 4OP\x1A
|
||||||
bool is_6op = (sbi_header == 0x1A504F36); // 6OP\x1A - Freq Monster 801-specific
|
bool is_6op = (sbi_header == 0x1A504F36); // 6OP\x1A - Freq Monster 801-specific
|
||||||
|
|
||||||
// 32-byte null terminated instrument name
|
// 32-byte null terminated instrument name
|
||||||
ins->name = reader.readString(32);
|
String patchName = reader.readString(32);
|
||||||
|
patchName = (patchName.length() == 0) ? stripPath : patchName;
|
||||||
|
|
||||||
// 2op SBI
|
// 2op SBI
|
||||||
uint8_t sbi_Mcharacteristics = reader.readC();
|
uint8_t sbi_Mcharacteristics = reader.readC();
|
||||||
|
@ -507,6 +510,8 @@ void DivEngine::loadSBI(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
DivInstrumentFM::Operator& opM = ins->fm.op[0];
|
DivInstrumentFM::Operator& opM = ins->fm.op[0];
|
||||||
DivInstrumentFM::Operator& opC = ins->fm.op[1];
|
DivInstrumentFM::Operator& opC = ins->fm.op[1];
|
||||||
ins->fm.ops = 2;
|
ins->fm.ops = 2;
|
||||||
|
ins->name = patchName;
|
||||||
|
|
||||||
opM.mult = sbi_Mcharacteristics & 0xF;
|
opM.mult = sbi_Mcharacteristics & 0xF;
|
||||||
opM.ksr = ((sbi_Mcharacteristics >> 4) & 0x1);
|
opM.ksr = ((sbi_Mcharacteristics >> 4) & 0x1);
|
||||||
opM.sus = ((sbi_Mcharacteristics >> 5) & 0x1);
|
opM.sus = ((sbi_Mcharacteristics >> 5) & 0x1);
|
||||||
|
@ -538,6 +543,7 @@ void DivEngine::loadSBI(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
|
|
||||||
// Ignore rest of file - rest is 'reserved padding'.
|
// Ignore rest of file - rest is 'reserved padding'.
|
||||||
reader.seek(0, SEEK_END);
|
reader.seek(0, SEEK_END);
|
||||||
|
ret.push_back(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_4op || is_6op) {
|
if (is_4op || is_6op) {
|
||||||
|
@ -549,6 +555,7 @@ void DivEngine::loadSBI(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
DivInstrumentFM::Operator& opM4 = ins->fm.op[1];
|
DivInstrumentFM::Operator& opM4 = ins->fm.op[1];
|
||||||
DivInstrumentFM::Operator& opC4 = ins->fm.op[3];
|
DivInstrumentFM::Operator& opC4 = ins->fm.op[3];
|
||||||
ins->fm.ops = 4;
|
ins->fm.ops = 4;
|
||||||
|
ins->name = patchName;
|
||||||
|
|
||||||
sbi_M4characteristics = reader.readC();
|
sbi_M4characteristics = reader.readC();
|
||||||
sbi_C4characteristics = reader.readC();
|
sbi_C4characteristics = reader.readC();
|
||||||
|
@ -617,19 +624,71 @@ void DivEngine::loadSBI(SafeReader& reader, std::vector<DivInstrument*>& ret, St
|
||||||
opC4.sl = ((sbi_C4eg_SR >> 4) & 0xF);
|
opC4.sl = ((sbi_C4eg_SR >> 4) & 0xF);
|
||||||
opC4.ws = sbi_C4wave;
|
opC4.ws = sbi_C4wave;
|
||||||
|
|
||||||
|
// Freq Monster 801 SBIs use a 4op+2op layout
|
||||||
|
if (is_6op) {
|
||||||
|
ins->name = ins->name + " (4op)";
|
||||||
|
ret.push_back(ins);
|
||||||
|
|
||||||
|
ins = new DivInstrument;
|
||||||
|
DivInstrumentFM::Operator& opM6 = ins->fm.op[0];
|
||||||
|
DivInstrumentFM::Operator& opC6 = ins->fm.op[1];
|
||||||
|
ins->type = DIV_INS_OPL;
|
||||||
|
ins->fm.ops = 2;
|
||||||
|
ins->name = patchName + " (2op)";
|
||||||
|
|
||||||
|
sbi_Mcharacteristics = reader.readC();
|
||||||
|
sbi_Ccharacteristics = reader.readC();
|
||||||
|
sbi_Mscaling_output = reader.readC();
|
||||||
|
sbi_Cscaling_output = reader.readC();
|
||||||
|
sbi_Meg_AD = reader.readC();
|
||||||
|
sbi_Ceg_AD = reader.readC();
|
||||||
|
sbi_Meg_SR = reader.readC();
|
||||||
|
sbi_Ceg_SR = reader.readC();
|
||||||
|
sbi_Mwave = reader.readC();
|
||||||
|
sbi_Cwave = reader.readC();
|
||||||
|
sbi_FeedConnect = reader.readC();
|
||||||
|
|
||||||
|
opM6.mult = sbi_Mcharacteristics & 0xF;
|
||||||
|
opM6.ksr = ((sbi_Mcharacteristics >> 4) & 0x1);
|
||||||
|
opM6.sus = ((sbi_Mcharacteristics >> 5) & 0x1);
|
||||||
|
opM6.vib = ((sbi_Mcharacteristics >> 6) & 0x1);
|
||||||
|
opM6.am = ((sbi_Mcharacteristics >> 7) & 0x1);
|
||||||
|
opM6.tl = sbi_Mscaling_output & 0x3F;
|
||||||
|
opM6.ksl = ((sbi_Mscaling_output >> 6) & 0x3);
|
||||||
|
opM6.ar = ((sbi_Meg_AD >> 4) & 0xF);
|
||||||
|
opM6.dr = (sbi_Meg_AD & 0xF);
|
||||||
|
opM6.rr = (sbi_Meg_SR & 0xF);
|
||||||
|
opM6.sl = ((sbi_Meg_SR >> 4) & 0xF);
|
||||||
|
opM6.ws = sbi_Mwave;
|
||||||
|
|
||||||
|
ins->fm.alg = (sbi_FeedConnect & 0x1);
|
||||||
|
ins->fm.fb = ((sbi_FeedConnect >> 1) & 0x7);
|
||||||
|
|
||||||
|
opC6.mult = sbi_Ccharacteristics & 0xF;
|
||||||
|
opC6.ksr = ((sbi_Ccharacteristics >> 4) & 0x1);
|
||||||
|
opC6.sus = ((sbi_Ccharacteristics >> 5) & 0x1);
|
||||||
|
opC6.vib = ((sbi_Ccharacteristics >> 6) & 0x1);
|
||||||
|
opC6.am = ((sbi_Ccharacteristics >> 7) & 0x1);
|
||||||
|
opC6.tl = sbi_Cscaling_output & 0x3F;
|
||||||
|
opC6.ksl = ((sbi_Cscaling_output >> 6) & 0x3);
|
||||||
|
opC6.ar = ((sbi_Ceg_AD >> 4) & 0xF);
|
||||||
|
opC6.dr = (sbi_Ceg_AD & 0xF);
|
||||||
|
opC6.rr = (sbi_Ceg_SR & 0xF);
|
||||||
|
opC6.sl = ((sbi_Ceg_SR >> 4) & 0xF);
|
||||||
|
opC6.ws = sbi_Cwave;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore rest of file once we've read in all we need.
|
// 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.
|
// Note: Freq Monster 801 adds a ton of other additional fields irrelevant to chip registers.
|
||||||
reader.seek(0, SEEK_END);
|
reader.seek(0, SEEK_END);
|
||||||
|
ret.push_back(ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (EndOfFileException& e) {
|
} catch (EndOfFileException& e) {
|
||||||
lastError = "premature end of file";
|
lastError = "premature end of file";
|
||||||
logE("premature end of file!");
|
logE("premature end of file!");
|
||||||
delete ins;
|
delete ins;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push_back(ins);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::loadFF(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath) {
|
void DivEngine::loadFF(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath) {
|
||||||
|
|
Loading…
Reference in New Issue