APU: Fixed "catch up" bug that caused the frame counter's pacing to be incorrect

This commit is contained in:
Sour 2019-01-25 20:39:22 -05:00
parent d528e6110b
commit bf86f5458a
2 changed files with 9 additions and 35 deletions

View file

@ -178,12 +178,7 @@ bool APU::NeedToRun(uint32_t currentCycle)
}
uint32_t cyclesToRun = currentCycle - _previousCycle;
if(_frameCounter->IrqPending(cyclesToRun)) {
return true;
} else if(_deltaModulationChannel->IrqPending(cyclesToRun)) {
return true;
}
return false;
return _frameCounter->NeedToRun(cyclesToRun) || _deltaModulationChannel->IrqPending(cyclesToRun);
}
void APU::Exec()

View file

@ -23,7 +23,6 @@ private:
shared_ptr<Console> _console;
int32_t _stepCycles[2][6];
NesModel _nesModel;
int32_t _nextIrqCycle;
int32_t _previousCycle;
uint32_t _currentStep;
uint32_t _stepMode; //0: 4-step mode, 1: 5-step mode
@ -43,8 +42,6 @@ public:
{
_nesModel = NesModel::Auto;
_nextIrqCycle = 29828;
_previousCycle = 0;
//"After reset: APU mode in $4017 was unchanged", so we need to keep whatever value _stepMode has for soft resets
@ -67,7 +64,8 @@ public:
void StreamState(bool saving) override
{
Stream(_nextIrqCycle, _previousCycle, _currentStep, _stepMode, _inhibitIRQ, _nesModel, _blockFrameCounterTick, _writeDelayCounter, _newValue);
int32_t unusednextIrqCycle;
Stream(unusednextIrqCycle, _previousCycle, _currentStep, _stepMode, _inhibitIRQ, _nesModel, _blockFrameCounterTick, _writeDelayCounter, _newValue);
if(!saving) {
SetNesModel(_nesModel);
@ -103,7 +101,6 @@ public:
if(!_inhibitIRQ && _stepMode == 0 && _currentStep >= 3) {
//Set irq on the last 3 cycles for 4-step mode
_console->GetCpu()->SetIrqSource(IRQSource::FrameCounter);
_nextIrqCycle++;
}
FrameType type = _frameType[_stepMode][_currentStep];
@ -127,9 +124,6 @@ public:
if(_currentStep == 6) {
_currentStep = 0;
_previousCycle = 0;
if(_stepMode == 0 && !_inhibitIRQ) {
_nextIrqCycle = 29828;
}
} else {
_previousCycle += cyclesRan;
}
@ -145,12 +139,6 @@ public:
//Apply new value after the appropriate number of cycles has elapsed
_stepMode = ((_newValue & 0x80) == 0x80) ? 1 : 0;
if(!_inhibitIRQ && _stepMode == 0) {
_nextIrqCycle = 29828;
} else {
_nextIrqCycle = -1;
}
_writeDelayCounter = -1;
_currentStep = 0;
_previousCycle = 0;
@ -171,22 +159,13 @@ public:
return cyclesRan;
}
bool IrqPending(uint32_t cyclesToRun)
bool NeedToRun(uint32_t cyclesToRun)
{
if(_newValue >= 0 || _blockFrameCounterTick > 0) {
return true;
}
if(_previousCycle + (int32_t)cyclesToRun >= _stepCycles[_stepMode][_currentStep]) {
return true;
}
if(_nextIrqCycle != -1) {
if(_previousCycle + cyclesToRun >= (uint32_t)_nextIrqCycle) {
return true;
}
}
return false;
//Run APU when:
// -A new value is pending
// -The "blockFrameCounterTick" process is running
// -We're at the before-last or last tick of the current step
return _newValue >= 0 || _blockFrameCounterTick > 0 || (_previousCycle + (int32_t)cyclesToRun >= _stepCycles[_stepMode][_currentStep] - 1);
}
void GetMemoryRanges(MemoryRanges &ranges) override