use super::*; macro_rules! test { ($value:expr, $mask:expr) => { $value & $mask != 0 }; } pub struct SpriteBuffer { data: [u8; 16], pointer: usize, colours: [u8; 4], } impl SpriteBuffer { pub fn new() -> Self { Self { data: [0; 16], pointer: 0, colours: [0; 4] } } pub fn push(&mut self, val: u8) { self.data[self.pointer] = val; self.pointer = (self.pointer + 1) % 16; } pub fn set_colour_high(&mut self, val: u8) { self.colours[0] = val >> 4; self.colours[1] = val & 0x0f; } pub fn set_colour_low(&mut self, val: u8) { self.colours[2] = val >> 4; self.colours[3] = val & 0x0f; } // Return the 64 transformed pixels of the current 1-bit sprite. // Each pixel is the palette index of that pixel, or 0xff if transparent. pub fn get_1bit_sprite(&self, params: u8) -> Sprite { let mut sprite = [[0u8; 8]; 8]; let plane = self.get_low_plane(params); let colours = self.get_colours(params); for (y, row) in plane.into_iter().enumerate() { for x in (0..8).rev() { sprite[y][7-x] = colours[(row >> x & 0x1) as usize]; } } return sprite; } // Return the 64 transformed pixels of the current 2-bit sprite. // Each pixel is the palette index of that pixel, or 0xff if transparent. pub fn get_2bit_sprite(&self, params: u8) -> Sprite { let mut sprite = [[0u8; 8]; 8]; let high_plane = self.get_high_plane(params); let low_plane = self.get_low_plane(params); let colours = self.get_colours(params); for (y, (row_h, row_l)) in zip(high_plane, low_plane).enumerate() { for x in (0..8).rev() { let bit_h = (row_h >> x) & 0x1; let bit_l = (row_l >> x) & 0x1; sprite[y][7-x] = colours[(bit_h << 1 | bit_l) as usize]; } } return sprite; } fn get_high_plane(&self, params: u8) -> Plane { let mut plane = [0u8; 8]; for (i, row) in plane.iter_mut().enumerate() { *row = self.data[(self.pointer + i) % 16] } transform_plane(plane, params) } fn get_low_plane(&self, params: u8) -> Plane { let mut plane = [0u8; 8]; for (i, row) in plane.iter_mut().enumerate() { *row = self.data[(self.pointer + i + 8) % 16] } transform_plane(plane, params) } fn get_colours(&self, params: u8) -> [u8; 4] { let mut colours = self.colours; if test!(params, TRANSPARENT) { colours[0] = 0xff; } return colours; } } fn transform_plane(mut plane: Plane, params: u8) -> Plane { if test!(params, FLIP_DIAGONAL) { let mut flipped = [0u8; 8]; for mut row in plane { for y in 0..8 { flipped[y] = flipped[y] << 1 | row >> 7; row <<= 1; } } plane = flipped; } if test!(params, FLIP_VERTICAL) { plane.reverse(); } if test!(params, FLIP_HORIZONTAL) { for row in plane.iter_mut() { *row = row.reverse_bits(); } } return plane; }