From ad09254cf41f0acc65bb193e66b78fdff8680616 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 7 Apr 2022 01:14:34 -0500 Subject: [PATCH] dev78 - new compat flag that fixes ExtCh --- papers/format.md | 4 +++- src/engine/engine.h | 4 ++-- src/engine/fileOps.cpp | 13 +++++++++++-- src/engine/platform/genesisext.cpp | 7 ++++++- src/engine/platform/ym2610bext.cpp | 7 ++++++- src/engine/platform/ym2610ext.cpp | 7 ++++++- src/engine/song.h | 4 +++- src/gui/compatFlags.cpp | 4 ++++ 8 files changed, 41 insertions(+), 9 deletions(-) diff --git a/papers/format.md b/papers/format.md index 2876ffe3..00534575 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: +- 78: Furnace dev78 - 77: Furnace dev77 - 76: Furnace dev76 - 75: Furnace dev75/April Fools' 0.6pre0 @@ -248,7 +249,8 @@ size | description 1 | ignore jump at end (>=71) or reserved 1 | buggy portamento after slide (>=72) or reserved 1 | new ins affects envelope (Game Boy) (>=72) or reserved - 26 | reserved + 1 | ExtCh channel state is shared (>=78) or reserved + 25 | reserved ``` # instrument diff --git a/src/engine/engine.h b/src/engine/engine.h index 8fc8427d..e5240ab9 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 "dev77" -#define DIV_ENGINE_VERSION 77 +#define DIV_VERSION "dev78" +#define DIV_ENGINE_VERSION 78 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 1bf73bcc..8ed6551b 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -890,6 +890,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { ds.buggyPortaAfterSlide=true; ds.gbInsAffectsEnvelope=false; } + if (ds.version<78) { + ds.sharedExtStat=false; + } ds.isDMF=false; reader.readS(); // reserved @@ -1222,7 +1225,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { reader.readC(); reader.readC(); } - for (int i=0; i<26; i++) { + if (ds.version>=78) { + ds.sharedExtStat=reader.readC(); + } else { + reader.readC(); + } + for (int i=0; i<25; i++) { reader.readC(); } } @@ -2125,7 +2133,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.ignoreJumpAtEnd); w->writeC(song.buggyPortaAfterSlide); w->writeC(song.gbInsAffectsEnvelope); - for (int i=0; i<26; i++) { + w->writeC(song.sharedExtStat); + for (int i=0; i<25; i++) { w->writeC(0); } diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index f77dbdf0..60f877b7 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -112,7 +112,12 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { } else { opChan[ch].pan=((c.value&15)>0)|(((c.value>>4)>0)<<1); } - // TODO: ??? + if (parent->song.sharedExtStat) { + for (int i=0; i<4; i++) { + if (ch==i) continue; + opChan[i].pan=opChan[ch].pan; + } + } rWrite(chanOffs[2]+0xb4,(opChan[ch].pan<<6)|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); break; } diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index adcd1e9e..03e9f869 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -105,7 +105,12 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) { opChan[ch].pan=((c.value&15)>0)|(((c.value>>4)>0)<<1); } DivInstrument* ins=parent->getIns(opChan[ch].ins); - // TODO: ??? + if (parent->song.sharedExtStat) { + for (int i=0; i<4; i++) { + if (ch==i) continue; + opChan[i].pan=opChan[ch].pan; + } + } rWrite(chanOffs[2]+0xb4,(opChan[ch].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4)); break; } diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index ed8aa14e..40294733 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -105,7 +105,12 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) { opChan[ch].pan=((c.value&15)>0)|(((c.value>>4)>0)<<1); } DivInstrument* ins=parent->getIns(opChan[ch].ins); - // TODO: ??? + if (parent->song.sharedExtStat) { + for (int i=0; i<4; i++) { + if (ch==i) continue; + opChan[i].pan=opChan[ch].pan; + } + } rWrite(chanOffs[1]+0xb4,(opChan[ch].pan<<6)|(ins->fm.fms&7)|((ins->fm.ams&3)<<4)); break; } diff --git a/src/engine/song.h b/src/engine/song.h index 1b8c85c2..7dca56b4 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -308,6 +308,7 @@ struct DivSong { bool ignoreJumpAtEnd; bool buggyPortaAfterSlide; bool gbInsAffectsEnvelope; + bool sharedExtStat; DivOrders orders; std::vector ins; @@ -386,7 +387,8 @@ struct DivSong { rowResetsArpPos(false), ignoreJumpAtEnd(false), buggyPortaAfterSlide(false), - gbInsAffectsEnvelope(true) { + gbInsAffectsEnvelope(true), + sharedExtStat(true) { 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 91aa34c7..15a900b2 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -154,6 +154,10 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("behavior changed in 0.6"); } + ImGui::Checkbox("ExtCh channel status is shared among operators",&e->song.sharedExtStat); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("behavior changed in 0.6"); + } } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_COMPAT_FLAGS; ImGui::End();