diff options
Diffstat (limited to 'src/devices/screen/sprite_data.rs')
-rw-r--r-- | src/devices/screen/sprite_data.rs | 98 |
1 files changed, 87 insertions, 11 deletions
diff --git a/src/devices/screen/sprite_data.rs b/src/devices/screen/sprite_data.rs index aade2c6..0a1d3c2 100644 --- a/src/devices/screen/sprite_data.rs +++ b/src/devices/screen/sprite_data.rs @@ -1,11 +1,17 @@ -pub struct SpriteData { +use super::*; + +macro_rules! test { ($value:expr, $mask:expr) => { $value & $mask != 0 }; } + + +pub struct SpriteBuffer { data: [u8; 16], pointer: usize, + colours: [u8; 4], } -impl SpriteData { +impl SpriteBuffer { pub fn new() -> Self { - Self { data: [0; 16], pointer: 0 } + Self { data: [0; 16], pointer: 0, colours: [0; 4] } } pub fn push(&mut self, val: u8) { @@ -13,21 +19,91 @@ impl SpriteData { self.pointer = (self.pointer + 1) % 16; } - pub fn get_1bit_sprite(&self) -> [u8; 8] { - let mut sprite = [0u8; 8]; - for (i, r) in sprite.iter_mut().enumerate() { - *r = self.data[(self.pointer + i + 8) % 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; } - pub fn get_2bit_sprite(&self) -> [u8; 16] { - let mut sprite = [0u8; 16]; - for (i, r) in sprite.iter_mut().enumerate() { - *r = self.data[(self.pointer + i) % 16] + // 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; +} |