From e0325806390762fe04acdc7dbcf38f7fc1ad33ca Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sat, 19 Mar 2022 17:13:00 +1100 Subject: [PATCH 1/7] Started SBI import work (Issue #79 SBI task). Also ensure catch by reference not value. --- src/engine/engine.cpp | 139 +++++++++++++++++++++++++++++++++++++---- src/engine/fileOps.cpp | 8 +-- src/gui/gui.cpp | 5 +- 3 files changed, 135 insertions(+), 17 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 3352a873..169dcb3c 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1222,7 +1222,8 @@ enum DivInsFormats { DIV_INSFORMAT_TFI, DIV_INSFORMAT_VGI, DIV_INSFORMAT_FTI, - DIV_INSFORMAT_BTI + DIV_INSFORMAT_BTI, + DIV_INSFORMAT_SBI, }; bool DivEngine::addInstrumentFromFile(const char* path) { @@ -1290,7 +1291,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { if (memcmp("-Furnace instr.-",magic,16)==0) { isFurnaceInstr=true; } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { reader.seek(0,SEEK_SET); } @@ -1313,7 +1314,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { delete[] buf; return false; } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1342,6 +1343,8 @@ bool DivEngine::addInstrumentFromFile(const char* path) { format=DIV_INSFORMAT_FTI; } else if (extS==String(".bti")) { format=DIV_INSFORMAT_BTI; + } else if (extS==String(".sbi")) { + format = DIV_INSFORMAT_SBI; } } switch (format) { @@ -1352,7 +1355,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { try { reader.seek(0,SEEK_SET); version=reader.readC(); - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1405,7 +1408,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { return false; break; } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1586,7 +1589,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { ins->gb.soundLen=reader.readC(); } } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1619,7 +1622,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { op.sl=reader.readC(); op.ssgEnv=reader.readC(); } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1658,7 +1661,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { op.sl=reader.readC(); op.ssgEnv=reader.readC(); } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { lastError="premature end of file"; logE("premature end of file!\n"); delete ins; @@ -1670,6 +1673,120 @@ bool DivEngine::addInstrumentFromFile(const char* path) { break; case DIV_INSFORMAT_BTI: break; + case DIV_INSFORMAT_SBI: + try { + reader.seek(0, SEEK_SET); + ins->type = DIV_INS_OPL; + + int sbi_header = reader.readI(); + // TODO check header == "SBI\x1A" (0x1A494253) + + // 60 bytes = 4op SBI + // 52 bytes = 2op SBI (assumed) + bool is4op = (reader.size() >= 60); + + // 32-byte null terminated instrument name + ins->name = reader.readString(32); + + // 2op SBI + uint8_t sbi_Mcharacteristics = reader.readC(); + uint8_t sbi_Ccharacteristics = reader.readC(); + uint8_t sbi_Mscaling_output = reader.readC(); + uint8_t sbi_Cscaling_output = reader.readC(); + uint8_t sbi_Meg_AD = reader.readC(); + uint8_t sbi_Ceg_AD = reader.readC(); + uint8_t sbi_Meg_SR = reader.readC(); + uint8_t sbi_Ceg_SR = reader.readC(); + uint8_t sbi_Mwave = reader.readC(); + uint8_t sbi_Cwave = reader.readC(); + uint8_t sbi_FeedConnect = reader.readC(); + + // 4op SBI + uint8_t sbi_M4characteristics; + uint8_t sbi_C4characteristics; + uint8_t sbi_M4scaling_output; + uint8_t sbi_C4scaling_output; + uint8_t sbi_M4eg_AD; + uint8_t sbi_C4eg_AD; + uint8_t sbi_M4eg_SR; + uint8_t sbi_C4eg_SR; + uint8_t sbi_M4wave; + uint8_t sbi_C4wave; + uint8_t sbi_4opConnect; + for (int j = 0; j < 6 && reader.tell() < reader.size(); ++j) { + reader.readC(); + } + + DivInstrumentFM::Operator& opM = ins->fm.op[0]; + DivInstrumentFM::Operator& opC = ins->fm.op[1]; + + opM.mult = sbi_Mcharacteristics & 0xF; + opM.tl = sbi_Mscaling_output & 0x3F; + //opM.rs = reader.readC(); + 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.ssgEnv = reader.readC(); + + 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_C4characteristics = reader.readC(); + sbi_M4scaling_output = reader.readC(); + sbi_C4scaling_output = reader.readC(); + sbi_M4eg_AD = reader.readC(); + sbi_M4eg_SR = reader.readC(); + sbi_M4wave = reader.readC(); + sbi_C4wave = reader.readC(); + sbi_4opConnect = reader.readC(); + for (int j = 0; j < 6 && reader.tell() < reader.size(); ++j) { + reader.readC(); + } + + + ins->fm.alg |= (sbi_4opConnect & 0x1); + DivInstrumentFM::Operator& opM4 = ins->fm.op[2]; + DivInstrumentFM::Operator& opC4 = ins->fm.op[3]; + + opM4.mult = sbi_M4characteristics & 0xF; + opM4.tl = sbi_M4scaling_output & 0x3F; + //opM4.rs = reader.readC(); + opM4.ar = ((sbi_M4eg_AD >> 4) & 0xF); + opM4.dr = (sbi_M4eg_AD & 0xF); + opM4.rr = (sbi_M4eg_SR & 0xF); + opM4.sl = ((sbi_M4eg_SR >> 4) & 0xF); + //opM4.ssgEnv = reader.readC(); + + opC4.mult = sbi_C4characteristics & 0xF; + opC4.tl = sbi_C4scaling_output & 0x3F; + //opC4.rs = ???; + opC4.ar = ((sbi_C4eg_AD >> 4) & 0xF); + opC4.dr = (sbi_C4eg_AD & 0xF); + opC4.rr = (sbi_C4eg_SR & 0xF); + opC4.sl = ((sbi_C4eg_SR >> 4) & 0xF); + //opC4.ssgEnv = ???; + } + } + catch (EndOfFileException& e) { + lastError = "premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; + } + break; } if (reader.tell()len=len; } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { // read as binary len=reader.size(); logI("reading binary for being too small...\n"); @@ -1824,7 +1941,7 @@ bool DivEngine::addWaveFromFile(const char* path) { wave->len=len; } } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { delete wave; delete[] buf; return false; diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index f6038f45..23570c47 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -742,7 +742,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { initDispatch(); syncReset(); } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { logE("premature end of file!\n"); lastError="incomplete file"; delete[] file; @@ -1228,7 +1228,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { initDispatch(); syncReset(); } - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { logE("premature end of file!\n"); lastError="incomplete file"; delete[] file; @@ -1593,10 +1593,10 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) { syncReset(); } success=true; - } catch (EndOfFileException e) { + } catch (EndOfFileException& e) { //logE("premature end of file!\n"); lastError="incomplete file"; - } catch (InvalidHeaderException e) { + } catch (InvalidHeaderException& e) { //logE("invalid info header!\n"); lastError="invalid info header!"; } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 78deccd3..03a679a6 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4658,9 +4658,9 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { if (!dirExists(workingDirIns)) workingDirIns=getHomeDir(); hasOpened=fileDialog->openLoad( "Load Instrument", - {"compatible files", "*.fui *.dmp *.tfi *.vgi", + {"compatible files", "*.fui *.dmp *.tfi *.vgi, *.sbi", "all files", ".*"}, - "compatible files{.fui,.dmp,.tfi,.vgi},.*", + "compatible files{.fui,.dmp,.tfi,.vgi.sbi},.*", workingDirIns, dpiScale ); @@ -6886,6 +6886,7 @@ bool FurnaceGUI::init() { ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".tfi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".vgi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".sbi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".fti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".bti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); From b1a0aa86ef9d4c4088a4c615607114cd7409af9a Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 00:52:43 +1100 Subject: [PATCH 2/7] Instrument File Import support for 2op SBI, 4op SBI, and Freq Monster 801 SBI format (4op portion only). --- src/engine/engine.cpp | 144 +++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 44 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 169dcb3c..2345f0d6 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1347,6 +1347,8 @@ bool DivEngine::addInstrumentFromFile(const char* path) { format = DIV_INSFORMAT_SBI; } } + + // TDOO these really should be refactored to separate functions/cpp files per instrument file type. switch (format) { case DIV_INSFORMAT_DMP: { // this is a ridiculous mess @@ -1679,12 +1681,11 @@ bool DivEngine::addInstrumentFromFile(const char* path) { ins->type = DIV_INS_OPL; 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 ins->name = reader.readString(32); @@ -1713,73 +1714,128 @@ bool DivEngine::addInstrumentFromFile(const char* path) { uint8_t sbi_M4wave; uint8_t sbi_C4wave; 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; - opM.tl = sbi_Mscaling_output & 0x3F; - //opM.rs = reader.readC(); - 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.ssgEnv = reader.readC(); + if (is_4op || is_6op) { + // Operator placement is different so need to place in correct registers. + // Note: 6op is an unofficial extension of 4op SBIs by Darron Broad (Freq Monster 801). + // We'll only use the 4op portion here for pure OPL3. + DivInstrumentFM::Operator& opM = ins->fm.op[0]; + DivInstrumentFM::Operator& opC = ins->fm.op[2]; + DivInstrumentFM::Operator& opM4 = ins->fm.op[1]; + 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_C4characteristics = reader.readC(); sbi_M4scaling_output = reader.readC(); sbi_C4scaling_output = reader.readC(); sbi_M4eg_AD = reader.readC(); + sbi_C4eg_AD = reader.readC(); sbi_M4eg_SR = reader.readC(); + sbi_C4eg_SR = reader.readC(); sbi_M4wave = reader.readC(); sbi_C4wave = 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); - DivInstrumentFM::Operator& opM4 = ins->fm.op[2]; - DivInstrumentFM::Operator& opC4 = ins->fm.op[3]; - + 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; + 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.rs = reader.readC(); + opM4.ksl = ((sbi_M4scaling_output >> 6) & 0x3); opM4.ar = ((sbi_M4eg_AD >> 4) & 0xF); opM4.dr = (sbi_M4eg_AD & 0xF); opM4.rr = (sbi_M4eg_SR & 0xF); opM4.sl = ((sbi_M4eg_SR >> 4) & 0xF); - //opM4.ssgEnv = reader.readC(); + opM4.ws = sbi_M4wave; 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.rs = ???; + opC4.ksl = ((sbi_C4scaling_output >> 6) & 0x3); opC4.ar = ((sbi_C4eg_AD >> 4) & 0xF); opC4.dr = (sbi_C4eg_AD & 0xF); opC4.rr = (sbi_C4eg_SR & 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"; logE("premature end of file!\n"); delete ins; From efdedd104466fae856a801a13849cb583259645a Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 01:02:34 +1100 Subject: [PATCH 3/7] Fix typo --- src/gui/gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 03a679a6..033ae2f0 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4660,7 +4660,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { "Load Instrument", {"compatible files", "*.fui *.dmp *.tfi *.vgi, *.sbi", "all files", ".*"}, - "compatible files{.fui,.dmp,.tfi,.vgi.sbi},.*", + "compatible files{.fui,.dmp,.tfi,.vgi,.sbi},.*", workingDirIns, dpiScale ); From 53968891955ff66108c35d32f2c680204d0dd70a Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 01:04:38 +1100 Subject: [PATCH 4/7] Missed feedback for 4op block --- src/engine/engine.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 2345f0d6..86fa0ec3 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1777,6 +1777,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { sbi_4opConnect = reader.readC(); ins->fm.alg = (sbi_FeedConnect & 0x1) | ((sbi_4opConnect & 0x1) << 1); + ins->fm.fb = ((sbi_FeedConnect >> 1) & 0x7); opM.mult = sbi_Mcharacteristics & 0xF; opM.ksr = ((sbi_Mcharacteristics >> 4) & 0x1); From 629049dea0ce5af426849fb1b09298e4222fd193 Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 05:50:22 +1100 Subject: [PATCH 5/7] Redundant if-statement --- src/engine/engine.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 86fa0ec3..835636bd 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1749,9 +1749,7 @@ bool DivEngine::addInstrumentFromFile(const char* path) { opC.ws = sbi_Cwave; // Ignore rest of file - rest is 'reserved padding'. - if (is_2op) { - reader.seek(0, SEEK_END); - } + reader.seek(0, SEEK_END); } if (is_4op || is_6op) { From cbe74b26adc38a633188f07967c18a1ef639bf78 Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 17:12:03 +1100 Subject: [PATCH 6/7] More #79 - Add S3I Adlib instrument support. Also fix SafeReader `SEEK_CUR` handling (wasn't used at all). --- src/engine/engine.cpp | 82 +++++++++++++++++++++++++++++++++++++++ src/engine/safeReader.cpp | 4 +- src/gui/gui.cpp | 5 ++- 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 835636bd..1f52ad16 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1223,6 +1223,7 @@ enum DivInsFormats { DIV_INSFORMAT_VGI, DIV_INSFORMAT_FTI, DIV_INSFORMAT_BTI, + DIV_INSFORMAT_S3I, DIV_INSFORMAT_SBI, }; @@ -1343,6 +1344,8 @@ bool DivEngine::addInstrumentFromFile(const char* path) { format=DIV_INSFORMAT_FTI; } else if (extS==String(".bti")) { format=DIV_INSFORMAT_BTI; + } else if (extS==String(".s3i")) { + format = DIV_INSFORMAT_S3I; } else if (extS==String(".sbi")) { format = DIV_INSFORMAT_SBI; } @@ -1675,6 +1678,85 @@ bool DivEngine::addInstrumentFromFile(const char* path) { break; case DIV_INSFORMAT_BTI: break; + case DIV_INSFORMAT_S3I: + try { + reader.seek(0, SEEK_SET); + + uint8_t s3i_type = reader.readC(); + + if (s3i_type >= 2) { + ins->type = DIV_INS_OPL; + // skip internal filename - we'll use the long name description + reader.seek(12, SEEK_CUR); + + // skip reserved bytes + reader.seek(3, SEEK_CUR); + + // 12-byte opl value + uint8_t s3i_Mcharacteristics = reader.readC(); + uint8_t s3i_Ccharacteristics = reader.readC(); + uint8_t s3i_Mscaling_output = reader.readC(); + uint8_t s3i_Cscaling_output = reader.readC(); + uint8_t s3i_Meg_AD = reader.readC(); + uint8_t s3i_Ceg_AD = reader.readC(); + uint8_t s3i_Meg_SR = reader.readC(); + uint8_t s3i_Ceg_SR = reader.readC(); + uint8_t s3i_Mwave = reader.readC(); + uint8_t s3i_Cwave = reader.readC(); + uint8_t s3i_FeedConnect = reader.readC(); + + DivInstrumentFM::Operator& opM = ins->fm.op[0]; + DivInstrumentFM::Operator& opC = ins->fm.op[1]; + ins->fm.ops = 2; + opM.mult = s3i_Mcharacteristics & 0xF; + opM.ksr = ((s3i_Mcharacteristics >> 4) & 0x1); + opM.sus = ((s3i_Mcharacteristics >> 5) & 0x1); + opM.vib = ((s3i_Mcharacteristics >> 6) & 0x1); + opM.am = ((s3i_Mcharacteristics >> 7) & 0x1); + opM.tl = s3i_Mscaling_output & 0x3F; + opM.ksl = ((s3i_Mscaling_output >> 6) & 0x3); + opM.ar = ((s3i_Meg_AD >> 4) & 0xF); + opM.dr = (s3i_Meg_AD & 0xF); + opM.rr = (s3i_Meg_SR & 0xF); + opM.sl = ((s3i_Meg_SR >> 4) & 0xF); + opM.ws = s3i_Mwave; + + ins->fm.alg = (s3i_FeedConnect & 0x1); + ins->fm.fb = ((s3i_FeedConnect >> 1) & 0x7); + + opC.mult = s3i_Ccharacteristics & 0xF; + opC.ksr = ((s3i_Ccharacteristics >> 4) & 0x1); + opC.sus = ((s3i_Ccharacteristics >> 5) & 0x1); + opC.vib = ((s3i_Ccharacteristics >> 6) & 0x1); + opC.am = ((s3i_Ccharacteristics >> 7) & 0x1); + opC.tl = s3i_Cscaling_output & 0x3F; + opC.ksl = ((s3i_Cscaling_output >> 6) & 0x3); + opC.ar = ((s3i_Ceg_AD >> 4) & 0xF); + opC.dr = (s3i_Ceg_AD & 0xF); + opC.rr = (s3i_Ceg_SR & 0xF); + opC.sl = ((s3i_Ceg_SR >> 4) & 0xF); + opC.ws = s3i_Cwave; + + // Skip more stuff we don't need + reader.seek(21, SEEK_CUR); + } else { + logE("S3I PCM samples currently not supported."); + } + ins->name = reader.readString(28); + int s3i_signature = reader.readI(); + + if (s3i_signature != 0x49524353) { + logW("S3I signature invalid."); + }; + } + catch (EndOfFileException& e) { + lastError = "premature end of file"; + logE("premature end of file!\n"); + delete ins; + delete[] buf; + return false; + } + break; case DIV_INSFORMAT_SBI: try { reader.seek(0, SEEK_SET); diff --git a/src/engine/safeReader.cpp b/src/engine/safeReader.cpp index b2b95551..9b096ef7 100644 --- a/src/engine/safeReader.cpp +++ b/src/engine/safeReader.cpp @@ -30,14 +30,14 @@ bool SafeReader::seek(ssize_t where, int whence) { curSeek=where; break; case SEEK_CUR: { - ssize_t finalSeek=len+where; + ssize_t finalSeek=curSeek+where; if (finalSeek<0) return false; if (finalSeek>(ssize_t)len) return false; curSeek=finalSeek; break; } case SEEK_END: { - ssize_t finalSeek=len-where; + ssize_t finalSeek=curSeek-where; if (finalSeek<0) return false; if (finalSeek>(ssize_t)len) return false; curSeek=finalSeek; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 033ae2f0..ae176447 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4658,9 +4658,9 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { if (!dirExists(workingDirIns)) workingDirIns=getHomeDir(); hasOpened=fileDialog->openLoad( "Load Instrument", - {"compatible files", "*.fui *.dmp *.tfi *.vgi, *.sbi", + {"compatible files", "*.fui *.dmp *.tfi *.vgi *.s3i *.sbi", "all files", ".*"}, - "compatible files{.fui,.dmp,.tfi,.vgi,.sbi},.*", + "compatible files{.fui,.dmp,.tfi,.vgi,.s3i,.sbi},.*", workingDirIns, dpiScale ); @@ -6886,6 +6886,7 @@ bool FurnaceGUI::init() { ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".tfi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".vgi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); + ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".s3i",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".sbi",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".fti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".bti",ImVec4(1.0f,0.5f,0.5f,1.0f),ICON_FA_FILE); From 5e005262a5832fc573364963350452b032b86a52 Mon Sep 17 00:00:00 2001 From: James Alan Nguyen Date: Sun, 20 Mar 2022 17:18:54 +1100 Subject: [PATCH 7/7] `SEEK_END` is correct - revert accidental change there. --- src/engine/safeReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/safeReader.cpp b/src/engine/safeReader.cpp index 9b096ef7..9add1b5a 100644 --- a/src/engine/safeReader.cpp +++ b/src/engine/safeReader.cpp @@ -37,7 +37,7 @@ bool SafeReader::seek(ssize_t where, int whence) { break; } case SEEK_END: { - ssize_t finalSeek=curSeek-where; + ssize_t finalSeek=len-where; if (finalSeek<0) return false; if (finalSeek>(ssize_t)len) return false; curSeek=finalSeek;