Mesen2/Core/NES/Mappers/Konami/VrcIrq.h

95 lines
No EOL
1.9 KiB
C++

#pragma once
#include "NES/NesConsole.h"
#include "NES/NesCpu.h"
#include "Utilities/ISerializable.h"
#include "Utilities/Serializer.h"
class VrcIrq final : public ISerializable
{
private:
NesConsole* _console;
uint8_t _irqReloadValue = 0;
uint8_t _irqCounter = 0;
int16_t _irqPrescalerCounter = 0;
bool _irqEnabled = false;
bool _irqEnabledAfterAck = false;
bool _irqCycleMode = false;
protected:
void Serialize(Serializer& s) override
{
SV(_irqReloadValue);
SV(_irqCounter);
SV(_irqPrescalerCounter);
SV(_irqEnabled);
SV(_irqEnabledAfterAck);
SV(_irqCycleMode);
}
public:
VrcIrq(NesConsole* console)
{
_console = console;
}
void Reset()
{
_irqPrescalerCounter = 0;
_irqReloadValue = 0;
_irqCounter = 0;
_irqEnabled = false;
_irqEnabledAfterAck = false;
_irqCycleMode = false;
}
void ProcessCpuClock()
{
if(_irqEnabled) {
_irqPrescalerCounter -= 3;
if(_irqCycleMode || (_irqPrescalerCounter <= 0 && !_irqCycleMode)) {
if(_irqCounter == 0xFF) {
_irqCounter = _irqReloadValue;
_console->GetCpu()->SetIrqSource(IRQSource::External);
} else {
_irqCounter++;
}
_irqPrescalerCounter += 341;
}
}
}
void SetReloadValue(uint8_t value)
{
_irqReloadValue = value;
}
void SetReloadValueNibble(uint8_t value, bool highBits)
{
if(highBits) {
_irqReloadValue = (_irqReloadValue & 0x0F) | ((value & 0x0F) << 4);
} else {
_irqReloadValue = (_irqReloadValue & 0xF0) | (value & 0x0F);
}
}
void SetControlValue(uint8_t value)
{
_irqEnabledAfterAck = (value & 0x01) == 0x01;
_irqEnabled = (value & 0x02) == 0x02;
_irqCycleMode = (value & 0x04) == 0x04;
if(_irqEnabled) {
_irqCounter = _irqReloadValue;
_irqPrescalerCounter = 341;
}
_console->GetCpu()->ClearIrqSource(IRQSource::External);
}
void AcknowledgeIrq()
{
_irqEnabled = _irqEnabledAfterAck;
_console->GetCpu()->ClearIrqSource(IRQSource::External);
}
};