MOD import: more improvements

- prepare for old Soundtracker MOD import
- add "bypass limits" flag - dope.mod plays correctly now
- automatic channel names
This commit is contained in:
tildearrow 2022-03-15 18:32:15 -05:00
parent 10cea9956b
commit 0a307fc4a6
4 changed files with 47 additions and 17 deletions

View File

@ -1250,32 +1250,44 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
ds.tuning=436.0;
ds.version=DIV_VERSION_MOD;
int insCount=31;
bool bypassLimits=false;
// check mod magic bytes
if (!reader.seek(1080,SEEK_SET)) {
logD("couldn't seek to 1080\n");
throw EndOfFileException(&reader,reader.tell());
}
reader.read(magic,4);
if (memcmp(magic,"M.K.",4)==0 || memcmp(magic,"M!K!",4)==0) {
if (memcmp(magic,"M.K.",4)==0 || memcmp(magic,"M!K!",4)==0 || memcmp(magic,"M&K!",4)==0) {
logD("detected a ProTracker module\n");
chCount=4;
} else if(memcmp(magic+1,"CHN",3)==0 && magic[0]>='1' && magic[0]<='9') {
} else if (memcmp(magic,"CD81",4)==0 || memcmp(magic,"OKTA",4)==0 || memcmp(magic,"OCTA",4)==0) {
logD("detected an Oktalyzer/Octalyzer/OctaMED module\n");
chCount=8;
} else if (memcmp(magic+1,"CHN",3)==0 && magic[0]>='1' && magic[0]<='9') {
logD("detected a FastTracker module\n");
chCount=magic[0]-'0';
} else if((memcmp(magic+2,"CH",2)==0 || memcmp(magic+2,"CN",2)==0)
&&(magic[0]>='1' && magic[0]<='9' && magic[1]>='0' && magic[1]<='9')) {
logD("detected a FastTracker module\n");
} else if (memcmp(magic,"FLT",3)==0 && magic[3]>='1' && magic[3]<='9') {
logD("detected a Fairlight module\n");
chCount=magic[3]-'0';
} else if (memcmp(magic,"TDZ",3)==0 && magic[3]>='1' && magic[3]<='9') {
logD("detected a TakeTracker module\n");
chCount=magic[3]-'0';
} else if ((memcmp(magic+2,"CH",2)==0 || memcmp(magic+2,"CN",2)==0)
&& (magic[0]>='1' && magic[0]<='9' && magic[1]>='0' && magic[1]<='9')) {
logD("detected a Fast/TakeTracker module\n");
chCount=((magic[0]-'0')*10)+(magic[1]-'0');
} else {
// TODO: Soundtracker MOD?
insCount=15;
throw InvalidHeaderException();
}
// song name
reader.seek(0,SEEK_SET);
ds.name=reader.readString(20);
// samples
ds.sampleLen=31;
for (int i=0;i<31;i++) {
for (int i=0;i<insCount;i++) {
DivSample* sample=new DivSample;
sample->depth=8;
sample->name=reader.readString(22);
@ -1302,6 +1314,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
sample->init(slen);
ds.sample.push_back(sample);
}
ds.sampleLen=ds.sample.size();
// orders
ds.ordersLen=ordCount=reader.readC();
reader.readC(); // restart position, unused
@ -1343,6 +1356,9 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
short note=(short)round(log2(3424.0/period)*12);
dstrow[0]=((note-1)%12)+1;
dstrow[1]=(note-1)/12+1;
if (period<114) {
bypassLimits=true;
}
}
// effects are done later
short fxtyp=data[2]&0x0f;
@ -1521,24 +1537,26 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
ds.systemLen=(chCount+3)/4;
for(int i=0; i<ds.systemLen; i++) {
ds.system[i]=DIV_SYSTEM_AMIGA;
ds.systemFlags[i]=1|(80<<8); // PAL
ds.systemFlags[i]=1|(80<<8)|(bypassLimits?4:0); // PAL
}
for(int i=0; i<chCount; i++) {
ds.chanShow[i]=true;
ds.chanName[i]=fmt::sprintf("Channel %d",i+1);
ds.chanShortName[i]=fmt::sprintf("C%d",i+1);
}
for(int i=chCount; i<ds.systemLen*4; i++) {
ds.pat[i].effectRows=1;
ds.chanShow[i]=false;
}
// instrument creation
ds.insLen=31;
for(int i=0; i<31; i++) {
for(int i=0; i<insCount; i++) {
DivInstrument* ins=new DivInstrument;
ins->type=DIV_INS_AMIGA;
ins->amiga.initSample=i;
ins->name=ds.sample[i]->name;
ds.ins.push_back(ins);
}
ds.insLen=ds.ins.size();
if (active) quitDispatch();
isBusy.lock();

View File

@ -93,7 +93,11 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
chan[i].busClock=0;
}
}*/
chan[i].audSub+=MAX(114,chan[i].freq);
if (bypassLimits) {
chan[i].audSub+=MAX(AMIGA_DIVIDER,chan[i].freq);
} else {
chan[i].audSub+=MAX(114,chan[i].freq);
}
}
}
if (!isMuted[i]) {
@ -355,6 +359,8 @@ void DivPlatformAmiga::setFlags(unsigned int flags) {
rate=chipClock/AMIGA_DIVIDER;
sep1=((flags>>8)&127)+127;
sep2=127-((flags>>8)&127);
amigaModel=flags&2;
bypassLimits=flags&4;
}
int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {

View File

@ -66,6 +66,8 @@ class DivPlatformAmiga: public DivDispatch {
};
Channel chan[4];
bool isMuted[4];
bool bypassLimits;
bool amigaModel;
int sep1, sep2;

View File

@ -5853,19 +5853,23 @@ bool FurnaceGUI::loop() {
if (ImGui::SliderInt("##StereoSep",&stereoSep,0,127)) {
if (stereoSep<0) stereoSep=0;
if (stereoSep>127) stereoSep=127;
e->setSysFlags(i,(flags&1)|((stereoSep&127)<<8),restart);
e->setSysFlags(i,(flags&(~0x7f00))|((stereoSep&127)<<8),restart);
updateWindowTitle();
} rightClickable
/* TODO LATER: I want 0.5 out already
if (ImGui::RadioButton("Amiga 500 (OCS)",(flags&2)==0)) {
e->setSysFlags(i,flags&1);
e->setSysFlags(i,flags&(~2),restart);
}
if (ImGui::RadioButton("Amiga 1200 (AGA)",(flags&2)==2)) {
e->setSysFlags(i,(flags&1)|2);
}*/
e->setSysFlags(i,(flags&(~2))|2,restart);
}
sysPal=flags&1;
if (ImGui::Checkbox("PAL",&sysPal)) {
e->setSysFlags(i,(flags&2)|sysPal,restart);
e->setSysFlags(i,(flags&(~1))|sysPal,restart);
updateWindowTitle();
}
bool bypassLimits=flags&4;
if (ImGui::Checkbox("Bypass frequency limits",&bypassLimits)) {
e->setSysFlags(i,(flags&(~4))|(bypassLimits<<2),restart);
updateWindowTitle();
}
break;