Mesen2/Core/NES/Mappers/Homebrew/RainbowAudio.h

91 lines
No EOL
1.7 KiB
C++

#pragma once
#include "NES/APU/BaseExpansionAudio.h"
#include "NES/Mappers/Audio/Vrc6Pulse.h"
#include "NES/Mappers/Audio/Vrc6Saw.h"
#include "NES/APU/NesApu.h"
#include "NES/NesConsole.h"
#include "Utilities/Serializer.h"
class RainbowAudio : public BaseExpansionAudio
{
private:
Vrc6Pulse _pulse1;
Vrc6Pulse _pulse2;
Vrc6Saw _saw;
bool _outputExpPin6 = false;
bool _outputExpPin9 = false;
bool _outputTo4011 = false;
uint8_t _volume = 0;
uint8_t _lastOutput = 0;
protected:
void Serialize(Serializer& s) override
{
SV(_pulse1);
SV(_pulse2);
SV(_saw);
SV(_outputExpPin6);
SV(_outputExpPin9);
SV(_outputTo4011);
SV(_volume);
SV(_lastOutput);
}
void ClockAudio() override
{
_pulse1.Clock();
_pulse2.Clock();
_saw.Clock();
uint8_t outputLevel = _pulse1.GetVolume() + _pulse2.GetVolume() + _saw.GetVolume();
if(_outputExpPin6 || _outputExpPin9) {
_console->GetApu()->AddExpansionAudioDelta(AudioChannel::VRC6, ((int16_t)outputLevel - (int16_t)_lastOutput) * 15 * _volume / 15);
}
_lastOutput = outputLevel;
}
public:
RainbowAudio(NesConsole* console) : BaseExpansionAudio(console)
{
Reset();
}
void Reset()
{
_lastOutput = 0;
}
uint8_t GetLastOutput()
{
return _lastOutput;
}
void WriteRegister(uint16_t addr, uint8_t value)
{
addr &= 0x0F;
switch(addr) {
case 0x00: case 0x01: case 0x02:
_pulse1.WriteReg(addr, value);
break;
case 0x03: case 0x04: case 0x05:
_pulse2.WriteReg(addr - 0x03, value);
break;
case 0x06: case 0x07: case 0x08:
_saw.WriteReg(addr - 0x06, value);
break;
case 0x09:
_outputExpPin6 = value & 0x01;
_outputExpPin9 = value & 0x02;
_outputTo4011 = value & 0x04;
break;
case 0x0A:
_volume = value & 0x0F;
break;
}
}
};