add two more compatibility flags
for songs that relied upon pre-0.5.5 broken behavior
This commit is contained in:
parent
e115d9e23b
commit
62f2f67b9d
|
@ -25,6 +25,8 @@ furthermore, an `or reserved` indicates this field is always present, but is res
|
||||||
|
|
||||||
the format versions are:
|
the format versions are:
|
||||||
|
|
||||||
|
- 47: Furnace 0.5.6pre1
|
||||||
|
- 46: Furnace 0.5.5
|
||||||
- 45: Furnace 0.5.5pre3
|
- 45: Furnace 0.5.5pre3
|
||||||
- 44: Furnace 0.5.5pre2
|
- 44: Furnace 0.5.5pre2
|
||||||
- 43: Furnace 0.5.5pre1
|
- 43: Furnace 0.5.5pre1
|
||||||
|
@ -161,7 +163,9 @@ size | description
|
||||||
1 | compatible arpeggio (>=45) or reserved
|
1 | compatible arpeggio (>=45) or reserved
|
||||||
1 | note off resets slides (>=45) or reserved
|
1 | note off resets slides (>=45) or reserved
|
||||||
1 | target resets slides (>=45) or reserved
|
1 | target resets slides (>=45) or reserved
|
||||||
10 | reserved
|
1 | arpeggio inhibits portamento (>=47) or reserved
|
||||||
|
1 | wack algorithm macro (>=47) or reserved
|
||||||
|
8 | reserved
|
||||||
4?? | pointers to instruments
|
4?? | pointers to instruments
|
||||||
4?? | pointers to wavetables
|
4?? | pointers to wavetables
|
||||||
4?? | pointers to samples
|
4?? | pointers to samples
|
||||||
|
|
|
@ -1551,6 +1551,8 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
ds.compatibleArpeggio=true;
|
ds.compatibleArpeggio=true;
|
||||||
ds.noteOffResetsSlides=true;
|
ds.noteOffResetsSlides=true;
|
||||||
ds.targetResetsSlides=true;
|
ds.targetResetsSlides=true;
|
||||||
|
ds.arpNonPorta=false;
|
||||||
|
ds.algMacroBehavior=false;
|
||||||
|
|
||||||
// Neo Geo detune
|
// Neo Geo detune
|
||||||
if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
||||||
|
@ -2093,6 +2095,13 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
ds.noteOffResetsSlides=true;
|
ds.noteOffResetsSlides=true;
|
||||||
ds.targetResetsSlides=true;
|
ds.targetResetsSlides=true;
|
||||||
}
|
}
|
||||||
|
if (ds.version<46) {
|
||||||
|
ds.arpNonPorta=true;
|
||||||
|
ds.algMacroBehavior=true;
|
||||||
|
} else {
|
||||||
|
ds.arpNonPorta=false;
|
||||||
|
ds.algMacroBehavior=false;
|
||||||
|
}
|
||||||
|
|
||||||
reader.readS(); // reserved
|
reader.readS(); // reserved
|
||||||
int infoSeek=reader.readI();
|
int infoSeek=reader.readI();
|
||||||
|
@ -2200,7 +2209,17 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
for (int i=0; i<10; i++) reader.readC();
|
if (ds.version>=47) {
|
||||||
|
ds.arpNonPorta=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
if (ds.version>=47) {
|
||||||
|
ds.algMacroBehavior=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
for (int i=0; i<8; i++) reader.readC();
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<20; i++) reader.readC();
|
for (int i=0; i<20; i++) reader.readC();
|
||||||
}
|
}
|
||||||
|
@ -2581,7 +2600,9 @@ SafeWriter* DivEngine::saveFur() {
|
||||||
w->writeC(song.compatibleArpeggio);
|
w->writeC(song.compatibleArpeggio);
|
||||||
w->writeC(song.noteOffResetsSlides);
|
w->writeC(song.noteOffResetsSlides);
|
||||||
w->writeC(song.targetResetsSlides);
|
w->writeC(song.targetResetsSlides);
|
||||||
for (int i=0; i<10; i++) {
|
w->writeC(song.arpNonPorta);
|
||||||
|
w->writeC(song.algMacroBehavior);
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#define DIV_VERSION "0.5.5"
|
#define DIV_VERSION "0.5.6pre1"
|
||||||
#define DIV_ENGINE_VERSION 46
|
#define DIV_ENGINE_VERSION 47
|
||||||
|
|
||||||
enum DivStatusView {
|
enum DivStatusView {
|
||||||
DIV_STATUS_NOTHING=0,
|
DIV_STATUS_NOTHING=0,
|
||||||
|
|
|
@ -276,7 +276,7 @@ void DivPlatformArcade::tick() {
|
||||||
} else {
|
} else {
|
||||||
rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|((chan[i].chVolL&1)<<6)|((chan[i].chVolR&1)<<7));
|
rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|((chan[i].chVolL&1)<<6)|((chan[i].chVolR&1)<<7));
|
||||||
}
|
}
|
||||||
for (int j=0; j<4; j++) {
|
if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
|
|
|
@ -201,7 +201,7 @@ void DivPlatformGenesis::tick() {
|
||||||
if (chan[i].std.hadAlg) {
|
if (chan[i].std.hadAlg) {
|
||||||
chan[i].state.alg=chan[i].std.alg;
|
chan[i].state.alg=chan[i].std.alg;
|
||||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
for (int j=0; j<4; j++) {
|
if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
|
|
|
@ -183,7 +183,7 @@ void DivPlatformYM2610::tick() {
|
||||||
if (chan[i].std.hadAlg) {
|
if (chan[i].std.hadAlg) {
|
||||||
chan[i].state.alg=chan[i].std.alg;
|
chan[i].state.alg=chan[i].std.alg;
|
||||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
for (int j=0; j<4; j++) {
|
if (!parent->song.algMacroBehavior) for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
|
|
|
@ -565,7 +565,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].portaNote=-1;
|
chan[i].portaNote=-1;
|
||||||
chan[i].portaSpeed=-1;
|
chan[i].portaSpeed=-1;
|
||||||
chan[i].inPorta=false;
|
chan[i].inPorta=false;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||||
} else {
|
} else {
|
||||||
chan[i].portaNote=song.limitSlides?0x60:255;
|
chan[i].portaNote=song.limitSlides?0x60:255;
|
||||||
chan[i].portaSpeed=effectVal;
|
chan[i].portaSpeed=effectVal;
|
||||||
|
@ -574,7 +574,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].stopOnOff=false;
|
chan[i].stopOnOff=false;
|
||||||
chan[i].scheduledSlideReset=false;
|
chan[i].scheduledSlideReset=false;
|
||||||
chan[i].inPorta=false;
|
chan[i].inPorta=false;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0));
|
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x02: // ramp down
|
case 0x02: // ramp down
|
||||||
|
@ -582,7 +582,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].portaNote=-1;
|
chan[i].portaNote=-1;
|
||||||
chan[i].portaSpeed=-1;
|
chan[i].portaSpeed=-1;
|
||||||
chan[i].inPorta=false;
|
chan[i].inPorta=false;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||||
} else {
|
} else {
|
||||||
chan[i].portaNote=song.limitSlides?disCont[dispatchOfChan[i]].dispatch->getPortaFloor(dispatchChanOfChan[i]):-60;
|
chan[i].portaNote=song.limitSlides?disCont[dispatchOfChan[i]].dispatch->getPortaFloor(dispatchChanOfChan[i]):-60;
|
||||||
chan[i].portaSpeed=effectVal;
|
chan[i].portaSpeed=effectVal;
|
||||||
|
@ -591,7 +591,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].stopOnOff=false;
|
chan[i].stopOnOff=false;
|
||||||
chan[i].scheduledSlideReset=false;
|
chan[i].scheduledSlideReset=false;
|
||||||
chan[i].inPorta=false;
|
chan[i].inPorta=false;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0));
|
if (!song.arpNonPorta) dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x03: // portamento
|
case 0x03: // portamento
|
||||||
|
|
|
@ -224,6 +224,8 @@ struct DivSong {
|
||||||
bool compatibleArpeggio;
|
bool compatibleArpeggio;
|
||||||
bool noteOffResetsSlides;
|
bool noteOffResetsSlides;
|
||||||
bool targetResetsSlides;
|
bool targetResetsSlides;
|
||||||
|
bool arpNonPorta;
|
||||||
|
bool algMacroBehavior;
|
||||||
|
|
||||||
DivOrders orders;
|
DivOrders orders;
|
||||||
std::vector<DivInstrument*> ins;
|
std::vector<DivInstrument*> ins;
|
||||||
|
@ -279,7 +281,9 @@ struct DivSong {
|
||||||
legacyVolumeSlides(false),
|
legacyVolumeSlides(false),
|
||||||
compatibleArpeggio(false),
|
compatibleArpeggio(false),
|
||||||
noteOffResetsSlides(true),
|
noteOffResetsSlides(true),
|
||||||
targetResetsSlides(true) {
|
targetResetsSlides(true),
|
||||||
|
arpNonPorta(false),
|
||||||
|
algMacroBehavior(false) {
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
system[i]=DIV_SYSTEM_NULL;
|
system[i]=DIV_SYSTEM_NULL;
|
||||||
systemVol[i]=64;
|
systemVol[i]=64;
|
||||||
|
|
|
@ -3997,6 +3997,19 @@ void FurnaceGUI::drawCompatFlags() {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("select to not reset channels on loop.");
|
ImGui::SetTooltip("select to not reset channels on loop.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::TextWrapped("the following flags are for compatibility with older Furnace versions.");
|
||||||
|
|
||||||
|
ImGui::Checkbox("Arpeggio inhibits non-porta slides",&e->song.arpNonPorta);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("behavior changed in 0.5.5");
|
||||||
|
}
|
||||||
|
ImGui::Checkbox("Wack FM algorithm macro",&e->song.algMacroBehavior);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("behavior changed in 0.5.5");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue