Merge branch 'tildearrow:master' into master
This commit is contained in:
commit
3709f1f0a3
|
@ -46,8 +46,8 @@
|
||||||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||||
|
|
||||||
#define DIV_VERSION "dev109"
|
#define DIV_VERSION "dev110"
|
||||||
#define DIV_ENGINE_VERSION 109
|
#define DIV_ENGINE_VERSION 110
|
||||||
|
|
||||||
// for imports
|
// for imports
|
||||||
#define DIV_VERSION_MOD 0xff01
|
#define DIV_VERSION_MOD 0xff01
|
||||||
|
|
|
@ -176,6 +176,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
ds.e1e2StopOnSameNote=true;
|
ds.e1e2StopOnSameNote=true;
|
||||||
ds.brokenPortaArp=false;
|
ds.brokenPortaArp=false;
|
||||||
ds.snNoLowPeriods=true;
|
ds.snNoLowPeriods=true;
|
||||||
|
ds.delayBehavior=0;
|
||||||
|
|
||||||
// 1.1 compat flags
|
// 1.1 compat flags
|
||||||
if (ds.version>24) {
|
if (ds.version>24) {
|
||||||
|
@ -1067,6 +1068,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
if (ds.version<108) {
|
if (ds.version<108) {
|
||||||
ds.snNoLowPeriods=true;
|
ds.snNoLowPeriods=true;
|
||||||
}
|
}
|
||||||
|
if (ds.version<110) {
|
||||||
|
ds.delayBehavior=1;
|
||||||
|
}
|
||||||
ds.isDMF=false;
|
ds.isDMF=false;
|
||||||
|
|
||||||
reader.readS(); // reserved
|
reader.readS(); // reserved
|
||||||
|
@ -1484,7 +1488,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
for (int i=0; i<6; i++) {
|
if (ds.version>=110) {
|
||||||
|
ds.delayBehavior=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1917,6 +1926,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
||||||
ds.noSlidesOnFirstTick=true;
|
ds.noSlidesOnFirstTick=true;
|
||||||
ds.rowResetsArpPos=true;
|
ds.rowResetsArpPos=true;
|
||||||
ds.ignoreJumpAtEnd=false;
|
ds.ignoreJumpAtEnd=false;
|
||||||
|
ds.delayBehavior=0;
|
||||||
|
|
||||||
int insCount=31;
|
int insCount=31;
|
||||||
bool bypassLimits=false;
|
bool bypassLimits=false;
|
||||||
|
@ -3729,7 +3739,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeC(song.e1e2StopOnSameNote);
|
w->writeC(song.e1e2StopOnSameNote);
|
||||||
w->writeC(song.brokenPortaArp);
|
w->writeC(song.brokenPortaArp);
|
||||||
w->writeC(song.snNoLowPeriods);
|
w->writeC(song.snNoLowPeriods);
|
||||||
for (int i=0; i<6; i++) {
|
w->writeC(song.delayBehavior);
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,19 +263,37 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].std.arp.had) {
|
if (i>=5 && chan[i].furnaceDac) {
|
||||||
if (!chan[i].inPorta) {
|
if (chan[i].std.arp.had) {
|
||||||
if (chan[i].std.arp.mode) {
|
if (!chan[i].inPorta) {
|
||||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].std.arp.val,11);
|
if (chan[i].std.arp.mode) {
|
||||||
} else {
|
chan[i].baseFreq=parent->calcBaseFreq(1,1,chan[i].std.arp.val,false);
|
||||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note+(signed char)chan[i].std.arp.val,11);
|
} else {
|
||||||
|
chan[i].baseFreq=parent->calcBaseFreq(1,1,chan[i].note+(signed char)chan[i].std.arp.val,false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
} else {
|
||||||
|
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||||
|
chan[i].baseFreq=parent->calcBaseFreq(1,1,chan[i].note,false);
|
||||||
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chan[i].freqChanged=true;
|
|
||||||
} else {
|
} else {
|
||||||
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
if (chan[i].std.arp.had) {
|
||||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note,11);
|
if (!chan[i].inPorta) {
|
||||||
|
if (chan[i].std.arp.mode) {
|
||||||
|
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].std.arp.val,11);
|
||||||
|
} else {
|
||||||
|
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note+(signed char)chan[i].std.arp.val,11);
|
||||||
|
}
|
||||||
|
}
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
|
} else {
|
||||||
|
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||||
|
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note,11);
|
||||||
|
chan[i].freqChanged=true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,6 +561,11 @@ void DivPlatformGenesisExt::forceIns() {
|
||||||
opChan[i].freqChanged=true;
|
opChan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (extMode && softPCM && chan[7].active) { // CSM
|
||||||
|
chan[7].insChanged=true;
|
||||||
|
chan[7].freqChanged=true;
|
||||||
|
chan[7].keyOn=true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* DivPlatformGenesisExt::getChanState(int ch) {
|
void* DivPlatformGenesisExt::getChanState(int ch) {
|
||||||
|
|
|
@ -361,7 +361,9 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
break;
|
break;
|
||||||
case 0xed: // delay
|
case 0xed: // delay
|
||||||
if (effectVal!=0) {
|
if (effectVal!=0) {
|
||||||
if (effectVal<=nextSpeed) {
|
bool comparison=(song.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<nextSpeed);
|
||||||
|
if (song.delayBehavior==2) comparison=true;
|
||||||
|
if (comparison) {
|
||||||
chan[i].rowDelay=effectVal+1;
|
chan[i].rowDelay=effectVal+1;
|
||||||
chan[i].delayOrder=whatOrder;
|
chan[i].delayOrder=whatOrder;
|
||||||
chan[i].delayRow=whatRow;
|
chan[i].delayRow=whatRow;
|
||||||
|
@ -372,6 +374,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
}
|
}
|
||||||
returnAfterPre=true;
|
returnAfterPre=true;
|
||||||
} else {
|
} else {
|
||||||
|
logV("higher than nextSpeed! %d>%d",effectVal,nextSpeed);
|
||||||
chan[i].delayLocked=false;
|
chan[i].delayLocked=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,6 +382,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (returnAfterPre) return;
|
if (returnAfterPre) return;
|
||||||
|
} else {
|
||||||
|
logV("honoring delay at position %d",whatRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].delayLocked) return;
|
if (chan[i].delayLocked) return;
|
||||||
|
@ -704,7 +709,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_BANK,i,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_BANK,i,effectVal));
|
||||||
break;
|
break;
|
||||||
case 0xec: // delayed note cut
|
case 0xec: // delayed note cut
|
||||||
if (effectVal>0 && effectVal<nextSpeed) {
|
if (effectVal>0 && (song.delayBehavior==2 || effectVal<nextSpeed)) {
|
||||||
chan[i].cut=effectVal+1;
|
chan[i].cut=effectVal+1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -900,7 +905,9 @@ void DivEngine::nextRow() {
|
||||||
prevRow=curRow;
|
prevRow=curRow;
|
||||||
|
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
chan[i].rowDelay=0;
|
if (song.delayBehavior!=2) {
|
||||||
|
chan[i].rowDelay=0;
|
||||||
|
}
|
||||||
processRow(i,false);
|
processRow(i,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,11 @@ struct DivSong {
|
||||||
// 1: fake reset on loop
|
// 1: fake reset on loop
|
||||||
// 2: don't do anything on loop
|
// 2: don't do anything on loop
|
||||||
unsigned char loopModality;
|
unsigned char loopModality;
|
||||||
|
// cut/delay effect behavior
|
||||||
|
// 0: strict (don't allow value higher than or equal to speed)
|
||||||
|
// 1: broken (don't allow value higher than speed)
|
||||||
|
// 2: lax (allow value higher than speed)
|
||||||
|
unsigned char delayBehavior;
|
||||||
bool properNoiseLayout;
|
bool properNoiseLayout;
|
||||||
bool waveDutyIsVol;
|
bool waveDutyIsVol;
|
||||||
bool resetMacroOnPorta;
|
bool resetMacroOnPorta;
|
||||||
|
@ -565,6 +570,7 @@ struct DivSong {
|
||||||
linearPitch(2),
|
linearPitch(2),
|
||||||
pitchSlideSpeed(4),
|
pitchSlideSpeed(4),
|
||||||
loopModality(0),
|
loopModality(0),
|
||||||
|
delayBehavior(2),
|
||||||
properNoiseLayout(true),
|
properNoiseLayout(true),
|
||||||
waveDutyIsVol(false),
|
waveDutyIsVol(false),
|
||||||
resetMacroOnPorta(false),
|
resetMacroOnPorta(false),
|
||||||
|
|
|
@ -193,6 +193,26 @@ void FurnaceGUI::drawCompatFlags() {
|
||||||
ImGui::SetTooltip("select to not reset channels on loop.");
|
ImGui::SetTooltip("select to not reset channels on loop.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Text("Cut/delay effect policy:");
|
||||||
|
if (ImGui::RadioButton("Strict",e->song.delayBehavior==0)) {
|
||||||
|
e->song.delayBehavior=0;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("only when time is less than speed (like DefleMask/ProTracker)");
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("Strict (old)",e->song.delayBehavior==1)) {
|
||||||
|
e->song.delayBehavior=1;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("only when time is less than or equal to speed (original buggy behavior)");
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("Lax",e->song.delayBehavior==2)) {
|
||||||
|
e->song.delayBehavior=2;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("no checks (like FamiTracker)");
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImGui::TextWrapped("the following flags are for compatibility with older Furnace versions.");
|
ImGui::TextWrapped("the following flags are for compatibility with older Furnace versions.");
|
||||||
|
|
Loading…
Reference in New Issue