98 lines
2.3 KiB
Rust
98 lines
2.3 KiB
Rust
use crate::Cycle;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub(crate) struct DirectMemoryAccess {
|
|
pub(crate) state: DmaState,
|
|
cycle: Cycle,
|
|
/// 0xFF46 | DMA - Transfer and Start Address
|
|
pub(crate) start: DmaAddress,
|
|
}
|
|
|
|
impl DirectMemoryAccess {
|
|
pub(crate) fn tick(&mut self) -> Option<(u16, u16)> {
|
|
match self.state {
|
|
DmaState::Pending => {
|
|
self.cycle += 1;
|
|
|
|
// Four Cycles pass before we actually start transferring
|
|
// files
|
|
|
|
if self.cycle == 4 {
|
|
self.state = DmaState::Transferring;
|
|
}
|
|
|
|
None
|
|
}
|
|
DmaState::Transferring => {
|
|
self.cycle += 1;
|
|
|
|
let src_addr = self
|
|
.start
|
|
.0
|
|
.as_mut()
|
|
.expect("Source Address present during DMA Transfer");
|
|
|
|
let addresses = if (self.cycle - 4) % 4 == 0 {
|
|
*src_addr += 1;
|
|
Some((*src_addr, 0xFE00 | (*src_addr & 0x00FF)))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
if self.cycle == 644 {
|
|
self.reset();
|
|
|
|
return None;
|
|
}
|
|
|
|
addresses
|
|
}
|
|
DmaState::Disabled => None,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn is_active(&self) -> bool {
|
|
self.state == DmaState::Transferring
|
|
}
|
|
|
|
fn reset(&mut self) {
|
|
self.cycle = 0;
|
|
self.state = DmaState::Disabled;
|
|
self.start.0 = None;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
pub(crate) enum DmaState {
|
|
Disabled,
|
|
Pending,
|
|
Transferring,
|
|
}
|
|
|
|
impl Default for DmaState {
|
|
fn default() -> Self {
|
|
Self::Disabled
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
pub(crate) struct DmaAddress(Option<u16>);
|
|
|
|
impl DmaAddress {
|
|
pub(crate) fn update(&mut self, byte: u8, state: &mut DmaState) {
|
|
let start = (byte as u16) << 8;
|
|
|
|
self.0 = Some(start);
|
|
*state = DmaState::Pending;
|
|
}
|
|
}
|
|
|
|
impl From<DmaAddress> for u8 {
|
|
fn from(ctrl: DmaAddress) -> Self {
|
|
match ctrl.0 {
|
|
Some(addr) => (addr >> 8) as u8,
|
|
None => 0xFF, // TODO: What garbage value should be here?
|
|
}
|
|
}
|
|
}
|