summaryrefslogtreecommitdiff
path: root/src/types/sprite_buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/types/sprite_buffer.rs')
-rw-r--r--src/types/sprite_buffer.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/types/sprite_buffer.rs b/src/types/sprite_buffer.rs
new file mode 100644
index 0000000..74c7b55
--- /dev/null
+++ b/src/types/sprite_buffer.rs
@@ -0,0 +1,85 @@
+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;
+ }
+}