dcpu 0.5.0

An assembler, debugger and emulator for the DCPU-16
Documentation
use std::any::Any;

use enum_primitive::FromPrimitive;

use emulator::Cpu;
use emulator::device::*;
use types::Register;

const ONE_MS: u16 = 100;
const MEMORY_SIZE: usize = 16;
const DEFAULT_MEM_VALUE: [u16; MEMORY_SIZE] = [0xffff; MEMORY_SIZE];
const INT_VALUE: u16 = 0xfff0;

enum_from_primitive! {
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)]
enum Command {
    GET = 1,
    SET = 2,
    RESET = 3,
}
}

#[derive(Debug)]
pub struct Eeprom<D: Device> {
    mem: [u16; MEMORY_SIZE],
    inner: D,
}

impl<D: Device> Eeprom<D> {
    pub fn new(inner: D) -> Eeprom<D> {
        Eeprom {
            mem: DEFAULT_MEM_VALUE,
            inner: inner,
        }
    }
}

impl<D: Device> Device for Eeprom<D> {
    fn hardware_id(&self) -> u32 {
        self.inner.hardware_id()
    }

    fn hardware_version(&self) -> u16 {
        self.inner.hardware_version()
    }

    fn manufacturer(&self) -> u32 {
        self.inner.manufacturer()
    }

    fn interrupt(&mut self, cpu: &mut Cpu) -> Result<InterruptDelay> {
        let a = cpu.registers[Register::A];
        if a == INT_VALUE {
            let b = cpu.registers[Register::B];
            let x = cpu.registers[Register::X] as usize;

            match Command::from_u16(b) {
                Some(Command::GET) => {
                    match self.mem.get(x) {
                        Some(word) => cpu.registers[Register::Y] = *word,
                        None => unimplemented!(),
                    }
                    Ok(ONE_MS)
                }
                Some(Command::SET) => {
                    match self.mem.get_mut(x) {
                        Some(word) => *word &= cpu.registers[Register::Y],
                        None => unimplemented!(),
                    }
                    Ok(5 * ONE_MS)
                }
                Some(Command::RESET) => {
                    self.mem = DEFAULT_MEM_VALUE;
                    Ok(10 * ONE_MS)
                }
                None => unimplemented!(),
            }
        } else {
            self.inner.interrupt(cpu)
        }
    }

    fn tick(&mut self, cpu: &mut Cpu, current_tick: u64) -> Result<TickResult> {
        self.inner.tick(cpu, current_tick)
    }

    fn inspect(&self) {
        self.inner.inspect();
        println!("Eeprom: {:?}", self.mem);
    }

    fn as_any(&mut self) -> &mut Any {
        &mut self.inner
    }
}