From f03ed7c83310816802303fd6aef8836d50683181 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 1 Feb 2022 18:28:48 -0500 Subject: [PATCH] NES: add hardware sweep effect --- papers/doc/7-systems/nes.md | 8 ++++++++ src/engine/dispatch.h | 2 ++ src/engine/platform/nes.cpp | 19 +++++++++++++++++-- src/engine/platform/nes.h | 2 +- src/engine/playback.cpp | 8 ++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/papers/doc/7-systems/nes.md b/papers/doc/7-systems/nes.md index 6ca0d8b77..dc6eb20af 100644 --- a/papers/doc/7-systems/nes.md +++ b/papers/doc/7-systems/nes.md @@ -8,3 +8,11 @@ also known as Famicom. - `12xx`: set duty cycle or noise mode of channel. - may be 0-3 for the pulse channels and 0-1 for the noise channel. +- `13xy`: setup sweep up. + - `x` is the time. + - `y` is the shift. + - set to 0 to disable it. +- `14xy`: setup sweep down. + - `x` is the time. + - `y` is the shift. + - set to 0 to disable it. \ No newline at end of file diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0ddc6cd30..c9d49861d 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -53,6 +53,8 @@ enum DivDispatchCmds { DIV_CMD_PCE_LFO_MODE, DIV_CMD_PCE_LFO_SPEED, + DIV_CMD_NES_SWEEP, + DIV_CMD_C64_CUTOFF, DIV_CMD_C64_RESONANCE, DIV_CMD_C64_FILTER_MODE, diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 5527418a2..222d6b37d 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -300,6 +300,19 @@ int DivPlatformNES::dispatch(DivCommand c) { chan[c.chan].freqChanged=true; } break; + case DIV_CMD_NES_SWEEP: + if (c.chan>1) break; + if (c.value2==0) { + chan[c.chan].sweep=0x08; + } else { + if (!c.value) { // down + chan[c.chan].sweep=0x88|(c.value2&0x77); + } else { // up + chan[c.chan].sweep=0x80|(c.value2&0x77); + } + } + rWrite(0x4001+(c.chan*4),chan[c.chan].sweep); + break; case DIV_CMD_SAMPLE_BANK: sampleBank=c.value; if (sampleBank>(parent->song.sample.size()/12)) { @@ -341,6 +354,8 @@ void DivPlatformNES::forceIns() { chan[i].insChanged=true; chan[i].prevFreq=65535; } + rWrite(0x4001,chan[0].sweep); + rWrite(0x4005,chan[1].sweep); } void* DivPlatformNES::getChanState(int ch) { @@ -366,8 +381,8 @@ void DivPlatformNES::reset() { nes->apu.cpu_opcode_cycle=0; rWrite(0x4015,(!isMuted[0])|((!isMuted[1])<<1)|((!isMuted[2])<<2)|((!isMuted[3])<<3)|((!isMuted[4])<<4)); - rWrite(0x4001,0x08); - rWrite(0x4005,0x08); + rWrite(0x4001,chan[0].sweep); + rWrite(0x4005,chan[1].sweep); } bool DivPlatformNES::keyOffAffectsArp(int ch) { diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index bb8b5adc8..edc130ae3 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -19,7 +19,7 @@ class DivPlatformNES: public DivDispatch { note(0), ins(-1), duty(0), - sweep(0), + sweep(8), active(false), insChanged(true), freqChanged(false), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 2ba7a5036..80e9e14c9 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -65,6 +65,8 @@ const char* cmdName[DIV_CMD_MAX]={ "PCE_LFO_MODE", "PCE_LFO_SPEED", + "NES_SWEEP", + "C64_CUTOFF", "C64_RESONANCE", "C64_FILTER_MODE", @@ -178,6 +180,12 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe case 0x12: // duty or noise mode dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal)); break; + case 0x13: // sweep up + dispatchCmd(DivCommand(DIV_CMD_NES_SWEEP,ch,0,effectVal)); + break; + case 0x14: // sweep down + dispatchCmd(DivCommand(DIV_CMD_NES_SWEEP,ch,1,effectVal)); + break; default: return false; }