bsnes/higan/gba/cpu/dma.cpp
Tim Allen 0b6f1df987 Update to v103r27 release.
byuu says:

Changelog:

  - hiro/windows: set dpiAware=false, fixes icarus window sizes relative
    to higan window sizes
  - higan, icarus, hiro, ruby: add support for high resolution displays
    on macOS [ncbncb]
  - processor/lr35902-legacy: removed
  - processor/arm7tdmi: new processor core started; intended to one day
    be a replacement for processor/arm

It will probably take several WIPs to get the new ARM core up and
running. It's the last processor rewrite. After this, all processor
cores will be up to date with all my current programming conventions.
2017-08-06 23:36:26 +10:00

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.get(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.set(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;
}