use std::cmp::Ordering;
fn expand(n: u8) -> u16 {
let mut result: u16 = 0;
for i in 0..8 {
result |= (n as u16 & (1 << i)) << i
}
result | (result << 1)
}
#[inline(always)]
pub fn get_px(d: &[u128; 64], x: usize, y: usize) -> bool {
let (shifted, _) = d[y].overflowing_shr(127 - x as u32);
(shifted & 1) == 1
}
pub struct Display {
d: Box<[u128; 64]>,
hi_res: bool,
dirty: bool,
}
impl Display {
pub fn new() -> Display {
Display {
d: Box::new([0; 64]),
hi_res: false,
dirty: false,
}
}
pub fn hi_res_mode(&mut self) {
self.hi_res = true
}
pub fn low_res_mode(&mut self) {
self.hi_res = false
}
pub fn scroll_down(&mut self, n: u32) {
let n = n as usize;
self.dirty = true;
self.d.copy_within(..64-n, n);
for i in 0..n {
self.d[i] = 0
}
}
#[allow(arithmetic_overflow)]
pub fn scroll_side(&mut self, n: i32) {
self.dirty = true;
for row in &mut *self.d {
match n.cmp(&0) {
Ordering::Greater => *row >>= n,
Ordering::Less => *row <<= n.abs(),
Ordering::Equal => {},
}
}
}
pub fn clear(&mut self) {
self.dirty = true;
self.d = Box::new([0; 64])
}
pub fn write(&mut self, b: u8, mut x: usize, mut y: usize) -> bool {
let b = if !self.hi_res {
x *= 2;
y *= 2;
expand(b)
} else {
(b as u16) << 8
};
let x = x % 128;
let y = y % 64;
let mut erased = false;
self.dirty = true;
let mut b = (b as u128) << 112;
b = b.rotate_right(x as u32);
if b & self.d[y] != 0 {
erased = true
};
self.d[y] ^= b;
if !self.hi_res {
if b & self.d[y + 1] != 0 {
erased = true
};
self.d[y + 1] ^= b;
}
erased
}
pub fn read(&mut self) -> &[u128; 64] {
self.dirty = false;
&self.d
}
pub fn read_px(&mut self, x: usize, y: usize) -> bool {
self.dirty = false;
get_px(&self.d, x, y)
}
pub fn hi_res(&self) -> bool {
self.hi_res
}
pub fn dirty(&self) -> bool {
self.dirty
}
}
impl Default for Display {
fn default() -> Self {
Display::new()
}
}
pub const DEFAULT_FONT: [u8; 240] = [
0xF0, 0x90, 0x90, 0x90, 0xF0, 0x20, 0x60, 0x20, 0x20, 0x70, 0xF0, 0x10, 0xF0, 0x80, 0xF0, 0xF0, 0x10, 0xF0, 0x10, 0xF0, 0x90, 0x90, 0xF0, 0x10, 0x10, 0xF0, 0x80, 0xF0, 0x10, 0xF0, 0xF0, 0x80, 0xF0, 0x90, 0xF0, 0xF0, 0x10, 0x20, 0x40, 0x40, 0xF0, 0x90, 0xF0, 0x90, 0xF0, 0xF0, 0x90, 0xF0, 0x10, 0xF0, 0xF0, 0x90, 0xF0, 0x90, 0x90, 0xE0, 0x90, 0xe0, 0x90, 0xE0, 0xF0, 0x80, 0x80, 0x80, 0x80, 0xF0, 0x90, 0x90, 0x90, 0xE0, 0xF0, 0x80, 0xF0, 0x80, 0xF0, 0xF0, 0x80, 0xF0, 0x80, 0x80, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0x18, 0x78, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xC3, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xC3, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0xFF, 0x7E, 0xFF, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xFC, 0xFC, 0xC3, 0xC3, 0xFC, 0xFC, 0xC3, 0xC3, 0xFC, 0xFC, 0x3C, 0xFF, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0xFF, 0x3C, 0xFC, 0xFE, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFE, 0xFC, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, ];