dev113 - loop detection changes

This commit is contained in:
tildearrow 2022-09-10 01:39:42 -05:00
parent ac0decd01b
commit 187653a70f
9 changed files with 87 additions and 16 deletions

View File

@ -15,8 +15,8 @@ android {
}
minSdkVersion 21
targetSdkVersion 26
versionCode 112
versionName "dev112"
versionCode 113
versionName "dev113"
externalNativeBuild {
cmake {
arguments "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static"

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.tildearrow.furnace"
android:versionCode="112"
android:versionName="dev112"
android:versionCode="113"
android:versionName="dev113"
android:installLocation="auto">
<!-- OpenGL ES 2.0 -->

View File

@ -32,6 +32,7 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
the format versions are:
- 113: Furnace dev113
- 112: Furnace dev112
- 111: Furnace dev111
- 110: Furnace dev110
@ -338,7 +339,8 @@ size | description
1 | broken initial position of porta after arp (>=101) or reserved
1 | SN periods under 8 are treated as 1 (>=108) or reserved
1 | cut/delay effect policy (>=110) or reserved
5 | reserved
1 | 0B/0D effect treatment (>=113) or reserved
4 | 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

@ -1658,6 +1658,7 @@ void DivEngine::playSub(bool preserveDrift, int goalRow) {
speedAB=false;
playing=true;
skipping=true;
memset(walked,0,8192);
for (int i=0; i<song.systemLen; i++) disCont[i].dispatch->setSkipRegisterWrites(true);
while (playing && curOrder<goal) {
if (nextTick(preserveDrift)) {

View File

@ -46,9 +46,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev112"
#define DIV_ENGINE_VERSION 112
#define DIV_VERSION "dev113"
#define DIV_ENGINE_VERSION 113
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02
@ -358,6 +357,8 @@ class DivEngine {
double exportFadeOut;
std::map<String,String> conf;
std::deque<DivNoteEvent> pendingNotes;
// bitfield
unsigned char walked[8192];
bool isMuted[DIV_MAX_CHANS];
std::mutex isBusy, saveLock;
String configPath;
@ -1072,6 +1073,7 @@ class DivEngine {
memset(reversePitchTable,0,4096*sizeof(int));
memset(pitchTable,0,4096*sizeof(int));
memset(sysDefs,0,256*sizeof(void*));
memset(walked,0,8192);
for (int i=0; i<256; i++) {
sysFileMapFur[i]=DIV_SYSTEM_NULL;

View File

@ -179,6 +179,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.brokenPortaArp=false;
ds.snNoLowPeriods=true;
ds.delayBehavior=0;
ds.jumpTreatment=2;
// 1.1 compat flags
if (ds.version>24) {
@ -1081,6 +1082,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
if (ds.version<110) {
ds.delayBehavior=1;
}
if (ds.version<113) {
ds.jumpTreatment=1;
}
ds.isDMF=false;
reader.readS(); // reserved
@ -1503,7 +1507,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} else {
reader.readC();
}
for (int i=0; i<5; i++) {
if (ds.version>=113) {
ds.jumpTreatment=reader.readC();
} else {
reader.readC();
}
for (int i=0; i<4; i++) {
reader.readC();
}
}
@ -3747,7 +3756,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
w->writeC(song.brokenPortaArp);
w->writeC(song.snNoLowPeriods);
w->writeC(song.delayBehavior);
for (int i=0; i<5; i++) {
w->writeC(song.jumpTreatment);
for (int i=0; i<4; i++) {
w->writeC(0);
}

View File

@ -31,7 +31,9 @@ void DivEngine::nextOrder() {
curRow=0;
if (repeatPattern) return;
if (++curOrder>=curSubSong->ordersLen) {
logV("end of orders reached");
endOfSong=true;
memset(walked,0,8192);
curOrder=0;
}
}
@ -348,15 +350,31 @@ void DivEngine::processRow(int i, bool afterDelay) {
if (effectVal>0) speed2=effectVal;
break;
case 0x0b: // change order
if (changeOrd==-1) {
if (changeOrd==-1 || song.jumpTreatment==0) {
changeOrd=effectVal;
changePos=0;
if (song.jumpTreatment==1 || song.jumpTreatment==2) {
changePos=0;
}
}
break;
case 0x0d: // next order
if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
changeOrd=-2;
changePos=effectVal;
if (song.jumpTreatment==2) {
if ((curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
changeOrd=-2;
changePos=effectVal;
}
} else if (song.jumpTreatment==1) {
if (changeOrd<0 && (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd)) {
changeOrd=-2;
changePos=effectVal;
}
} else {
if (curOrder<(curSubSong->ordersLen-1) || !song.ignoreJumpAtEnd) {
if (changeOrd<0) {
changeOrd=-2;
}
changePos=effectVal;
}
}
break;
case 0xed: // delay
@ -911,18 +929,23 @@ void DivEngine::nextRow() {
processRow(i,false);
}
walked[((curOrder<<5)+(curRow>>3))&8191]|=1<<(curRow&7);
if (changeOrd!=-1) {
if (repeatPattern) {
curRow=0;
changeOrd=-1;
} else {
curRow=changePos;
changePos=0;
if (changeOrd==-2) changeOrd=curOrder+1;
if (changeOrd<=curOrder) endOfSong=true;
// old loop detection routine
//if (changeOrd<=curOrder) endOfSong=true;
curOrder=changeOrd;
if (curOrder>=curSubSong->ordersLen) {
curOrder=0;
endOfSong=true;
memset(walked,0,8192);
}
changeOrd=-1;
}
@ -932,6 +955,13 @@ void DivEngine::nextRow() {
if (haltOn==DIV_HALT_PATTERN) halted=true;
}
// new loop detection routine
if (!endOfSong && walked[((curOrder<<5)+(curRow>>3))&8191]&(1<<(curRow&7))) {
logV("loop reached");
endOfSong=true;
memset(walked,0,8192);
}
if (song.brokenSpeedSel) {
if ((curSubSong->patLen&1) && curOrder&1) {
ticks=((curRow&1)?speed2:speed1)*(curSubSong->timeBase+1);

View File

@ -468,6 +468,11 @@ struct DivSong {
// 1: broken (don't allow value higher than speed)
// 2: lax (allow value higher than speed)
unsigned char delayBehavior;
// 0B/0D treatment
// 0: normal (0B/0D accepted)
// 1: old Furnace (first one accepted)
// 2: DefleMask (0D takes priority over 0B)
unsigned char jumpTreatment;
bool properNoiseLayout;
bool waveDutyIsVol;
bool resetMacroOnPorta;
@ -571,6 +576,7 @@ struct DivSong {
pitchSlideSpeed(4),
loopModality(2),
delayBehavior(2),
jumpTreatment(0),
properNoiseLayout(true),
waveDutyIsVol(false),
resetMacroOnPorta(false),

View File

@ -213,6 +213,26 @@ void FurnaceGUI::drawCompatFlags() {
ImGui::SetTooltip("no checks (like FamiTracker)");
}
ImGui::Text("Simultaneous jump (0B+0D) treatment:");
if (ImGui::RadioButton("Normal",e->song.jumpTreatment==0)) {
e->song.jumpTreatment=0;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("accept 0B+0D to jump to a specific row of an order");
}
if (ImGui::RadioButton("Old Furnace",e->song.jumpTreatment==1)) {
e->song.jumpTreatment=1;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("only accept the first jump effect");
}
if (ImGui::RadioButton("DefleMask",e->song.jumpTreatment==2)) {
e->song.jumpTreatment=2;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("only accept 0Dxx");
}
ImGui::Separator();
ImGui::TextWrapped("the following flags are for compatibility with older Furnace versions.");