Skip to content

Commit

Permalink
window layer rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanballs committed Sep 17, 2024
1 parent e435591 commit 3cabc29
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 54 deletions.
102 changes: 72 additions & 30 deletions src/mmu/ppu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::debugger::is_gameboy_doctor;
const VRAM_SIZE: usize = 0x2000;
const VOAM_SIZE: usize = 0xA0;

const SCREEN_WIDTH: usize = 160;
const SCREEN_HEIGHT: usize = 144;
pub const SCREEN_WIDTH: usize = 160;
pub const SCREEN_HEIGHT: usize = 144;

const TARGET_FPS: f64 = 60.0;

Expand Down Expand Up @@ -265,11 +265,17 @@ impl PPU {
let background_y = line.wrapping_add(self.scy);
let tile_map_row = background_y / 8;

// draw background
for buffer_x_offset in 0..SCREEN_WIDTH {
let background_x = (buffer_x_offset + self.scx as usize) % 256;

let tile_map_index = (tile_map_row as usize * 32) + (background_x / 8);
let tile_index = self.get_byte(0x9800 + tile_map_index as u16);
let tile_map_data_area = if self.lcdc & 0x8 == 0x8 {
0x9C00
} else {
0x9800
};
let tile_index = self.get_byte(tile_map_data_area + tile_map_index as u16);

let tile_line = background_y % 8;
let tile_col = background_x % 8;
Expand All @@ -280,44 +286,80 @@ impl PPU {
self.frame_buffer[buffer_y_offset + buffer_x_offset] = palette(tile_pixel);
}

// For each object we should
for i in 0..40 {
let start_position = 0xFE00 + i * 4;

let object_y = self.get_byte(start_position);
let object_line = line.wrapping_sub(object_y).wrapping_add(16);
if object_line >= 8 {
continue;
}
let x_position = self.get_byte(start_position + 1);
let tile_index = self.get_byte(start_position + 2);
let flags = self.get_byte(start_position + 3);
// draw window
if self.lcdc & 0x20 == 0x20 {
for buffer_x_offset in 0..SCREEN_WIDTH {
let window_x = buffer_x_offset
.wrapping_sub(self.wx as usize)
.wrapping_add(7);
if window_x >= SCREEN_WIDTH {
continue;
};

let x_flip = flags & 0x20 == 0x20;
let y_flip = flags & 0x40 == 0x40;
let window_y = (line as usize).wrapping_sub(self.wy as usize);
if window_y as usize >= SCREEN_HEIGHT {
continue;
};

for x_offset in 0..8 {
let x_position = if x_flip {
(x_position as usize).wrapping_sub(x_offset as usize)
let tile_map_index = ((window_y / 8) as usize * 32) + (window_x / 8);
let tile_map_data_area = if self.lcdc & 0x40 == 0x40 {
0x9C00
} else {
(x_position as usize)
.wrapping_add(x_offset as usize)
.wrapping_sub(8)
0x9800
};
let tile_index = self.get_byte(tile_map_data_area + tile_map_index as u16);

if x_position >= SCREEN_WIDTH {
continue;
}
let tile_line = window_y % 8;
let tile_col = window_x % 8;

let tile_line = if y_flip { 8 - object_line } else { object_line };
let tile_pixel =
self.get_tile_pixel(tile_index, tile_line as u16, tile_col as u16, false);

let tile_pixel = self.get_tile_pixel(tile_index, tile_line as u16, x_offset, true);
self.frame_buffer[buffer_y_offset + buffer_x_offset] = palette(tile_pixel);
}
}

// For each object we should
if self.lcdc & 0x2 == 0x2 {
for i in 0..40 {
let start_position = 0xFE00 + i * 4;

if tile_pixel == 0 {
let object_y = self.get_byte(start_position);
let object_line = line.wrapping_sub(object_y).wrapping_add(16);
if object_line >= 8 {
continue;
}
let x_position = self.get_byte(start_position + 1);
let tile_index = self.get_byte(start_position + 2);
let flags = self.get_byte(start_position + 3);

let x_flip = flags & 0x20 == 0x20;
let y_flip = flags & 0x40 == 0x40;

for x_offset in 0..8 {
let x_position = if x_flip {
(x_position as usize).wrapping_sub(x_offset as usize)
} else {
(x_position as usize)
.wrapping_add(x_offset as usize)
.wrapping_sub(8)
};

if x_position >= SCREEN_WIDTH {
continue;
}

let tile_line = if y_flip { 8 - object_line } else { object_line };

self.frame_buffer[buffer_y_offset + x_position] = palette(tile_pixel);
let tile_pixel =
self.get_tile_pixel(tile_index, tile_line as u16, x_offset, true);

if tile_pixel == 0 {
continue;
}

self.frame_buffer[buffer_y_offset + x_position] = palette(tile_pixel);
}
}
}
}
Expand Down
47 changes: 23 additions & 24 deletions src/renderer.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
use minifb::{Key, KeyRepeat, Scale, Window, WindowOptions};
use std::sync::mpsc::{Receiver, Sender, TryRecvError};

const SCREEN_WIDTH: usize = 160;
const SCREEN_HEIGHT: usize = 144;

fn most_recent_frame(rx: &Receiver<Vec<u32>>) -> Option<Vec<u32>> {
let mut latest_frame = None;

loop {
match rx.try_recv() {
Ok(frame) => {
// Update the latest frame
latest_frame = Some(frame);
}
Err(TryRecvError::Empty) => {
break;
}
Err(TryRecvError::Disconnected) => {
panic!("");
}
}
}

latest_frame
}
use crate::mmu::ppu::{SCREEN_HEIGHT, SCREEN_WIDTH};

pub fn window_loop(rx: Receiver<Vec<u32>>, tx: Sender<(bool, Key)>, game_title: &String) {
let mut window = Window::new(
Expand All @@ -44,7 +22,7 @@ pub fn window_loop(rx: Receiver<Vec<u32>>, tx: Sender<(bool, Key)>, game_title:
.unwrap();
}

// dispatch unreleased keys
// dispatch pressed keys
window
.get_keys_pressed(KeyRepeat::No)
.iter()
Expand All @@ -57,3 +35,24 @@ pub fn window_loop(rx: Receiver<Vec<u32>>, tx: Sender<(bool, Key)>, game_title:
.for_each(|key| tx.send((false, *key)).unwrap());
}
}

fn most_recent_frame(rx: &Receiver<Vec<u32>>) -> Option<Vec<u32>> {
let mut latest_frame = None;

loop {
match rx.try_recv() {
Ok(frame) => {
// Update the latest frame
latest_frame = Some(frame);
}
Err(TryRecvError::Empty) => {
break;
}
Err(TryRecvError::Disconnected) => {
panic!("");
}
}
}

latest_frame
}

0 comments on commit 3cabc29

Please sign in to comment.