summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <ben@derelict.engineering>2024-11-20 10:42:57 +1300
committerBen Bridle <ben@derelict.engineering>2024-11-20 10:42:57 +1300
commit39dfe987cbd99f42d85ea1a0c7d5df866fe739e5 (patch)
tree085c3a44712b1ae6c17163691efdc6d2f74fedf9
parent2bc38ca471cfb37fb6f65740f7a9f0d374183dce (diff)
downloadbedrock-pc-39dfe987cbd99f42d85ea1a0c7d5df866fe739e5.zip
Cache transformed sprite data
In programs where the same sprite is drawn many times repeatedly, a lot of time is saved by caching the transformed sprite data instead of having to recalculate it for every draw operation. No testing has been done on the efficiency improvements this offers, but it doesn't seem like it could have any downsides.
-rw-r--r--src/devices/screen_device.rs19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/devices/screen_device.rs b/src/devices/screen_device.rs
index b4eae22..a10ab20 100644
--- a/src/devices/screen_device.rs
+++ b/src/devices/screen_device.rs
@@ -419,6 +419,7 @@ impl HasDimensions<u16> for ScreenDevice {
pub struct SpriteBuffer {
pub mem: [u8; 16],
pub pointer: usize,
+ pub cached: Option<(Sprite, u8)>,
}
impl SpriteBuffer {
@@ -426,15 +427,22 @@ impl SpriteBuffer {
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(&self, draw: u8) -> Sprite {
+ 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]; };
@@ -455,10 +463,16 @@ impl SpriteBuffer {
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(&self, draw: u8) -> 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]; };
@@ -480,6 +494,7 @@ impl SpriteBuffer {
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;
}
}