Skip to content
Snippets Groups Projects
Verified Commit f85b1b73 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: initial support for sprite drawing

parent dbc385d0
No related branches found
No related tags found
1 merge request!3Support for sprites/object drawing 💪
Pipeline #925 failed
...@@ -48,19 +48,6 @@ pub struct Tile { ...@@ -48,19 +48,6 @@ pub struct Tile {
buffer: [u8; 64], buffer: [u8; 64],
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
#[derive(Clone, Copy, PartialEq)]
pub struct ObjectData {
x: i16,
y: i16,
tile: u8,
palette: u8,
xflip: bool,
yflip: bool,
prio: u8,
num: u8,
}
#[cfg_attr(feature = "wasm", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
impl Tile { impl Tile {
pub fn get(&self, x: usize, y: usize) -> u8 { pub fn get(&self, x: usize, y: usize) -> u8 {
...@@ -102,6 +89,29 @@ impl Display for Tile { ...@@ -102,6 +89,29 @@ impl Display for Tile {
} }
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
#[derive(Clone, Copy, PartialEq)]
pub struct ObjectData {
x: i16,
y: i16,
tile: u8,
palette: u8,
xflip: bool,
yflip: bool,
prio: u8,
index: u8,
}
impl Display for ObjectData {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"Index => {} X => {} Y => {} Tile => {}",
self.index, self.x, self.y, self.tile
)
}
}
/// Represents the Game Boy PPU (Pixel Processing Unit) and controls /// Represents the Game Boy PPU (Pixel Processing Unit) and controls
/// all of the logic behind the graphics processing and presentation. /// all of the logic behind the graphics processing and presentation.
/// Should store both the VRAM and HRAM together with the internal /// Should store both the VRAM and HRAM together with the internal
...@@ -236,7 +246,7 @@ impl Ppu { ...@@ -236,7 +246,7 @@ impl Ppu {
xflip: false, xflip: false,
yflip: false, yflip: false,
prio: 0, prio: 0,
num: 0, index: 0,
}; OBJ_COUNT], }; OBJ_COUNT],
palette: [[0u8; RGB_SIZE]; PALETTE_SIZE], palette: [[0u8; RGB_SIZE]; PALETTE_SIZE],
palette_obj_0: [[0u8; RGB_SIZE]; PALETTE_SIZE], palette_obj_0: [[0u8; RGB_SIZE]; PALETTE_SIZE],
...@@ -534,16 +544,17 @@ impl Ppu { ...@@ -534,16 +544,17 @@ impl Ppu {
if obj_index >= OBJ_COUNT { if obj_index >= OBJ_COUNT {
return; return;
} }
let mut obj_data = self.obj_data[obj_index]; let mut obj = self.obj_data[obj_index].borrow_mut();
match addr & 0x03 { match addr & 0x03 {
0x00 => obj_data.y = value as i16 - 16, 0x00 => obj.y = value as i16 - 16,
0x01 => obj_data.x = value as i16 - 16, 0x01 => obj.x = value as i16 - 8,
0x02 => obj_data.tile = value, 0x02 => obj.tile = value,
0x03 => { 0x03 => {
obj_data.palette = if value & 0x10 == 0x10 { 1 } else { 0 }; obj.palette = if value & 0x10 == 0x10 { 1 } else { 0 };
obj_data.xflip = if value & 0x20 == 0x20 { true } else { false }; obj.xflip = if value & 0x20 == 0x20 { true } else { false };
obj_data.yflip = if value & 0x40 == 0x40 { true } else { false }; obj.yflip = if value & 0x40 == 0x40 { true } else { false };
obj_data.prio = if value & 0x80 == 0x80 { 1 } else { 0 }; obj.prio = if value & 0x80 == 0x80 { 1 } else { 0 };
obj.index = obj_index as u8;
} }
_ => (), _ => (),
} }
...@@ -628,18 +639,20 @@ impl Ppu { ...@@ -628,18 +639,20 @@ impl Ppu {
fn render_objects(&mut self) { fn render_objects(&mut self) {
for index in 0..OBJ_COUNT { for index in 0..OBJ_COUNT {
let obj_data = self.obj_data[index]; // obtains the meta data of the object that is currently
// under iteration to be checked for drawing
let obj = self.obj_data[index];
// verifies if the sprite is currently located at the // verifies if the sprite is currently located at the
// current line that is going to be drawn and skips it // current line that is going to be drawn and skips it
// in case it's not // in case it's not
let is_contained = (obj_data.y <= self.ly as i16) let is_contained =
&& ((obj_data.y + TILE_HEIGHT as i16) > self.ly as i16); (obj.y <= self.ly as i16) && ((obj.y + TILE_HEIGHT as i16) > self.ly as i16);
if !is_contained { if !is_contained {
continue; continue;
} }
let palette = if obj_data.palette == 0 { let palette = if obj.palette == 0 {
self.palette_obj_0 self.palette_obj_0
} else { } else {
self.palette_obj_1 self.palette_obj_1
...@@ -648,20 +661,20 @@ impl Ppu { ...@@ -648,20 +661,20 @@ impl Ppu {
// calculates the offset in the frame buffer for the sprite // calculates the offset in the frame buffer for the sprite
// that is going to be drawn, this is going to be the starting // that is going to be drawn, this is going to be the starting
// point for the draw operation to be performed // point for the draw operation to be performed
let mut frame_offset = (self.ly as usize * DISPLAY_WIDTH + obj_data.x as usize) * RGB_SIZE; let mut frame_offset = (self.ly as usize * DISPLAY_WIDTH + obj.x as usize) * RGB_SIZE;
let tile_offset = self.ly as i16 - obj_data.y; let tile_offset = self.ly as i16 - obj.y;
let tile_row: &[u8]; let tile_row: &[u8];
if obj_data.yflip { if obj.yflip {
tile_row = tile_row = self.tiles[obj.tile as usize].get_row((7 - tile_offset) as usize);
self.tiles[obj_data.tile as usize].get_row((7 - tile_offset) as usize);
} else { } else {
tile_row = self.tiles[obj_data.tile as usize].get_row((tile_offset) as usize); tile_row = self.tiles[obj.tile as usize].get_row((tile_offset) as usize);
} }
for x in 0..TILE_WIDTH { for x in 0..TILE_WIDTH {
let is_contained = (obj_data.x + x as i16 >= 0) && ((obj_data.x + x as i16) < DISPLAY_WIDTH as i16); let is_contained =
(obj.x + x as i16 >= 0) && ((obj.x + x as i16) < DISPLAY_WIDTH as i16);
if !is_contained { if !is_contained {
continue; continue;
} }
...@@ -678,6 +691,8 @@ impl Ppu { ...@@ -678,6 +691,8 @@ impl Ppu {
self.frame_buffer[frame_offset + 1] = color[1]; self.frame_buffer[frame_offset + 1] = color[1];
self.frame_buffer[frame_offset + 2] = color[2]; self.frame_buffer[frame_offset + 2] = color[2];
// increments the offset of the frame buffer by the
// size of an RGB pixel (which is 3 bytes)
frame_offset += RGB_SIZE; frame_offset += RGB_SIZE;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment