diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0f075e56..7469f903 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -234,6 +234,8 @@ enum DivDispatchCmds { DIV_CMD_SNES_GLOBAL_VOL_LEFT, DIV_CMD_SNES_GLOBAL_VOL_RIGHT, + DIV_CMD_NES_LINEAR_LENGTH, + DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol DIV_CMD_MAX diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 974e71d5..a25568d0 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -211,7 +211,7 @@ void DivPlatformNES::tick(bool sysTick) { chan[i].outVol=VOL_SCALE_LINEAR_BROKEN(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); if (chan[i].outVol<0) chan[i].outVol=0; if (i==2) { // triangle - rWrite(0x4000+i*4,(chan[i].outVol==0)?0:255); + rWrite(0x4000+i*4,(chan[i].outVol==0)?0:linearCount); chan[i].freqChanged=true; } else { rWrite(0x4000+i*4,(chan[i].envMode<<4)|chan[i].outVol|((chan[i].duty&3)<<6)); @@ -262,7 +262,7 @@ void DivPlatformNES::tick(bool sysTick) { //rWrite(16+i*5,chan[i].sweep); } } - if (i<2) if (chan[i].std.phaseReset.had) { + if (i<3) if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.val==1) { chan[i].freqChanged=true; chan[i].prevFreq=-1; @@ -449,7 +449,7 @@ int DivPlatformNES::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; } if (c.chan==2) { - rWrite(0x4000+c.chan*4,0xff); + rWrite(0x4000+c.chan*4,linearCount); } else if (!parent->song.brokenOutVol2) { rWrite(0x4000+c.chan*4,(chan[c.chan].envMode<<4)|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); } @@ -481,7 +481,7 @@ int DivPlatformNES::dispatch(DivCommand c) { } if (chan[c.chan].active) { if (c.chan==2) { - rWrite(0x4000+c.chan*4,0xff); + rWrite(0x4000+c.chan*4,linearCount); } else { rWrite(0x4000+c.chan*4,(chan[c.chan].envMode<<4)|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); } @@ -557,6 +557,16 @@ int DivPlatformNES::dispatch(DivCommand c) { countMode=c.value; rWrite(0x4017,countMode?0x80:0); break; + case DIV_CMD_NES_LINEAR_LENGTH: + if (c.chan==2) { + linearCount=c.value; + if (chan[c.chan].active) { + rWrite(0x4000+c.chan*4,(chan[c.chan].outVol==0)?0:linearCount); + chan[c.chan].freqChanged=true; + chan[c.chan].prevFreq=-1; + } + } + break; case DIV_CMD_NES_DMC: rWrite(0x4011,c.value&0x7f); break; @@ -682,6 +692,7 @@ void DivPlatformNES::reset() { goingToLoop=false; countMode=false; nextDPCMFreq=-1; + linearCount=255; if (useNP) { nes1_NP->Reset(); diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index 2ab7ede2..da0a848d 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -52,6 +52,7 @@ class DivPlatformNES: public DivDispatch { unsigned char sampleBank; unsigned char writeOscBuf; unsigned char apuType; + unsigned char linearCount; signed char nextDPCMFreq; bool dpcmMode; bool dpcmModeDefault; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 11428882..d1cc1996 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -234,6 +234,8 @@ const char* cmdName[]={ "SNES_GLOBAL_VOL_LEFT", "SNES_GLOBAL_VOL_RIGHT", + "NES_LINEAR_LENGTH", + "ALWAYS_SET_VOLUME" }; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 4e45df01..023a8133 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -713,6 +713,7 @@ void DivEngine::registerSystems() { {0x16, {DIV_CMD_NES_LENGTH, "16xx: Set length counter (refer to manual for a list of values)"}}, {0x17, {DIV_CMD_NES_COUNT_MODE, "17xx: Set frame counter mode (0: 4-step, 1: 5-step)"}}, {0x18, {DIV_CMD_SAMPLE_MODE, "18xx: Select PCM/DPCM mode (0: PCM; 1: DPCM)"}}, + {0x19, {DIV_CMD_NES_LINEAR_LENGTH, "19xx: Set triangle linear counter (0 to 7F; 80 and higher halt)"}}, {0x20, {DIV_CMD_SAMPLE_FREQ, "20xx: Set DPCM frequency (0 to F)"}} } );