1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/// Abstraction of the device hosting the Z80 CPU
///
/// The device hosting the CPU has to provide implementations
/// of the memory and port access. A simple implementation is
/// provided with PlainMachine
pub trait Machine {
/// Returns the memory contents in [address]
fn peek(&self, address: u16) -> u8;
/// Sets the memory content to [value] in [address]
fn poke(&mut self, address: u16, value: u8);
/// Returns the memory contents in [address] as word
fn peek16(&self, address: u16) -> u16 {
self.peek(address) as u16
+ ((self.peek(address.wrapping_add(1)) as u16) << 8)
}
/// Sets the memory content to the word [value] in [address]
fn poke16(&mut self, address: u16, value: u16) {
self.poke(address, value as u8 );
self.poke(address.wrapping_add(1), (value >> 8) as u8);
}
/// Port in, from the device to the CPU. Returns the port value
/// in the hosting device.
fn port_in(&mut self, address: u16) -> u8;
/// Port out, from the CPU to the device. Sets a port value on
/// the hosting device.
fn port_out(&mut self, address: u16, value: u8);
}
/// A simple Machine implementation
///
/// A minimum implementation of Machine. It uses two arrays of 65536 bytes to back the peeks and
/// pokes to memory and the ins and outs of ports.
pub struct PlainMachine {
mem: [u8; 65536],
io: [u8; 65536]
}
impl PlainMachine {
/// Returns a new PlainMachine instance
pub fn new() -> PlainMachine {
PlainMachine {
mem: [0; 65536],
io: [0; 65536]
}
}
}
impl Default for PlainMachine {
fn default() -> Self {
Self::new()
}
}
impl Machine for PlainMachine {
fn peek(&self, address: u16) -> u8 {
self.mem[address as usize]
}
fn poke(&mut self, address: u16, value: u8) {
self.mem[address as usize] = value;
}
fn port_in(&mut self, address: u16) -> u8 {
self.io[address as usize]
}
fn port_out(&mut self, address: u16, value: u8) {
self.io[address as usize] = value;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn set_get_byte() {
let mut m = PlainMachine::new();
const A:u16 = 0x2345;
const V:u8 = 0xa0;
m.poke(A, V);
assert_eq!(V, m.peek(A));
}
}