Mesen/Core/VrcIrq.h

88 lines
1.8 KiB
C++

#pragma once
#include "Snapshotable.h"
#include "CPU.h"
class VrcIrq : public Snapshotable
{
private:
shared_ptr<Console> _console;
uint8_t _irqReloadValue;
uint8_t _irqCounter;
int16_t _irqPrescalerCounter;
bool _irqEnabled;
bool _irqEnabledAfterAck;
bool _irqCycleMode;
protected:
void StreamState(bool saving) override
{
Stream(_irqReloadValue, _irqCounter, _irqPrescalerCounter, _irqEnabled, _irqEnabledAfterAck, _irqCycleMode);
}
public:
VrcIrq(shared_ptr<Console> 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);
}
};