NES: fix Furnace-style DPCM
This commit is contained in:
parent
ce40085d3b
commit
960048cf4b
|
|
@ -313,8 +313,6 @@ void DivPlatformNES::tick(bool sysTick) {
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
}
|
}
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
//rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63)));
|
|
||||||
//rWrite(16+i*5+2,((chan[i].vol<<4))|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3));
|
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff) {
|
if (chan[i].keyOff) {
|
||||||
//rWrite(16+i*5+2,8);
|
//rWrite(16+i*5+2,8);
|
||||||
|
|
@ -343,7 +341,7 @@ void DivPlatformNES::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PCM
|
// PCM
|
||||||
if (chan[4].freqChanged) {
|
if (chan[4].freqChanged || chan[4].keyOn) {
|
||||||
chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,false);
|
chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,false);
|
||||||
if (chan[4].furnaceDac) {
|
if (chan[4].furnaceDac) {
|
||||||
double off=1.0;
|
double off=1.0;
|
||||||
|
|
@ -352,11 +350,27 @@ void DivPlatformNES::tick(bool sysTick) {
|
||||||
off=(double)s->centerRate/8363.0;
|
off=(double)s->centerRate/8363.0;
|
||||||
}
|
}
|
||||||
dacRate=MIN(chan[4].freq*off,32000);
|
dacRate=MIN(chan[4].freq*off,32000);
|
||||||
if (dpcmMode && !skipRegisterWrites) {
|
if (chan[4].keyOn) {
|
||||||
|
if (dpcmMode && !skipRegisterWrites && dacSample>=0 && dacSample<parent->song.sampleLen) {
|
||||||
|
unsigned int dpcmAddr=parent->getSample(dacSample)->offDPCM;
|
||||||
|
unsigned int dpcmLen=(parent->getSample(dacSample)->lengthDPCM+15)>>4;
|
||||||
|
if (dpcmLen>255) dpcmLen=255;
|
||||||
|
// write DPCM
|
||||||
|
rWrite(0x4015,15);
|
||||||
|
rWrite(0x4010,calcDPCMRate(dacRate));
|
||||||
|
rWrite(0x4012,(dpcmAddr>>6)&0xff);
|
||||||
|
rWrite(0x4013,dpcmLen&0xff);
|
||||||
|
rWrite(0x4015,31);
|
||||||
|
dpcmBank=dpcmAddr>>14;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dpcmMode) {
|
||||||
rWrite(0x4010,calcDPCMRate(dacRate));
|
rWrite(0x4010,calcDPCMRate(dacRate));
|
||||||
}
|
}
|
||||||
if (dumpWrites) addWrite(0xffff0001,dacRate);
|
|
||||||
}
|
}
|
||||||
|
if (dumpWrites && !dpcmMode) addWrite(0xffff0001,dacRate);
|
||||||
|
}
|
||||||
|
if (chan[4].keyOn) chan[4].keyOn=false;
|
||||||
chan[4].freqChanged=false;
|
chan[4].freqChanged=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -378,25 +392,13 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
||||||
dacPos=0;
|
dacPos=0;
|
||||||
dacPeriod=0;
|
dacPeriod=0;
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=parent->song.tuning*pow(2.0f,((float)(c.value+3)/12.0f));
|
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
}
|
}
|
||||||
chan[c.chan].active=true;
|
chan[c.chan].active=true;
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
chan[c.chan].furnaceDac=true;
|
chan[c.chan].furnaceDac=true;
|
||||||
if (dpcmMode && !skipRegisterWrites) {
|
|
||||||
unsigned int dpcmAddr=parent->getSample(dacSample)->offDPCM;
|
|
||||||
unsigned int dpcmLen=(parent->getSample(dacSample)->lengthDPCM+15)>>4;
|
|
||||||
if (dpcmLen>255) dpcmLen=255;
|
|
||||||
// write DPCM
|
|
||||||
rWrite(0x4015,15);
|
|
||||||
rWrite(0x4010,calcDPCMRate(chan[c.chan].baseFreq));
|
|
||||||
rWrite(0x4012,(dpcmAddr>>6)&0xff);
|
|
||||||
rWrite(0x4013,dpcmLen&0xff);
|
|
||||||
rWrite(0x4015,31);
|
|
||||||
dpcmBank=dpcmAddr>>14;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
|
|
@ -492,7 +494,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_PORTA: {
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
int destFreq=NOTE_PERIODIC(c.value2);
|
int destFreq=(c.chan==4)?(parent->calcBaseFreq(1,1,c.value2,false)):(NOTE_PERIODIC(c.value2));
|
||||||
bool return2=false;
|
bool return2=false;
|
||||||
if (destFreq>chan[c.chan].baseFreq) {
|
if (destFreq>chan[c.chan].baseFreq) {
|
||||||
chan[c.chan].baseFreq+=c.value;
|
chan[c.chan].baseFreq+=c.value;
|
||||||
|
|
@ -554,7 +556,11 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
if (c.chan==3) break;
|
if (c.chan==3) break;
|
||||||
|
if (c.chan==4) {
|
||||||
|
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)),false);
|
||||||
|
} else {
|
||||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
}
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue