From 23be8d93367f0960338725fb26cf7f9e65437fcf Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 24 Apr 2022 14:40:07 -0500 Subject: [PATCH] the final piece of f-num/block work --- papers/format.md | 6 +++++- src/engine/engine.h | 4 ++-- src/engine/fileOps.cpp | 14 ++++++++++++-- src/engine/platform/genesisext.cpp | 20 ++++++++++++++------ src/engine/song.h | 4 +++- src/gui/compatFlags.cpp | 6 +++++- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/papers/format.md b/papers/format.md index 7775e9ea3..ef8ab7e50 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,8 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 85: Furnace dev85 +- 84: Furnace dev84 - 83: Furnace dev83 - 82: Furnace dev82 - 81: Furnace dev81 @@ -269,7 +271,9 @@ size | description 1 | ExtCh channel state is shared (>=78) or 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 + 1 | new Sega PCM (with macros and proper vol/pan) (>=84) or reserved + 1 | weird f-num/block-based chip pitch slides (>=85) or reserved + 21 | reserved ``` # instrument diff --git a/src/engine/engine.h b/src/engine/engine.h index 515b9c590..81e15f726 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -43,8 +43,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev84" -#define DIV_ENGINE_VERSION 84 +#define DIV_VERSION "dev85" +#define DIV_ENGINE_VERSION 85 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index aee7de71f..48ef68bba 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -162,6 +162,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ds.gbInsAffectsEnvelope=true; ds.ignoreDACModeOutsideIntendedChannel=false; ds.e1e2AlsoTakePriority=true; + ds.fbPortaPause=true; // 1.1 compat flags if (ds.version>24) { @@ -993,6 +994,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { if (ds.version<84) { ds.newSegaPCM=false; } + if (ds.version<85) { + ds.fbPortaPause=true; + } ds.isDMF=false; reader.readS(); // reserved @@ -1342,7 +1346,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } else { reader.readC(); } - for (int i=0; i<22; i++) { + if (ds.version>=85) { + ds.fbPortaPause=reader.readC(); + } else { + reader.readC(); + } + for (int i=0; i<21; i++) { reader.readC(); } } @@ -2283,7 +2292,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.ignoreDACModeOutsideIntendedChannel); w->writeC(song.e1e2AlsoTakePriority); w->writeC(song.newSegaPCM); - for (int i=0; i<22; i++) { + w->writeC(song.fbPortaPause); + for (int i=0; i<21; i++) { w->writeC(0); } diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index eefec5d8f..479e42421 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -149,14 +149,22 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { // what the heck! if (!opChan[ch].portaPause) { if ((newFreq&0x7ff)>1288) { - opChan[ch].portaPauseFreq=(644)|((newFreq+0x800)&0xf800); - opChan[ch].portaPause=true; - break; + if (parent->song.fbPortaPause) { + opChan[ch].portaPauseFreq=(644)|((newFreq+0x800)&0xf800); + opChan[ch].portaPause=true; + break; + } else { + newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800); + } } if ((newFreq&0x7ff)<644) { - opChan[ch].portaPauseFreq=newFreq=(1287)|((newFreq-0x800)&0xf800); - opChan[ch].portaPause=true; - break; + if (parent->song.fbPortaPause) { + opChan[ch].portaPauseFreq=newFreq=(1287)|((newFreq-0x800)&0xf800); + opChan[ch].portaPause=true; + break; + } else { + newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800); + } } } opChan[ch].portaPause=false; diff --git a/src/engine/song.h b/src/engine/song.h index 20b17ae60..9b9187ac6 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -324,6 +324,7 @@ struct DivSong { bool ignoreDACModeOutsideIntendedChannel; bool e1e2AlsoTakePriority; bool newSegaPCM; + bool fbPortaPause; DivOrders orders; std::vector ins; @@ -406,7 +407,8 @@ struct DivSong { sharedExtStat(true), ignoreDACModeOutsideIntendedChannel(false), e1e2AlsoTakePriority(false), - newSegaPCM(true) { + newSegaPCM(true), + fbPortaPause(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 d2035ff70..8d1fd6d18 100644 --- a/src/gui/compatFlags.cpp +++ b/src/gui/compatFlags.cpp @@ -101,6 +101,10 @@ void FurnaceGUI::drawCompatFlags() { if (ImGui::IsItemHovered()) { ImGui::SetTooltip("simulates a bug in where portamento does not work after sliding."); } + ImGui::Checkbox("FM pitch slide octave boundary odd behavior",&e->song.fbPortaPause); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("if this is on, a pitch slide that crosses the octave boundary will stop for one tick and then continue from the nearest octave boundary.\nfor .dmf compatibility."); + } ImGui::Checkbox("Apply Game Boy envelope on note-less instrument change",&e->song.gbInsAffectsEnvelope); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("if this is on, an instrument change will also affect the envelope."); @@ -173,4 +177,4 @@ void FurnaceGUI::drawCompatFlags() { } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_COMPAT_FLAGS; ImGui::End(); -} \ No newline at end of file +}