mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-15 17:25:06 +00:00
Merge branch 'tildearrow:master' into master
This commit is contained in:
commit
3709f1f0a3
7 changed files with 83 additions and 16 deletions
|
@ -46,8 +46,8 @@
|
|||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||
|
||||
#define DIV_VERSION "dev109"
|
||||
#define DIV_ENGINE_VERSION 109
|
||||
#define DIV_VERSION "dev110"
|
||||
#define DIV_ENGINE_VERSION 110
|
||||
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
|
|
|
@ -176,6 +176,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
ds.e1e2StopOnSameNote=true;
|
||||
ds.brokenPortaArp=false;
|
||||
ds.snNoLowPeriods=true;
|
||||
ds.delayBehavior=0;
|
||||
|
||||
// 1.1 compat flags
|
||||
if (ds.version>24) {
|
||||
|
@ -1067,6 +1068,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
if (ds.version<108) {
|
||||
ds.snNoLowPeriods=true;
|
||||
}
|
||||
if (ds.version<110) {
|
||||
ds.delayBehavior=1;
|
||||
}
|
||||
ds.isDMF=false;
|
||||
|
||||
reader.readS(); // reserved
|
||||
|
@ -1484,7 +1488,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
} else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1917,6 +1926,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
|||
ds.noSlidesOnFirstTick=true;
|
||||
ds.rowResetsArpPos=true;
|
||||
ds.ignoreJumpAtEnd=false;
|
||||
ds.delayBehavior=0;
|
||||
|
||||
int insCount=31;
|
||||
bool bypassLimits=false;
|
||||
|
@ -3729,7 +3739,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
|||
w->writeC(song.e1e2StopOnSameNote);
|
||||
w->writeC(song.brokenPortaArp);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -263,19 +263,37 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.arp.had) {
|
||||
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);
|
||||
if (i>=5 && chan[i].furnaceDac) {
|
||||
if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=parent->calcBaseFreq(1,1,chan[i].std.arp.val,false);
|
||||
} 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 {
|
||||
if (chan[i].std.arp.mode && chan[i].std.arp.finished) {
|
||||
chan[i].baseFreq=NOTE_FNUM_BLOCK(chan[i].note,11);
|
||||
if (chan[i].std.arp.had) {
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
if (extMode && softPCM && chan[7].active) { // CSM
|
||||
chan[7].insChanged=true;
|
||||
chan[7].freqChanged=true;
|
||||
chan[7].keyOn=true;
|
||||
}
|
||||
}
|
||||
|
||||
void* DivPlatformGenesisExt::getChanState(int ch) {
|
||||
|
|
|
@ -361,7 +361,9 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
break;
|
||||
case 0xed: // delay
|
||||
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].delayOrder=whatOrder;
|
||||
chan[i].delayRow=whatRow;
|
||||
|
@ -372,6 +374,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
returnAfterPre=true;
|
||||
} else {
|
||||
logV("higher than nextSpeed! %d>%d",effectVal,nextSpeed);
|
||||
chan[i].delayLocked=false;
|
||||
}
|
||||
}
|
||||
|
@ -379,6 +382,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
}
|
||||
if (returnAfterPre) return;
|
||||
} else {
|
||||
logV("honoring delay at position %d",whatRow);
|
||||
}
|
||||
|
||||
if (chan[i].delayLocked) return;
|
||||
|
@ -704,7 +709,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_BANK,i,effectVal));
|
||||
break;
|
||||
case 0xec: // delayed note cut
|
||||
if (effectVal>0 && effectVal<nextSpeed) {
|
||||
if (effectVal>0 && (song.delayBehavior==2 || effectVal<nextSpeed)) {
|
||||
chan[i].cut=effectVal+1;
|
||||
}
|
||||
break;
|
||||
|
@ -900,7 +905,9 @@ void DivEngine::nextRow() {
|
|||
prevRow=curRow;
|
||||
|
||||
for (int i=0; i<chans; i++) {
|
||||
chan[i].rowDelay=0;
|
||||
if (song.delayBehavior!=2) {
|
||||
chan[i].rowDelay=0;
|
||||
}
|
||||
processRow(i,false);
|
||||
}
|
||||
|
||||
|
|
|
@ -463,6 +463,11 @@ struct DivSong {
|
|||
// 1: fake reset on loop
|
||||
// 2: don't do anything on loop
|
||||
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 waveDutyIsVol;
|
||||
bool resetMacroOnPorta;
|
||||
|
@ -565,6 +570,7 @@ struct DivSong {
|
|||
linearPitch(2),
|
||||
pitchSlideSpeed(4),
|
||||
loopModality(0),
|
||||
delayBehavior(2),
|
||||
properNoiseLayout(true),
|
||||
waveDutyIsVol(false),
|
||||
resetMacroOnPorta(false),
|
||||
|
|
|
@ -193,6 +193,26 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
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::TextWrapped("the following flags are for compatibility with older Furnace versions.");
|
||||
|
|
Loading…
Reference in a new issue