chip8/src/periph.rs

96 lines
2.5 KiB
Rust

#[derive(Copy, Clone)]
pub struct Display {
pub buf: [u8; Self::WIDTH as usize * Self::HEIGHT as usize],
}
impl Display {
const WIDTH: u8 = 64;
const HEIGHT: u8 = 32;
pub fn clear(&mut self) {
self.buf = [0x0; Self::WIDTH as usize * Self::HEIGHT as usize]
}
pub fn draw_sprite(&mut self, coords: (u8, u8), data: &[u8]) -> bool {
let x = coords.0 % Self::WIDTH;
let y = coords.1 % Self::HEIGHT;
let mut set_vf = false;
// Each byte in data is a row, with the column being data.len() tall
// This means when writing this sprite, x will change for each bit in a byte and y
// should be incremented by 1 for every new byte we draw to the graphics buffer
for (y_offset, byte) in data.iter().enumerate() {
// Access every bit of the byte
for x_bit_offset in 0..8 {
// The Coordinates of this bit in the gfx buffer
let gfx_x = x + (7 - x_bit_offset);
let gfx_y = y + y_offset as u8;
let bit = (byte >> x_bit_offset) & 0x01;
// Translate the gfx_x and gfx_y to an index in the 1D buffer
let gfx_i = (Self::WIDTH as usize * gfx_y as usize) + gfx_x as usize;
if gfx_i >= self.buf.len() {
break; // Stop Drawing this spite and move on to the next
}
if bit == 0x1 && self.buf[gfx_i] == 0x01 {
set_vf = true;
}
self.buf[gfx_i] ^= bit;
}
}
set_vf
}
}
impl Default for Display {
fn default() -> Self {
Display {
buf: [0x0; Self::WIDTH as usize * Self::HEIGHT as usize],
}
}
}
#[derive(Debug, Default, Copy, Clone)]
pub struct Keypad {
keys: [bool; 16],
}
impl Keypad {
pub fn get_any_pressed(&self) -> Option<u8> {
for (i, key) in self.keys.iter().enumerate() {
if *key {
return Some(i as u8);
}
}
None
}
pub fn reset(&mut self) {
self.keys = [false; 16];
}
pub fn get_overview(&self) -> [bool; 16] {
self.keys
}
pub fn is_pressed(&self, key: u8) -> bool {
self.keys[key as usize]
}
pub fn set_all(&mut self, keys: [bool; 16]) {
self.keys = keys;
}
pub fn set_key(&mut self, index: usize) {
self.keys[index] = true;
}
pub fn unset_key(&mut self, index: usize) {
self.keys[index] = false;
}
}