Imported existing sources
This commit is contained in:
1 parent
b848581174
commit
619ec483e7
69 files changed
+7961
-36
No files matched your search
@@ -0,0 +1,199 @@
|
||||
#include "dma.h"
|
||||
|
||||
// Qt includes
|
||||
#include <QDataStream>
|
||||
|
||||
// local includes
|
||||
#include "nesemulator.h"
|
||||
|
||||
Dma::Dma(NesEmulator &emu) :
|
||||
m_emu(emu)
|
||||
{
|
||||
}
|
||||
|
||||
void Dma::hardReset()
|
||||
{
|
||||
m_dmcDmaWaitCycles = 0;
|
||||
m_oamDmaWaitCycles = 0;
|
||||
m_isOamDma = false;
|
||||
m_dmcOn = false;
|
||||
m_oamOn = false;
|
||||
m_dmcOccurring = false;
|
||||
m_oamOccurring = false;
|
||||
m_oamFinishCounter = 0;
|
||||
m_oamAddress = 0;
|
||||
m_oamCycle = 0;
|
||||
m_latch = 0;
|
||||
}
|
||||
|
||||
void Dma::softReset()
|
||||
{
|
||||
m_dmcDmaWaitCycles = 0;
|
||||
m_oamDmaWaitCycles = 0;
|
||||
m_isOamDma = false;
|
||||
m_dmcOn = false;
|
||||
m_oamOn = false;
|
||||
m_dmcOccurring = false;
|
||||
m_oamOccurring = false;
|
||||
m_oamFinishCounter = 0;
|
||||
m_oamAddress = 0;
|
||||
m_oamCycle = 0;
|
||||
m_latch = 0;
|
||||
}
|
||||
|
||||
void Dma::assertDmcDma()
|
||||
{
|
||||
if(m_oamOccurring)
|
||||
{
|
||||
if(m_oamCycle < 508)
|
||||
// OAM DMA is occurring here
|
||||
m_dmcDmaWaitCycles = m_emu.memory().busRw() ? 1 : 0;
|
||||
else
|
||||
{
|
||||
// Here the oam dma is about to finish
|
||||
// Remaining cycles of oam dma determines the dmc dma waiting cycles.
|
||||
m_dmcDmaWaitCycles = 4 - (512 - m_oamCycle);
|
||||
}
|
||||
}
|
||||
else if(m_dmcOccurring)
|
||||
{
|
||||
// DMC occurring now !!? is that possible ?
|
||||
// Anyway, let's ignore this call !
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing occurring, initialize brand new dma
|
||||
// DMC DMA depends on r/w flag forthe wait cycles.
|
||||
m_dmcDmaWaitCycles = m_emu.memory().busRw() ? 3 : 2;
|
||||
// After 2 cycles of oam dma, add extra cycle forthe waiting.
|
||||
if(m_oamFinishCounter == 3)
|
||||
m_dmcDmaWaitCycles++;
|
||||
}
|
||||
m_isOamDma = false;
|
||||
m_dmcOn = true;
|
||||
}
|
||||
|
||||
void Dma::assertOamDma()
|
||||
{
|
||||
if(m_oamOccurring)
|
||||
return;
|
||||
// Setup
|
||||
// OAM DMA depends on apu odd timer forodd cycles
|
||||
m_oamDmaWaitCycles = m_emu.apu().oddCycle() ? 1 : 2;
|
||||
m_isOamDma = true;
|
||||
m_oamOn = true;
|
||||
}
|
||||
|
||||
void Dma::clock()
|
||||
{
|
||||
if(m_oamFinishCounter > 0)
|
||||
m_oamFinishCounter--;
|
||||
|
||||
if(!m_emu.memory().busRw()) // Clocks only on reads
|
||||
{
|
||||
if(m_dmcDmaWaitCycles > 0)
|
||||
m_dmcDmaWaitCycles--;
|
||||
if(m_oamDmaWaitCycles > 0)
|
||||
m_oamDmaWaitCycles--;
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_dmcOn)
|
||||
{
|
||||
m_dmcOccurring = true;
|
||||
// This is it !
|
||||
m_dmcOn = false;
|
||||
// Do wait cycles (extra reads)
|
||||
if(m_dmcDmaWaitCycles > 0)
|
||||
{
|
||||
if(m_emu.memory().busAddress() == 0x4016 || m_emu.memory().busAddress() == 0x4017)
|
||||
{
|
||||
m_emu.memory().read(m_emu.memory().busAddress());
|
||||
m_dmcDmaWaitCycles--;
|
||||
|
||||
while(m_dmcDmaWaitCycles > 0)
|
||||
{
|
||||
m_emu.emuClockComponents();
|
||||
m_dmcDmaWaitCycles--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(m_dmcDmaWaitCycles > 0)
|
||||
{
|
||||
m_emu.memory().read(m_emu.memory().busAddress());
|
||||
m_dmcDmaWaitCycles--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do DMC DMA
|
||||
m_emu.apu().dmc().apuDmcDoDma();
|
||||
|
||||
m_dmcOccurring = false;
|
||||
}
|
||||
|
||||
if(m_oamOn)
|
||||
{
|
||||
m_oamOccurring = true;
|
||||
// This is it ! pause the cpu
|
||||
m_oamOn = false;
|
||||
// Do wait cycles (extra reads)
|
||||
if(m_oamDmaWaitCycles > 0)
|
||||
{
|
||||
if(m_emu.memory().busAddress() == 0x4016 || m_emu.memory().busAddress() == 0x4017)
|
||||
{
|
||||
m_emu.memory().read(m_emu.memory().busAddress());
|
||||
m_oamDmaWaitCycles--;
|
||||
|
||||
while(m_oamDmaWaitCycles > 0)
|
||||
{
|
||||
m_emu.emuClockComponents();
|
||||
m_oamDmaWaitCycles--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(m_oamDmaWaitCycles > 0)
|
||||
{
|
||||
m_emu.memory().read(m_emu.memory().busAddress());
|
||||
m_oamDmaWaitCycles--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do OAM DMA
|
||||
m_oamCycle = 0;
|
||||
for(auto i = 0; i < 256; i++)
|
||||
{
|
||||
m_latch = m_emu.memory().read(m_oamAddress);
|
||||
m_oamCycle++;
|
||||
m_emu.memory().write(0x2004, m_latch);
|
||||
m_oamCycle++;
|
||||
m_oamAddress++;
|
||||
m_oamAddress = m_oamAddress & 0xFFFF;
|
||||
}
|
||||
|
||||
m_oamCycle = 0;
|
||||
m_oamFinishCounter = 5;
|
||||
m_oamOccurring = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Dma::writeState(QDataStream &dataStream) const
|
||||
{
|
||||
dataStream << m_dmcDmaWaitCycles << m_oamDmaWaitCycles << m_isOamDma << m_dmcOn << m_oamOn << m_dmcOccurring
|
||||
<< m_oamOccurring << m_oamFinishCounter << m_oamAddress << m_oamCycle << m_latch;
|
||||
}
|
||||
|
||||
void Dma::readState(QDataStream &dataStream)
|
||||
{
|
||||
dataStream >> m_dmcDmaWaitCycles >> m_oamDmaWaitCycles >> m_isOamDma >> m_dmcOn >> m_oamOn >> m_dmcOccurring
|
||||
>> m_oamOccurring >> m_oamFinishCounter >> m_oamAddress >> m_oamCycle >> m_latch;
|
||||
}
|
||||
|
||||
void Dma::setOamAddress(quint16 oamAddress)
|
||||
{
|
||||
m_oamAddress = oamAddress;
|
||||
}
|
||||
Reference in new issue
Block a user