allow saving patterns in old format
This commit is contained in:
parent
c3ccd74a15
commit
4947d02c68
|
@ -591,7 +591,7 @@ class DivEngine {
|
||||||
SafeWriter* saveDMF(unsigned char version);
|
SafeWriter* saveDMF(unsigned char version);
|
||||||
// save as .fur.
|
// save as .fur.
|
||||||
// if notPrimary is true then the song will not be altered
|
// if notPrimary is true then the song will not be altered
|
||||||
SafeWriter* saveFur(bool notPrimary=false);
|
SafeWriter* saveFur(bool notPrimary=false, bool newPatternFormat=true);
|
||||||
// build a ROM file (TODO).
|
// build a ROM file (TODO).
|
||||||
// specify system to build ROM for.
|
// specify system to build ROM for.
|
||||||
std::vector<DivROMExportOutput> buildROM(DivROMExportOptions sys);
|
std::vector<DivROMExportOutput> buildROM(DivROMExportOptions sys);
|
||||||
|
|
|
@ -5077,9 +5077,7 @@ DivDataErrors DivEngine::readAssetDirData(SafeReader& reader, std::vector<DivAss
|
||||||
return DIV_DATA_SUCCESS;
|
return DIV_DATA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NEW_PATTERN_FORMAT
|
SafeWriter* DivEngine::saveFur(bool notPrimary, bool newPatternFormat) {
|
||||||
|
|
||||||
SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
|
||||||
saveLock.lock();
|
saveLock.lock();
|
||||||
std::vector<int> subSongPtr;
|
std::vector<int> subSongPtr;
|
||||||
std::vector<int> sysFlagsPtr;
|
std::vector<int> sysFlagsPtr;
|
||||||
|
@ -5514,132 +5512,132 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
DivPattern* pat=song.subsong[i.subsong]->pat[i.chan].getPattern(i.pat,false);
|
DivPattern* pat=song.subsong[i.subsong]->pat[i.chan].getPattern(i.pat,false);
|
||||||
patPtr.push_back(w->tell());
|
patPtr.push_back(w->tell());
|
||||||
|
|
||||||
#ifdef NEW_PATTERN_FORMAT
|
if (newPatternFormat) {
|
||||||
w->write("PATN",4);
|
w->write("PATN",4);
|
||||||
blockStartSeek=w->tell();
|
blockStartSeek=w->tell();
|
||||||
w->writeI(0);
|
w->writeI(0);
|
||||||
|
|
||||||
w->writeC(i.subsong);
|
w->writeC(i.subsong);
|
||||||
w->writeC(i.chan);
|
w->writeC(i.chan);
|
||||||
w->writeS(i.pat);
|
w->writeS(i.pat);
|
||||||
w->writeString(pat->name,false);
|
w->writeString(pat->name,false);
|
||||||
|
|
||||||
unsigned char emptyRows=0;
|
unsigned char emptyRows=0;
|
||||||
|
|
||||||
for (int j=0; j<song.subsong[i.subsong]->patLen; j++) {
|
for (int j=0; j<song.subsong[i.subsong]->patLen; j++) {
|
||||||
unsigned char mask=0;
|
unsigned char mask=0;
|
||||||
unsigned char finalNote=255;
|
unsigned char finalNote=255;
|
||||||
unsigned short effectMask=0;
|
unsigned short effectMask=0;
|
||||||
|
|
||||||
if (pat->data[j][0]==100) {
|
if (pat->data[j][0]==100) {
|
||||||
finalNote=180;
|
finalNote=180;
|
||||||
} else if (pat->data[j][0]==101) { // note release
|
} else if (pat->data[j][0]==101) { // note release
|
||||||
finalNote=181;
|
finalNote=181;
|
||||||
} else if (pat->data[j][0]==102) { // macro release
|
} else if (pat->data[j][0]==102) { // macro release
|
||||||
finalNote=182;
|
finalNote=182;
|
||||||
} else if (pat->data[j][1]==0 && pat->data[j][0]==0) {
|
} else if (pat->data[j][1]==0 && pat->data[j][0]==0) {
|
||||||
finalNote=255;
|
|
||||||
} else {
|
|
||||||
int seek=(pat->data[j][0]+(signed char)pat->data[j][1]*12)+60;
|
|
||||||
if (seek<0 || seek>=180) {
|
|
||||||
finalNote=255;
|
finalNote=255;
|
||||||
} else {
|
} else {
|
||||||
finalNote=seek;
|
int seek=(pat->data[j][0]+(signed char)pat->data[j][1]*12)+60;
|
||||||
|
if (seek<0 || seek>=180) {
|
||||||
|
finalNote=255;
|
||||||
|
} else {
|
||||||
|
finalNote=seek;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (finalNote!=255) mask|=1; // note
|
if (finalNote!=255) mask|=1; // note
|
||||||
if (pat->data[j][2]!=-1) mask|=2; // instrument
|
if (pat->data[j][2]!=-1) mask|=2; // instrument
|
||||||
if (pat->data[j][3]!=-1) mask|=4; // volume
|
if (pat->data[j][3]!=-1) mask|=4; // volume
|
||||||
for (int k=0; k<song.subsong[i.subsong]->pat[i.chan].effectCols*2; k+=2) {
|
for (int k=0; k<song.subsong[i.subsong]->pat[i.chan].effectCols*2; k+=2) {
|
||||||
if (k==0) {
|
if (k==0) {
|
||||||
if (pat->data[j][4+k]!=-1) mask|=8;
|
if (pat->data[j][4+k]!=-1) mask|=8;
|
||||||
if (pat->data[j][5+k]!=-1) mask|=16;
|
if (pat->data[j][5+k]!=-1) mask|=16;
|
||||||
} else if (k<8) {
|
} else if (k<8) {
|
||||||
if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=32;
|
if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=32;
|
||||||
|
} else {
|
||||||
|
if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pat->data[j][4+k]!=-1) effectMask|=(1<<k);
|
||||||
|
if (pat->data[j][5+k]!=-1) effectMask|=(2<<k);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask==0) {
|
||||||
|
emptyRows++;
|
||||||
|
if (emptyRows>127) {
|
||||||
|
w->writeC(128|(emptyRows-2));
|
||||||
|
emptyRows=0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (pat->data[j][4+k]!=-1 || pat->data[j][5+k]!=-1) mask|=64;
|
if (emptyRows>1) {
|
||||||
}
|
w->writeC(128|(emptyRows-2));
|
||||||
|
emptyRows=0;
|
||||||
|
} else if (emptyRows) {
|
||||||
|
w->writeC(0);
|
||||||
|
emptyRows=0;
|
||||||
|
}
|
||||||
|
|
||||||
if (pat->data[j][4+k]!=-1) effectMask|=(1<<k);
|
w->writeC(mask);
|
||||||
if (pat->data[j][5+k]!=-1) effectMask|=(2<<k);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mask==0) {
|
if (mask&32) w->writeC(effectMask&0xff);
|
||||||
emptyRows++;
|
if (mask&64) w->writeC((effectMask>>8)&0xff);
|
||||||
if (emptyRows>127) {
|
|
||||||
w->writeC(128|(emptyRows-2));
|
|
||||||
emptyRows=0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (emptyRows>1) {
|
|
||||||
w->writeC(128|(emptyRows-2));
|
|
||||||
emptyRows=0;
|
|
||||||
} else if (emptyRows) {
|
|
||||||
w->writeC(0);
|
|
||||||
emptyRows=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
w->writeC(mask);
|
if (mask&1) w->writeC(finalNote);
|
||||||
|
if (mask&2) w->writeC(pat->data[j][2]);
|
||||||
if (mask&32) w->writeC(effectMask&0xff);
|
if (mask&4) w->writeC(pat->data[j][3]);
|
||||||
if (mask&64) w->writeC((effectMask>>8)&0xff);
|
if (mask&8) w->writeC(pat->data[j][4]);
|
||||||
|
if (mask&16) w->writeC(pat->data[j][5]);
|
||||||
if (mask&1) w->writeC(finalNote);
|
if (mask&32) {
|
||||||
if (mask&2) w->writeC(pat->data[j][2]);
|
if (effectMask&4) w->writeC(pat->data[j][6]);
|
||||||
if (mask&4) w->writeC(pat->data[j][3]);
|
if (effectMask&8) w->writeC(pat->data[j][7]);
|
||||||
if (mask&8) w->writeC(pat->data[j][4]);
|
if (effectMask&16) w->writeC(pat->data[j][8]);
|
||||||
if (mask&16) w->writeC(pat->data[j][5]);
|
if (effectMask&32) w->writeC(pat->data[j][9]);
|
||||||
if (mask&32) {
|
if (effectMask&64) w->writeC(pat->data[j][10]);
|
||||||
if (effectMask&4) w->writeC(pat->data[j][6]);
|
if (effectMask&128) w->writeC(pat->data[j][11]);
|
||||||
if (effectMask&8) w->writeC(pat->data[j][7]);
|
}
|
||||||
if (effectMask&16) w->writeC(pat->data[j][8]);
|
if (mask&64) {
|
||||||
if (effectMask&32) w->writeC(pat->data[j][9]);
|
if (effectMask&256) w->writeC(pat->data[j][12]);
|
||||||
if (effectMask&64) w->writeC(pat->data[j][10]);
|
if (effectMask&512) w->writeC(pat->data[j][13]);
|
||||||
if (effectMask&128) w->writeC(pat->data[j][11]);
|
if (effectMask&1024) w->writeC(pat->data[j][14]);
|
||||||
}
|
if (effectMask&2048) w->writeC(pat->data[j][15]);
|
||||||
if (mask&64) {
|
if (effectMask&4096) w->writeC(pat->data[j][16]);
|
||||||
if (effectMask&256) w->writeC(pat->data[j][12]);
|
if (effectMask&8192) w->writeC(pat->data[j][17]);
|
||||||
if (effectMask&512) w->writeC(pat->data[j][13]);
|
if (effectMask&16384) w->writeC(pat->data[j][18]);
|
||||||
if (effectMask&1024) w->writeC(pat->data[j][14]);
|
if (effectMask&32768) w->writeC(pat->data[j][19]);
|
||||||
if (effectMask&2048) w->writeC(pat->data[j][15]);
|
}
|
||||||
if (effectMask&4096) w->writeC(pat->data[j][16]);
|
|
||||||
if (effectMask&8192) w->writeC(pat->data[j][17]);
|
|
||||||
if (effectMask&16384) w->writeC(pat->data[j][18]);
|
|
||||||
if (effectMask&32768) w->writeC(pat->data[j][19]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// stop
|
// stop
|
||||||
w->writeC(0xff);
|
w->writeC(0xff);
|
||||||
#else
|
} else {
|
||||||
w->write("PATR",4);
|
w->write("PATR",4);
|
||||||
blockStartSeek=w->tell();
|
blockStartSeek=w->tell();
|
||||||
w->writeI(0);
|
w->writeI(0);
|
||||||
|
|
||||||
w->writeS(i.chan);
|
w->writeS(i.chan);
|
||||||
w->writeS(i.pat);
|
w->writeS(i.pat);
|
||||||
w->writeS(i.subsong);
|
w->writeS(i.subsong);
|
||||||
|
|
||||||
w->writeS(0); // reserved
|
w->writeS(0); // reserved
|
||||||
|
|
||||||
for (int j=0; j<song.subsong[i.subsong]->patLen; j++) {
|
for (int j=0; j<song.subsong[i.subsong]->patLen; j++) {
|
||||||
w->writeS(pat->data[j][0]); // note
|
w->writeS(pat->data[j][0]); // note
|
||||||
w->writeS(pat->data[j][1]); // octave
|
w->writeS(pat->data[j][1]); // octave
|
||||||
w->writeS(pat->data[j][2]); // instrument
|
w->writeS(pat->data[j][2]); // instrument
|
||||||
w->writeS(pat->data[j][3]); // volume
|
w->writeS(pat->data[j][3]); // volume
|
||||||
#ifdef TA_BIG_ENDIAN
|
#ifdef TA_BIG_ENDIAN
|
||||||
for (int k=0; k<song.subsong[i.subsong]->pat[i.chan].effectCols*2; k++) {
|
for (int k=0; k<song.subsong[i.subsong]->pat[i.chan].effectCols*2; k++) {
|
||||||
w->writeS(pat->data[j][4+k]);
|
w->writeS(pat->data[j][4+k]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
w->write(&pat->data[j][4],2*song.subsong[i.subsong]->pat[i.chan].effectCols*2); // effects
|
w->write(&pat->data[j][4],2*song.subsong[i.subsong]->pat[i.chan].effectCols*2); // effects
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
w->writeString(pat->name,false);
|
w->writeString(pat->name,false);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
blockEndSeek=w->tell();
|
blockEndSeek=w->tell();
|
||||||
w->seek(blockStartSeek,SEEK_SET);
|
w->seek(blockStartSeek,SEEK_SET);
|
||||||
|
|
|
@ -1975,7 +1975,7 @@ int FurnaceGUI::save(String path, int dmfVersion) {
|
||||||
if (dmfVersion<24) dmfVersion=24;
|
if (dmfVersion<24) dmfVersion=24;
|
||||||
w=e->saveDMF(dmfVersion);
|
w=e->saveDMF(dmfVersion);
|
||||||
} else {
|
} else {
|
||||||
w=e->saveFur();
|
w=e->saveFur(false,settings.newPatternFormat);
|
||||||
}
|
}
|
||||||
if (w==NULL) {
|
if (w==NULL) {
|
||||||
lastError=e->getLastError();
|
lastError=e->getLastError();
|
||||||
|
@ -5674,7 +5674,7 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logD("saving backup...");
|
logD("saving backup...");
|
||||||
SafeWriter* w=e->saveFur(true);
|
SafeWriter* w=e->saveFur(true,true);
|
||||||
logV("writing file...");
|
logV("writing file...");
|
||||||
|
|
||||||
if (w!=NULL) {
|
if (w!=NULL) {
|
||||||
|
|
|
@ -1425,6 +1425,7 @@ class FurnaceGUI {
|
||||||
int iCannotWait;
|
int iCannotWait;
|
||||||
int orderButtonPos;
|
int orderButtonPos;
|
||||||
int compress;
|
int compress;
|
||||||
|
int newPatternFormat;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
String mainFontPath;
|
String mainFontPath;
|
||||||
String patFontPath;
|
String patFontPath;
|
||||||
|
@ -1571,6 +1572,7 @@ class FurnaceGUI {
|
||||||
iCannotWait(0),
|
iCannotWait(0),
|
||||||
orderButtonPos(2),
|
orderButtonPos(2),
|
||||||
compress(1),
|
compress(1),
|
||||||
|
newPatternFormat(1),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
mainFontPath(""),
|
mainFontPath(""),
|
||||||
patFontPath(""),
|
patFontPath(""),
|
||||||
|
|
|
@ -662,6 +662,13 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::SetTooltip("use zlib to compress saved songs.");
|
ImGui::SetTooltip("use zlib to compress saved songs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool newPatternFormatB=settings.newPatternFormat;
|
||||||
|
if (ImGui::Checkbox("Use new pattern format when saving",&newPatternFormatB)) {
|
||||||
|
settings.newPatternFormat=newPatternFormatB;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("use a packed format which saves space when saving songs.\ndisable if you need compatibility with older Furnace and/or tools\nwhich do not support this format.");
|
||||||
|
}
|
||||||
|
|
||||||
bool cursorFollowsOrderB=settings.cursorFollowsOrder;
|
bool cursorFollowsOrderB=settings.cursorFollowsOrder;
|
||||||
if (ImGui::Checkbox("Cursor follows current order when moving it",&cursorFollowsOrderB)) {
|
if (ImGui::Checkbox("Cursor follows current order when moving it",&cursorFollowsOrderB)) {
|
||||||
|
@ -2683,6 +2690,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.iCannotWait=e->getConfInt("iCannotWait",0);
|
settings.iCannotWait=e->getConfInt("iCannotWait",0);
|
||||||
settings.orderButtonPos=e->getConfInt("orderButtonPos",2);
|
settings.orderButtonPos=e->getConfInt("orderButtonPos",2);
|
||||||
settings.compress=e->getConfInt("compress",1);
|
settings.compress=e->getConfInt("compress",1);
|
||||||
|
settings.newPatternFormat=e->getConfInt("newPatternFormat",1);
|
||||||
|
|
||||||
clampSetting(settings.mainFontSize,2,96);
|
clampSetting(settings.mainFontSize,2,96);
|
||||||
clampSetting(settings.patFontSize,2,96);
|
clampSetting(settings.patFontSize,2,96);
|
||||||
|
@ -2804,6 +2812,7 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.iCannotWait,0,1);
|
clampSetting(settings.iCannotWait,0,1);
|
||||||
clampSetting(settings.orderButtonPos,0,2);
|
clampSetting(settings.orderButtonPos,0,2);
|
||||||
clampSetting(settings.compress,0,1);
|
clampSetting(settings.compress,0,1);
|
||||||
|
clampSetting(settings.newPatternFormat,0,1);
|
||||||
|
|
||||||
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
||||||
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
||||||
|
@ -3020,6 +3029,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("iCannotWait",settings.iCannotWait);
|
e->setConf("iCannotWait",settings.iCannotWait);
|
||||||
e->setConf("orderButtonPos",settings.orderButtonPos);
|
e->setConf("orderButtonPos",settings.orderButtonPos);
|
||||||
e->setConf("compress",settings.compress);
|
e->setConf("compress",settings.compress);
|
||||||
|
e->setConf("newPatternFormat",settings.newPatternFormat);
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
||||||
|
|
Loading…
Reference in a new issue