From 5770f381ba3f0a1b79e8580235048597dd3ca14a Mon Sep 17 00:00:00 2001 From: LTVA1 <87536432+LTVA1@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:40:17 +0300 Subject: [PATCH] setting to choose between OPL2 and OPL3, channel naming --- src/engine/engine.h | 4 +- src/engine/fileOps/fileOpsCommon.cpp | 4 +- src/engine/fileOps/s3m.cpp | 78 ++++++++++++++++++---------- src/gui/gui.cpp | 4 +- src/gui/gui.h | 2 + src/gui/settings.cpp | 12 +++++ 6 files changed, 72 insertions(+), 32 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index f010d7001..4364adf13 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -597,7 +597,7 @@ class DivEngine { bool loadDMF(unsigned char* file, size_t len); bool loadFur(unsigned char* file, size_t len, int variantID=0); bool loadMod(unsigned char* file, size_t len); - bool loadS3M(unsigned char* file, size_t len); + bool loadS3M(unsigned char* file, size_t len, bool opl2=false); bool loadXM(unsigned char* file, size_t len); bool loadIT(unsigned char* file, size_t len); bool loadFTM(unsigned char* file, size_t len, bool dnft, bool dnftSig, bool eft); @@ -689,7 +689,7 @@ class DivEngine { void createNew(const char* description, String sysName, bool inBase64=true); void createNewFromDefaults(); // load a file. - bool load(unsigned char* f, size_t length, const char* nameHint=NULL); + bool load(unsigned char* f, size_t length, const char* nameHint=NULL, bool s3mOPL2=false); // play a binary command stream. bool playStream(unsigned char* f, size_t length); // get the playing stream. diff --git a/src/engine/fileOps/fileOpsCommon.cpp b/src/engine/fileOps/fileOpsCommon.cpp index 1a2f36319..78bf00b41 100644 --- a/src/engine/fileOps/fileOpsCommon.cpp +++ b/src/engine/fileOps/fileOpsCommon.cpp @@ -19,7 +19,7 @@ #include "fileOpsCommon.h" -bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) { +bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint, bool s3mOPL2) { unsigned char* file; size_t len; if (slen<21) { @@ -158,7 +158,7 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) { return loadIT(file,len); } else if (len>=48) { if (memcmp(&file[0x2c],DIV_S3M_MAGIC,4)==0) { - return loadS3M(file,len); + return loadS3M(file,len,s3mOPL2); } else if (memcmp(file,DIV_XM_MAGIC,17)==0) { return loadXM(file,len); } diff --git a/src/engine/fileOps/s3m.cpp b/src/engine/fileOps/s3m.cpp index ea8d2d58e..5974f2f11 100644 --- a/src/engine/fileOps/s3m.cpp +++ b/src/engine/fileOps/s3m.cpp @@ -48,7 +48,7 @@ static void readSbiOpData(sbi_t& sbi, SafeReader& reader) { sbi.FeedConnect = reader.readC(); } -bool DivEngine::loadS3M(unsigned char* file, size_t len) { +bool DivEngine::loadS3M(unsigned char* file, size_t len, bool opl2) { struct InvalidHeaderException {}; bool success=false; char magic[4]={0,0,0,0}; @@ -273,11 +273,16 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { bool hasPCM=false; bool hasFM=false; int numChans=0; + int realNumChans=0; - for (int i=0; i<32; i++) { - if (chanSettings[i]==255) continue; - if ((chanSettings[i]&127)>=32) continue; - if ((chanSettings[i]&127)>=16) { + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]!=255) realNumChans++; + } + + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]==255) continue; + if ((chanSettings[ch]&127)>=32) continue; + if ((chanSettings[ch]&127)>=16) { hasFM=true; } else { hasPCM=true; @@ -287,48 +292,69 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { if (hasFM && hasPCM) break; } - int pcmChan=hasFM?18:0; + int pcmChan=hasFM?(opl2 ? 9 : 18):0; int fmChan=hasPCM?32:0; int invalidChan=40; - for (int i=0; i<32; i++) { - if (chanSettings[i]==255) { - chanMap[i]=invalidChan++; + for (int ch=0; ch<32; ch++) { + if (chanSettings[ch]==255) { + chanMap[ch]=invalidChan++; continue; } - if ((chanSettings[i]&127)>=32) { - chanMap[i]=invalidChan++; + if ((chanSettings[ch]&127)>=32) { + chanMap[ch]=invalidChan++; continue; } - if ((chanSettings[i]&127)>=16) { - chanMap[i]=fmChan++; + if ((chanSettings[ch]&127)>=16) { + chanMap[ch]=fmChan++; } else { - chanMap[i]=pcmChan++; + chanMap[ch]=pcmChan++; } } + char buffer[40]; + int chanIndex = 1; + if (hasPCM) { - for (int i=pcmChan; i<32; i++) { - ds.subsong[0]->chanShow[i]=false; - ds.subsong[0]->chanShowChanOsc[i]=false; + for(int ch = 0; ch < pcmChan - (realNumChans - (hasFM ? 9 : 0)); ch++) + { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; } - if (hasFM) { - for (int i=0; i<18; i++) { - ds.subsong[0]->chanShow[i]=false; - ds.subsong[0]->chanShowChanOsc[i]=false; + for (int ch=pcmChan; ch<32; ch++) { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; + } + + for(int ch = 0; ch < 32; ch++) + { + if(ds.subsong[0]->chanShow[ch]) + { + snprintf(buffer, 40, _("Channel %d"), chanIndex); + ds.subsong[0]->chanName[ch] = buffer; + chanIndex++; } } } - if (hasFM) { - for (int i=(hasPCM?32:0) + 9; i<(hasPCM?32:0) + 18; i++) { - ds.subsong[0]->chanShow[i]=false; - ds.subsong[0]->chanShowChanOsc[i]=false; + if (hasFM && !opl2) { + for (int ch=(hasPCM?32:0) + 9; ch<(hasPCM?32:0) + 18; ch++) { + ds.subsong[0]->chanShow[ch]=false; + ds.subsong[0]->chanShowChanOsc[ch]=false; + } + + chanIndex = 1; + + for (int ch=(hasPCM?32:0); ch<(hasPCM?32:0) + 9; ch++) { + snprintf(buffer, 40, _("FM %d"), chanIndex); + ds.subsong[0]->chanName[ch] = buffer; + chanIndex++; } } logV("numChans: %d",numChans); + logV("realNumChans: %d",realNumChans); ds.systemName="PC"; if (hasPCM) { @@ -341,7 +367,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { ds.systemLen++; } if (hasFM) { - ds.system[ds.systemLen]=DIV_SYSTEM_OPL3; + ds.system[ds.systemLen]=opl2 ? DIV_SYSTEM_OPL2 : DIV_SYSTEM_OPL3; ds.systemVol[ds.systemLen]=1.0f; ds.systemPan[ds.systemLen]=0; ds.systemLen++; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 37443c46e..0ce0a69fa 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2417,7 +2417,7 @@ int FurnaceGUI::load(String path) { return 1; } fclose(f); - if (!e->load(file,(size_t)len,path.c_str())) { + if (!e->load(file,(size_t)len,path.c_str(),settings.OPL2s3mImport)) { lastError=e->getLastError(); logE("could not open file!"); return 1; @@ -4110,7 +4110,7 @@ bool FurnaceGUI::loop() { if (!tutorial.introPlayed || settings.alwaysPlayIntro==3 || (settings.alwaysPlayIntro==2 && curFileName.empty())) { unsigned char* introTemp=new unsigned char[intro_fur_len]; memcpy(introTemp,intro_fur,intro_fur_len); - e->load(introTemp,intro_fur_len); + e->load(introTemp,intro_fur_len,NULL,settings.OPL2s3mImport); } } diff --git a/src/gui/gui.h b/src/gui/gui.h index ae6dde1ef..b4b134be9 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1958,6 +1958,7 @@ class FurnaceGUI { unsigned int maxUndoSteps; float vibrationStrength; int vibrationLength; + bool OPL2s3mImport; String mainFontPath; String headFontPath; String patFontPath; @@ -2214,6 +2215,7 @@ class FurnaceGUI { maxUndoSteps(100), vibrationStrength(0.5f), vibrationLength(20), + OPL2s3mImport(false), mainFontPath(""), headFontPath(""), patFontPath(""), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 8241e9ab1..5a125d0f8 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1254,6 +1254,14 @@ void FurnaceGUI::drawSettings() { } popDestColor(); + // SUBSECTION CONFIGURATION + CONFIG_SUBSECTION(_("Modules import")); + bool s3mOPL2B=settings.OPL2s3mImport; + if (ImGui::Checkbox(_("Use OPL2 instead of OPL3 for .s3m modules import"),&s3mOPL2B)) { + settings.OPL2s3mImport=s3mOPL2B; + settingsChanged=true; + } + END_SECTION; } CONFIG_SECTION(_("Audio")) { @@ -4746,6 +4754,8 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.vibrationStrength=conf.getFloat("vibrationStrength",0.5f); settings.vibrationLength=conf.getInt("vibrationLength",20); + settings.OPL2s3mImport=conf.getInt("OPL2s3mImport",false); + settings.backupEnable=conf.getInt("backupEnable",1); settings.backupInterval=conf.getInt("backupInterval",30); settings.backupMaxCopies=conf.getInt("backupMaxCopies",5); @@ -5331,6 +5341,8 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("vibrationStrength",settings.vibrationStrength); conf.set("vibrationLength",settings.vibrationLength); + conf.set("OPL2s3mImport",settings.OPL2s3mImport); + conf.set("backupEnable",settings.backupEnable); conf.set("backupInterval",settings.backupInterval); conf.set("backupMaxCopies",settings.backupMaxCopies);