chipmunk-backend 1.0.0

Shared, platform agnostic, backend for the chipmunk emulator
Documentation
#![allow(clippy::upper_case_acronyms)]

use crate::{error::EmulatorError, registers::Reg, utils::stretch_u16};
#[derive(Debug)]
pub enum OpCode {
    _00E0,
    _00EE,
    _1NNN(u16),
    _2NNN(u16),
    _3XNN { reg: Reg, value: u8 },
    _4XNN { reg: Reg, value: u8 },
    _5XY0 { x: Reg, y: Reg },
    _6XNN { reg: Reg, value: u8 },
    _7XNN { reg: Reg, value: u8 },
    _8XY0 { x: Reg, y: Reg },
    _8XY1 { x: Reg, y: Reg },
    _8XY2 { x: Reg, y: Reg },
    _8XY3 { x: Reg, y: Reg },
    _8XY4 { x: Reg, y: Reg },
    _8XY5 { x: Reg, y: Reg },
    _8XY6 { x: Reg, y: Reg },
    _8XY7 { x: Reg, y: Reg },
    _8XYE { x: Reg, y: Reg },
    _9XY0 { x: Reg, y: Reg },
    ANNN(u16),
    BNNN(u16),
    CXNN { reg: Reg, value: u8 },
    DXYN { x: Reg, y: Reg, height: u8 },
    EX9E(Reg),
    EXA1(Reg),
    FX07(Reg),
    FX0A(Reg),
    FX15(Reg),
    FX18(Reg),
    FX1E(Reg),
    FX29(Reg),
    FX33(Reg),
    FX55(Reg),
    FX65(Reg),
}

impl TryInto<OpCode> for u16 {
    type Error = EmulatorError;
    fn try_into(self) -> Result<OpCode, Self::Error> {
        let parts = stretch_u16(self);

        println!("raw code = {:?}", parts);
        match parts {
            [0x0, 0x0, 0xe, 0x0] => Ok(OpCode::_00E0),
            [0x0, 0x0, 0xe, 0xe] => Ok(OpCode::_00EE),
            [0x1, n1, n2, n3] => {
                let nnn = ((n1 as u16) << 8) | ((n2 as u16) << 4) | n3 as u16;

                Ok(OpCode::_1NNN(nnn))
            }
            [0x2, n1, n2, n3] => {
                let nnn = ((n1 as u16) << 8) | ((n2 as u16) << 4) | n3 as u16;

                Ok(OpCode::_2NNN(nnn))
            }
            [0x3, x, n1, n2] => {
                let value = (n1 << 4) | n2;
                let reg = x.into();

                Ok(OpCode::_3XNN { reg, value })
            }
            [0x4, x, n1, n2] => {
                let value = (n1 << 4) | n2;
                let reg = x.into();

                Ok(OpCode::_4XNN { reg, value })
            }
            [0x5, x, y, 0x0] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_5XY0 { x, y })
            }
            [0x6, x, n1, n2] => {
                let value = (n1 << 4) | n2;
                let reg = x.into();

                Ok(OpCode::_6XNN { reg, value })
            }
            [0x7, x, n1, n2] => {
                let value = (n1 << 4) | n2;
                let reg = x.into();

                Ok(OpCode::_7XNN { reg, value })
            }
            [0x8, x, y, 0x0] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY0 { x, y })
            }
            [0x8, x, y, 0x1] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY1 { x, y })
            }
            [0x8, x, y, 0x2] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY2 { x, y })
            }
            [0x8, x, y, 0x3] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY3 { x, y })
            }
            [0x8, x, y, 0x4] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY4 { x, y })
            }
            [0x8, x, y, 0x5] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY5 { x, y })
            }
            [0x8, x, y, 0x6] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY6 { x, y })
            }
            [0x8, x,  y, 0x7] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XY7 { x, y })
            }
            [0x8, x, y, 0xe] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_8XYE { x, y })
            }
            [0x9, x, y, 0] => {
                let x = x.into();
                let y = y.into();

                Ok(OpCode::_9XY0 { x, y })
            }
            [0xa, n1, n2, n3] => {
                let nnn = ((n1 as u16) << 8) | ((n2 as u16) << 4) | n3 as u16;

                Ok(OpCode::ANNN(nnn))
            }
            [0xb, n1, n2, n3] => {
                let nnn = ((n1 as u16) << 8) | ((n2 as u16) << 4) | n3 as u16;

                Ok(OpCode::BNNN(nnn))
            }
            [0xe, x, 0x9, 0xe] => {
                let reg = x.into();

                Ok(OpCode::EX9E(reg))
            }
            [0xe, x, 0xa, 0x1] => {
                let reg = x.into();

                Ok(OpCode::EXA1(reg))
            }
            [0xc, x, n1, n2] => {
                let value = (n1 << 4) | n2;
                let reg = x.into();

                Ok(OpCode::CXNN { reg, value })
            }
            [0xd, x, y, n] => {
                let x = x.into();
                let y = y.into();
                let height = n;

                Ok(OpCode::DXYN { x, y, height })
            }
            [0xf, x, 0x0, 0x7] => {
                let reg = x.into();

                Ok(OpCode::FX07(reg))
            }
            [0xf, x, 0x0, 0xa] => {
                let dest = x.into();

                Ok(OpCode::FX0A(dest))
            }
            [0xf, x, 0x1, 0x5] => {
                let reg = x.into();
                Ok(OpCode::FX15(reg))
            }
            [0xf, x, 0x1, 0x8] => {
                let reg = x.into();

                Ok(OpCode::FX18(reg))
            }
            [0xf, x, 0x1, 0xe] => {
                let reg = x.into();

                Ok(OpCode::FX1E(reg))
            }
            [0xf, x, 0x2, 0x9] => {
                let reg = x.into();
                Ok(OpCode::FX29(reg))
            }
            [0xf, x, 0x3, 0x3] => {
                let reg = x.into();
                Ok(OpCode::FX33(reg))
            }
            [0xf, x, 0x5, 0x5] => {
                let reg = x.into();
                Ok(OpCode::FX55(reg))
            }
            [0xf, x, 0x6, 0x5] => {
                let reg = x.into();
                Ok(OpCode::FX65(reg))
            }
            _ => Err(EmulatorError::UnknownOpCode(format!("{:x}", self))),
        }
    }
}