mirror of https://github.com/bsnes-emu/bsnes.git
77 lines
1.8 KiB
C++
77 lines
1.8 KiB
C++
auto CPU::DMA::run() -> bool {
|
|
if(cpu.stopped() || !active || waiting) return false;
|
|
|
|
transfer();
|
|
if(irq) cpu.irq.flag |= CPU::Interrupt::DMA0 << id;
|
|
if(drq && id == 3) cpu.irq.flag |= CPU::Interrupt::Cartridge;
|
|
return true;
|
|
}
|
|
|
|
auto CPU::DMA::transfer() -> void {
|
|
uint seek = size ? 4 : 2;
|
|
uint mode = size ? Word : Half;
|
|
mode |= latch.length == length ? Nonsequential : Sequential;
|
|
|
|
if(mode & Nonsequential) {
|
|
if((source & 0x0800'0000) && (target & 0x0800'0000)) {
|
|
//ROM -> ROM transfer
|
|
} else {
|
|
cpu.idle();
|
|
cpu.idle();
|
|
}
|
|
}
|
|
|
|
if(latch.source < 0x0200'0000) {
|
|
cpu.idle(); //cannot access BIOS
|
|
} else {
|
|
uint32 addr = latch.source;
|
|
if(mode & Word) addr &= ~3;
|
|
if(mode & Half) addr &= ~1;
|
|
data = cpu._read(mode, addr);
|
|
}
|
|
|
|
if(latch.target < 0x0200'0000) {
|
|
cpu.idle(); //cannot access BIOS
|
|
} else {
|
|
uint32 addr = latch.target;
|
|
if(mode & Word) addr &= ~3;
|
|
if(mode & Half) addr &= ~1;
|
|
cpu._write(mode, addr, data);
|
|
}
|
|
|
|
switch(sourceMode) {
|
|
case 0: latch.source += seek; break;
|
|
case 1: latch.source -= seek; break;
|
|
}
|
|
|
|
switch(targetMode) {
|
|
case 0: latch.target += seek; break;
|
|
case 1: latch.target -= seek; break;
|
|
case 3: latch.target += seek; break;
|
|
}
|
|
|
|
if(--latch.length == 0) {
|
|
active = false;
|
|
if(targetMode == 3) latch.target = target;
|
|
if(repeat == 1) latch.length = length;
|
|
if(repeat == 0) enable = false;
|
|
}
|
|
}
|
|
|
|
auto CPU::dmaVblank() -> void {
|
|
for(auto& dma : this->dma) {
|
|
if(dma.enable && dma.timingMode == 1) dma.active = true;
|
|
}
|
|
}
|
|
|
|
auto CPU::dmaHblank() -> void {
|
|
for(auto& dma : this->dma) {
|
|
if(dma.enable && dma.timingMode == 2) dma.active = true;
|
|
}
|
|
}
|
|
|
|
auto CPU::dmaHDMA() -> void {
|
|
auto& dma = this->dma[3];
|
|
if(dma.enable && dma.timingMode == 3) dma.active = true;
|
|
}
|