diff --git a/src/engine/defines.h b/src/engine/defines.h new file mode 100644 index 000000000..172190c9e --- /dev/null +++ b/src/engine/defines.h @@ -0,0 +1,30 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _DEFINES_H +#define _DEFINES_H + +#define DIV_MAX_CHIPS 32 +#define DIV_MAX_CHANS 128 +#define DIV_MAX_PATTERNS 256 +#define DIV_MAX_ROWS 256 +#define DIV_MAX_COLS 32 +#define DIV_MAX_SAMPLE_TYPE 4 + +#endif diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 585f32646..e80f06ca2 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -884,10 +884,10 @@ void DivEngine::runExportThread() { break; } case DIV_EXPORT_MODE_MANY_SYS: { - SNDFILE* sf[32]; - SF_INFO si[32]; - String fname[32]; - SFWrapper sfWrap[32]; + SNDFILE* sf[DIV_MAX_CHIPS]; + SF_INFO si[DIV_MAX_CHIPS]; + String fname[DIV_MAX_CHIPS]; + SFWrapper sfWrap[DIV_MAX_CHIPS]; for (int i=0; iord[dest][i]^=curOrders->ord[src][i]; curOrders->ord[src][i]^=curOrders->ord[dest][i]; curOrders->ord[dest][i]^=curOrders->ord[src][i]; @@ -1487,7 +1487,7 @@ void DivEngine::swapChannels(int src, int dest) { void DivEngine::stompChannel(int ch) { logV("stomping channel %d",ch); - for (int i=0; i<256; i++) { + for (int i=0; iord[ch][i]=0; } curPat[ch].wipePatterns(); @@ -1649,8 +1649,8 @@ void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { } bool DivEngine::addSystem(DivSystem which) { - if (song.systemLen>32) { - lastError="max number of systems is 32"; + if (song.systemLen>DIV_MAX_CHIPS) { + lastError=fmt::sprintf("max number of systems is %d",DIV_MAX_CHIPS); return false; } if (chans+getChannelCount(which)>DIV_MAX_CHANS) { @@ -1794,7 +1794,7 @@ bool DivEngine::swapSystem(int src, int dest, bool preserveOrder) { unsigned char prevChanCollapse[DIV_MAX_CHANS]; for (int j=0; jpat[j].data[k]; } prevEffectCols[j]=song.subsong[i]->pat[j].effectCols; @@ -1806,7 +1806,7 @@ bool DivEngine::swapSystem(int src, int dest, bool preserveOrder) { } for (int j=0; jorders.ord[j][k]=prevOrders.ord[swappedChannels[j]][k]; song.subsong[i]->pat[j].data[k]=prevPat[swappedChannels[j]][k]; } @@ -2768,7 +2768,7 @@ void DivEngine::delInstrument(int index) { song.insLen=song.ins.size(); for (int i=0; ipat[i].data[k]==NULL) continue; for (int l=0; lpatLen; l++) { if (song.subsong[j]->pat[i].data[k]->data[l][2]>index) { @@ -3468,7 +3468,7 @@ void DivEngine::delSample(int index) { void DivEngine::addOrder(bool duplicate, bool where) { unsigned char order[DIV_MAX_CHANS]; - if (curSubSong->ordersLen>=0xff) return; + if (curSubSong->ordersLen>=(DIV_MAX_PATTERNS-1)) return; memset(order,0,DIV_MAX_CHANS); BUSY_BEGIN_SOFT; if (duplicate) { @@ -3476,14 +3476,14 @@ void DivEngine::addOrder(bool duplicate, bool where) { order[i]=curOrders->ord[i][curOrder]; } } else { - bool used[256]; + bool used[DIV_MAX_PATTERNS]; for (int i=0; iordersLen; j++) { used[curOrders->ord[i][j]]=true; } - order[i]=0xff; - for (int j=0; j<256; j++) { + order[i]=(DIV_MAX_PATTERNS-1); + for (int j=0; jordersLen>=0xff) return; + if (curSubSong->ordersLen>=(DIV_MAX_PATTERNS-1)) return; warnings=""; BUSY_BEGIN_SOFT; for (int i=0; iord[i][curOrder]; // find free slot - for (int j=0; j<256; j++) { + for (int j=0; jdata,oldPat->data,256*32*sizeof(short)); + memcpy(pat->data,oldPat->data,DIV_MAX_ROWS*32*sizeof(short)); logD("found at %d",j); didNotFind=false; break; @@ -3629,7 +3629,7 @@ void DivEngine::moveOrderDown() { void DivEngine::exchangeIns(int one, int two) { for (int i=0; ipat[i].data[k]==NULL) continue; for (int l=0; lpatLen; l++) { if (song.subsong[j]->pat[i].data[k]->data[l][2]==one) { diff --git a/src/engine/engine.h b/src/engine/engine.h index 3b8881213..12150fbb6 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -318,7 +318,7 @@ enum DivChanTypes { extern const char* cmdName[]; class DivEngine { - DivDispatchContainer disCont[32]; + DivDispatchContainer disCont[DIV_MAX_CHIPS]; TAAudio* output; TAAudioDesc want, got; String exportPath; diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index e01a57101..d27db9ea9 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1581,7 +1581,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { unsigned int wavePtr[256]; unsigned int samplePtr[256]; unsigned int subSongPtr[256]; - unsigned int sysFlagsPtr[32]; + unsigned int sysFlagsPtr[DIV_MAX_CHIPS]; std::vector patPtr; int numberOfSubSongs=0; char magic[5]; @@ -1760,7 +1760,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { delete[] file; return false; } - if (subSong->patLen>256) { + if (subSong->patLen>DIV_MAX_ROWS) { logE("pattern length is too large!"); lastError="pattern length is too large!"; delete[] file; @@ -1772,7 +1772,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { delete[] file; return false; } - if (subSong->ordersLen>256) { + if (subSong->ordersLen>DIV_MAX_PATTERNS) { logE("song is too long!"); lastError="song is too long!"; delete[] file; @@ -1804,7 +1804,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { } logD("systems:"); - for (int i=0; i<32; i++) { + for (int i=0; i32) ds.systemLen=32; + if (++ds.systemLen>DIV_MAX_CHIPS) ds.systemLen=DIV_MAX_CHIPS; if (ds.system[i]==DIV_SYSTEM_GENESIS) { ds.system[i]=DIV_SYSTEM_YM2612; @@ -2198,7 +2198,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { // read system flags if (ds.version>=119) { logD("reading chip flags..."); - for (int i=0; i<32; i++) { + for (int i=0; i255) { + if (index<0 || index>(DIV_MAX_PATTERNS-1)) { logE("pattern index out of range!",i); lastError="pattern index out of range!"; ds.unload(); @@ -4175,14 +4175,14 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { // fail if values are out of range /* - if (subSong->ordersLen>256) { - logE("maximum song length is 256!"); - lastError="maximum song length is 256"; + if (subSong->ordersLen>DIV_MAX_PATTERNS) { + logE(fmt::sprintf("maximum song length is %d!",DIV_MAX_PATTERNS).c_str()); + lastError=fmt::sprintf("maximum song length is %d",DIV_MAX_PATTERNS); return NULL; } - if (subSong->patLen>256) { - logE("maximum pattern length is 256!"); - lastError="maximum pattern length is 256"; + if (subSong->patLen>DIV_MAX_ROWS) { + logE(fmt::sprintf("maximum pattern length is %d!",DIV_MAX_ROWS).c_str()); + lastError=fmt::sprintf("maximum pattern length is %d",DIV_MAX_ROWS); return NULL; } */ @@ -4236,18 +4236,18 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { for (int i=0; ipat[i].data[k]==NULL) continue; patsToWrite.push_back(PatToWrite(j,i,k)); } } } } else { - bool alreadyAdded[256]; + bool alreadyAdded[DIV_MAX_PATTERNS]; for (int i=0; iordersLen; k++) { if (alreadyAdded[subs->orders.ord[i][k]]) continue; patsToWrite.push_back(PatToWrite(j,i,subs->orders.ord[i][k])); @@ -4276,7 +4276,7 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeS(song.sampleLen); w->writeI(patsToWrite.size()); - for (int i=0; i<32; i++) { + for (int i=0; i=song.systemLen) { w->writeC(0); } else { @@ -4284,17 +4284,17 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { } } - for (int i=0; i<32; i++) { + for (int i=0; iwriteC(song.systemVol[i]); } - for (int i=0; i<32; i++) { + for (int i=0; iwriteC(song.systemPan[i]); } // chip flags (we'll seek here later) sysFlagsPtrSeek=w->tell(); - for (int i=0; i<32; i++) { + for (int i=0; iwriteI(0); } diff --git a/src/engine/orders.h b/src/engine/orders.h index c57d1aab7..78a05f0c1 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][256]; + unsigned char ord[DIV_MAX_CHANS][DIV_MAX_PATTERNS]; DivOrders() { - memset(ord,0,DIV_MAX_CHANS*256); + memset(ord,0,DIV_MAX_CHANS*DIV_MAX_PATTERNS); } }; diff --git a/src/engine/pattern.cpp b/src/engine/pattern.cpp index 77255e084..6acdc2842 100644 --- a/src/engine/pattern.cpp +++ b/src/engine/pattern.cpp @@ -23,8 +23,8 @@ static DivPattern emptyPat; DivPattern::DivPattern() { - memset(data,-1,256*32*sizeof(short)); - for (int i=0; i<256; i++) { + memset(data,-1,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short)); + for (int i=0; i> DivChannelData::optimize() { std::vector> ret; - for (int i=0; i<256; i++) { + for (int i=0; idata,data[j]->data,256*32*sizeof(short))==0) { + if (memcmp(data[i]->data,data[j]->data,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short))==0) { delete data[j]; data[j]=NULL; logV("%d == %d",i,j); @@ -63,15 +63,15 @@ std::vector> DivChannelData::optimize() { std::vector> DivChannelData::rearrange() { std::vector> ret; - for (int i=0; i<256; i++) { + for (int i=0; i %d",j,i); ret.push_back(std::pair(j,i)); - if (++i>=256) break; + if (++i>=DIV_MAX_PATTERNS) break; } } } @@ -80,7 +80,7 @@ std::vector> DivChannelData::rearrange() { } void DivChannelData::wipePatterns() { - for (int i=0; i<256; i++) { + for (int i=0; iwriteI(loop?loopStart:-1); w->writeI(loop?loopEnd:-1); - for (int i=0; i<4; i++) { + for (int i=0; iwriteI(out); @@ -137,9 +137,9 @@ DivDataErrors DivSample::readSampleData(SafeReader& reader, short version) { loopEnd=reader.readI(); loop=(loopStart>=0)&&(loopEnd>=0); - for (int i=0; i<4; i++) { + for (int i=0; i @@ -115,7 +116,7 @@ struct DivSample { // - 2: Pingpong loop DivSampleLoopMode loopMode; - bool renderOn[4][32]; + bool renderOn[DIV_MAX_SAMPLE_TYPE][DIV_MAX_CHIPS]; // these are the new data structures. signed char* data8; // 8 @@ -331,11 +332,10 @@ struct DivSample { lengthBRR(0), lengthVOX(0), samples(0) { - for (int i=0; i<32; i++) { - renderOn[0][i]=true; - renderOn[1][i]=true; - renderOn[2][i]=true; - renderOn[3][i]=true; + for (int i=0; i> clearOuts=pat[i].optimize(); for (auto& j: clearOuts) { - for (int k=0; k<256; k++) { + for (int k=0; k> clearOuts=pat[i].rearrange(); for (auto& j: clearOuts) { - for (int k=0; k<256; k++) { + for (int k=0; k #include -#define DIV_MAX_CHANS 128 - +#include "defines.h" #include "../ta-utils.h" #include "config.h" #include "orders.h" @@ -230,11 +229,11 @@ struct DivSong { bool isDMF; // system - DivSystem system[32]; + DivSystem system[DIV_MAX_CHIPS]; unsigned char systemLen; - signed char systemVol[32]; - signed char systemPan[32]; - DivConfig systemFlags[32]; + signed char systemVol[DIV_MAX_CHIPS]; + signed char systemPan[DIV_MAX_CHIPS]; + DivConfig systemFlags[DIV_MAX_CHIPS]; // song information String name, author, systemName; @@ -428,7 +427,7 @@ struct DivSong { snNoLowPeriods(false), disableSampleMacro(false), autoSystem(true) { - for (int i=0; i<32; i++) { + for (int i=0; iwriteI(0); // will be written later w->writeI(version); - bool willExport[32]; - bool isSecond[32]; - int streamIDs[32]; + bool willExport[DIV_MAX_CHIPS]; + bool isSecond[DIV_MAX_CHIPS]; + int streamIDs[DIV_MAX_CHIPS]; double loopTimer[DIV_MAX_CHANS]; double loopFreq[DIV_MAX_CHANS]; int loopSample[DIV_MAX_CHANS]; bool sampleDir[DIV_MAX_CHANS]; std::vector chipVol; - std::vector delayedWrites[32]; + std::vector delayedWrites[DIV_MAX_CHIPS]; std::vector> sortedWrites; for (int i=0; igetDispatch(j); if (dispatch==NULL) continue; - for (int k=0; k<4; k++) { + for (int k=0; kgetSampleMemCapacity(k)==0) continue; if (!dispatch->isSampleLoaded(k,i) && sample->renderOn[k][j]) { memWarning=true; diff --git a/src/gui/editing.cpp b/src/gui/editing.cpp index 17d2886a4..f18efece3 100644 --- a/src/gui/editing.cpp +++ b/src/gui/editing.cpp @@ -119,7 +119,7 @@ void FurnaceGUI::makeUndo(ActionType action) { for (int i=0; igetTotalChannelCount(); i++) { DivPattern* p=e->curPat[i].getPattern(e->curOrders->ord[i][curOrder],false); for (int j=0; jcurSubSong->patLen; j++) { - for (int k=0; k<32; k++) { + for (int k=0; kdata[j][k]!=oldPat[i]->data[j][k]) { s.pat.push_back(UndoPatternData(subSong,i,e->curOrders->ord[i][curOrder],j,k,oldPat[i]->data[j][k],p->data[j][k])); } diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 91b494210..e66108cfc 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -220,20 +220,20 @@ void FurnaceGUI::doReplace() { UndoStep us; us.type=GUI_UNDO_REPLACE; - short prevVal[32]; - memset(prevVal,0,32*sizeof(short)); + short prevVal[DIV_MAX_COLS]; + memset(prevVal,0,DIV_MAX_COLS*sizeof(short)); for (FurnaceGUIQueryResult& i: curQueryResults) { int patIndex=e->song.subsong[i.subsong]->orders.ord[i.x][i.order]; DivPattern* p=e->song.subsong[i.subsong]->pat[i.x].getPattern(patIndex,true); if (touched[i.x]==NULL) { - touched[i.x]=new bool[256*256]; - memset(touched[i.x],0,256*256*sizeof(bool)); + touched[i.x]=new bool[DIV_MAX_PATTERNS*DIV_MAX_ROWS]; + memset(touched[i.x],0,DIV_MAX_PATTERNS*DIV_MAX_ROWS*sizeof(bool)); } if (touched[i.x][(patIndex<<8)|i.y]) continue; touched[i.x][(patIndex<<8)|i.y]=true; - memcpy(prevVal,p->data[i.y],32*sizeof(short)); + memcpy(prevVal,p->data[i.y],DIV_MAX_COLS*sizeof(short)); if (queryReplaceNoteDo) { switch (queryReplaceNoteMode) { @@ -462,7 +462,7 @@ void FurnaceGUI::doReplace() { } // issue undo step - for (int j=0; j<32; j++) { + for (int j=0; jdata[i.y][j]!=prevVal[j]) { us.pat.push_back(UndoPatternData(i.subsong,i.x,patIndex,i.y,j,prevVal[j],p->data[i.y][j])); } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 2825f3b39..1487b50f5 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4766,7 +4766,7 @@ bool FurnaceGUI::loop() { if (ImGui::Button("Orders")) { stop(); e->lockEngine([this]() { - memset(e->curOrders->ord,0,DIV_MAX_CHANS*256); + memset(e->curOrders->ord,0,DIV_MAX_CHANS*DIV_MAX_PATTERNS); e->curSubSong->ordersLen=1; }); e->setOrder(0); @@ -4782,8 +4782,8 @@ bool FurnaceGUI::loop() { e->lockEngine([this]() { for (int i=0; igetTotalChannelCount(); i++) { DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][curOrder],true); - memset(pat->data,-1,256*32*sizeof(short)); - for (int j=0; j<256; j++) { + memset(pat->data,-1,DIV_MAX_ROWS*DIV_MAX_COLS*sizeof(short)); + for (int j=0; jdata[j][0]=0; pat->data[j][1]=0; } @@ -6032,7 +6032,7 @@ FurnaceGUI::FurnaceGUI(): valueKeys[SDLK_KP_8]=8; valueKeys[SDLK_KP_9]=9; - memset(willExport,1,32*sizeof(bool)); + memset(willExport,1,DIV_MAX_CHIPS*sizeof(bool)); peak[0]=0; peak[1]=0; diff --git a/src/gui/gui.h b/src/gui/gui.h index 2ad196287..e5e589852 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1089,7 +1089,7 @@ class FurnaceGUI { bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex; bool mobileEdit; - bool willExport[32]; + bool willExport[DIV_MAX_CHIPS]; int vgmExportVersion; int drawHalt; int zsmExportTickRate; diff --git a/src/gui/patManager.cpp b/src/gui/patManager.cpp index 22d5b645e..161a42cb2 100644 --- a/src/gui/patManager.cpp +++ b/src/gui/patManager.cpp @@ -30,8 +30,8 @@ void FurnaceGUI::drawPatManager() { } if (!patManagerOpen) return; char id[1024]; - unsigned char isUsed[256]; - bool isNull[256]; + unsigned char isUsed[DIV_MAX_PATTERNS]; + bool isNull[DIV_MAX_PATTERNS]; if (ImGui::Begin("Pattern Manager",&patManagerOpen,globalWinFlags)) { ImGui::Text("Global Tasks"); @@ -52,19 +52,19 @@ void FurnaceGUI::drawPatManager() { for (int i=0; igetTotalChannelCount(); i++) { ImGui::TableNextRow(); - memset(isUsed,0,256); - memset(isNull,0,256*sizeof(bool)); + memset(isUsed,0,DIV_MAX_PATTERNS); + memset(isNull,0,DIV_MAX_PATTERNS*sizeof(bool)); for (int j=0; jcurSubSong->ordersLen; j++) { isUsed[e->curSubSong->orders.ord[i][j]]++; } - for (int j=0; j<256; j++) { + for (int j=0; jcurSubSong->pat[i].data[j]==NULL); } ImGui::TableNextColumn(); ImGui::Text("%s",e->getChannelShortName(i)); ImGui::PushID(1000+i); - for (int k=0; k<256; k++) { + for (int k=0; ksong.systemLen; i++) { DivDispatch* dispatch=e->getDispatch(i); if (dispatch==NULL) continue; - for (int j=0; j<4; j++) { + for (int j=0; jgetSampleMemCapacity(j)==0) continue; isChipVisible[i]=true; isTypeVisible[j]=true; @@ -155,7 +155,7 @@ void FurnaceGUI::drawSampleEdit() { } } int selColumns=1; - for (int i=0; i<32; i++) { + for (int i=0; icurSubSong->patLen; if (ImGui::InputInt("##PatLength",&patLen,1,3)) { MARK_MODIFIED if (patLen<1) patLen=1; - if (patLen>256) patLen=256; + if (patLen>DIV_MAX_PATTERNS) patLen=DIV_MAX_PATTERNS; e->curSubSong->patLen=patLen; } @@ -192,7 +192,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) { int ordLen=e->curSubSong->ordersLen; if (ImGui::InputInt("##OrdLength",&ordLen,1,3)) { MARK_MODIFIED if (ordLen<1) ordLen=1; - if (ordLen>256) ordLen=256; + if (ordLen>DIV_MAX_PATTERNS) ordLen=DIV_MAX_PATTERNS; e->curSubSong->ordersLen=ordLen; if (curOrder>=ordLen) { setOrder(ordLen-1); diff --git a/src/gui/sysManager.cpp b/src/gui/sysManager.cpp index 1de5ac1f8..dda5ed963 100644 --- a/src/gui/sysManager.cpp +++ b/src/gui/sysManager.cpp @@ -112,7 +112,7 @@ void FurnaceGUI::drawSysManager() { ImGui::EndDisabled(); ImGui::PopID(); } - if (e->song.systemLen<32) { + if (e->song.systemLen