Overclocking: Changed APU behavior when adding extra lines before/after NMI (helps reduce overclocking-related issues)

This commit is contained in:
Souryo 2017-04-29 21:39:57 -04:00
parent aab1c25a2b
commit cf8c98f384
8 changed files with 71 additions and 24 deletions

View file

@ -11,6 +11,7 @@
#include "MemoryManager.h"
APU* APU::Instance = nullptr;
bool APU::_apuEnabled = true;
APU::APU(MemoryManager* memoryManager)
{
@ -20,6 +21,8 @@ APU::APU(MemoryManager* memoryManager)
_nesModel = NesModel::Auto;
_apuEnabled = true;
_mixer.reset(new SoundMixer());
_squareChannel[0].reset(new SquareChannel(AudioChannel::Square1, _mixer.get(), true));
@ -202,6 +205,7 @@ void APU::EndFrame()
void APU::Reset(bool softReset)
{
_apuEnabled = true;
_cyclesNeeded = 0;
_currentCycle = 0;
_previousCycle = 0;
@ -236,4 +240,18 @@ void APU::StreamState(bool saving)
void APU::AddExpansionAudioDelta(AudioChannel channel, int16_t delta)
{
Instance->_mixer->AddDelta(channel, Instance->_currentCycle, delta);
}
void APU::SetApuStatus(bool enabled)
{
_apuEnabled = enabled;
}
bool APU::IsApuEnabled()
{
//Adding extra lines before/after NMI temporarely turns off the APU
//This appears to result in less side-effects than spreading out the APU's
//load over the entire PPU frame, like what was done before.
//This is most likely due to the timing of the Frame Counter & DMC IRQs.
return _apuEnabled;
}

View file

@ -20,6 +20,7 @@ class APU : public Snapshotable, public IMemoryHandler
{
private:
static APU* Instance;
static bool _apuEnabled;
uint32_t _previousCycle;
uint32_t _currentCycle;
@ -65,13 +66,15 @@ class APU : public Snapshotable, public IMemoryHandler
__forceinline static void ExecStatic()
{
if(EmulationSettings::GetOverclockRate(true) == 100) {
Instance->Exec();
} else {
Instance->_cyclesNeeded += 1.0 / ((double)EmulationSettings::GetOverclockRate(true) / 100.0);
while(Instance->_cyclesNeeded >= 1.0) {
if(APU::_apuEnabled) {
if(EmulationSettings::GetOverclockRate() == 100 || !EmulationSettings::GetOverclockAdjustApu()) {
Instance->Exec();
Instance->_cyclesNeeded--;
} else {
Instance->_cyclesNeeded += 1.0 / ((double)EmulationSettings::GetOverclockRate() / 100.0);
while(Instance->_cyclesNeeded >= 1.0) {
Instance->Exec();
Instance->_cyclesNeeded--;
}
}
}
}
@ -79,4 +82,6 @@ class APU : public Snapshotable, public IMemoryHandler
static void StaticRun();
static void AddExpansionAudioDelta(AudioChannel channel, int16_t delta);
static void SetApuStatus(bool enabled);
static bool IsApuEnabled();
};

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include "Snapshotable.h"
#include "EmulationSettings.h"
#include "APU.h"
class BaseExpansionAudio : public Snapshotable
{
@ -19,13 +20,15 @@ protected:
public:
void Clock()
{
if(EmulationSettings::GetOverclockRate(true) == 100) {
ClockAudio();
} else {
_clocksNeeded += 1.0 / ((double)EmulationSettings::GetOverclockRate(true) / 100);
while(_clocksNeeded >= 1.0) {
if(APU::IsApuEnabled()) {
if(EmulationSettings::GetOverclockRate() == 100 || !EmulationSettings::GetOverclockAdjustApu()) {
ClockAudio();
_clocksNeeded--;
} else {
_clocksNeeded += 1.0 / ((double)EmulationSettings::GetOverclockRate() / 100);
while(_clocksNeeded >= 1.0) {
ClockAudio();
_clocksNeeded--;
}
}
}
}

View file

@ -43,7 +43,6 @@ uint32_t EmulationSettings::_extraScanlinesBeforeNmi = 0;
uint32_t EmulationSettings::_extraScanlinesAfterNmi = 0;
uint32_t EmulationSettings::_ppuScanlineCount = 262;
double EmulationSettings::_effectiveOverclockRate = 100;
double EmulationSettings::_effectiveOverclockRateSound = 100;
bool EmulationSettings::_overclockAdjustApu = true;
bool EmulationSettings::_disableOverclocking = false;

View file

@ -677,13 +677,12 @@ public:
static void UpdateEffectiveOverclockRate()
{
if(_disableOverclocking) {
_effectiveOverclockRateSound = 100;
_effectiveOverclockRate = 100;
} else {
_effectiveOverclockRateSound = _overclockRate * (double)(1 + (double)(_extraScanlinesBeforeNmi + _extraScanlinesAfterNmi) / _ppuScanlineCount);
_effectiveOverclockRate = _overclockRate;
}
_hasOverclock = _effectiveOverclockRate != 100;
_audioSettingsChanged = true;
}
static void SetPpuScanlineCount(uint32_t scanlineCount)
@ -708,15 +707,9 @@ public:
return _hasOverclock;
}
static double GetOverclockRate(bool forApu = false, bool forSoundMixer = false)
static double GetOverclockRate()
{
if(forApu && _overclockAdjustApu || forSoundMixer) {
return _effectiveOverclockRateSound;
} else if(!forApu) {
return _effectiveOverclockRate;
} else {
return 100;
}
return _effectiveOverclockRate;
}
static bool GetOverclockAdjustApu()

View file

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "PPU.h"
#include "CPU.h"
#include "APU.h"
#include "EmulationSettings.h"
#include "VideoDecoder.h"
#include "Debugger.h"
@ -109,16 +110,22 @@ void PPU::SetNesModel(NesModel model)
case NesModel::NTSC:
_nmiScanline = 241;
_vblankEnd = 260;
_standardNmiScanline = 241;
_standardVblankEnd = 260;
EmulationSettings::SetPpuScanlineCount(262);
break;
case NesModel::PAL:
_nmiScanline = 241;
_vblankEnd = 310;
_standardNmiScanline = 241;
_standardVblankEnd = 310;
EmulationSettings::SetPpuScanlineCount(312);
break;
case NesModel::Dendy:
_nmiScanline = 291;
_vblankEnd = 310;
_standardNmiScanline = 291;
_standardVblankEnd = 310;
EmulationSettings::SetPpuScanlineCount(312);
break;
}
@ -1000,6 +1007,20 @@ void PPU::TriggerNmi()
}
}
void PPU::UpdateApuStatus()
{
APU::SetApuStatus(true);
if(_scanline > 240) {
if(_scanline > _standardVblankEnd) {
//Disable APU for extra lines after NMI
APU::SetApuStatus(false);
} else if(_scanline < _standardNmiScanline) {
//Disable APU for extra lines before NMI
APU::SetApuStatus(false);
}
}
}
void PPU::Exec()
{
if(_cycle > 339) {
@ -1011,6 +1032,8 @@ void PPU::Exec()
}
Debugger::ProcessPpuCycle();
UpdateApuStatus();
//Cycle = 0
if(_scanline == -1) {
@ -1137,5 +1160,7 @@ void PPU::StreamState(bool saving)
}
_lastUpdatedPixel = -1;
UpdateApuStatus();
}
}

View file

@ -48,6 +48,8 @@ class PPU : public IMemoryHandler, public Snapshotable
uint16_t *_outputBuffers[2];
NesModel _nesModel;
uint16_t _standardVblankEnd;
uint16_t _standardNmiScanline;
uint16_t _vblankEnd;
uint16_t _nmiScanline;
@ -137,6 +139,8 @@ class PPU : public IMemoryHandler, public Snapshotable
void UpdateGrayscaleAndIntensifyBits();
virtual void SendFrame();
void UpdateApuStatus();
PPURegisters GetRegisterID(uint16_t addr)
{
if(addr == 0x4014) {

View file

@ -166,7 +166,7 @@ void SoundMixer::UpdateRates(bool forceUpdate)
{
uint32_t newRate = CPU::GetClockRate(_model);
if(!EmulationSettings::GetOverclockAdjustApu()) {
newRate = (uint32_t)(newRate * (double)EmulationSettings::GetOverclockRate(false, true) / 100);
newRate = (uint32_t)(newRate * (double)EmulationSettings::GetOverclockRate() / 100);
}
if(_clockRate != newRate || forceUpdate) {