1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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;
}
}
|