1 #pragma once 2 #include "Snapshotable.h" 3 #include "CPU.h" 4 5 class VrcIrq : public Snapshotable 6 { 7 private: 8 shared_ptr<Console> _console; 9 uint8_t _irqReloadValue; 10 uint8_t _irqCounter; 11 int16_t _irqPrescalerCounter; 12 bool _irqEnabled; 13 bool _irqEnabledAfterAck; 14 bool _irqCycleMode; 15 16 protected: StreamState(bool saving)17 void StreamState(bool saving) override 18 { 19 Stream(_irqReloadValue, _irqCounter, _irqPrescalerCounter, _irqEnabled, _irqEnabledAfterAck, _irqCycleMode); 20 } 21 22 public: VrcIrq(shared_ptr<Console> console)23 VrcIrq(shared_ptr<Console> console) 24 { 25 _console = console; 26 } 27 Reset()28 void Reset() 29 { 30 _irqPrescalerCounter = 0; 31 _irqReloadValue = 0; 32 _irqCounter = 0; 33 _irqEnabled = false; 34 _irqEnabledAfterAck = false; 35 _irqCycleMode = false; 36 } 37 ProcessCpuClock()38 void ProcessCpuClock() 39 { 40 if(_irqEnabled) { 41 _irqPrescalerCounter -= 3; 42 43 if(_irqCycleMode || (_irqPrescalerCounter <= 0 && !_irqCycleMode)) { 44 if(_irqCounter == 0xFF) { 45 _irqCounter = _irqReloadValue; 46 _console->GetCpu()->SetIrqSource(IRQSource::External); 47 } else { 48 _irqCounter++; 49 } 50 _irqPrescalerCounter += 341; 51 } 52 } 53 } 54 SetReloadValue(uint8_t value)55 void SetReloadValue(uint8_t value) 56 { 57 _irqReloadValue = value; 58 } 59 SetReloadValueNibble(uint8_t value,bool highBits)60 void SetReloadValueNibble(uint8_t value, bool highBits) 61 { 62 if(highBits) { 63 _irqReloadValue = (_irqReloadValue & 0x0F) | ((value & 0x0F) << 4); 64 } else { 65 _irqReloadValue = (_irqReloadValue & 0xF0) | (value & 0x0F); 66 } 67 } 68 SetControlValue(uint8_t value)69 void SetControlValue(uint8_t value) 70 { 71 _irqEnabledAfterAck = (value & 0x01) == 0x01; 72 _irqEnabled = (value & 0x02) == 0x02; 73 _irqCycleMode = (value & 0x04) == 0x04; 74 75 if(_irqEnabled) { 76 _irqCounter = _irqReloadValue; 77 _irqPrescalerCounter = 341; 78 } 79 80 _console->GetCpu()->ClearIrqSource(IRQSource::External); 81 } 82 AcknowledgeIrq()83 void AcknowledgeIrq() 84 { 85 _irqEnabled = _irqEnabledAfterAck; 86 _console->GetCpu()->ClearIrqSource(IRQSource::External); 87 } 88 };