draw window with tiledata

This commit is contained in:
Alex Janka 2023-02-06 12:14:51 +11:00
parent bec5a0c3d6
commit 805ae0c817
2 changed files with 83 additions and 3 deletions

View file

@ -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<u32>,
scaled_buffer: Vec<u32>,
mode: DrawMode,
mode_clock: usize,
scanline: u8,
sprite_buffer: Vec<u32>,
sprite_buffer_scaled: Vec<u32>,
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));
}

View file

@ -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();
}
}