From 6f1a41de1e491361a06d1267f7d849fd7700d9f0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 28 Sep 2022 18:28:01 -0500 Subject: [PATCH] SNES: implement more effects --- src/engine/platform/snes.cpp | 122 ++++++++++++++++++++++++++++------- src/engine/platform/snes.h | 1 + src/engine/sysDef.cpp | 28 ++++---- 3 files changed, 115 insertions(+), 36 deletions(-) diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 6d448abef..0454ed357 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -296,29 +296,7 @@ int DivPlatformSNES::dispatch(DivCommand c) { } if (chan[c.chan].insChanged) { chan[c.chan].state=ins->snes; - if (chan[c.chan].state.useEnv) { - chWrite(c.chan,5,chan[c.chan].state.a|(chan[c.chan].state.d<<4)|0x80); - chWrite(c.chan,6,chan[c.chan].state.r|(chan[c.chan].state.s<<5)); - } else { - chWrite(c.chan,5,0); - switch (chan[c.chan].state.gainMode) { - case DivInstrumentSNES::GAIN_MODE_DIRECT: - chWrite(c.chan,7,chan[c.chan].state.gain&127); - break; - case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR: - chWrite(c.chan,7,0x80|(chan[c.chan].state.gain&31)); - break; - case DivInstrumentSNES::GAIN_MODE_INC_LINEAR: - chWrite(c.chan,7,0xc0|(chan[c.chan].state.gain&31)); - break; - case DivInstrumentSNES::GAIN_MODE_DEC_LOG: - chWrite(c.chan,7,0xa0|(chan[c.chan].state.gain&31)); - break; - case DivInstrumentSNES::GAIN_MODE_INC_INVLOG: - chWrite(c.chan,7,0xe0|(chan[c.chan].state.gain&31)); - break; - } - } + writeEnv(c.chan); } if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value)); @@ -368,6 +346,11 @@ int DivPlatformSNES::dispatch(DivCommand c) { chan[c.chan].pitch=c.value; chan[c.chan].freqChanged=true; break; + case DIV_CMD_WAVE: + if (!chan[c.chan].useWave) break; + chan[c.chan].wave=c.value; + chan[c.chan].ws.changeWave1(chan[c.chan].wave); + break; case DIV_CMD_NOTE_PORTA: { int destFreq=round(NOTE_FREQUENCY(c.value2)); bool return2=false; @@ -404,9 +387,76 @@ int DivPlatformSNES::dispatch(DivCommand c) { chan[c.chan].inPorta=c.value; break; case DIV_CMD_SAMPLE_POS: + // may have to remove this chan[c.chan].audPos=c.value; chan[c.chan].setPos=true; break; + case DIV_CMD_STD_NOISE_MODE: + chan[c.chan].noise=c.value; + writeNoise=true; + break; + case DIV_CMD_SNES_PITCH_MOD: + chan[c.chan].pitchMod=c.value; + writePitchMod=true; + break; + case DIV_CMD_SNES_INVERT: + chan[c.chan].invertL=(c.value>>4); + chan[c.chan].invertR=c.chan&15; + writeOutVol(c.chan); + break; + case DIV_CMD_SNES_GAIN_MODE: + if (c.value) { + chan[c.chan].state.useEnv=false; + switch (c.value) { + case 1: + chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DIRECT; + break; + case 2: + chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DEC_LINEAR; + break; + case 3: + chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DEC_LOG; + break; + case 4: + chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_INC_LINEAR; + break; + case 5: + chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_INC_INVLOG; + break; + } + } else { + chan[c.chan].state.useEnv=true; + } + writeEnv(c.chan); + break; + case DIV_CMD_SNES_GAIN: + if (chan[c.chan].state.gainMode==DivInstrumentSNES::GAIN_MODE_DIRECT) { + chan[c.chan].state.gain=c.value&0x7f; + } else { + chan[c.chan].state.gain=c.value&0x1f; + } + if (!chan[c.chan].state.useEnv) writeEnv(c.chan); + break; + case DIV_CMD_STD_NOISE_FREQ: + noiseFreq=c.value&0x1f; + writeControl=true; + break; + case DIV_CMD_FM_AR: + chan[c.chan].state.a=c.value&15; + if (chan[c.chan].state.useEnv) writeEnv(c.chan); + break; + case DIV_CMD_FM_DR: + chan[c.chan].state.d=c.value&7; + if (chan[c.chan].state.useEnv) writeEnv(c.chan); + break; + case DIV_CMD_FM_SL: + chan[c.chan].state.s=c.value&7; + if (chan[c.chan].state.useEnv) writeEnv(c.chan); + break; + case DIV_CMD_FM_RR: + chan[c.chan].state.r=c.value&0x1f; + if (chan[c.chan].state.useEnv) writeEnv(c.chan); + break; case DIV_CMD_SNES_ECHO: chan[c.chan].echo=c.value; writeEcho=true; @@ -484,6 +534,32 @@ void DivPlatformSNES::writeOutVol(int ch) { chWrite(ch,1,outR); } +void DivPlatformSNES::writeEnv(int ch) { + if (chan[ch].state.useEnv) { + chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80); + chWrite(ch,6,chan[ch].state.r|(chan[ch].state.s<<5)); + } else { + chWrite(ch,5,0); + switch (chan[ch].state.gainMode) { + case DivInstrumentSNES::GAIN_MODE_DIRECT: + chWrite(ch,7,chan[ch].state.gain&127); + break; + case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR: + chWrite(ch,7,0x80|(chan[ch].state.gain&31)); + break; + case DivInstrumentSNES::GAIN_MODE_INC_LINEAR: + chWrite(ch,7,0xc0|(chan[ch].state.gain&31)); + break; + case DivInstrumentSNES::GAIN_MODE_DEC_LOG: + chWrite(ch,7,0xa0|(chan[ch].state.gain&31)); + break; + case DivInstrumentSNES::GAIN_MODE_INC_INVLOG: + chWrite(ch,7,0xe0|(chan[ch].state.gain&31)); + break; + } + } +} + void DivPlatformSNES::muteChannel(int ch, bool mute) { isMuted[ch]=mute; writeOutVol(ch); diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 4a91f543e..61ddb486b 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -131,6 +131,7 @@ class DivPlatformSNES: public DivDispatch { private: void updateWave(int ch); void writeOutVol(int ch); + void writeEnv(int ch); void initEcho(); }; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 9d2aa6633..9a10d26c0 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -867,23 +867,11 @@ void DivEngine::registerSystems() { {DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES}, {}, { - {0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}}, - {0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Toggle noise mode"}}, - {0x12, {DIV_CMD_SNES_ECHO, "12xx: Toggle echo on this channel"}}, - {0x13, {DIV_CMD_SNES_PITCH_MOD, "13xx: Toggle pitch modulation"}}, - {0x14, {DIV_CMD_SNES_INVERT, "14xy: Toggle invert (x: left; y: right)"}}, - {0x15, {DIV_CMD_SNES_GAIN_MODE, "15xx: Set gain mode"}}, - {0x16, {DIV_CMD_SNES_GAIN, "16xx: Set gain"}}, {0x18, {DIV_CMD_SNES_ECHO_ENABLE, "18xx: Enable echo buffer"}}, - {0x19, {DIV_CMD_SNES_ECHO_DELAY, "19xx: Set echo delay"}}, + {0x19, {DIV_CMD_SNES_ECHO_DELAY, "19xx: Set echo delay (0 to F)"}}, {0x1a, {DIV_CMD_SNES_ECHO_VOL_LEFT, "1Axx: Set left echo volume"}}, {0x1b, {DIV_CMD_SNES_ECHO_VOL_RIGHT, "1Bxx: Set right echo volume"}}, {0x1c, {DIV_CMD_SNES_ECHO_FEEDBACK, "1Cxx: Set echo feedback"}}, - {0x1d, {DIV_CMD_STD_NOISE_FREQ, "1Dxx: Set noise frequency"}}, - {0x20, {DIV_CMD_FM_AR, "20xx: Set attack"}}, - {0x21, {DIV_CMD_FM_DR, "21xx: Set decay"}}, - {0x22, {DIV_CMD_FM_SL, "22xx: Set sustain"}}, - {0x23, {DIV_CMD_FM_RR, "23xx: Set release"}}, {0x30, {DIV_CMD_SNES_ECHO_FIR, "30xx: Set echo filter coefficient 0",constVal<0>,effectVal}}, {0x31, {DIV_CMD_SNES_ECHO_FIR, "31xx: Set echo filter coefficient 1",constVal<1>,effectVal}}, {0x32, {DIV_CMD_SNES_ECHO_FIR, "32xx: Set echo filter coefficient 2",constVal<2>,effectVal}}, @@ -892,6 +880,20 @@ void DivEngine::registerSystems() { {0x35, {DIV_CMD_SNES_ECHO_FIR, "35xx: Set echo filter coefficient 5",constVal<5>,effectVal}}, {0x36, {DIV_CMD_SNES_ECHO_FIR, "36xx: Set echo filter coefficient 6",constVal<6>,effectVal}}, {0x37, {DIV_CMD_SNES_ECHO_FIR, "37xx: Set echo filter coefficient 7",constVal<7>,effectVal}}, + }, + { + {0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}}, + {0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Toggle noise mode"}}, + {0x12, {DIV_CMD_SNES_ECHO, "12xx: Toggle echo on this channel"}}, + {0x13, {DIV_CMD_SNES_PITCH_MOD, "13xx: Toggle pitch modulation"}}, + {0x14, {DIV_CMD_SNES_INVERT, "14xy: Toggle invert (x: left; y: right)"}}, + {0x15, {DIV_CMD_SNES_GAIN_MODE, "15xx: Set envelope mode (0: ADSR, 1: gain/direct, 2: dec, 3: exp, 4: inc, 5: bent)"}}, + {0x16, {DIV_CMD_SNES_GAIN, "16xx: Set gain (00 to 7F if direct; 00 to 1F otherwise)"}}, + {0x1d, {DIV_CMD_STD_NOISE_FREQ, "1Dxx: Set noise frequency (00 to 1F)"}}, + {0x20, {DIV_CMD_FM_AR, "20xx: Set attack (0 to F)"}}, + {0x21, {DIV_CMD_FM_DR, "21xx: Set decay (0 to 7)"}}, + {0x22, {DIV_CMD_FM_SL, "22xx: Set sustain (0 to 7)"}}, + {0x23, {DIV_CMD_FM_RR, "23xx: Set release (00 to 1F)"}}, } );