2015-07-14 21:50:14 -04:00
|
|
|
#pragma once
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "BaseApuChannel.h"
|
|
|
|
|
2016-01-24 18:51:07 -05:00
|
|
|
class ApuLengthCounter : public BaseApuChannel
|
2015-07-14 21:50:14 -04:00
|
|
|
{
|
|
|
|
private:
|
2017-03-31 22:14:16 -04:00
|
|
|
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 };
|
2015-07-19 01:30:13 -04:00
|
|
|
bool _newHaltValue;
|
2015-07-19 22:24:56 -04:00
|
|
|
static bool _needToRun;
|
2015-07-14 21:50:14 -04:00
|
|
|
|
|
|
|
protected:
|
2017-08-30 18:31:27 -04:00
|
|
|
bool _enabled = false;
|
2015-07-19 01:30:13 -04:00
|
|
|
bool _lengthCounterHalt;
|
|
|
|
uint8_t _lengthCounter;
|
2016-01-02 17:35:30 -05:00
|
|
|
uint8_t _lengthCounterReloadValue;
|
|
|
|
uint8_t _lengthCounterPreviousValue;
|
|
|
|
|
2015-07-14 21:50:14 -04:00
|
|
|
void InitializeLengthCounter(bool haltFlag)
|
|
|
|
{
|
2015-07-19 01:30:13 -04:00
|
|
|
SetRunFlag();
|
|
|
|
_newHaltValue = haltFlag;
|
2015-07-14 21:50:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void LoadLengthCounter(uint8_t value)
|
|
|
|
{
|
|
|
|
if(_enabled) {
|
2016-01-02 17:35:30 -05:00
|
|
|
_lengthCounterReloadValue = _lcLookupTable[value];
|
|
|
|
_lengthCounterPreviousValue = _lengthCounter;
|
|
|
|
SetRunFlag();
|
2015-07-14 21:50:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-19 22:24:56 -04:00
|
|
|
void SetRunFlag()
|
|
|
|
{
|
|
|
|
ApuLengthCounter::_needToRun = true;
|
|
|
|
}
|
|
|
|
|
2015-07-14 21:50:14 -04:00
|
|
|
public:
|
2016-01-14 01:21:09 -05:00
|
|
|
ApuLengthCounter(AudioChannel channel, SoundMixer* mixer) : BaseApuChannel(channel, mixer)
|
2015-07-14 23:35:30 -04:00
|
|
|
{
|
|
|
|
}
|
2015-07-19 22:24:56 -04:00
|
|
|
|
|
|
|
static bool NeedToRun()
|
|
|
|
{
|
2017-03-31 22:14:16 -04:00
|
|
|
bool needToRun = ApuLengthCounter::_needToRun;
|
|
|
|
ApuLengthCounter::_needToRun = false;
|
|
|
|
return needToRun;
|
2015-07-19 22:24:56 -04:00
|
|
|
}
|
2015-07-14 23:35:30 -04:00
|
|
|
|
2016-12-17 23:14:47 -05:00
|
|
|
virtual void Reset(bool softReset) override
|
2015-07-14 23:35:30 -04:00
|
|
|
{
|
2015-07-19 01:30:13 -04:00
|
|
|
BaseApuChannel::Reset(softReset);
|
2015-07-14 23:35:30 -04:00
|
|
|
|
2015-07-19 01:30:13 -04:00
|
|
|
if(softReset) {
|
|
|
|
_enabled = false;
|
|
|
|
if(GetChannel() != AudioChannel::Triangle) {
|
|
|
|
//"At reset, length counters should be enabled, triangle unaffected"
|
|
|
|
_lengthCounterHalt = false;
|
|
|
|
_lengthCounter = 0;
|
|
|
|
_newHaltValue = false;
|
2016-12-16 07:13:33 -05:00
|
|
|
_lengthCounterReloadValue = 0;
|
|
|
|
_lengthCounterPreviousValue = 0;
|
2015-07-19 01:30:13 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_enabled = false;
|
|
|
|
_lengthCounterHalt = false;
|
|
|
|
_lengthCounter = 0;
|
|
|
|
_newHaltValue = false;
|
2016-12-16 07:13:33 -05:00
|
|
|
_lengthCounterReloadValue = 0;
|
|
|
|
_lengthCounterPreviousValue = 0;
|
|
|
|
}
|
2015-07-19 22:24:56 -04:00
|
|
|
|
|
|
|
ApuLengthCounter::_needToRun = false;
|
2015-07-14 23:35:30 -04:00
|
|
|
}
|
|
|
|
|
2016-12-17 23:14:47 -05:00
|
|
|
virtual void StreamState(bool saving) override
|
2015-07-14 23:35:30 -04:00
|
|
|
{
|
|
|
|
BaseApuChannel::StreamState(saving);
|
|
|
|
|
2016-06-02 20:20:26 -04:00
|
|
|
Stream(_enabled, _lengthCounterHalt, _newHaltValue, _lengthCounter, _lengthCounterPreviousValue, _lengthCounterReloadValue);
|
2015-07-14 23:35:30 -04:00
|
|
|
}
|
|
|
|
|
2016-12-17 23:14:47 -05:00
|
|
|
bool GetStatus() override
|
2015-07-14 21:50:14 -04:00
|
|
|
{
|
|
|
|
return _lengthCounter > 0;
|
|
|
|
}
|
2017-03-31 22:14:16 -04:00
|
|
|
|
2016-01-02 17:35:30 -05:00
|
|
|
void ReloadCounter()
|
|
|
|
{
|
|
|
|
if(_lengthCounterReloadValue) {
|
|
|
|
if(_lengthCounter == _lengthCounterPreviousValue) {
|
|
|
|
_lengthCounter = _lengthCounterReloadValue;
|
|
|
|
}
|
|
|
|
_lengthCounterReloadValue = 0;
|
|
|
|
}
|
2017-03-31 22:14:16 -04:00
|
|
|
|
|
|
|
_lengthCounterHalt = _newHaltValue;
|
2016-01-02 17:35:30 -05:00
|
|
|
}
|
|
|
|
|
2015-07-14 21:50:14 -04:00
|
|
|
void TickLengthCounter()
|
|
|
|
{
|
|
|
|
if(_lengthCounter > 0 && !_lengthCounterHalt) {
|
|
|
|
_lengthCounter--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
if(!enabled) {
|
|
|
|
_lengthCounter = 0;
|
|
|
|
}
|
|
|
|
_enabled = enabled;
|
|
|
|
}
|
2017-08-30 18:31:27 -04:00
|
|
|
|
|
|
|
ApuLengthCounterState GetState()
|
|
|
|
{
|
|
|
|
ApuLengthCounterState state;
|
|
|
|
state.Counter = _lengthCounter;
|
|
|
|
state.Halt = _lengthCounterHalt;
|
|
|
|
state.ReloadValue = _lengthCounterReloadValue;
|
|
|
|
return state;
|
|
|
|
}
|
2015-07-14 21:50:14 -04:00
|
|
|
};
|