better subsong detection for import
This commit is contained in:
parent
40a24d6c01
commit
e1746def3a
|
@ -188,79 +188,8 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
}
|
||||
|
||||
void DivEngine::walkSong(int& loopOrder, int& loopRow, int& loopEnd) {
|
||||
loopOrder=0;
|
||||
loopRow=0;
|
||||
loopEnd=-1;
|
||||
int nextOrder=-1;
|
||||
int nextRow=0;
|
||||
int effectVal=0;
|
||||
int lastSuspectedLoopEnd=-1;
|
||||
DivPattern* pat[DIV_MAX_CHANS];
|
||||
unsigned char wsWalked[8192];
|
||||
memset(wsWalked,0,8192);
|
||||
for (int i=0; i<curSubSong->ordersLen; i++) {
|
||||
for (int j=0; j<chans; j++) {
|
||||
pat[j]=curPat[j].getPattern(curOrders->ord[j][i],false);
|
||||
}
|
||||
if (i>lastSuspectedLoopEnd) {
|
||||
lastSuspectedLoopEnd=i;
|
||||
}
|
||||
for (int j=nextRow; j<curSubSong->patLen; j++) {
|
||||
nextRow=0;
|
||||
bool changingOrder=false;
|
||||
bool jumpingOrder=false;
|
||||
if (wsWalked[((i<<5)+(j>>3))&8191]&(1<<(j&7))) {
|
||||
loopOrder=i;
|
||||
loopRow=j;
|
||||
loopEnd=lastSuspectedLoopEnd;
|
||||
return;
|
||||
}
|
||||
for (int k=0; k<chans; k++) {
|
||||
for (int l=0; l<curPat[k].effectCols; l++) {
|
||||
effectVal=pat[k]->data[j][5+(l<<1)];
|
||||
if (effectVal<0) effectVal=0;
|
||||
if (pat[k]->data[j][4+(l<<1)]==0x0d) {
|
||||
if (song.jumpTreatment==2) {
|
||||
if ((i<curSubSong->ordersLen-1 || !song.ignoreJumpAtEnd)) {
|
||||
nextOrder=i+1;
|
||||
nextRow=effectVal;
|
||||
jumpingOrder=true;
|
||||
}
|
||||
} else if (song.jumpTreatment==1) {
|
||||
if (nextOrder==-1 && (i<curSubSong->ordersLen-1 || !song.ignoreJumpAtEnd)) {
|
||||
nextOrder=i+1;
|
||||
nextRow=effectVal;
|
||||
jumpingOrder=true;
|
||||
}
|
||||
} else {
|
||||
if ((i<curSubSong->ordersLen-1 || !song.ignoreJumpAtEnd)) {
|
||||
if (!changingOrder) {
|
||||
nextOrder=i+1;
|
||||
}
|
||||
jumpingOrder=true;
|
||||
nextRow=effectVal;
|
||||
}
|
||||
}
|
||||
} else if (pat[k]->data[j][4+(l<<1)]==0x0b) {
|
||||
if (nextOrder==-1 || song.jumpTreatment==0) {
|
||||
nextOrder=effectVal;
|
||||
if (song.jumpTreatment==1 || song.jumpTreatment==2 || !jumpingOrder) {
|
||||
nextRow=0;
|
||||
}
|
||||
changingOrder=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wsWalked[((i<<5)+(j>>3))&8191]|=1<<(j&7);
|
||||
|
||||
if (nextOrder!=-1) {
|
||||
i=nextOrder-1;
|
||||
nextOrder=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (curSubSong!=NULL) {
|
||||
curSubSong->walk(loopOrder,loopRow,loopEnd,chans,song.jumpTreatment,song.ignoreJumpAtEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1031,7 +1031,7 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
logV("maxChan: %d",maxChan);
|
||||
|
||||
// set channel visibility
|
||||
for (int i=maxChan+1; i<((maxChan+32)&(~31)); i++) {
|
||||
for (int i=maxChan; i<((maxChan+32)&(~31)); i++) {
|
||||
ds.subsong[0]->chanShow[i]=false;
|
||||
ds.subsong[0]->chanShowChanOsc[i]=false;
|
||||
}
|
||||
|
@ -1085,7 +1085,7 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
|||
ds.systemLen=(maxChan+32)>>5;
|
||||
|
||||
// find subsongs
|
||||
ds.findSubSongs();
|
||||
ds.findSubSongs(maxChan);
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
|
|
|
@ -419,7 +419,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
|||
ds.insLen=ds.ins.size();
|
||||
|
||||
// find subsongs
|
||||
ds.findSubSongs();
|
||||
ds.findSubSongs(chCount);
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
|
|
|
@ -1026,7 +1026,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
|||
}
|
||||
|
||||
// find subsongs
|
||||
ds.findSubSongs();
|
||||
ds.findSubSongs(DIV_MAX_CHANS);
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
|
|
|
@ -371,7 +371,7 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
|||
ds.sampleLen=ds.sample.size();
|
||||
|
||||
// find subsongs
|
||||
ds.findSubSongs();
|
||||
ds.findSubSongs(totalChans);
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
|
|
|
@ -20,6 +20,88 @@
|
|||
#include "song.h"
|
||||
#include "../ta-log.h"
|
||||
|
||||
|
||||
bool DivSubSong::walk(int& loopOrder, int& loopRow, int& loopEnd, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat) {
|
||||
loopOrder=0;
|
||||
loopRow=0;
|
||||
loopEnd=-1;
|
||||
int nextOrder=-1;
|
||||
int nextRow=0;
|
||||
int effectVal=0;
|
||||
int lastSuspectedLoopEnd=-1;
|
||||
DivPattern* subPat[DIV_MAX_CHANS];
|
||||
unsigned char wsWalked[8192];
|
||||
memset(wsWalked,0,8192);
|
||||
if (firstPat>0) {
|
||||
memset(wsWalked,255,32*firstPat);
|
||||
}
|
||||
for (int i=firstPat; i<ordersLen; i++) {
|
||||
for (int j=0; j<chans; j++) {
|
||||
subPat[j]=pat[j].getPattern(orders.ord[j][i],false);
|
||||
}
|
||||
if (i>lastSuspectedLoopEnd) {
|
||||
lastSuspectedLoopEnd=i;
|
||||
}
|
||||
for (int j=nextRow; j<patLen; j++) {
|
||||
nextRow=0;
|
||||
bool changingOrder=false;
|
||||
bool jumpingOrder=false;
|
||||
if (wsWalked[((i<<5)+(j>>3))&8191]&(1<<(j&7))) {
|
||||
loopOrder=i;
|
||||
loopRow=j;
|
||||
loopEnd=lastSuspectedLoopEnd;
|
||||
return true;
|
||||
}
|
||||
for (int k=0; k<chans; k++) {
|
||||
for (int l=0; l<pat[k].effectCols; l++) {
|
||||
effectVal=subPat[k]->data[j][5+(l<<1)];
|
||||
if (effectVal<0) effectVal=0;
|
||||
if (subPat[k]->data[j][4+(l<<1)]==0x0d) {
|
||||
if (jumpTreatment==2) {
|
||||
if ((i<ordersLen-1 || !ignoreJumpAtEnd)) {
|
||||
nextOrder=i+1;
|
||||
nextRow=effectVal;
|
||||
jumpingOrder=true;
|
||||
}
|
||||
} else if (jumpTreatment==1) {
|
||||
if (nextOrder==-1 && (i<ordersLen-1 || !ignoreJumpAtEnd)) {
|
||||
nextOrder=i+1;
|
||||
nextRow=effectVal;
|
||||
jumpingOrder=true;
|
||||
}
|
||||
} else {
|
||||
if ((i<ordersLen-1 || !ignoreJumpAtEnd)) {
|
||||
if (!changingOrder) {
|
||||
nextOrder=i+1;
|
||||
}
|
||||
jumpingOrder=true;
|
||||
nextRow=effectVal;
|
||||
}
|
||||
}
|
||||
} else if (subPat[k]->data[j][4+(l<<1)]==0x0b) {
|
||||
if (nextOrder==-1 || jumpTreatment==0) {
|
||||
nextOrder=effectVal;
|
||||
if (jumpTreatment==1 || jumpTreatment==2 || !jumpingOrder) {
|
||||
nextRow=0;
|
||||
}
|
||||
changingOrder=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wsWalked[((i<<5)+(j>>3))&8191]|=1<<(j&7);
|
||||
|
||||
if (nextOrder!=-1) {
|
||||
i=nextOrder-1;
|
||||
nextOrder=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DivSubSong::clearData() {
|
||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
pat[i].wipePatterns();
|
||||
|
@ -128,7 +210,122 @@ void DivSubSong::makePatUnique() {
|
|||
}
|
||||
}
|
||||
|
||||
void DivSong::findSubSongs() {
|
||||
void DivSong::findSubSongs(int chans) {
|
||||
std::vector<DivSubSong*> newSubSongs;
|
||||
for (DivSubSong* i: subsong) {
|
||||
std::vector<int> subSongStart;
|
||||
std::vector<int> subSongEnd;
|
||||
int loopOrder=0;
|
||||
int loopRow=0;
|
||||
int loopEnd=-1;
|
||||
int curStart=-1;
|
||||
|
||||
// find possible subsongs
|
||||
logD("finding subsongs...");
|
||||
while (++curStart<i->ordersLen) {
|
||||
if (!i->walk(loopOrder,loopRow,loopEnd,chans,jumpTreatment,ignoreJumpAtEnd,curStart)) break;
|
||||
|
||||
// make sure we don't pick the same range twice
|
||||
if (!subSongEnd.empty()) {
|
||||
if (subSongEnd.back()==loopEnd) continue;
|
||||
}
|
||||
|
||||
logV("found a subsong: %d-%d",curStart,loopEnd);
|
||||
subSongStart.push_back(curStart);
|
||||
subSongEnd.push_back(loopEnd);
|
||||
}
|
||||
|
||||
// if this is the only song, quit
|
||||
if (subSongStart.size()<2) {
|
||||
subSongStart.clear();
|
||||
subSongEnd.clear();
|
||||
newSubSongs.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
// now copy the song
|
||||
bool isTouched[DIV_MAX_CHANS][DIV_MAX_PATTERNS];
|
||||
memset(isTouched,0,DIV_MAX_CHANS*DIV_MAX_PATTERNS*sizeof(bool));
|
||||
for (size_t j=1; j<subSongStart.size(); j++) {
|
||||
bool isUsed[DIV_MAX_CHANS][DIV_MAX_PATTERNS];
|
||||
int start=subSongStart[j];
|
||||
int end=subSongEnd[j];
|
||||
|
||||
DivSubSong* theCopy=new DivSubSong;
|
||||
|
||||
theCopy->name=i->name;
|
||||
theCopy->notes=i->notes;
|
||||
theCopy->hilightA=i->hilightA;
|
||||
theCopy->hilightB=i->hilightB;
|
||||
theCopy->timeBase=i->timeBase;
|
||||
theCopy->arpLen=i->arpLen;
|
||||
theCopy->speeds=i->speeds;
|
||||
theCopy->virtualTempoN=i->virtualTempoN;
|
||||
theCopy->virtualTempoD=i->virtualTempoD;
|
||||
theCopy->hz=i->hz;
|
||||
theCopy->patLen=i->patLen;
|
||||
|
||||
// copy orders
|
||||
memset(isUsed,0,DIV_MAX_CHANS*DIV_MAX_PATTERNS*sizeof(bool));
|
||||
for (int k=start, kIndex=0; k<=end; k++, kIndex++) {
|
||||
for (int l=0; l<DIV_MAX_CHANS; l++) {
|
||||
theCopy->orders.ord[l][kIndex]=i->orders.ord[l][k];
|
||||
isUsed[l][i->orders.ord[l][k]]=true;
|
||||
isTouched[l][i->orders.ord[l][k]]=true;
|
||||
}
|
||||
}
|
||||
theCopy->ordersLen=end-start+1;
|
||||
|
||||
memcpy(theCopy->chanShow,i->chanShow,DIV_MAX_CHANS*sizeof(bool));
|
||||
memcpy(theCopy->chanShowChanOsc,i->chanShowChanOsc,DIV_MAX_CHANS*sizeof(bool));
|
||||
memcpy(theCopy->chanCollapse,i->chanCollapse,DIV_MAX_CHANS);
|
||||
|
||||
for (int k=0; k<DIV_MAX_CHANS; k++) {
|
||||
theCopy->chanName[k]=i->chanName[k];
|
||||
theCopy->chanShortName[j]=i->chanShortName[k];
|
||||
|
||||
theCopy->pat[k].effectCols=i->pat[k].effectCols;
|
||||
|
||||
for (int l=0; l<DIV_MAX_PATTERNS; l++) {
|
||||
if (i->pat[k].data[l]==NULL) continue;
|
||||
if (!isUsed[k][l]) continue;
|
||||
DivPattern* origPat=i->pat[k].getPattern(l,false);
|
||||
DivPattern* copyPat=theCopy->pat[k].getPattern(l,true);
|
||||
origPat->copyOn(copyPat);
|
||||
}
|
||||
}
|
||||
|
||||
newSubSongs.push_back(theCopy);
|
||||
}
|
||||
|
||||
// and cut this one
|
||||
i->ordersLen=subSongEnd[0]+1;
|
||||
|
||||
// remove taken patterns as well, as long as they're not used in the original subsong
|
||||
// first unmark patterns which are used
|
||||
for (int j=subSongStart[0]; j<=subSongEnd[0]; j++) {
|
||||
for (int k=0; k<DIV_MAX_CHANS; k++) {
|
||||
isTouched[k][i->orders.ord[k][j]]=false;
|
||||
}
|
||||
}
|
||||
|
||||
// then remove the rest
|
||||
for (int j=0; j<DIV_MAX_CHANS; j++) {
|
||||
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
|
||||
if (isTouched[j][k]) {
|
||||
if (i->pat[j].data[k]!=NULL) {
|
||||
delete i->pat[j].data[k];
|
||||
i->pat[j].data[k]=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append every subsong we found
|
||||
for (DivSubSong* i: newSubSongs) {
|
||||
subsong.push_back(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,11 @@ struct DivSubSong {
|
|||
String chanName[DIV_MAX_CHANS];
|
||||
String chanShortName[DIV_MAX_CHANS];
|
||||
|
||||
/**
|
||||
* walk through the song and determine loop position.
|
||||
*/
|
||||
bool walk(int& loopOrder, int& loopRow, int& loopEnd, int chans, int jumpTreatment, int ignoreJumpAtEnd, int firstPat=0);
|
||||
|
||||
void clearData();
|
||||
void optimizePatterns();
|
||||
void rearrangePatterns();
|
||||
|
@ -356,7 +361,7 @@ struct DivSong {
|
|||
/**
|
||||
* find data past 0Bxx effects and place that into new sub-songs.
|
||||
*/
|
||||
void findSubSongs();
|
||||
void findSubSongs(int chans);
|
||||
|
||||
/**
|
||||
* clear orders and patterns.
|
||||
|
|
Loading…
Reference in a new issue