Skip to content

Commit

Permalink
Implement window rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
Miwgt committed Jun 18, 2024
1 parent 088c793 commit 3cce2d1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 34 deletions.
15 changes: 13 additions & 2 deletions src/cpu/render_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const OAM_ADDRESS: u16 = 0xFE00;

const SPRITE_SIZE: u16 = 4;

const WY_ADDRESS: u16 = 0xFF4A;
const WX_ADDRESS: u16 = 0xFF4B;

pub struct Sprite {
pub y_pos: i32,
pub x_pos: i32,
Expand All @@ -23,7 +26,7 @@ impl CPU {
self.memory.read_byte(0xFF40) & (1 << 7) == (1 << 7)
}

pub fn get_lcdc_window_tile_map_high(&self) -> bool {
pub fn get_lcdc_window_tile_high_map(&self) -> bool {
self.memory.read_byte(0xFF40) & (1 << 6) == (1 << 6)
}

Expand All @@ -35,7 +38,7 @@ impl CPU {
self.memory.read_byte(0xFF40) & (1 << 4) == (1 << 4)
}

pub fn get_lcdc_bg_tile_map(&self) -> bool {
pub fn get_lcdc_bg_tile_high_map(&self) -> bool {
self.memory.read_byte(0xFF40) & (1 << 3) == (1 << 3)
}

Expand Down Expand Up @@ -64,6 +67,14 @@ impl CPU {
self.memory.read_byte(SCX_ADDRESS)
}

pub fn get_window_wy(&mut self) -> u8 {
self.memory.read_byte(WY_ADDRESS)
}

pub fn get_window_wx(&mut self) -> u8 {
self.memory.read_byte(WX_ADDRESS)
}

// VRAM getters
pub fn get_vram_tile_line(
&self,
Expand Down
80 changes: 48 additions & 32 deletions src/rendering/line_rendering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ const DOTS_PER_LINE: u32 = 456;

const SCAN_DOTS: u32 = 80;
const MIN_DRAW_DOTS: u32 = 172;
#[allow(dead_code)]
const MIN_HBLANK_DOTS: u32 = 87;

const SCANLINES_ACTUAL: u8 = 144;
const SCANLINES_EXTRA: u8 = 10;
Expand All @@ -20,45 +18,64 @@ pub fn oam_scan(_cpu: &CPU) {}

// Mode 3
pub fn draw_line(cpu: &mut CPU, game_diplay: &mut Image, palette: &[Color; 4]) {
let high_map: bool = false;
let high_addressing: bool = !cpu.get_lcdc_bg_window_tile_data();

let scx = cpu.get_lcd_scx();
let scy = cpu.get_lcd_scy();

let line: u8 = cpu.get_lcd_y_coordinate();

let mut display_x: u32 = 0;
let mut line_x_pos = scx as u32 % 8;

let mut bg_line_x_pos = scx as u32 % 8;

let high_adressing = !cpu.get_lcdc_bg_window_tile_data();

// Draw Background
for xtile in 0..TILES_PER_LINE {
let tile_index = cpu.get_vram_tile_map_entry(
high_map,
// Fetch Background Line Data
let bg_tile_idx = cpu.get_vram_tile_map_entry(
cpu.get_lcdc_bg_tile_high_map(),
(((line + scy) / 8) as u16 % 0x100) * 32 + (xtile + (scx as u16 / 8)) % 32,
);
let line_data =
cpu.get_vram_tile_line(high_addressing, tile_index as u16, (line + scy) % 8);
let bg_line = cpu.get_vram_tile_line(high_adressing, bg_tile_idx as u16, (line + scy) % 8);

for x_pixel in (line_x_pos % 8)..8 {
for x_pixel in (bg_line_x_pos as usize % 8)..8 {
if display_x >= game_diplay.width() as u32 {
break;
}

if (line as usize * game_diplay.width() + display_x as usize)
>= game_diplay.get_image_data().len()
{
log::warn!("Pixel out of bounds: x: {}, y: {}", display_x, line);
continue;
}

game_diplay.set_pixel(
display_x,
line as u32,
palette[line_data[x_pixel as usize] as usize],
);
game_diplay.set_pixel(display_x, line as u32, palette[bg_line[x_pixel] as usize]);

display_x += 1;
line_x_pos += 1;
bg_line_x_pos += 1;
}
}

// Draw Window
if cpu.get_lcdc_window_enable() {
let wd_offset_y = cpu.get_window_wy();
let wd_offset_x = cpu.get_window_wx() as i32 - 7;

for xtile in 0..20 {
// Fetch Window Line Data

if line >= wd_offset_y {
let wd_tile_idx = cpu.get_vram_tile_map_entry(
cpu.get_lcdc_window_tile_high_map(),
((line - wd_offset_y) as u16 / 8) * 32 + (xtile - wd_offset_x) as u16,
);
let wd_line = cpu.get_vram_tile_line(high_adressing, wd_tile_idx as u16, line % 8);

for x_pixel in 0..8 as usize {
let x_coord: i32 = xtile as i32 * 8 + x_pixel as i32 + wd_offset_x;
if x_coord >= 0 && line >= wd_offset_y {
game_diplay.set_pixel(
x_coord as u32,
line as u32,
palette[wd_line[x_pixel] as usize],
);
}
}
}
}
}

Expand All @@ -67,14 +84,15 @@ pub fn draw_line(cpu: &mut CPU, game_diplay: &mut Image, palette: &[Color; 4]) {

// Draw Objects (Sprites)
for sprite_idx in 0..40 {
let mut sprite = cpu.get_oam_entry(sprite_idx);
let sprite = cpu.get_oam_entry(sprite_idx);

if (line as i32) >= sprite.y_pos - 16 && (line as i32) < sprite.y_pos - 8 {
let line_data = cpu.get_vram_tile_line(
false,
sprite.tile_idx,
(line + 16 - sprite.y_pos as u8) % 8,
);
let mut tile_line = (line + 16 - sprite.y_pos as u8) % 8;
if sprite.y_flip {
tile_line = 7 - tile_line;
}

let line_data = cpu.get_vram_tile_line(false, sprite.tile_idx, tile_line);

sprites_drawn += 1;

Expand Down Expand Up @@ -102,8 +120,6 @@ pub fn draw_line(cpu: &mut CPU, game_diplay: &mut Image, palette: &[Color; 4]) {
}
}
}

//log::info!("Sprites Drawn: {}", sprites_drawn);
}

pub struct Ppu {
Expand Down

0 comments on commit 3cce2d1

Please sign in to comment.