diff --git a/papers/doc/7-systems/qsound.md b/papers/doc/7-systems/qsound.md new file mode 100644 index 000000000..9da79d822 --- /dev/null +++ b/papers/doc/7-systems/qsound.md @@ -0,0 +1,18 @@ +# Capcom QSound (DL-1425) + +This chip was used in Capcom's CP System Dash, CP System II and ZN arcade PCBs. + +It supports 16 PCM channels and uses the patented (now expired) QSound stereo expansion algorithm, as the name implies. + +Because the chip lacks sample interpolation, it's recommended that you try to play samples at around 24038 Hz to avoid aliasing. This is especially important for e.g. cymbals. + +The QSound chip also has a small echo buffer, somewhat similar to the SNES, although with a very basic (and non-adjustable) filter. It is however possible to adjust the feedback and length of the echo buffer. The initial values can be set in the "Configure system" dialog. + +There are also 3 ADPCM channels, however they cannot be used in Furnace yet. They have been reserved in case this feature is added later. ADPCM samples are limited to 8012 Hz. + +# effects + +- `08xx`: Set panning. Valid range is 00-20. 00 for full left, 10 for center and 20 for full right. It is also possible to bypass the QSound algorithm by using the range 30-50. +- `10xx`: Set echo feedback level. This effect will apply to all channels. +- `11xx`: Set echo level. +- `3xxx`: Set the length of the echo delay buffer. diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index d02bebe6b..da9690a12 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -98,6 +98,7 @@ enum DivDispatchCmds { DIV_CMD_SAA_ENVELOPE, DIV_CMD_QSOUND_ECHO_FEEDBACK, + DIV_CMD_QSOUND_ECHO_DELAY, DIV_CMD_QSOUND_ECHO_LEVEL, DIV_ALWAYS_SET_VOLUME, diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 4c4d0a37c..47e6bdb50 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -257,6 +257,9 @@ const char* DivPlatformQSound::getEffectName(unsigned char effect) { case 0x11: return "11xx: Set channel echo level (00 to FF)"; break; + default: + if((effect & 0xf0) == 0x30) + return "3xxx: Set echo delay buffer length (000 to AA5)"; } return NULL; } @@ -433,6 +436,9 @@ int DivPlatformQSound::dispatch(DivCommand c) { case DIV_CMD_QSOUND_ECHO_FEEDBACK: immWrite(Q1_ECHO_FEEDBACK, c.value << 6); break; + case DIV_CMD_QSOUND_ECHO_DELAY: + immWrite(Q1_ECHO_LENGTH, (c.value > 2725 ? 0xfff : 0xfff - (2725 - c.value))); + break; case DIV_CMD_PITCH: chan[c.chan].pitch=c.value; chan[c.chan].freqChanged=true; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index b16262d08..2424f0845 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -110,6 +110,7 @@ const char* cmdName[DIV_CMD_MAX]={ "SAA_ENVELOPE", "QSOUND_ECHO_FEEDBACK", + "QSOUND_ECHO_DELAY", "QSOUND_ECHO_LEVEL", "ALWAYS_SET_VOLUME" @@ -230,7 +231,10 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe dispatchCmd(DivCommand(DIV_CMD_QSOUND_ECHO_LEVEL,ch,effectVal)); break; default: - return false; + if((effect & 0xf0) == 0x30) + dispatchCmd(DivCommand(DIV_CMD_QSOUND_ECHO_DELAY,ch,((effect & 0x0f) << 8) | effectVal)); + else + return false; } break; default: