fix tile rendering

This commit is contained in:
Alex Janka 2023-02-09 11:10:49 +11:00
parent d6b95e6c6c
commit 09b1cb1e57

View file

@ -167,47 +167,47 @@ impl CPU {
pub fn advance_gpu_clock(&mut self, steps: u8) { pub fn advance_gpu_clock(&mut self, steps: u8) {
let lcdc = self.get_lcdc(); let lcdc = self.get_lcdc();
if lcdc.enable { if lcdc.enable {
let real_steps = (steps as usize) * 4; let real_steps = (steps as usize) * 4;
self.gpu.mode_clock += real_steps; self.gpu.mode_clock += real_steps;
match self.gpu.mode { match self.gpu.mode {
DrawMode::HBlank => { DrawMode::HBlank => {
// mode 0: hblank // mode 0: hblank
if self.gpu.mode_clock >= 204 { if self.gpu.mode_clock >= 204 {
self.gpu.mode_clock = 0; self.gpu.mode_clock = 0;
self.gpu.scanline += 1; self.gpu.scanline += 1;
if self.gpu.scanline == 143 { if self.gpu.scanline == 143 {
self.enter_vblank(); self.enter_vblank();
} else { } else {
self.gpu.mode = DrawMode::Mode2; self.gpu.mode = DrawMode::Mode2;
}
}
}
DrawMode::VBlank => {
// mode 1: vblank
if self.gpu.mode_clock >= 456 {
self.gpu.mode_clock = 0;
self.gpu.scanline += 1;
if self.gpu.scanline == 153 {
self.exit_vblank();
}
}
}
DrawMode::Mode2 => {
// search oam for sprites on this line
// we dont really have to emulate this
if self.gpu.mode_clock >= 80 {
self.gpu.mode_clock = 0;
self.gpu.mode = DrawMode::Mode3;
}
}
DrawMode::Mode3 => {
// generate scanline
if self.gpu.mode_clock >= 172 {
self.gpu.mode_clock = 0;
self.enter_hblank(&lcdc);
} }
} }
} }
DrawMode::VBlank => {
// mode 1: vblank
if self.gpu.mode_clock >= 456 {
self.gpu.mode_clock = 0;
self.gpu.scanline += 1;
if self.gpu.scanline == 153 {
self.exit_vblank();
}
}
}
DrawMode::Mode2 => {
// search oam for sprites on this line
// we dont really have to emulate this
if self.gpu.mode_clock >= 80 {
self.gpu.mode_clock = 0;
self.gpu.mode = DrawMode::Mode3;
}
}
DrawMode::Mode3 => {
// generate scanline
if self.gpu.mode_clock >= 172 {
self.gpu.mode_clock = 0;
self.enter_hblank(&lcdc);
}
}
}
} else { } else {
self.gpu.mode_clock = 0; self.gpu.mode_clock = 0;
self.gpu.mode = DrawMode::VBlank; self.gpu.mode = DrawMode::VBlank;
@ -254,9 +254,9 @@ impl CPU {
fn enter_vblank(&mut self) { fn enter_vblank(&mut self) {
self.memory.update_pressed_keys(self.window.get_keys()); self.memory.update_pressed_keys(self.window.get_keys());
self.gpu.mode = DrawMode::VBlank; self.gpu.mode = DrawMode::VBlank;
self.render_window(); self.render_window();
self.memory.set(0xFF0F, set_bit(self.memory.get(0xFF0F), 0)); self.memory.set(0xFF0F, set_bit(self.memory.get(0xFF0F), 0));
} }
fn exit_vblank(&mut self) { fn exit_vblank(&mut self) {
self.gpu.mode = DrawMode::Mode2; self.gpu.mode = DrawMode::Mode2;
@ -330,6 +330,7 @@ impl CPU {
palette, palette,
scroll_x, scroll_x,
scroll_y, scroll_y,
true,
); );
} }
@ -345,6 +346,7 @@ impl CPU {
palette, palette,
pos_x, pos_x,
pos_y, pos_y,
false,
) )
} }
} }
@ -429,28 +431,39 @@ impl CPU {
tilemap: &TilemapArea, tilemap: &TilemapArea,
tiledata: &TiledataArea, tiledata: &TiledataArea,
palette: Palette, palette: Palette,
_offset_x: u8, offset_x: u8,
offset_y: u8, offset_y: u8,
wrap: bool,
) { ) {
let tile_line = (scanline as usize) + (offset_y as usize); let tile_line_y = scanline.wrapping_add(offset_y);
let tilemap_row = tile_line / 8; if (scanline as usize + offset_y as usize) % 0xFF > 0 && !wrap {
let tile_px = (tile_line) % 8; return;
let tiledata_offset = tile_px * 2; }
let row_addr = ((tilemap_row * 32) % 0x400) as u16; let tilemap_row = tile_line_y / 8;
for x in 0..32_u16 { let tile_px_y = (tile_line_y) % 8;
let tile_addr = tiledata.get_addr(self.memory.get(tilemap.get_addr(row_addr + x))) let tiledata_offset = tile_px_y * 2;
+ tiledata_offset as u16; let row_addr = ((tilemap_row as usize * 32) % 0x400) as u16;
for x in 0..WIDTH {
let tile_line_x = (x as u8).wrapping_add(offset_x);
if ((x + offset_x as usize) / 0xFF) > 0 && !wrap {
continue;
}
let tilemap_column = (tile_line_x / 8) as u16;
let tile_px_x = (tile_line_x % 8) as u8;
let tile_addr = tiledata.get_addr(
self.memory
.get(tilemap.get_addr(row_addr + (tilemap_column))),
) + tiledata_offset as u16;
let lsbs = self.memory.get(tile_addr); let lsbs = self.memory.get(tile_addr);
let msbs = self.memory.get(tile_addr + 1); let msbs = self.memory.get(tile_addr + 1);
for px_x in 0..8 { let lsb = get_bit(lsbs, 7 - tile_px_x);
let lsb = get_bit(lsbs, 7 - px_x); let msb = get_bit(msbs, 7 - tile_px_x);
let msb = get_bit(msbs, 7 - px_x); let colour = bits_to_mapped_colour(lsb, msb, palette);
let colour = bits_to_mapped_colour(lsb, msb, palette);
let x_coord = ((x * 8) + (px_x as u16)) as usize; self.gpu.buffer[(scanline as usize * WIDTH) + x] = colour.to_rgb();
if x_coord < WIDTH {
self.gpu.buffer[(scanline as usize * WIDTH) + x_coord] = colour.to_rgb();
}
}
} }
} }