CPU: Fixed pre/post-DMA timings when writing to $420B
i.e: read next opcode pre-DMA, finish that instruction post-DMA
This commit is contained in:
parent
a36a09df32
commit
66c3d0a3b1
3 changed files with 16 additions and 31 deletions
20
Core/Cpu.cpp
20
Core/Cpu.cpp
|
@ -74,17 +74,15 @@ void Cpu::Exec()
|
|||
|
||||
#ifndef DUMMYCPU
|
||||
//Use the state of the IRQ/NMI flags on the previous cycle to determine if an IRQ is processed or not
|
||||
if(!_dmaController->HasNmiIrqDelay()) {
|
||||
if(_state.PrevNmiFlag) {
|
||||
uint32_t originalPc = GetProgramAddress(_state.PC);
|
||||
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector, true);
|
||||
_console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), true);
|
||||
_state.NmiFlag = false;
|
||||
} else if(_state.PrevIrqSource) {
|
||||
uint32_t originalPc = GetProgramAddress(_state.PC);
|
||||
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector, true);
|
||||
_console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), false);
|
||||
}
|
||||
if(_state.PrevNmiFlag) {
|
||||
uint32_t originalPc = GetProgramAddress(_state.PC);
|
||||
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector, true);
|
||||
_console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), true);
|
||||
_state.NmiFlag = false;
|
||||
} else if(_state.PrevIrqSource) {
|
||||
uint32_t originalPc = GetProgramAddress(_state.PC);
|
||||
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector, true);
|
||||
_console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -25,18 +25,10 @@ DmaController::DmaController(MemoryManager *memoryManager)
|
|||
|
||||
void DmaController::Reset()
|
||||
{
|
||||
_dmaStartDelay = false;
|
||||
_hdmaChannels = 0;
|
||||
}
|
||||
|
||||
bool DmaController::HasNmiIrqDelay()
|
||||
{
|
||||
if(_nmiIrqDelayCounter > 0) {
|
||||
_nmiIrqDelayCounter--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DmaController::CopyDmaByte(uint32_t addressBusA, uint16_t addressBusB, bool fromBtoA)
|
||||
{
|
||||
if(fromBtoA) {
|
||||
|
@ -280,9 +272,6 @@ void DmaController::ProcessHdmaChannels(bool applyOverhead)
|
|||
//If we ran a HDMA transfer, sync
|
||||
SyncEndDma();
|
||||
}
|
||||
|
||||
//When DMA runs, the next instruction will not check the NMI/IRQ flags, which allows 2 instructions to run after DMA
|
||||
_nmiIrqDelayCounter = 2;
|
||||
}
|
||||
|
||||
void DmaController::BeginHdmaTransfer()
|
||||
|
@ -304,7 +293,8 @@ void DmaController::BeginHdmaInit()
|
|||
|
||||
void DmaController::ProcessPendingTransfers()
|
||||
{
|
||||
if(_inDma) {
|
||||
if(_inDma || _dmaStartDelay) {
|
||||
_dmaStartDelay = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -344,9 +334,6 @@ void DmaController::ProcessPendingTransfers()
|
|||
|
||||
SyncEndDma();
|
||||
|
||||
//When DMA runs, the next instruction will not check the NMI/IRQ flags, which allows 2 instructions to run after DMA
|
||||
_nmiIrqDelayCounter = 2;
|
||||
|
||||
_requestedDmaChannels = 0;
|
||||
|
||||
_inDma = false;
|
||||
|
@ -359,6 +346,7 @@ void DmaController::Write(uint16_t addr, uint8_t value)
|
|||
case 0x420B: {
|
||||
//MDMAEN - DMA Enable
|
||||
_requestedDmaChannels = value;
|
||||
_dmaStartDelay = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -558,7 +546,8 @@ DmaChannelConfig DmaController::GetChannelConfig(uint8_t channel)
|
|||
|
||||
void DmaController::Serialize(Serializer &s)
|
||||
{
|
||||
s.Stream(_hdmaPending, _hdmaChannels, _nmiIrqDelayCounter, _requestedDmaChannels, _inDma, _dmaStartClock, _hdmaInitPending);
|
||||
uint8_t unused_nmiIrqDelayCounter = 0;
|
||||
s.Stream(_hdmaPending, _hdmaChannels, unused_nmiIrqDelayCounter, _requestedDmaChannels, _inDma, _dmaStartClock, _hdmaInitPending, _dmaStartDelay);
|
||||
for(int i = 0; i < 8; i++) {
|
||||
s.Stream(
|
||||
_channel[i].Decrement, _channel[i].DestAddress, _channel[i].DoTransfer, _channel[i].FixedTransfer,
|
||||
|
|
|
@ -35,8 +35,8 @@ private:
|
|||
bool _hdmaPending = false;
|
||||
bool _hdmaInitPending = false;
|
||||
bool _inDma = false;
|
||||
bool _dmaStartDelay = false;
|
||||
uint8_t _hdmaChannels = 0;
|
||||
uint8_t _nmiIrqDelayCounter = 0;
|
||||
uint8_t _requestedDmaChannels = 0;
|
||||
uint64_t _dmaStartClock = 0;
|
||||
|
||||
|
@ -62,8 +62,6 @@ public:
|
|||
|
||||
void Reset();
|
||||
|
||||
bool HasNmiIrqDelay();
|
||||
|
||||
void BeginHdmaTransfer();
|
||||
void BeginHdmaInit();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue