Skip to main content

DmaBus

Trait DmaBus 

Source
pub trait DmaBus {
    // Required methods
    fn read_a(&mut self, addr: u32) -> u8;
    fn write_a(&mut self, addr: u32, val: u8);
    fn read_b(&mut self, addr: u8) -> u8;
    fn write_b(&mut self, addr: u8, val: u8);

    // Provided methods
    fn step(&mut self, _clocks: u32) { ... }
    fn scanline(&self) -> u16 { ... }
    fn visible_height(&self) -> u16 { ... }
    fn hdma_last_line(&self) -> u16 { ... }
    fn set_hdma_last_line(&mut self, _line: u16) { ... }
}
Expand description

Read/write split across the SNES A-bus (24-bit) and B-bus ($21xx) for the DMA controller.

Required Methods§

Source

fn read_a(&mut self, addr: u32) -> u8

Read a byte from the A-bus (24-bit CPU address). Invalid A-bus regions return open bus.

Source

fn write_a(&mut self, addr: u32, val: u8)

Write a byte to the A-bus (24-bit CPU address). Invalid regions are dropped.

Source

fn read_b(&mut self, addr: u8) -> u8

Read a byte from the B-bus register $2100 | addr.

Source

fn write_b(&mut self, addr: u8, val: u8)

Write a byte to the B-bus register $2100 | addr.

Provided Methods§

Source

fn step(&mut self, _clocks: u32)

Advance the master clock by clocks during a transfer, so time-dependent state that gates the transfer — chiefly the PPU scanline that decides VRAM/CGRAM/OAM accessibility ($2118/$2119 land only in force-blank or V-blank) — tracks the transfer in lockstep, exactly as the real bus keeps scanning while a DMA runs (ares Channel::stepcpu.step). A big GP-DMA that starts late in active display and crosses into V-blank must have its V-blank portion actually reach VRAM; freezing the scanline for the whole burst would drop every write (the Star Fox framebuffer-transfer bug). Default no-op so the controller stays unit-testable against an isolated bus with no clock.

Source

fn scanline(&self) -> u16

The PPU scanline the bus is currently scanning. On real hardware HDMA preempts a running GP-DMA at the start of every scanline; a long GP-DMA that spans scanline boundaries must therefore let those HDMA transfers interleave (Star Fox force-blanks its framebuffer DMA via an HDMA-driven $2100 write on the very lines the DMA is filling). crate::dma::Dma drives that interleave itself from inside run_gp because the bus’s own per-tick HDMA path is dormant while the bus has lent out its controller. Default u16::MAX so a clockless unit-test bus never trips the interleave.

Source

fn visible_height(&self) -> u16

The last visible scanline HDMA services this frame (visible_height), so the in-GP-DMA interleave knows the visible-line window. Default 0 (unit-test buses run no HDMA).

Source

fn hdma_last_line(&self) -> u16

The scanline the bus last serviced HDMA for, so the in-GP-DMA interleave resumes from the bus’s own bookkeeping and hands it back afterwards (no line runs twice, none is skipped). Default u16::MAX.

Source

fn set_hdma_last_line(&mut self, _line: u16)

Record that HDMA has now been serviced for line, syncing the bus’s bookkeeping with the interleave driven from inside run_gp. Default no-op.

Implementors§

Source§

impl DmaBus for Bus

The DMA controller’s view: A-bus (24-bit) via the decode, B-bus via b_read/b_write.