use crate::*; pub struct SpriteBuffer { pub mem: [u8; 16], pub pointer: usize, pub cached: Option<(Sprite, u8)>, } impl SpriteBuffer { pub fn new() -> Self { Self { mem: [0; 16], pointer: 0, cached: None, } } pub fn push_byte(&mut self, byte: u8) { self.mem[self.pointer] = byte; self.pointer = (self.pointer + 1) % 16; self.cached = None; } pub fn read_1bit_sprite(&mut self, draw: u8) -> Sprite { if let Some((sprite, transform)) = self.cached { if transform == (draw & 0x77) { return sprite; } } macro_rules! c { ($v:ident=mem[$p:ident++]) => { let $v = self.mem[$p % 16]; $p = $p.wrapping_add(1); }; ($v:ident=mem[--$p:ident]) => { $p = $p.wrapping_sub(1); let $v = self.mem[$p % 16]; }; } let mut sprite = [[0; 8]; 8]; let mut p = match draw & 0x02 != 0 { true => self.pointer, false => self.pointer + 8, }; match draw & 0x07 { 0x0 => { for y in 0..8 { c!(l=mem[p++]); for x in 0..8 { sprite[y][x] = l>>(7-x) & 1; } } }, 0x1 => { for y in 0..8 { c!(l=mem[p++]); for x in 0..8 { sprite[y][x] = l>>( x) & 1; } } }, 0x2 => { for y in 0..8 { c!(l=mem[--p]); for x in 0..8 { sprite[y][x] = l>>(7-x) & 1; } } }, 0x3 => { for y in 0..8 { c!(l=mem[--p]); for x in 0..8 { sprite[y][x] = l>>( x) & 1; } } }, 0x4 => { for y in 0..8 { c!(l=mem[p++]); for x in 0..8 { sprite[x][y] = l>>(7-x) & 1; } } }, 0x5 => { for y in 0..8 { c!(l=mem[p++]); for x in 0..8 { sprite[x][y] = l>>( x) & 1; } } }, 0x6 => { for y in 0..8 { c!(l=mem[--p]); for x in 0..8 { sprite[x][y] = l>>(7-x) & 1; } } }, 0x7 => { for y in 0..8 { c!(l=mem[--p]); for x in 0..8 { sprite[x][y] = l>>( x) & 1; } } }, _ => unreachable!(), } self.cached = Some((sprite, draw & 0x77)); return sprite; } pub fn read_2bit_sprite(&mut self, draw: u8) -> Sprite { if let Some((sprite, transform)) = self.cached { if transform == (draw & 0x77) { return sprite; } } macro_rules! c { ($v:ident=mem[$p:ident++]) => { let $v = self.mem[$p % 16]; $p = $p.wrapping_add(1); }; ($v:ident=mem[--$p:ident]) => { $p = $p.wrapping_sub(1); let $v = self.mem[$p % 16]; }; } let mut sprite = [[0; 8]; 8]; let mut p = match draw & 0x02 != 0 { true => self.pointer, false => self.pointer + 8, }; let mut s = p + 8; match draw & 0x07 { 0x0 => for y in 0..8 { c!(l=mem[p++]); c!(h=mem[s++]); for x in 0..8 { let i=7-x; sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x1 => for y in 0..8 { c!(l=mem[p++]); c!(h=mem[s++]); for x in 0..8 { let i= x; sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x2 => for y in 0..8 { c!(l=mem[--p]); c!(h=mem[--s]); for x in 0..8 { let i=7-x; sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x3 => for y in 0..8 { c!(l=mem[--p]); c!(h=mem[--s]); for x in 0..8 { let i= x; sprite[y][x] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x4 => for y in 0..8 { c!(l=mem[p++]); c!(h=mem[s++]); for x in 0..8 { let i=7-x; sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x5 => for y in 0..8 { c!(l=mem[p++]); c!(h=mem[s++]); for x in 0..8 { let i= x; sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x6 => for y in 0..8 { c!(l=mem[--p]); c!(h=mem[--s]); for x in 0..8 { let i=7-x; sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }, 0x7 => for y in 0..8 { c!(l=mem[--p]); c!(h=mem[--s]); for x in 0..8 { let i= x; sprite[x][y] = (l>>i & 1) | (h>>i & 1) << 1; } }, _ => unreachable!(), } self.cached = Some((sprite, draw & 0x77)); return sprite; } }