bsnes/higan/md/vdp/dma.cpp

52 lines
1.2 KiB
C++

auto VDP::DMA::run() -> void {
if(!io.enable || io.wait) return;
if(!vdp.io.command.bit(5)) return;
if(io.mode <= 1) return load();
if(io.mode == 2) return fill();
if(!vdp.io.command.bit(4)) return;
if(io.mode == 3) return copy();
}
auto VDP::DMA::load() -> void {
cpu.wait |= Wait::VDP_DMA;
auto data = cpu.readWord(io.mode.bit(0) << 23 | io.source << 1);
vdp.writeDataPort(data);
io.source.bits(0,15)++;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
cpu.wait &=~ Wait::VDP_DMA;
}
}
//todo: supposedly, this can also write to VSRAM and CRAM (undocumented)
auto VDP::DMA::fill() -> void {
if(vdp.io.command.bits(0,3) == 1) {
vdp.vram.writeByte(vdp.io.address, io.fill);
}
io.source.bits(0,15)++;
vdp.io.address += vdp.io.dataIncrement;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
}
}
//note: this can only copy to VRAM
auto VDP::DMA::copy() -> void {
auto data = vdp.vram.readByte(io.source);
vdp.vram.writeByte(vdp.io.address, data);
io.source.bits(0,15)++;
vdp.io.address += vdp.io.dataIncrement;
if(--io.length == 0) {
vdp.io.command.bit(5) = 0;
}
}
auto VDP::DMA::power() -> void {
memory::fill(&io, sizeof(IO));
}