diff --git a/papers/format.md b/papers/format.md index 9ce20d2d..ce1685c6 100644 --- a/papers/format.md +++ b/papers/format.md @@ -29,6 +29,7 @@ furthermore, an `or reserved` indicates this field is always present, but is res the format versions are: +- 80: Furnace dev80 - 79: Furnace dev79 - 78: Furnace dev78 - 77: Furnace dev77 @@ -119,12 +120,17 @@ size | description | - 60 is NTSC | - 50 is PAL 2 | pattern length + | - the limit is 256. 2 | orders length + | - the limit is 256 (>=80) or 127 (<80). 1 | highlight A 1 | highlight B 2 | instrument count + | - the limit is 256. 2 | wavetable count + | - the limit is 256. 2 | sample count + | - the limit is 256. 4 | pattern count 32 | list of sound chips | - possible soundchips: @@ -230,6 +236,7 @@ size | description | - a table of bytes | - size=channels*ordLen | - read orders then channels + | - the maximum value of a cell is FF (>=80) or 7F (<80). ??? | effect columns | - size=channels 1?? | channel hide status diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index c26058e6..78ae1ce4 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1281,7 +1281,7 @@ void DivEngine::delInstrument(int index) { song.ins.erase(song.ins.begin()+index); song.insLen=song.ins.size(); for (int i=0; idata[k][2]>index) { @@ -1556,7 +1556,7 @@ void DivEngine::delSample(int index) { void DivEngine::addOrder(bool duplicate, bool where) { unsigned char order[DIV_MAX_CHANS]; - if (song.ordersLen>=0x7e) return; + if (song.ordersLen>=0xff) return; BUSY_BEGIN_SOFT; if (duplicate) { for (int i=0; i=0x7e) return; + if (song.ordersLen>=0xff) return; warnings=""; BUSY_BEGIN_SOFT; for (int i=0; idata[k][2]==one) { diff --git a/src/engine/engine.h b/src/engine/engine.h index 677cdeaa..89005675 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -42,8 +42,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev79" -#define DIV_ENGINE_VERSION 79 +#define DIV_VERSION "dev80" +#define DIV_ENGINE_VERSION 80 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 7988992b..37964c68 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -959,7 +959,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { delete[] file; return false; } - if (ds.ordersLen>127) { + if (ds.ordersLen>256) { logE("song is too long!\n"); lastError="song is too long!"; delete[] file; @@ -1407,6 +1407,8 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { int index=reader.readS(); reader.readI(); + logD("- %d, %d\n",chan,index); + if (chan<0 || chan>=tchans) { logE("pattern channel out of range!\n",i); lastError="pattern channel out of range!"; @@ -1414,7 +1416,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { delete[] file; return false; } - if (index<0 || index>127) { + if (index<0 || index>255) { logE("pattern index out of range!\n",i); lastError="pattern index out of range!"; ds.unload(); @@ -1422,8 +1424,6 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { return false; } - logD("- %d, %d\n",chan,index); - DivPattern* pat=ds.pat[chan].getPattern(index,true); for (int j=0; jdata[j][0]=reader.readS(); @@ -2292,6 +2292,31 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) { lastError="this system is not possible on .dmf"; return NULL; } + // fail if values are out of range + if (song.ordersLen>127) { + logE("maximum .dmf song length is 127!\n"); + lastError="maximum .dmf song length is 127"; + return NULL; + } + if (song.ins.size()>128) { + logE("maximum number of instruments in .dmf is 128!\n"); + lastError="maximum number of instruments in .dmf is 128"; + return NULL; + } + if (song.wave.size()>64) { + logE("maximum number of wavetables in .dmf is 64!\n"); + lastError="maximum number of wavetables in .dmf is 64"; + return NULL; + } + for (int i=0; i0x7f) { + logE("order %d, %d is out of range (0-127)!\n",song.orders.ord[i][j]); + lastError=fmt::sprintf("order %d, %d is out of range (0-127)",song.orders.ord[i][j]); + return NULL; + } + } + } saveLock.lock(); warnings=""; song.version=version; diff --git a/src/engine/orders.h b/src/engine/orders.h index d10dbe4c..c57d1aab 100644 --- a/src/engine/orders.h +++ b/src/engine/orders.h @@ -21,10 +21,10 @@ #define _ORDERS_H struct DivOrders { - unsigned char ord[DIV_MAX_CHANS][128]; + unsigned char ord[DIV_MAX_CHANS][256]; DivOrders() { - memset(ord,0,DIV_MAX_CHANS*128); + memset(ord,0,DIV_MAX_CHANS*256); } }; diff --git a/src/engine/pattern.cpp b/src/engine/pattern.cpp index 91a4ecd4..8241255b 100644 --- a/src/engine/pattern.cpp +++ b/src/engine/pattern.cpp @@ -41,7 +41,7 @@ DivPattern* DivChannelData::getPattern(int index, bool create) { } void DivChannelData::wipePatterns() { - for (int i=0; i<128; i++) { + for (int i=0; i<256; i++) { if (data[i]!=NULL) { delete data[i]; data[i]=NULL; @@ -131,5 +131,5 @@ SafeReader* DivPattern::compile(int len, int fxRows) { DivChannelData::DivChannelData(): effectRows(1) { - memset(data,0,128*sizeof(void*)); + memset(data,0,256*sizeof(void*)); } diff --git a/src/engine/pattern.h b/src/engine/pattern.h index 1af744b6..fd0b0d07 100644 --- a/src/engine/pattern.h +++ b/src/engine/pattern.h @@ -49,7 +49,7 @@ struct DivChannelData { // 3: volume // 4-5+: effect/effect value // do NOT access directly unless you know what you're doing! - DivPattern* data[128]; + DivPattern* data[256]; /** * get a pattern from this channel, or the empty pattern if not initialized. diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index bae782ff..755b825a 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1131,7 +1131,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) { if (orderCursor>=0 && orderCursorgetTotalChannelCount()) { int curOrder=e->getOrder(); e->lockSave([this,curOrder,num]() { - e->song.orders.ord[orderCursor][curOrder]=((e->song.orders.ord[orderCursor][curOrder]<<4)|num)&0x7f; + e->song.orders.ord[orderCursor][curOrder]=((e->song.orders.ord[orderCursor][curOrder]<<4)|num); }); if (orderEditMode==2 || orderEditMode==3) { curNibble=!curNibble; diff --git a/src/gui/gui.h b/src/gui/gui.h index 445369f0..a797700f 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -952,7 +952,7 @@ class FurnaceGUI { int oldOrdersLen; DivOrders oldOrders; - DivPattern* oldPat[128]; + DivPattern* oldPat[DIV_MAX_CHANS]; std::deque undoHist; std::deque redoHist; diff --git a/src/gui/orders.cpp b/src/gui/orders.cpp index b233c48b..945f551d 100644 --- a/src/gui/orders.cpp +++ b/src/gui/orders.cpp @@ -102,10 +102,10 @@ void FurnaceGUI::drawOrders() { e->lockSave([this,i,j]() { if (changeAllOrders) { for (int k=0; kgetTotalChannelCount(); k++) { - if (e->song.orders.ord[k][i]<0x7f) e->song.orders.ord[k][i]++; + if (e->song.orders.ord[k][i]<0xff) e->song.orders.ord[k][i]++; } } else { - if (e->song.orders.ord[j][i]<0x7f) e->song.orders.ord[j][i]++; + if (e->song.orders.ord[j][i]<0xff) e->song.orders.ord[j][i]++; } }); e->walkSong(loopOrder,loopRow,loopEnd); diff --git a/src/gui/songInfo.cpp b/src/gui/songInfo.cpp index b5923801..a2f788c3 100644 --- a/src/gui/songInfo.cpp +++ b/src/gui/songInfo.cpp @@ -122,7 +122,7 @@ void FurnaceGUI::drawSongInfo() { int ordLen=e->song.ordersLen; if (ImGui::InputInt("##OrdLength",&ordLen,1,3)) { MARK_MODIFIED if (ordLen<1) ordLen=1; - if (ordLen>127) ordLen=127; + if (ordLen>256) ordLen=256; e->song.ordersLen=ordLen; if (e->getOrder()>=ordLen) { e->setOrder(ordLen-1);