mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-27 11:00:50 +00:00
Run APU every 1 CPU clock
This commit is contained in:
parent
444db81dfc
commit
d70010f324
53
Core/APU.cpp
53
Core/APU.cpp
@ -109,21 +109,17 @@ void APU::Run()
|
||||
//-At the end of a frame
|
||||
//-Before APU registers are read/written to
|
||||
//-When a DMC or FrameCounter interrupt needs to be fired
|
||||
uint32_t targetCycle = CPU::GetCycleCount();
|
||||
uint32_t currentCycle = _previousCycle;
|
||||
uint32_t cyclesToRun = targetCycle - _previousCycle;
|
||||
uint32_t cyclesToRun = _currentCycle - _previousCycle;
|
||||
|
||||
while(currentCycle < targetCycle) {
|
||||
currentCycle += _frameCounter->Run(cyclesToRun);
|
||||
while(_previousCycle < _currentCycle) {
|
||||
_previousCycle += _frameCounter->Run(cyclesToRun);
|
||||
|
||||
_squareChannel[0]->Run(currentCycle);
|
||||
_squareChannel[1]->Run(currentCycle);
|
||||
_noiseChannel->Run(currentCycle);
|
||||
_triangleChannel->Run(currentCycle);
|
||||
_deltaModulationChannel->Run(currentCycle);
|
||||
_squareChannel[0]->Run(_previousCycle);
|
||||
_squareChannel[1]->Run(_previousCycle);
|
||||
_noiseChannel->Run(_previousCycle);
|
||||
_triangleChannel->Run(_previousCycle);
|
||||
_deltaModulationChannel->Run(_previousCycle);
|
||||
}
|
||||
|
||||
_previousCycle = targetCycle;
|
||||
}
|
||||
|
||||
void APU::StaticRun()
|
||||
@ -142,21 +138,16 @@ bool APU::IrqPending(uint32_t currentCycle)
|
||||
return false;
|
||||
}
|
||||
|
||||
void APU::ExecStatic(uint32_t currentCpuCycle)
|
||||
void APU::ExecStatic()
|
||||
{
|
||||
Instance->Exec(currentCpuCycle);
|
||||
Instance->Exec();
|
||||
}
|
||||
|
||||
bool APU::Exec(uint32_t currentCpuCycle)
|
||||
void APU::Exec()
|
||||
{
|
||||
if(IrqPending(currentCpuCycle)) {
|
||||
_currentCycle++;
|
||||
if(_currentCycle == 20000) {
|
||||
Run();
|
||||
}
|
||||
|
||||
if(currentCpuCycle >= 29780) {
|
||||
Run();
|
||||
|
||||
_previousCycle = 0;
|
||||
|
||||
_squareChannel[0]->EndFrame();
|
||||
_squareChannel[1]->EndFrame();
|
||||
@ -164,19 +155,19 @@ bool APU::Exec(uint32_t currentCpuCycle)
|
||||
_noiseChannel->EndFrame();
|
||||
_deltaModulationChannel->EndFrame();
|
||||
|
||||
_blipBuffer->end_frame(currentCpuCycle);
|
||||
_blipBuffer->end_frame(_currentCycle);
|
||||
|
||||
// Read some samples out of Blip_Buffer if there are enough to fill our output buffer
|
||||
uint32_t availableSampleCount = _blipBuffer->samples_avail();
|
||||
if(availableSampleCount >= APU::SamplesPerFrame) {
|
||||
size_t sampleCount = _blipBuffer->read_samples(_outputBuffer, APU::SamplesPerFrame);
|
||||
if(APU::AudioDevice) {
|
||||
APU::AudioDevice->PlayBuffer(_outputBuffer, (uint32_t)(sampleCount * BitsPerSample / 8));
|
||||
}
|
||||
size_t sampleCount = _blipBuffer->read_samples(_outputBuffer, APU::SamplesPerFrame);
|
||||
if(APU::AudioDevice) {
|
||||
APU::AudioDevice->PlayBuffer(_outputBuffer, (uint32_t)(sampleCount * BitsPerSample / 8));
|
||||
}
|
||||
return true;
|
||||
_currentCycle = 0;
|
||||
_previousCycle = 0;
|
||||
} else if(IrqPending(_currentCycle)) {
|
||||
Run();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void APU::StopAudio()
|
||||
@ -189,6 +180,7 @@ void APU::StopAudio()
|
||||
|
||||
void APU::Reset()
|
||||
{
|
||||
_currentCycle = 0;
|
||||
_previousCycle = 0;
|
||||
_squareChannel[0]->Reset();
|
||||
_squareChannel[1]->Reset();
|
||||
@ -200,6 +192,7 @@ void APU::Reset()
|
||||
|
||||
void APU::StreamState(bool saving)
|
||||
{
|
||||
Stream<uint32_t>(_currentCycle);
|
||||
Stream<uint32_t>(_previousCycle);
|
||||
Stream(_squareChannel[0].get());
|
||||
Stream(_squareChannel[1].get());
|
||||
|
@ -21,6 +21,7 @@ class APU : public Snapshotable, public IMemoryHandler
|
||||
static APU* Instance;
|
||||
|
||||
uint32_t _previousCycle = 0;
|
||||
uint32_t _currentCycle = 0;
|
||||
|
||||
vector<unique_ptr<SquareChannel>> _squareChannel;
|
||||
unique_ptr<TriangleChannel> _triangleChannel;
|
||||
@ -62,8 +63,8 @@ class APU : public Snapshotable, public IMemoryHandler
|
||||
void WriteRAM(uint16_t addr, uint8_t value);
|
||||
void GetMemoryRanges(MemoryRanges &ranges);
|
||||
|
||||
bool Exec(uint32_t currentCpuCycle);
|
||||
static void ExecStatic(uint32_t currentCpuCycle);
|
||||
void Exec();
|
||||
static void ExecStatic();
|
||||
|
||||
static void StaticRun();
|
||||
static void StopAudio();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "CPU.h"
|
||||
#include "PPU.h"
|
||||
#include "APU.h"
|
||||
|
||||
CPU* CPU::Instance = nullptr;
|
||||
|
||||
@ -121,6 +122,7 @@ void CPU::EndFrame()
|
||||
void CPU::IncCycleCount()
|
||||
{
|
||||
PPU::ExecStatic();
|
||||
APU::ExecStatic();
|
||||
_cycleCount++;
|
||||
}
|
||||
|
||||
|
@ -662,7 +662,6 @@ public:
|
||||
static const uint32_t ClockRate = 1789773;
|
||||
|
||||
CPU(MemoryManager *memoryManager);
|
||||
static int32_t GetCycleCount() { return CPU::Instance->_cycleCount; }
|
||||
static int32_t GetRelativeCycleCount() { return CPU::Instance->_relativeCycleCount + CPU::Instance->_cycleCount; }
|
||||
static void SetNMIFlag() { CPU::Instance->_state.NMIFlag = true; }
|
||||
static void ClearNMIFlag() { CPU::Instance->_state.NMIFlag = false; }
|
||||
|
@ -169,13 +169,15 @@ void Console::Run()
|
||||
_runLock.Acquire();
|
||||
_stopLock.Acquire();
|
||||
|
||||
uint32_t lastFrameNumber = -1;
|
||||
while(true) {
|
||||
bool frameDone = _apu->Exec(_cpu->Exec());
|
||||
|
||||
if(frameDone) {
|
||||
_cpu->Exec();
|
||||
uint32_t currentFrameNumber = PPU::GetFrameCount();
|
||||
if(currentFrameNumber != lastFrameNumber) {
|
||||
lastFrameNumber = currentFrameNumber;
|
||||
_cpu->EndFrame();
|
||||
|
||||
if(CheckFlag(EmulationFlags::LimitFPS) && frameDone) {
|
||||
if(CheckFlag(EmulationFlags::LimitFPS)) {
|
||||
elapsedTime = clockTimer.GetElapsedMS();
|
||||
while(targetTime > elapsedTime) {
|
||||
if(targetTime - elapsedTime > 2) {
|
||||
|
Loading…
Reference in New Issue
Block a user