Merge branch 'tildearrow:master' into master

This commit is contained in:
AuroraFields 2022-08-22 09:49:44 +03:00 committed by GitHub
commit 3709f1f0a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 16 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -263,6 +263,23 @@ void DivPlatformGenesis::tick(bool sysTick) {
}
}
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;
}
}
} else {
if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
if (chan[i].std.arp.mode) {
@ -278,6 +295,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
chan[i].freqChanged=true;
}
}
}
if (i>=5 && chan[i].furnaceDac) {
if (chan[i].std.panL.had) {

View file

@ -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) {

View file

@ -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++) {
if (song.delayBehavior!=2) {
chan[i].rowDelay=0;
}
processRow(i,false);
}

View file

@ -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),

View file

@ -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.");