NES: envelope and length counter effects

This commit is contained in:
tildearrow 2022-10-25 00:43:03 -05:00
parent 07f247af12
commit 9a1447e392
6 changed files with 100 additions and 8 deletions

View file

@ -214,7 +214,7 @@ void DivPlatformNES::tick(bool sysTick) {
rWrite(0x4000+i*4,(chan[i].outVol==0)?0:255);
chan[i].freqChanged=true;
} else {
rWrite(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
rWrite(0x4000+i*4,(chan[i].envMode<<4)|chan[i].outVol|((chan[i].duty&3)<<6));
}
}
if (chan[i].std.arp.had) {
@ -239,7 +239,7 @@ void DivPlatformNES::tick(bool sysTick) {
}
}
if (i!=2) {
rWrite(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
rWrite(0x4000+i*4,(chan[i].envMode<<4)|chan[i].outVol|((chan[i].duty&3)<<6));
}
if (i==3) { // noise
chan[i].freqChanged=true;
@ -289,11 +289,11 @@ void DivPlatformNES::tick(bool sysTick) {
}
if (i==3) { // noise
rWrite(0x4002+i*4,(chan[i].duty<<7)|chan[i].freq);
rWrite(0x4003+i*4,0xf0);
rWrite(0x4003+i*4,(chan[i].len<<3));
} else {
rWrite(0x4002+i*4,chan[i].freq&0xff);
if ((chan[i].prevFreq>>8)!=(chan[i].freq>>8) || i==2) {
rWrite(0x4003+i*4,0xf8|(chan[i].freq>>8));
rWrite(0x4003+i*4,(chan[i].len<<3)|(chan[i].freq>>8));
}
if (chan[i].freq!=65535 && chan[i].freq!=0) {
chan[i].prevFreq=chan[i].freq;
@ -419,7 +419,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
if (c.chan==2) {
rWrite(0x4000+c.chan*4,0xff);
} else if (!parent->song.brokenOutVol2) {
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
rWrite(0x4000+c.chan*4,(chan[c.chan].envMode<<4)|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
}
break;
case DIV_CMD_NOTE_OFF:
@ -451,7 +451,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
if (c.chan==2) {
rWrite(0x4000+c.chan*4,0xff);
} else {
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
rWrite(0x4000+c.chan*4,(chan[c.chan].envMode<<4)|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
}
}
}
@ -491,7 +491,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
if (c.chan==3) { // noise
chan[c.chan].freqChanged=true;
} else if (c.chan<2) {
rWrite(0x4000+c.chan*4,0x30|(chan[c.chan].active?chan[c.chan].outVol:0)|((chan[c.chan].duty&3)<<6));
rWrite(0x4000+c.chan*4,(chan[c.chan].active?((chan[c.chan].envMode<<4)|chan[c.chan].outVol):0x30)|((chan[c.chan].duty&3)<<6));
}
break;
case DIV_CMD_NES_SWEEP:
@ -507,6 +507,24 @@ int DivPlatformNES::dispatch(DivCommand c) {
}
rWrite(0x4001+(c.chan*4),chan[c.chan].sweep);
break;
case DIV_CMD_NES_ENV_MODE:
chan[c.chan].envMode=c.value&3;
if (c.chan==3) { // noise
chan[c.chan].freqChanged=true;
} else if (c.chan<2) {
rWrite(0x4000+c.chan*4,(chan[c.chan].active?((chan[c.chan].envMode<<4)|chan[c.chan].outVol):0x30)|((chan[c.chan].duty&3)<<6));
}
break;
case DIV_CMD_NES_LENGTH:
if (c.chan>=4) break;
chan[c.chan].len=c.value&0x1f;
chan[c.chan].freqChanged=true;
chan[c.chan].prevFreq=-1;
break;
case DIV_CMD_NES_COUNT_MODE:
countMode=c.value;
rWrite(0x4017,countMode?0x80:0);
break;
case DIV_CMD_NES_DMC:
rWrite(0x4011,c.value&0x7f);
break;
@ -572,6 +590,7 @@ void DivPlatformNES::forceIns() {
}
rWrite(0x4001,chan[0].sweep);
rWrite(0x4005,chan[1].sweep);
rWrite(0x4017,countMode?0x80:0);
}
void* DivPlatformNES::getChanState(int ch) {
@ -615,6 +634,7 @@ void DivPlatformNES::reset() {
dpcmBank=0;
dpcmMode=false;
goingToLoop=false;
countMode=false;
if (useNP) {
nes1_NP->Reset();

View file

@ -28,7 +28,7 @@
class DivPlatformNES: public DivDispatch {
struct Channel {
int freq, baseFreq, pitch, pitch2, prevFreq, note, ins;
unsigned char duty, sweep;
unsigned char duty, sweep, envMode, len;
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, furnaceDac;
signed char vol, outVol, wave;
DivMacroInt std;
@ -46,6 +46,8 @@ class DivPlatformNES: public DivDispatch {
ins(-1),
duty(0),
sweep(8),
envMode(3),
len(0x1f),
active(false),
insChanged(true),
freqChanged(false),
@ -74,6 +76,7 @@ class DivPlatformNES: public DivDispatch {
bool dacAntiClickOn;
bool useNP;
bool goingToLoop;
bool countMode;
struct NESAPU* nes;
xgm::NES_APU* nes1_NP;
xgm::NES_DMC* nes2_NP;