#pragma once #include "stdafx.h" #include "BaseApuChannel.h" #include "Console.h" #include "APU.h" class ApuLengthCounter : public BaseApuChannel { private: uint8_t _lcLookupTable[32] = { 10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30 }; bool _newHaltValue; protected: bool _enabled = false; bool _lengthCounterHalt; uint8_t _lengthCounter; uint8_t _lengthCounterReloadValue; uint8_t _lengthCounterPreviousValue; void InitializeLengthCounter(bool haltFlag) { _console->GetApu()->SetNeedToRun(); _newHaltValue = haltFlag; } void LoadLengthCounter(uint8_t value) { if(_enabled) { _lengthCounterReloadValue = _lcLookupTable[value]; _lengthCounterPreviousValue = _lengthCounter; _console->GetApu()->SetNeedToRun(); } } public: ApuLengthCounter(AudioChannel channel, shared_ptr console, SoundMixer* mixer) : BaseApuChannel(channel, console, mixer) { } virtual void Reset(bool softReset) override { BaseApuChannel::Reset(softReset); if(softReset) { _enabled = false; if(GetChannel() != AudioChannel::Triangle) { //"At reset, length counters should be enabled, triangle unaffected" _lengthCounterHalt = false; _lengthCounter = 0; _newHaltValue = false; _lengthCounterReloadValue = 0; _lengthCounterPreviousValue = 0; } } else { _enabled = false; _lengthCounterHalt = false; _lengthCounter = 0; _newHaltValue = false; _lengthCounterReloadValue = 0; _lengthCounterPreviousValue = 0; } } virtual void StreamState(bool saving) override { BaseApuChannel::StreamState(saving); Stream(_enabled, _lengthCounterHalt, _newHaltValue, _lengthCounter, _lengthCounterPreviousValue, _lengthCounterReloadValue); } bool GetStatus() override { return _lengthCounter > 0; } void ReloadCounter() { if(_lengthCounterReloadValue) { if(_lengthCounter == _lengthCounterPreviousValue) { _lengthCounter = _lengthCounterReloadValue; } _lengthCounterReloadValue = 0; } _lengthCounterHalt = _newHaltValue; } void TickLengthCounter() { if(_lengthCounter > 0 && !_lengthCounterHalt) { _lengthCounter--; } } void SetEnabled(bool enabled) { if(!enabled) { _lengthCounter = 0; } _enabled = enabled; } ApuLengthCounterState GetState() { ApuLengthCounterState state; state.Counter = _lengthCounter; state.Halt = _lengthCounterHalt; state.ReloadValue = _lengthCounterReloadValue; return state; } };