use crate::{Dei, Deo, DeviceHandler, Devices, Jmp, Pc, Peek, Poke, Uxn}; use std::fmt::{self, Debug}; use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Shl, Shr, Sub}; pub(crate) trait Value: Debug + Eq + Ord + Add + Add + Sub + Mul + Div + BitAnd + BitOr + BitXor + Shl + Shr + Size + IsZero + Peek + Poke + Dei + Deo + Jmp + Copy + Sized { } pub trait Size { fn size() -> u16; } pub trait IsZero { fn is_zero(&self) -> bool; } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Byte(u8); impl Debug for Byte { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:02x}", self.0) } } impl From for Byte { fn from(value: u8) -> Self { Self(value) } } impl From for Byte { fn from(value: bool) -> Self { Self(value as u8) } } impl From for u8 { fn from(value: Byte) -> Self { value.0 } } impl From for bool { fn from(value: Byte) -> Self { value.0 != 0 } } impl From for u16 { fn from(value: Byte) -> Self { value.0 as u16 } } impl PartialEq for Byte { fn eq(&self, other: &u8) -> bool { self.0.eq(other) } } impl Add for Byte { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_add(rhs.0)) } } impl Add for Byte { type Output = Self; fn add(self, rhs: usize) -> Self::Output { Self(self.0.wrapping_add(rhs as u8)) } } impl Sub for Byte { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_sub(rhs.0)) } } impl Mul for Byte { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_mul(rhs.0)) } } impl Div for Byte { type Output = Self; fn div(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_div(rhs.0)) } } impl BitAnd for Byte { type Output = Self; fn bitand(self, rhs: Self) -> Self::Output { Self(self.0.bitand(rhs.0)) } } impl BitOr for Byte { type Output = Self; fn bitor(self, rhs: Self) -> Self::Output { Self(self.0.bitor(rhs.0)) } } impl BitXor for Byte { type Output = Self; fn bitxor(self, rhs: Self) -> Self::Output { Self(self.0.bitxor(rhs.0)) } } impl Shl for Byte { type Output = Self; fn shl(self, rhs: u8) -> Self::Output { // Self(self.0.shl(rhs)) Self((self.0 as u32).wrapping_shl(rhs as u32) as u8) } } impl Shr for Byte { type Output = Self; fn shr(self, rhs: u8) -> Self::Output { // Self(self.0.shr(rhs)) Self((self.0 as u32).wrapping_shr(rhs as u32) as u8) } } impl Size for Byte { fn size() -> u16 { 1 } } impl IsZero for Byte { fn is_zero(&self) -> bool { self.0 == 0 } } impl Peek for Byte { type Ram = [u8; 65536]; fn peek(ram: &Self::Ram, addr: Short) -> Self { ram[u16::from(addr) as usize].into() } } impl Poke for Byte { type Ram = [u8; 65536]; fn poke(self, ram: &mut Self::Ram, addr: Short) { ram[u16::from(addr) as usize] = self.into(); } } impl Dei for Byte { fn dei(dev: &mut Devices, uxn: &mut Uxn, addr: Byte) -> Self { dev.get(uxn, addr.into()).into() } } impl Deo for Byte { fn deo(self, dev: &mut Devices, uxn: &mut Uxn, addr: Byte) { dev.set(uxn, addr.into(), self.into()) } } impl Jmp for Byte { type Pc = u16; fn jmp(self, pc: &mut Self::Pc) { pc.advance_by(self.0 as i8 as i16 as u16) } } impl Value for Byte {} #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Short(u16); impl Debug for Short { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:04x}", self.0) } } impl From for Short { fn from(value: u16) -> Self { Self(value) } } impl From for u16 { fn from(value: Short) -> Self { value.0 } } impl From for Short { fn from(value: Byte) -> Self { Self(value.0 as u16) } } impl PartialEq for Short { fn eq(&self, other: &u16) -> bool { self.0.eq(other) } } impl Add for Short { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_add(rhs.0)) } } impl Add for Short { type Output = Self; fn add(self, rhs: usize) -> Self::Output { Self(self.0.wrapping_add(rhs as u16)) } } impl Sub for Short { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_sub(rhs.0)) } } impl Mul for Short { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_mul(rhs.0)) } } impl Div for Short { type Output = Self; fn div(self, rhs: Self) -> Self::Output { Self(self.0.wrapping_div(rhs.0)) } } impl BitAnd for Short { type Output = Self; fn bitand(self, rhs: Self) -> Self::Output { Self(self.0.bitand(rhs.0)) } } impl BitOr for Short { type Output = Self; fn bitor(self, rhs: Self) -> Self::Output { Self(self.0.bitor(rhs.0)) } } impl BitXor for Short { type Output = Self; fn bitxor(self, rhs: Self) -> Self::Output { Self(self.0.bitxor(rhs.0)) } } impl Shl for Short { type Output = Self; fn shl(self, rhs: u8) -> Self::Output { Self((self.0 as u32).wrapping_shl(rhs as u32) as u16) } } impl Shr for Short { type Output = Self; fn shr(self, rhs: u8) -> Self::Output { Self((self.0 as u32).wrapping_shr(rhs as u32) as u16) } } impl Size for Short { fn size() -> u16 { 2 } } impl IsZero for Short { fn is_zero(&self) -> bool { self.0 == 0 } } impl Peek for Short { type Ram = [u8; 65536]; fn peek(ram: &Self::Ram, addr: Short) -> Self { let msb = ram[u16::from(addr) as usize] as u16; let lsb = ram[u16::from(addr) as usize + 1] as u16; // Shouldn't ever wrap because last index of RAM is u16::MAX + 1. ((msb << 8) | lsb).into() } } impl Poke for Short { type Ram = [u8; 65536]; fn poke(self, ram: &mut Self::Ram, addr: Short) { ram[u16::from(addr) as usize] = (self.0 >> 8) as u8; ram[u16::from(addr) as usize + 1] = self.0 as u8; // Shouldn't ever wrap because last index of RAM is u16::MAX + 1. } } impl Dei for Short { fn dei(dev: &mut Devices, uxn: &mut Uxn, addr: Byte) -> Self { let msb = dev.get(uxn, u8::from(addr)) as u16; let lsb = dev.get(uxn, u8::from(addr + 1)) as u16; // FIXME: What should really happen when this wraps? ((msb << 8) | lsb).into() } } impl Deo for Short { fn deo(self, dev: &mut Devices, uxn: &mut Uxn, addr: Byte) { dev.set(uxn, u8::from(addr), (self.0 >> 8) as u8); dev.set(uxn, u8::from(addr + 1), self.0 as u8); // FIXME: What should really happen when this wraps? } } impl Jmp for Short { type Pc = u16; fn jmp(self, pc: &mut Self::Pc) { *pc = self.0; } } impl Value for Short {} impl Short { pub fn offset(self, offs: Byte) -> Self { Self(self.0.wrapping_add(u8::from(offs) as i8 as i16 as u16)) } }