Mesen2/Core/NES/APU/ApuTimer.h
2022-09-08 21:29:52 -04:00

97 lines
No EOL
1.5 KiB
C++

#pragma once
#include "pch.h"
#include "Utilities/ISerializable.h"
#include "Utilities/Serializer.h"
#include "NES/INesMemoryHandler.h"
#include "NES/NesConsole.h"
#include "NES/NesSoundMixer.h"
class ApuTimer : public ISerializable
{
private:
uint32_t _previousCycle;
uint16_t _timer = 0;
uint16_t _period = 0;
int8_t _lastOutput = 0;
AudioChannel _channel = AudioChannel::Square1;
NesSoundMixer* _mixer = nullptr;
public:
ApuTimer(AudioChannel channel, NesSoundMixer* mixer)
{
_channel = channel;
_mixer = mixer;
Reset(false);
}
void Reset(bool softReset)
{
_timer = 0;
_period = 0;
_previousCycle = 0;
_lastOutput = 0;
}
void Serialize(Serializer& s) override
{
if(!s.IsSaving()) {
_previousCycle = 0;
}
SV(_timer); SV(_period); SV(_lastOutput);
}
__forceinline void AddOutput(int8_t output)
{
if(output != _lastOutput) {
_mixer->AddDelta(_channel, _previousCycle, output - _lastOutput);
_lastOutput = output;
}
}
int8_t GetLastOutput()
{
return _lastOutput;
}
__forceinline bool Run(uint32_t targetCycle)
{
int32_t cyclesToRun = targetCycle - _previousCycle;
if(cyclesToRun > _timer) {
_previousCycle += _timer + 1;
_timer = _period;
return true;
}
_timer -= cyclesToRun;
_previousCycle = targetCycle;
return false;
}
void SetPeriod(uint16_t period)
{
_period = period;
}
uint16_t GetPeriod()
{
return _period;
}
uint16_t GetTimer()
{
return _timer;
}
void SetTimer(uint16_t timer)
{
_timer = timer;
}
__forceinline void EndFrame()
{
_previousCycle = 0;
}
};