fix tile rendering
This commit is contained in:
parent
d6b95e6c6c
commit
09b1cb1e57
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue