diff --git a/sources/APU/DSP/DSP.hpp b/sources/APU/DSP/DSP.hpp index 3ae3fd0..6de6b07 100644 --- a/sources/APU/DSP/DSP.hpp +++ b/sources/APU/DSP/DSP.hpp @@ -48,10 +48,14 @@ namespace ComSquare::APU::DSP uint8_t data; //! @brief Offset position after data start uint16_t offset; + //! @brief offset maximum + uint16_t length; //! @brief Echo delay size register (EDL) uint8_t delay; //! @brief Echo enabled (5th bit FLG) bool enabled = true; + //! @brief Application of enabled to channels. + bool toggle; //! @brief Last sound produced for each voice in each channel std::array, 2> history; //! @brief Current position inside history @@ -417,6 +421,7 @@ namespace ComSquare::APU::DSP int32_t loadFIR(bool channel, int fir); void loadEcho(bool channel); int16_t outputEcho(bool channel); + void writeEcho(bool channel); void timerTick(); bool timerPoll(uint32_t rate); diff --git a/sources/APU/DSP/Echo.cpp b/sources/APU/DSP/Echo.cpp index 51823c4..d11a444 100644 --- a/sources/APU/DSP/Echo.cpp +++ b/sources/APU/DSP/Echo.cpp @@ -23,6 +23,18 @@ namespace ComSquare::APU::DSP this->_echo.history[channel][this->_echo.historyOffset] = echo >> 1; } + void DSP::writeEcho(bool channel) + { + if (!this->_echo.toggle) { + uint16_t address = this->_echo.address + channel * 2; + int16_t sample = this->_echo.output[channel]; + + this->_writeRAM(address++, sample); + this->_writeRAM(address, sample >> 8); + } + this->_echo.output[channel] = 0; + } + int16_t DSP::outputEcho(bool channel) { int16_t master = this->_master.output[channel] * this->_master.volume[channel] >> 7; @@ -93,36 +105,65 @@ namespace ComSquare::APU::DSP void DSP::echo28() { - + this->_echo.toggle = this->_echo.enabled; } void DSP::echo29() { + this->_echo.value = this->_echo.data; + if (!this->_echo.offset) + this->_echo.length = this->_echo.delay << 11; + + this->_echo.offset += 4; + if (this->_echo.offset >= this->_echo.length) + this->_echo.offset = 0; + + this->writeEcho(0); + + echo28(); } void DSP::echo30() { - + this->writeEcho(1); } void DSP::misc27() { - + for (int i = 0; i < 8; i++) + this->_voices[i].prevPmon = this->_voices[i].pmon; } void DSP::misc28() { - + for (int i = 0; i < 8; i++) + this->_voices[i].tempNon = this->_voices[i].non; + this->_brr.offsetAddr = this->_brr.offset; } void DSP::misc29() { - + this->_timer.sample = !this->_timer.sample; + if (this->_timer.sample) { + for (int i = 0; i < 8; i++) + this->_voices[i].kon = 0; + } } void DSP::misc30() { + if (this->_timer.sample) { + for (int i = 0; i < 8; i++) + this->_voices[i].kof = 0; + } + this->timerTick(); + + if (!this->timerPoll(this->_noise.clock)) + return; + int32_t feedback = this->_noise.lfsr << 13 ^ this->_noise.lfsr << 14; + + this->_noise.lfsr = feedback & 0x4000 ^ this->_noise.lfsr >> 1; } } \ No newline at end of file