dev97 - add old octave boundary compat flag

This commit is contained in:
tildearrow 2022-05-22 13:25:59 -05:00
parent b40c95013a
commit 393d1c018d
10 changed files with 94 additions and 36 deletions

View File

@ -29,6 +29,7 @@ furthermore, an `or reserved` indicates this field is always present, but is res
the format versions are:
- 97: Furnace dev97
- 96: Furnace dev96
- 95: Furnace dev95
- 94: Furnace dev94
@ -300,7 +301,8 @@ size | description
1 | SN duty macro always resets phase (>=86) or reserved
1 | pitch macro is linear (>=90) or reserved
1 | pitch slide speed in full linear pitch mode (>=94) or reserved
14 | reserved
1 | old octave boundary behavior (>=97) or reserved
13 | reserved
--- | **virtual tempo data**
2 | virtual tempo numerator of first song (>=96) or reserved
2 | virtual tempo denominator of first song (>=96) or reserved

View File

@ -45,8 +45,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev96"
#define DIV_ENGINE_VERSION 96
#define DIV_VERSION "dev97"
#define DIV_ENGINE_VERSION 97
// for imports
#define DIV_VERSION_MOD 0xff01

View File

@ -166,6 +166,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.e1e2AlsoTakePriority=true;
ds.fbPortaPause=true;
ds.snDutyReset=true;
ds.oldOctaveBoundary=false;
// 1.1 compat flags
if (ds.version>24) {
@ -1027,6 +1028,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
if (ds.version<90) {
ds.pitchMacroIsLinear=false;
}
if (ds.version<97) {
ds.oldOctaveBoundary=true;
}
ds.isDMF=false;
reader.readS(); // reserved
@ -1404,7 +1408,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} else {
reader.readC();
}
for (int i=0; i<14; i++) {
if (ds.version>=97) {
ds.oldOctaveBoundary=reader.readC();
} else {
reader.readC();
}
for (int i=0; i<13; i++) {
reader.readC();
}
}
@ -2871,7 +2880,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
w->writeC(song.snDutyReset);
w->writeC(song.pitchMacroIsLinear);
w->writeC(song.pitchSlideSpeed);
for (int i=0; i<14; i++) {
w->writeC(song.oldOctaveBoundary);
for (int i=0; i<13; i++) {
w->writeC(0);
}

View File

@ -781,14 +781,22 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
// what the heck!
if (!chan[c.chan].portaPause) {
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=(parent->song.oldOctaveBoundary?(newFreq>>1):boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
}
}
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=newFreq=(parent->song.oldOctaveBoundary?(newFreq<<1):(boundaryTop-1))|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
}
}
}
chan[c.chan].portaPause=false;

View File

@ -684,14 +684,22 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
// what the heck!
if (!chan[c.chan].portaPause) {
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=(parent->song.oldOctaveBoundary?(newFreq>>1):boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
}
}
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=newFreq=(parent->song.oldOctaveBoundary?(newFreq<<1):(boundaryTop-1))|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
}
}
}
chan[c.chan].portaPause=false;

View File

@ -1005,14 +1005,22 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
// what the heck!
if (!chan[c.chan].portaPause) {
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=(parent->song.oldOctaveBoundary?(newFreq>>1):boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
}
}
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=newFreq=(parent->song.oldOctaveBoundary?(newFreq<<1):(boundaryTop-1))|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
}
}
}
chan[c.chan].portaPause=false;

View File

@ -1052,14 +1052,22 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
// what the heck!
if (!chan[c.chan].portaPause) {
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=(parent->song.oldOctaveBoundary?(newFreq>>1):boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
}
}
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=newFreq=(parent->song.oldOctaveBoundary?(newFreq<<1):(boundaryTop-1))|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
}
}
}
chan[c.chan].portaPause=false;

View File

@ -1030,14 +1030,22 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
// what the heck!
if (!chan[c.chan].portaPause) {
if ((newFreq&0x7ff)>boundaryTop && (newFreq&0xf800)<0x3800) {
chan[c.chan].portaPauseFreq=(boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=(parent->song.oldOctaveBoundary?(newFreq>>1):boundaryBottom)|((newFreq+0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq>>1)|((newFreq+0x800)&0xf800);
}
}
if ((newFreq&0x7ff)<boundaryBottom && (newFreq&0xf800)>0) {
chan[c.chan].portaPauseFreq=newFreq=(boundaryTop-1)|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
if (parent->song.fbPortaPause) {
chan[c.chan].portaPauseFreq=newFreq=(parent->song.oldOctaveBoundary?(newFreq<<1):(boundaryTop-1))|((newFreq-0x800)&0xf800);
chan[c.chan].portaPause=true;
break;
} else {
newFreq=(newFreq<<1)|((newFreq-0x800)&0xf800);
}
}
}
chan[c.chan].portaPause=false;

View File

@ -393,6 +393,7 @@ struct DivSong {
bool fbPortaPause;
bool snDutyReset;
bool pitchMacroIsLinear;
bool oldOctaveBoundary;
std::vector<DivInstrument*> ins;
std::vector<DivWavetable*> wave;
@ -485,7 +486,8 @@ struct DivSong {
newSegaPCM(true),
fbPortaPause(false),
snDutyReset(false),
pitchMacroIsLinear(true) {
pitchMacroIsLinear(true),
oldOctaveBoundary(false) {
for (int i=0; i<32; i++) {
system[i]=DIV_SYSTEM_NULL;
systemVol[i]=64;

View File

@ -209,6 +209,10 @@ void FurnaceGUI::drawCompatFlags() {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("behavior changed in 0.6");
}
ImGui::Checkbox("Old FM octave boundary behavior",&e->song.oldOctaveBoundary);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("behavior changed in 0.6");
}
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_COMPAT_FLAGS;
ImGui::End();