diff --git a/src/processor/gpu.rs b/src/processor/gpu.rs index 875a6ca..d139ae2 100644 --- a/src/processor/gpu.rs +++ b/src/processor/gpu.rs @@ -1,6 +1,10 @@ +use minifb::{Window, WindowOptions}; + use crate::{FACTOR, HEIGHT, WIDTH}; -use super::{as_signed, clear_bit, get_bit, set_bit, set_or_clear_bit, CPU}; +use super::{as_signed, get_bit, set_bit, set_or_clear_bit, CPU}; + +mod tile_window; #[derive(PartialEq)] enum DrawMode { @@ -32,8 +36,8 @@ enum TiledataArea { impl TiledataArea { fn get_addr(&self, addr: u8) -> u16 { match self { - TiledataArea::D8000 => 0x8000 + (addr as u16), - TiledataArea::D9000 => 0x9000_u16.wrapping_add_signed(as_signed(addr) as i16), + TiledataArea::D8000 => 0x8000 + ((addr as u16) * 16), + TiledataArea::D9000 => 0x9000_u16.wrapping_add_signed((as_signed(addr) as i16) * 16), } } } @@ -86,22 +90,44 @@ struct Palette { three: Colour, } +const TILE_WINDOW_EDGE_LENGTH: usize = 16 * 8; +const TILE_WINDOW_EDGE_LENGTH_SCALED: usize = TILE_WINDOW_EDGE_LENGTH * FACTOR; + pub struct GPU { pub buffer: Vec, scaled_buffer: Vec, mode: DrawMode, mode_clock: usize, scanline: u8, + sprite_buffer: Vec, + sprite_buffer_scaled: Vec, + sprite_window: Window, } impl Default for GPU { fn default() -> Self { + let window = Window::new( + "Tiles", + TILE_WINDOW_EDGE_LENGTH_SCALED, + TILE_WINDOW_EDGE_LENGTH_SCALED, + WindowOptions::default(), + ) + .unwrap_or_else(|e| { + panic!("{}", e); + }); Self { buffer: vec![0; WIDTH * HEIGHT], scaled_buffer: vec![0; WIDTH * HEIGHT * 4], mode: DrawMode::Mode2, mode_clock: 0, scanline: 0, + sprite_buffer: vec![0; TILE_WINDOW_EDGE_LENGTH * TILE_WINDOW_EDGE_LENGTH], + sprite_buffer_scaled: vec![ + 0; + TILE_WINDOW_EDGE_LENGTH_SCALED + * TILE_WINDOW_EDGE_LENGTH_SCALED + ], + sprite_window: window, } } } @@ -201,6 +227,10 @@ impl CPU { fn exit_vblank(&mut self) { self.gpu.mode = DrawMode::Mode2; self.gpu.scanline = 0; + self.draw_sprite_window( + TiledataArea::D8000, + byte_to_palette(self.memory.get(0xFF47)), + ); // self.memory // .set(0xFF0F, clear_bit(self.memory.get(0xFF0F), 0)); } diff --git a/src/processor/gpu/tile_window.rs b/src/processor/gpu/tile_window.rs new file mode 100644 index 0000000..deb6f9f --- /dev/null +++ b/src/processor/gpu/tile_window.rs @@ -0,0 +1,50 @@ +use crate::{ + processor::{get_bit, CPU}, + FACTOR, +}; + +use super::{ + bits_to_mapped_colour, scale_buffer, Palette, TiledataArea, TILE_WINDOW_EDGE_LENGTH, + TILE_WINDOW_EDGE_LENGTH_SCALED, +}; + +impl CPU { + pub(super) fn draw_sprite_window(&mut self, area: TiledataArea, palette: Palette) { + for tile_y in 0..16 { + for tile_x in 0..16 { + let tile_num = (tile_y * 16) + tile_x; + let data_begin = area.get_addr(tile_num); + for px_y in 0..8 { + let lsbs = self.memory.get((px_y * 2) + data_begin); + let msbs = self.memory.get((px_y * 2) + data_begin + 1); + for px_x in 0..8 { + let real_px_y = (tile_y as usize * 8) + px_y as usize; + let real_px_x = (tile_x as usize * 8) + px_x as usize; + let lsb = get_bit(lsbs, 7 - px_x); + let msb = get_bit(msbs, 7 - px_x); + let colour = bits_to_mapped_colour(lsb, msb, palette); + + // if buself.gpu.b + self.gpu.sprite_buffer[real_px_x + (real_px_y * TILE_WINDOW_EDGE_LENGTH)] = + colour.to_rgb(); + } + } + } + } + + self.gpu.sprite_buffer_scaled = scale_buffer( + &self.gpu.sprite_buffer, + TILE_WINDOW_EDGE_LENGTH, + TILE_WINDOW_EDGE_LENGTH, + FACTOR, + ); + self.gpu + .sprite_window + .update_with_buffer( + &self.gpu.sprite_buffer_scaled, + TILE_WINDOW_EDGE_LENGTH_SCALED, + TILE_WINDOW_EDGE_LENGTH_SCALED, + ) + .unwrap(); + } +}