diff options
author | Ben Bridle <ben@derelict.engineering> | 2024-11-20 10:42:57 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2024-11-20 10:42:57 +1300 |
commit | 39dfe987cbd99f42d85ea1a0c7d5df866fe739e5 (patch) | |
tree | 085c3a44712b1ae6c17163691efdc6d2f74fedf9 | |
parent | 2bc38ca471cfb37fb6f65740f7a9f0d374183dce (diff) | |
download | bedrock-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.rs | 19 |
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; } } |