Merge branch 'master' of https://github.com/tildearrow/furnace into k007232

This commit is contained in:
cam900 2022-12-10 13:03:37 +09:00
commit 3a4197c464
44 changed files with 488 additions and 181 deletions

36
src/engine/defines.h Normal file
View file

@ -0,0 +1,36 @@
/**
* 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
// global
#define DIV_MAX_CHIPS 32
#define DIV_MAX_CHANS 128
#define DIV_MAX_PATTERNS 256
// in-pattern
#define DIV_MAX_ROWS 256
#define DIV_MAX_COLS 32
#define DIV_MAX_EFFECTS 8
// sample related
#define DIV_MAX_SAMPLE_TYPE 4
#endif

View file

@ -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; i<song.systemLen; i++) {
sf[i]=NULL;
si[i].samplerate=got.rate;
@ -915,7 +915,7 @@ void DivEngine::runExportThread() {
float* outBuf[2];
outBuf[0]=new float[EXPORT_BUFSIZE];
outBuf[1]=new float[EXPORT_BUFSIZE];
short* sysBuf[32];
short* sysBuf[DIV_MAX_CHIPS];
for (int i=0; i<song.systemLen; i++) {
sysBuf[i]=new short[EXPORT_BUFSIZE*2];
}
@ -1399,7 +1399,7 @@ void DivEngine::initSongWithDesc(const char* description, bool inBase64) {
c.loadFromMemory(description);
}
int index=0;
for (; index<32; index++) {
for (; index<DIV_MAX_CHIPS; index++) {
song.system[index]=systemFromFileFur(c.getInt(fmt::sprintf("id%d",index),0));
if (song.system[index]==DIV_SYSTEM_NULL) {
break;
@ -1456,7 +1456,7 @@ void DivEngine::swapChannels(int src, int dest) {
return;
}
for (int i=0; i<256; i++) {
for (int i=0; i<DIV_MAX_PATTERNS; i++) {
curOrders->ord[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; i<DIV_MAX_PATTERNS; i++) {
curOrders->ord[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) {
@ -1786,7 +1786,7 @@ bool DivEngine::swapSystem(int src, int dest, bool preserveOrder) {
for (size_t i=0; i<song.subsong.size(); i++) {
DivOrders prevOrders=song.subsong[i]->orders;
DivPattern* prevPat[DIV_MAX_CHANS][256];
DivPattern* prevPat[DIV_MAX_CHANS][DIV_MAX_PATTERNS];
unsigned char prevEffectCols[DIV_MAX_CHANS];
String prevChanName[DIV_MAX_CHANS];
String prevChanShortName[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; j<tchans; j++) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
prevPat[j][k]=song.subsong[i]->pat[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; j<tchans; j++) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
song.subsong[i]->orders.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; i<chans; i++) {
for (size_t j=0; j<song.subsong.size(); j++) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
if (song.subsong[j]->pat[i].data[k]==NULL) continue;
for (int l=0; l<song.subsong[j]->patLen; 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; i<chans; i++) {
memset(used,0,sizeof(bool)*256);
memset(used,0,sizeof(bool)*DIV_MAX_PATTERNS);
for (int j=0; j<curSubSong->ordersLen; 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; j<DIV_MAX_PATTERNS; j++) {
if (!used[j]) {
order[i]=j;
break;
@ -3518,7 +3518,7 @@ void DivEngine::addOrder(bool duplicate, bool where) {
void DivEngine::deepCloneOrder(bool where) {
unsigned char order[DIV_MAX_CHANS];
if (curSubSong->ordersLen>=0xff) return;
if (curSubSong->ordersLen>=(DIV_MAX_PATTERNS-1)) return;
warnings="";
BUSY_BEGIN_SOFT;
for (int i=0; i<chans; i++) {
@ -3526,14 +3526,14 @@ void DivEngine::deepCloneOrder(bool where) {
logD("channel %d",i);
order[i]=curOrders->ord[i][curOrder];
// find free slot
for (int j=0; j<256; j++) {
for (int j=0; j<DIV_MAX_PATTERNS; j++) {
logD("finding free slot in %d...",j);
if (curPat[i].data[j]==NULL) {
int origOrd=order[i];
order[i]=j;
DivPattern* oldPat=curPat[i].getPattern(origOrd,false);
DivPattern* pat=curPat[i].getPattern(j,true);
memcpy(pat->data,oldPat->data,256*32*sizeof(short));
memcpy(pat->data,oldPat->data,DIV_MAX_ROWS*DIV_MAX_COLS*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; i<chans; i++) {
for (size_t j=0; j<song.subsong.size(); j++) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
if (song.subsong[j]->pat[i].data[k]==NULL) continue;
for (int l=0; l<song.subsong[j]->patLen; l++) {
if (song.subsong[j]->pat[i].data[k]->data[l][2]==one) {

View file

@ -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;

View file

@ -1584,7 +1584,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<int> patPtr;
int numberOfSubSongs=0;
char magic[5];
@ -1763,7 +1763,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;
@ -1775,7 +1775,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;
@ -1807,7 +1807,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
}
logD("systems:");
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
unsigned char sysID=reader.readC();
ds.system[i]=systemFromFileFur(sysID);
logD("- %d: %.2x (%s)",i,sysID,getSystemName(ds.system[i]));
@ -1829,7 +1829,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
}
// system volume
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
ds.systemVol[i]=reader.readC();
if (ds.version<59 && ds.system[i]==DIV_SYSTEM_NES) {
ds.systemVol[i]/=4;
@ -1837,15 +1837,15 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
}
// system panning
for (int i=0; i<32; i++) ds.systemPan[i]=reader.readC();
for (int i=0; i<DIV_MAX_CHIPS; i++) ds.systemPan[i]=reader.readC();
// system props
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
sysFlagsPtr[i]=reader.readI();
}
// handle compound systems
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
if (ds.system[i]==DIV_SYSTEM_GENESIS ||
ds.system[i]==DIV_SYSTEM_GENESIS_EXT ||
ds.system[i]==DIV_SYSTEM_ARCADE) {
@ -1854,7 +1854,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
ds.systemVol[j]=ds.systemVol[j-1];
ds.systemPan[j]=ds.systemPan[j-1];
}
if (++ds.systemLen>32) 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;
@ -2003,7 +2003,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
for (int i=0; i<tchans; i++) {
subSong->pat[i].effectCols=reader.readC();
if (subSong->pat[i].effectCols<1 || subSong->pat[i].effectCols>8) {
if (subSong->pat[i].effectCols<1 || subSong->pat[i].effectCols>DIV_MAX_EFFECTS) {
logE("channel %d has zero or too many effect columns! (%d)",i,subSong->pat[i].effectCols);
lastError=fmt::sprintf("channel %d has too many effect columns! (%d)",i,subSong->pat[i].effectCols);
delete[] file;
@ -2201,7 +2201,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; i<DIV_MAX_CHIPS; i++) {
if (sysFlagsPtr[i]==0) continue;
if (!reader.seek(sysFlagsPtr[i],SEEK_SET)) {
@ -2419,7 +2419,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
delete[] file;
return false;
}
if (index<0 || index>255) {
if (index<0 || index>(DIV_MAX_PATTERNS-1)) {
logE("pattern index out of range!",i);
lastError="pattern index out of range!";
ds.unload();
@ -4178,14 +4178,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("maximum song length is %d!",DIV_MAX_PATTERNS);
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("maximum pattern length is %d!",DIV_MAX_ROWS);
lastError=fmt::sprintf("maximum pattern length is %d",DIV_MAX_ROWS);
return NULL;
}
*/
@ -4239,18 +4239,18 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
for (int i=0; i<chans; i++) {
for (size_t j=0; j<song.subsong.size(); j++) {
DivSubSong* subs=song.subsong[j];
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
if (subs->pat[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; i<chans; i++) {
for (size_t j=0; j<song.subsong.size(); j++) {
DivSubSong* subs=song.subsong[j];
memset(alreadyAdded,0,256*sizeof(bool));
memset(alreadyAdded,0,DIV_MAX_PATTERNS*sizeof(bool));
for (int k=0; k<subs->ordersLen; k++) {
if (alreadyAdded[subs->orders.ord[i][k]]) continue;
patsToWrite.push_back(PatToWrite(j,i,subs->orders.ord[i][k]));
@ -4279,7 +4279,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<DIV_MAX_CHIPS; i++) {
if (i>=song.systemLen) {
w->writeC(0);
} else {
@ -4287,17 +4287,17 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
}
}
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
w->writeC(song.systemVol[i]);
}
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
w->writeC(song.systemPan[i]);
}
// chip flags (we'll seek here later)
sysFlagsPtrSeek=w->tell();
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
w->writeI(0);
}

View file

@ -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);
}
};

