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

# Conflicts:
#	src/engine/engine.cpp
#	src/engine/playback.cpp
This commit is contained in:
cam900 2022-02-25 23:47:28 +09:00
commit cd4c876c5e
29 changed files with 2814 additions and 89 deletions

View file

@ -101,6 +101,13 @@ const char* DivPlatformYM2610B::getEffectName(unsigned char effect) {
return NULL;
}
double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
DivInstrument* ins=parent->getIns(chan[15].ins);
if (ins->type!=DIV_INS_AMIGA) return 0;
double off=(double)(parent->getSample(ins->amiga.initSample)->centerRate)/8363.0;
return off*parent->calcBaseFreq((double)chipClock/144,65535,note,false);
}
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
@ -357,6 +364,37 @@ void DivPlatformYM2610B::tick() {
chan[i].keyOff=false;
}
}
// ADPCM-B
if (chan[15].furnacePCM) {
chan[15].std.next();
if (chan[15].std.hadVol) {
chan[15].outVol=(chan[15].vol*MIN(64,chan[15].std.vol))/64;
immWrite(0x1b,chan[15].outVol);
}
if (chan[15].std.hadArp) {
if (!chan[15].inPorta) {
if (chan[15].std.arpMode) {
chan[15].baseFreq=NOTE_ADPCMB(chan[15].std.arp);
} else {
chan[15].baseFreq=NOTE_ADPCMB(chan[15].note+(signed char)chan[15].std.arp);
}
}
chan[15].freqChanged=true;
} else {
if (chan[15].std.arpMode && chan[15].std.finishedArp) {
chan[15].baseFreq=NOTE_ADPCMB(chan[15].note);
chan[15].freqChanged=true;
}
}
}
if (chan[15].freqChanged) {
chan[15].freq=parent->calcFreq(chan[15].baseFreq,chan[15].pitch,false,4);
immWrite(0x19,chan[15].freq&0xff);
immWrite(0x1a,(chan[15].freq>>8)&0xff);
chan[15].freqChanged=false;
}
for (int i=0; i<512; i++) {
if (pendingWrites[i]!=oldWrites[i]) {
@ -426,7 +464,60 @@ int DivPlatformYM2610B::toFreq(int freq) {
int DivPlatformYM2610B::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
if (c.chan>8) { // ADPCM
if (c.chan>14) { // ADPCM-B
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
if (ins->type==DIV_INS_AMIGA) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].std.init(ins);
if (!chan[c.chan].std.willVol) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol);
}
DivSample* s=parent->getSample(ins->amiga.initSample);
immWrite(0x12,(s->offB>>8)&0xff);
immWrite(0x13,s->offB>>16);
int end=s->offB+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,0x80); // start
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
chan[c.chan].std.init(NULL);
chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
immWrite(0x10,0x01); // reset
immWrite(0x12,0);
immWrite(0x13,0);
immWrite(0x14,0);
immWrite(0x15,0);
break;
}
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
immWrite(0x12,(s->offB>>8)&0xff);
immWrite(0x13,s->offB>>16);
int end=s->offB+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(0x10,0x80); // start
chan[c.chan].baseFreq=(((unsigned int)s->rate)<<16)/(chipClock/144);
chan[c.chan].freqChanged=true;
}
break;
}
if (c.chan>8) { // ADPCM-A
if (skipRegisterWrites) break;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
immWrite(0x100,0x80|(1<<(c.chan-9)));
@ -436,7 +527,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
immWrite(0x128+c.chan-9,0);
break;
}
DivSample* s=parent->song.sample[12*sampleBank+c.value%12];
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
immWrite(0x110+c.chan-9,(s->offA>>8)&0xff);
immWrite(0x118+c.chan-9,s->offA>>16);
int end=s->offA+s->lengthA-1;
@ -511,6 +602,10 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
break;
}
case DIV_CMD_NOTE_OFF:
if (c.chan>14) {
immWrite(0x10,0x01); // reset
break;
}
if (c.chan>8) {
immWrite(0x100,0x80|(1<<(c.chan-9)));
break;
@ -521,6 +616,10 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
chan[c.chan].std.init(NULL);
break;
case DIV_CMD_NOTE_OFF_ENV:
if (c.chan>14) {
immWrite(0x10,0x01); // reset
break;
}
if (c.chan>8) {
immWrite(0x100,0x80|(1<<(c.chan-9)));
break;
@ -542,7 +641,11 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
if (!chan[c.chan].std.hasVol) {
chan[c.chan].outVol=c.value;
}
if (c.chan>8) { // ADPCM
if (c.chan>14) { // ADPCM-B
immWrite(0x1b,chan[c.chan].outVol);
break;
}
if (c.chan>8) { // ADPCM-A
immWrite(0x108+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
break;
}
@ -587,6 +690,10 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
chan[c.chan].pan=3;
break;
}
if (c.chan>14) {
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
break;
}
if (c.chan>8) {
immWrite(0x108+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
break;
@ -797,7 +904,10 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
void DivPlatformYM2610B::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
if (ch>8) { // ADPCM
if (ch>14) { // ADPCM-B
immWrite(0x11,isMuted[ch]?0:(chan[ch].pan<<6));
}
if (ch>8) { // ADPCM-A
immWrite(0x108+(ch-9),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].vol));
return;
}
@ -916,7 +1026,8 @@ void DivPlatformYM2610B::reset() {
immWrite(0x22,0x08);
// PCM volume
immWrite(0x101,0x3f);
immWrite(0x101,0x3f); // A
immWrite(0x1b,0xff); // B
}
bool DivPlatformYM2610B::isStereo() {