diff --git a/papers/format.md b/papers/format.md index e8f076176..2f4037a06 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,7 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 83: Furnace dev83 - 82: Furnace dev82 - 81: Furnace dev81 - 80: Furnace dev80 @@ -266,7 +267,9 @@ size | description 1 | buggy portamento after slide (>=72) or reserved 1 | new ins affects envelope (Game Boy) (>=72) or reserved 1 | ExtCh channel state is shared (>=78) or reserved - 25 | reserved + 1 | ignore DAC mode change outside of intended channel (>=83) or reserved + 1 | E1xx and E2xx also take priority over Slide00 (>=83) or reserved + 23 | reserved ``` # instrument diff --git a/src/engine/engine.h b/src/engine/engine.h index d11c54709..6b93666bf 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -42,8 +42,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev82" -#define DIV_ENGINE_VERSION 82 +#define DIV_VERSION "dev83" +#define DIV_ENGINE_VERSION 83 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 356e40e7e..6e91ac4aa 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -154,6 +154,8 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ds.ignoreJumpAtEnd=true; ds.buggyPortaAfterSlide=true; ds.gbInsAffectsEnvelope=true; + ds.ignoreDACModeOutsideIntendedChannel=false; + ds.e1e2AlsoTakePriority=true; // 1.1 compat flags if (ds.version>24) { @@ -1315,7 +1317,14 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } else { reader.readC(); } - for (int i=0; i<25; i++) { + if (ds.version>=82) { + ds.ignoreDACModeOutsideIntendedChannel=reader.readC(); + ds.e1e2AlsoTakePriority=reader.readC(); + } else { + reader.readC(); + reader.readC(); + } + for (int i=0; i<23; i++) { reader.readC(); } } @@ -2219,7 +2228,9 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.buggyPortaAfterSlide); w->writeC(song.gbInsAffectsEnvelope); w->writeC(song.sharedExtStat); - for (int i=0; i<25; i++) { + w->writeC(song.ignoreDACModeOutsideIntendedChannel); + w->writeC(song.e1e2AlsoTakePriority); + for (int i=0; i<23; i++) { w->writeC(0); } diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 60f877b7e..e8ddbdc79 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -156,9 +156,21 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { break; } case DIV_CMD_SAMPLE_MODE: { - // ignored on extended channel 3 mode. + // not ignored actually! + if (!parent->song.ignoreDACModeOutsideIntendedChannel) { + dacMode=c.value; + rWrite(0x2b,c.value<<7); + } break; } + case DIV_CMD_SAMPLE_BANK: + if (!parent->song.ignoreDACModeOutsideIntendedChannel) { + sampleBank=c.value; + if (sampleBank>(parent->song.sample.size()/12)) { + sampleBank=parent->song.sample.size()/12; + } + } + break; case DIV_CMD_LEGATO: { opChan[ch].baseFreq=NOTE_FREQUENCY(c.value); opChan[ch].freqChanged=true; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 97047b64d..05cb890c5 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1174,6 +1174,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].inPorta=true; chan[i].shorthandPorta=true; if (!song.brokenShortcutSlides) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); + if (song.e1e2AlsoTakePriority) lastSlide=0x1337; // ... } else { chan[i].inPorta=false; if (!song.brokenShortcutSlides) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); @@ -1190,6 +1191,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].inPorta=true; chan[i].shorthandPorta=true; if (!song.brokenShortcutSlides) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0)); + if (song.e1e2AlsoTakePriority) lastSlide=0x1337; // ... } else { chan[i].inPorta=false; if (!song.brokenShortcutSlides) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0)); diff --git a/src/engine/song.h b/src/engine/song.h index 009b40980..6cda7c533 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -321,6 +321,8 @@ struct DivSong { bool buggyPortaAfterSlide; bool gbInsAffectsEnvelope; bool sharedExtStat; + bool ignoreDACModeOutsideIntendedChannel; + bool e1e2AlsoTakePriority; DivOrders orders; std::vector ins; @@ -400,7 +402,9 @@ struct DivSong { ignoreJumpAtEnd(false), buggyPortaAfterSlide(false), gbInsAffectsEnvelope(true), - sharedExtStat(true) { + sharedExtStat(true), + ignoreDACModeOutsideIntendedChannel(false), + e1e2AlsoTakePriority(false) { for (int i=0; i<32; i++) { system[i]=DIV_SYSTEM_NULL; systemVol[i]=64; diff --git a/src/gui/compatFlags.cpp b/src/gui/compatFlags.cpp index 15a900b2d..8a45741f8 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -105,6 +105,14 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("if this is on, an instrument change will also affect the envelope."); } + ImGui::Checkbox("Ignore DAC mode change outside of intended channel in ExtCh mode",&e->song.ignoreDACModeOutsideIntendedChannel); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("if this is on, 17xx has no effect on the operator channels in YM2612."); + } + ImGui::Checkbox("E1xy/E2xy also take priority over slide stops",&e->song.e1e2AlsoTakePriority); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("does this make any sense by now?"); + } ImGui::Text("Loop modality:"); if (ImGui::RadioButton("Reset channels",e->song.loopModality==0)) {