View file

@ -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<DIV_MAX_ROWS; i++) {
data[i][0]=0;
data[i][1]=0;
}
@ -43,13 +43,13 @@ DivPattern* DivChannelData::getPattern(int index, bool create) {
std::vector<std::pair<int,int>> DivChannelData::optimize() {
std::vector<std::pair<int,int>> ret;
for (int i=0; i<256; i++) {
for (int i=0; i<DIV_MAX_PATTERNS; i++) {
if (data[i]!=NULL) {
// compare
for (int j=0; j<256; j++) {
for (int j=0; j<DIV_MAX_PATTERNS; j++) {
if (j==i) continue;
if (data[j]==NULL) continue;
if (memcmp(data[i]->data,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<std::pair<int,int>> DivChannelData::optimize() {
std::vector<std::pair<int,int>> DivChannelData::rearrange() {
std::vector<std::pair<int,int>> ret;
for (int i=0; i<256; i++) {
for (int i=0; i<DIV_MAX_PATTERNS; i++) {
if (data[i]==NULL) {
for (int j=i; j<256; j++) {
for (int j=i; j<DIV_MAX_PATTERNS; j++) {
if (data[j]!=NULL) {
data[i]=data[j];
data[j]=NULL;
logV("%d -> %d",j,i);
ret.push_back(std::pair<int,int>(j,i));
if (++i>=256) break;
if (++i>=DIV_MAX_PATTERNS) break;
}
}
}
@ -80,7 +80,7 @@ std::vector<std::pair<int,int>> DivChannelData::rearrange() {
}
void DivChannelData::wipePatterns() {
for (int i=0; i<256; i++) {
for (int i=0; i<DIV_MAX_PATTERNS; i++) {
if (data[i]!=NULL) {
delete data[i];
data[i]=NULL;
@ -95,5 +95,5 @@ void DivPattern::copyOn(DivPattern* dest) {
DivChannelData::DivChannelData():
effectCols(1) {
memset(data,0,256*sizeof(void*));
memset(data,0,DIV_MAX_PATTERNS*sizeof(void*));
}

View file

@ -22,7 +22,7 @@
struct DivPattern {
String name;
short data[256][32];
short data[DIV_MAX_ROWS][DIV_MAX_COLS];
/**
* copy this pattern to another.
@ -42,7 +42,7 @@ struct DivChannelData {
// 3: volume
// 4-5+: effect/effect value
// do NOT access directly unless you know what you're doing!
DivPattern* data[256];
DivPattern* data[DIV_MAX_PATTERNS];
/**
* get a pattern from this channel, or the empty pattern if not initialized.

View file

@ -126,8 +126,7 @@ double DivPlatformSMS::NOTE_SN(int ch, int note) {
return NOTE_PERIODIC(note);
}
int easyStartingPeriod=16;
//int easyThreshold=round(CHIP_CLOCK/(parent->song.tuning*0.0625*pow(2.0,(float)(nbase+384)/(128.0*12.0)))/CHIP_DIVIDER);
int easyThreshold=round(log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0));
int easyThreshold=round(12.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/(0.0625*parent->song.tuning))/log(2.0))-3;
if (note>easyThreshold) {
return MAX(0,easyStartingPeriod-(note-easyThreshold));
}
@ -138,7 +137,7 @@ int DivPlatformSMS::snCalcFreq(int ch) {
double CHIP_DIVIDER=toneDivider;
if (ch==3) CHIP_DIVIDER=noiseDivider;
int easyStartingPeriod=16;
int easyThreshold=round(128.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0));
int easyThreshold=round(128.0*12.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/(0.0625*parent->song.tuning))/log(2.0))-384+64;
if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold)) {
int ret=(((easyStartingPeriod<<7))-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold)))>>7;
if (ret<0) ret=0;
@ -151,7 +150,7 @@ void DivPlatformSMS::tick(bool sysTick) {
for (int i=0; i<4; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=VOL_SCALE_LOG_BROKEN(chan[i].std.vol.val,chan[i].vol,15);
chan[i].outVol=VOL_SCALE_LOG(chan[i].std.vol.val,chan[i].vol,15);
if (chan[i].outVol<0) chan[i].outVol=0;
// old formula
// ((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4;
@ -159,7 +158,6 @@ void DivPlatformSMS::tick(bool sysTick) {
}
if (chan[i].std.arp.had) {
if (!chan[i].inPorta) {
// TODO: check whether this weird octave boundary thing applies to other systems as well
// TODO: add compatibility flag. this is horrible.
int areYouSerious=parent->calcArp(chan[i].note,chan[i].std.arp.val);
while (areYouSerious>0x60) areYouSerious-=12;
@ -429,7 +427,7 @@ void DivPlatformSMS::reset() {
YMPSG_Init(&sn_nuked,isRealSN,12,isRealSN?13:15,isRealSN?16383:32767);
snNoiseMode=3;
rWrite(0,0xe7);
updateSNMode=false;
updateSNMode=true;
oldValue=0xff;
lastPan=0xff;
if (stereo) {

View file

@ -1581,7 +1581,11 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
if (disCont[i].lastAvail>0) {
disCont[i].flush(disCont[i].lastAvail);
}
disCont[i].runtotal=blip_clocks_needed(disCont[i].bb[0],size-disCont[i].lastAvail);
if (size<disCont[i].lastAvail) {
disCont[i].runtotal=0;
} else {
disCont[i].runtotal=blip_clocks_needed(disCont[i].bb[0],size-disCont[i].lastAvail);
}
if (disCont[i].runtotal>disCont[i].bbInLen) {
logV("growing dispatch %d bbIn to %d",i,disCont[i].runtotal+256);
delete[] disCont[i].bbIn[0];

View file

@ -57,9 +57,9 @@ void DivSample::putSampleData(SafeWriter* w) {
w->writeI(loop?loopStart:-1);
w->writeI(loop?loopEnd:-1);
for (int i=0; i<4; i++) {
for (int i=0; i<DIV_MAX_SAMPLE_TYPE; i++) {
unsigned int out=0;
for (int j=0; j<32; j++) {
for (int j=0; j<DIV_MAX_CHIPS; j++) {
if (renderOn[i][j]) out|=1<<j;
}
w->writeI(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<DIV_MAX_SAMPLE_TYPE; i++) {
unsigned int outMask=(unsigned int)reader.readI();
for (int j=0; j<32; j++) {
for (int j=0; j<DIV_MAX_CHIPS; j++) {
renderOn[i][j]=outMask&(1<<j);
}
}

View file

@ -21,6 +21,7 @@
#define _SAMPLE_H
#include "../ta-utils.h"
#include "defines.h"
#include "safeWriter.h"
#include "dataErrors.h"
#include <deque>
@ -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<DIV_MAX_CHIPS; i++) {
for (int j=0; j<DIV_MAX_SAMPLE_TYPE; j++) {
renderOn[j][i]=true;
}
}
}
~DivSample();

View file

@ -25,7 +25,7 @@ void DivSubSong::clearData() {
pat[i].wipePatterns();
}
memset(orders.ord,0,DIV_MAX_CHANS*256);
memset(orders.ord,0,DIV_MAX_CHANS*DIV_MAX_PATTERNS);
ordersLen=1;
}
@ -34,7 +34,7 @@ void DivSubSong::optimizePatterns() {
logD("optimizing channel %d...",i);
std::vector<std::pair<int,int>> clearOuts=pat[i].optimize();
for (auto& j: clearOuts) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
if (orders.ord[i][k]==j.first) {
orders.ord[i][k]=j.second;
}
@ -48,7 +48,7 @@ void DivSubSong::rearrangePatterns() {
logD("re-arranging channel %d...",i);
std::vector<std::pair<int,int>> clearOuts=pat[i].rearrange();
for (auto& j: clearOuts) {
for (int k=0; k<256; k++) {
for (int k=0; k<DIV_MAX_PATTERNS; k++) {
if (orders.ord[i][k]==j.first) {
orders.ord[i][k]=j.second;
}

View file

@ -22,8 +22,7 @@
#include <stdio.h>
#include <vector>
#define DIV_MAX_CHANS 128
#include "defines.h"
#include "../ta-utils.h"
#include "config.h"
#include "orders.h"
@ -231,11 +230,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;
@ -429,7 +428,7 @@ struct DivSong {
snNoLowPeriods(false),
disableSampleMacro(false),
autoSystem(true) {
for (int i=0; i<32; i++) {
for (int i=0; i<DIV_MAX_CHIPS; i++) {
system[i]=DIV_SYSTEM_NULL;
systemVol[i]=64;
systemPan[i]=0;

View file

@ -945,15 +945,15 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
w->writeI(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<unsigned int> chipVol;
std::vector<DivDelayedWrite> delayedWrites[32];
std::vector<DivDelayedWrite> delayedWrites[DIV_MAX_CHIPS];
std::vector<std::pair<int,DivDelayedWrite>> sortedWrites;
for (int i=0; i<DIV_MAX_CHANS; i++) {

View file

@ -58,11 +58,21 @@ DivDataErrors DivWavetable::readWaveData(SafeReader& reader, short version) {
min=reader.readI();
max=reader.readI();
if (len>256 || min!=0 || max>255) {
logV("invalid len/min/max: %d %d %d",len,min,max);
if (len>256) {
logE("invalid len: %d",len);
return DIV_DATA_INVALID_DATA;
}
if (min!=0) {
logW("invalid min %d",min);
min=0;
}
if (max>255) {
logW("invalid max %d",max);
max=255;
}
for (int i=0; i<len; i++) {
data[i]=reader.readI();
}