From b037b07c30b503769e55b54f86cae1ebfb4389a9 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 4 May 2023 16:49:47 -0500 Subject: [PATCH] SNES: add global volume control effects --- papers/doc/7-systems/snes.md | 4 ++++ src/engine/dispatch.h | 3 +++ src/engine/platform/snes.cpp | 18 ++++++++++++++++++ src/engine/platform/snes.h | 2 ++ src/engine/playback.cpp | 3 +++ src/engine/sysDef.cpp | 2 ++ 6 files changed, 32 insertions(+) diff --git a/papers/doc/7-systems/snes.md b/papers/doc/7-systems/snes.md index a2ecd9aee..61b30635d 100644 --- a/papers/doc/7-systems/snes.md +++ b/papers/doc/7-systems/snes.md @@ -54,6 +54,10 @@ Furnace also allows the SNES to use wavetables (and the wavetable synthesizer) i - 80 to FF for -128 to -1. - setting this to -128 is not recommended as it may cause echo output to overflow and therefore click. - `1Dxx`: set noise generator frequency (00 to 1F). +- `1Exx`: set left dry/global volume. + - this does not affect echo. +- `1Fxx`: set right dry/global volume. + - this does not affect echo. - `20xx`: set attack (0 to F). - only in ADSR envelope mode. - `21xx`: set decay (0 to 7). diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0c9d2ca74..0f075e56c 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -231,6 +231,9 @@ enum DivDispatchCmds { DIV_CMD_HINT_ARP_TIME, // (value) + DIV_CMD_SNES_GLOBAL_VOL_LEFT, + DIV_CMD_SNES_GLOBAL_VOL_RIGHT, + DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol DIV_CMD_MAX diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 48351493c..a5684d0e8 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -300,6 +300,11 @@ void DivPlatformSNES::tick(bool sysTick) { rWrite(0x4d,echoBits); writeEcho=false; } + if (writeDryVol) { + rWrite(0x0c,dryVolL); + rWrite(0x1c,dryVolR); + writeDryVol=false; + } for (int i=0; i<8; i++) { if (chan[i].shallWriteEnv) { writeEnv(i); @@ -563,6 +568,14 @@ int DivPlatformSNES::dispatch(DivCommand c) { rWrite(0x3c,echoVolR); } break; + case DIV_CMD_SNES_GLOBAL_VOL_LEFT: + dryVolL=c.value; + writeDryVol=true; + break; + case DIV_CMD_SNES_GLOBAL_VOL_RIGHT: + dryVolR=c.value; + writeDryVol=true; + break; case DIV_CMD_GET_VOLMAX: return 127; break; @@ -673,6 +686,7 @@ void DivPlatformSNES::forceIns() { writeNoise=true; writePitchMod=true; writeEcho=true; + writeDryVol=true; initEcho(); } @@ -761,6 +775,10 @@ void DivPlatformSNES::reset() { writeNoise=false; writePitchMod=false; writeEcho=true; + writeDryVol=false; + + dryVolL=127; + dryVolR=127; echoDelay=initEchoDelay; echoFeedback=initEchoFeedback; diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 3c3426466..68637be82 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -59,6 +59,7 @@ class DivPlatformSNES: public DivDispatch { unsigned char noiseFreq; signed char delay; signed char echoVolL, echoVolR, echoFeedback; + signed char dryVolL, dryVolR; signed char echoFIR[8]; unsigned char echoDelay; size_t sampleTableBase; @@ -66,6 +67,7 @@ class DivPlatformSNES: public DivDispatch { bool writeNoise; bool writePitchMod; bool writeEcho; + bool writeDryVol; bool echoOn; bool initEchoOn; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 8cc2f825f..114288827 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -231,6 +231,9 @@ const char* cmdName[]={ "HINT_ARP_TIME", + "SNES_GLOBAL_VOL_LEFT", + "SNES_GLOBAL_VOL_RIGHT", + "ALWAYS_SET_VOLUME" }; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index d92573bb7..42fab2cbf 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -911,6 +911,8 @@ void DivEngine::registerSystems() { {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"}}, + {0x1e, {DIV_CMD_SNES_GLOBAL_VOL_LEFT, "1Exx: Set dry output volume (left)"}}, + {0x1f, {DIV_CMD_SNES_GLOBAL_VOL_RIGHT, "1Fxx: Set dry output volume (right)"}}, {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}},