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.tuning=436.0;
ds.version=DIV_VERSION_MOD; ds.version=DIV_VERSION_MOD;
int insCount=31;
bool bypassLimits=false;
// check mod magic bytes // check mod magic bytes
if (!reader.seek(1080,SEEK_SET)) { if (!reader.seek(1080,SEEK_SET)) {
logD("couldn't seek to 1080\n"); logD("couldn't seek to 1080\n");
throw EndOfFileException(&reader,reader.tell()); throw EndOfFileException(&reader,reader.tell());
} }
reader.read(magic,4); 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"); logD("detected a ProTracker module\n");
chCount=4; 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"); logD("detected a FastTracker module\n");
chCount=magic[0]-'0'; chCount=magic[0]-'0';
} else if((memcmp(magic+2,"CH",2)==0 || memcmp(magic+2,"CN",2)==0) } else if (memcmp(magic,"FLT",3)==0 && magic[3]>='1' && magic[3]<='9') {
&&(magic[0]>='1' && magic[0]<='9' && magic[1]>='0' && magic[1]<='9')) { logD("detected a Fairlight module\n");
logD("detected a FastTracker 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'); chCount=((magic[0]-'0')*10)+(magic[1]-'0');
} else { } else {
// TODO: Soundtracker MOD? // TODO: Soundtracker MOD?
insCount=15;
throw InvalidHeaderException(); throw InvalidHeaderException();
} }
// song name // song name
reader.seek(0,SEEK_SET); reader.seek(0,SEEK_SET);
ds.name=reader.readString(20); ds.name=reader.readString(20);
// samples // samples
ds.sampleLen=31; for (int i=0;i<insCount;i++) {
for (int i=0;i<31;i++) {
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
sample->depth=8; sample->depth=8;
sample->name=reader.readString(22); sample->name=reader.readString(22);
@ -1302,6 +1314,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
sample->init(slen); sample->init(slen);
ds.sample.push_back(sample); ds.sample.push_back(sample);
} }
ds.sampleLen=ds.sample.size();
// orders // orders
ds.ordersLen=ordCount=reader.readC(); ds.ordersLen=ordCount=reader.readC();
reader.readC(); // restart position, unused 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); short note=(short)round(log2(3424.0/period)*12);
dstrow[0]=((note-1)%12)+1; dstrow[0]=((note-1)%12)+1;
dstrow[1]=(note-1)/12+1; dstrow[1]=(note-1)/12+1;
if (period<114) {
bypassLimits=true;
}
} }
// effects are done later // effects are done later
short fxtyp=data[2]&0x0f; short fxtyp=data[2]&0x0f;
@ -1521,24 +1537,26 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
ds.systemLen=(chCount+3)/4; ds.systemLen=(chCount+3)/4;
for(int i=0; i<ds.systemLen; i++) { for(int i=0; i<ds.systemLen; i++) {
ds.system[i]=DIV_SYSTEM_AMIGA; 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++) { for(int i=0; i<chCount; i++) {
ds.chanShow[i]=true; 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++) { for(int i=chCount; i<ds.systemLen*4; i++) {
ds.pat[i].effectRows=1; ds.pat[i].effectRows=1;
ds.chanShow[i]=false; ds.chanShow[i]=false;
} }
// instrument creation // instrument creation
ds.insLen=31; for(int i=0; i<insCount; i++) {
for(int i=0; i<31; i++) {
DivInstrument* ins=new DivInstrument; DivInstrument* ins=new DivInstrument;
ins->type=DIV_INS_AMIGA; ins->type=DIV_INS_AMIGA;
ins->amiga.initSample=i; ins->amiga.initSample=i;
ins->name=ds.sample[i]->name; ins->name=ds.sample[i]->name;
ds.ins.push_back(ins); ds.ins.push_back(ins);
} }
ds.insLen=ds.ins.size();
if (active) quitDispatch(); if (active) quitDispatch();
isBusy.lock(); 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].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]) { if (!isMuted[i]) {
@ -355,6 +359,8 @@ void DivPlatformAmiga::setFlags(unsigned int flags) {
rate=chipClock/AMIGA_DIVIDER; rate=chipClock/AMIGA_DIVIDER;
sep1=((flags>>8)&127)+127; sep1=((flags>>8)&127)+127;
sep2=127-((flags>>8)&127); sep2=127-((flags>>8)&127);
amigaModel=flags&2;
bypassLimits=flags&4;
} }
int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { 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]; Channel chan[4];
bool isMuted[4]; bool isMuted[4];
bool bypassLimits;
bool amigaModel;
int sep1, sep2; int sep1, sep2;

View file

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