Skip to content

Commit

Permalink
Reorganise PPU
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaacMarovitz committed May 4, 2024
1 parent 148bb6d commit 010f9a0
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 114 deletions.
27 changes: 27 additions & 0 deletions src/components/ppu/bgpi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
pub struct BGPI {
pub address: u8,
pub auto_increment: bool
}

impl BGPI {
pub fn new() -> Self {
Self {
address: 0,
auto_increment: false
}
}

pub fn read(&self) -> u8 {
let a = if self.auto_increment {
0x80
} else {
0x00
};
a | self.address
}

pub fn write(&mut self, v: u8) {
self.auto_increment = v & 0x80 != 0x00;
self.address = v & 0x3F;
}
}
4 changes: 3 additions & 1 deletion src/components/ppu/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod ppu;
mod cc;
mod cc;
mod bgpi;
mod structs;
134 changes: 21 additions & 113 deletions src/components/ppu/ppu.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::components::prelude::*;
use crate::config::{Color, Config, Palette, PPUConfig};
use crate::Framebuffer;
use bitflags::bitflags;
use crate::components::ppu::bgpi::BGPI;
use crate::components::ppu::cc::ColorCorrection;
use crate::components::ppu::structs::*;

/// RGBA (4 bytes) per pixel
pub const FRAMEBUFFER_SIZE: usize = 4 * SCREEN_W * SCREEN_H;
Expand Down Expand Up @@ -41,99 +42,6 @@ pub struct PPU {
pub framebuffer: Framebuffer,
}

#[derive(PartialEq, Copy, Clone)]
enum Priority {
Color0,
Priority,
Normal,
}

#[derive(PartialEq, Copy, Clone)]
enum PPUMode {
OAMScan = 2,
Draw = 3,
HBlank = 0,
VBlank = 1,
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct Attributes: u8 {
const PRIORITY = 0b1000_0000;
const Y_FLIP = 0b0100_0000;
const X_FLIP = 0b0010_0000;
const PALETTE_NO_0 = 0b0001_0000;
const BANK = 0b0000_1000;
}
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct LCDC: u8 {
// LCD & PPU enable: 0 = Off; 1 = On
const LCD_ENABLE = 0b1000_0000;
// Window tile map area: 0 = 9800–9BFF; 1 = 9C00–9FFF
const WINDOW_AREA = 0b0100_0000;
// Window enable: 0 = Off; 1 = On
const WINDOW_ENABLE = 0b0010_0000;
// BG & Window tile data area: 0 = 8800–97FF; 1 = 8000–8FFF
const TILE_DATA_AREA = 0b0001_0000;
// BG tile map area: 0 = 9800–9BFF; 1 = 9C00–9FFF
const BG_TILE_MAP_AREA = 0b0000_1000;
// OBJ size: 0 = 8×8; 1 = 8×16
const OBJ_SIZE = 0b0000_0100;
// OBJ enable: 0 = Off; 1 = On
const OBJ_ENABLE = 0b0000_0010;
// BG & Window enable (GB) / priority (CGB): 0 = Off; 1 = On
const WINDOW_PRIORITY = 0b0000_0001;
}
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct LCDS: u8 {
// LYC int select (Read/Write): If set, selects the LYC == LY condition for the STAT interrupt.
const LYC_SELECT = 0b0100_0000;
// Mode 2 int select (Read/Write): If set, selects the Mode 2 condition for the STAT interrupt.
const MODE_2_SELECT = 0b0010_0000;
// Mode 1 int select (Read/Write): If set, selects the Mode 1 condition for the STAT interrupt.
const MODE_1_SELECT = 0b0001_0000;
// Mode 0 int select (Read/Write): If set, selects the Mode 0 condition for the STAT interrupt.
const MODE_0_SELECT = 0b0000_1000;
// LYC == LY (Read-only): Set when LY contains the same value as LYC; it is constantly updated.
const LYC_EQUALS = 0b0000_0100;
// PPU mode (Read-only): Indicates the PPU’s current status.
}
}

struct BGPI {
address: u8,
auto_increment: bool
}

impl BGPI {
fn new() -> Self {
Self {
address: 0,
auto_increment: false
}
}

fn read(&self) -> u8 {
let a = if self.auto_increment {
0x80
} else {
0x00
};
a | self.address
}

fn write(&mut self, v: u8) {
self.auto_increment = v & 0x80 != 0x00;
self.address = v & 0x3F;
}
}

impl PPU {
pub fn new(config: Config, framebuffer: Framebuffer) -> Self {
Self {
Expand Down Expand Up @@ -296,7 +204,22 @@ impl PPU {
CCMode::SGB => self.cc.sgb_color_lut[color as usize],
};

self.write_pixel(color[0], color[1], color[2], x, self.ly);
self.set_pixel(color[0], color[1], color[2], x, self.ly);
}

fn set_pixel(&mut self, r: u8, g: u8, b: u8, x: usize, y: u8) {
pub const BYTES_PER_PIXEL: usize = 4;
pub const BYTES_PER_ROW: usize = BYTES_PER_PIXEL * SCREEN_W;

let vertical_offset = y as usize * BYTES_PER_ROW;
let horizontal_offset = x * BYTES_PER_PIXEL;
let total_offset = vertical_offset + horizontal_offset;

let mut framebuffer = self.framebuffer.write().unwrap();
framebuffer[total_offset + 0] = r;
framebuffer[total_offset + 1] = g;
framebuffer[total_offset + 2] = b;
framebuffer[total_offset + 3] = 0xFF;
}

fn draw_bg(&mut self) {
Expand Down Expand Up @@ -407,7 +330,7 @@ impl PPU {
Self::grey_to_l(self.ppu_config.palette, self.bgp, color)
};

self.write_pixel(color.r(), color.g(), color.b(), x, self.ly);
self.set_pixel(color.r(), color.g(), color.b(), x, self.ly);
}
}
}
Expand Down Expand Up @@ -516,7 +439,7 @@ impl PPU {
Self::grey_to_l(self.ppu_config.palette, self.obp0, color)
};

self.write_pixel(color.r(), color.g(), color.b(), px.wrapping_add(x) as usize, self.ly);
self.set_pixel(color.r(), color.g(), color.b(), px.wrapping_add(x) as usize, self.ly);
}
}
}
Expand All @@ -529,21 +452,6 @@ impl PPU {
fn write_vram(&mut self, a: u16, v: u8, bank: usize) {
self.vram[(bank * 0x2000) + a as usize - 0x8000] = v;
}

fn write_pixel(&mut self, r: u8, g: u8, b: u8, x: usize, y: u8) {
pub const BYTES_PER_PIXEL: usize = 4;
pub const BYTES_PER_ROW: usize = BYTES_PER_PIXEL * SCREEN_W;

let vertical_offset = y as usize * BYTES_PER_ROW;
let horizontal_offset = x * BYTES_PER_PIXEL;
let total_offset = vertical_offset + horizontal_offset;

let mut framebuffer = self.framebuffer.write().unwrap();
framebuffer[total_offset + 0] = r;
framebuffer[total_offset + 1] = g;
framebuffer[total_offset + 2] = b;
framebuffer[total_offset + 3] = 0xFF;
}
}

impl Memory for PPU {
Expand Down Expand Up @@ -625,7 +533,7 @@ impl Memory for PPU {

for y in 0..SCREEN_H {
for x in 0..SCREEN_W {
self.write_pixel(r, g, b, x, y as u8);
self.set_pixel(r, g, b, x, y as u8);
}
}
},
Expand Down
66 changes: 66 additions & 0 deletions src/components/ppu/structs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use bitflags::bitflags;

#[derive(PartialEq, Copy, Clone)]
pub enum Priority {
Color0,
Priority,
Normal,
}

#[derive(PartialEq, Copy, Clone)]
pub enum PPUMode {
OAMScan = 2,
Draw = 3,
HBlank = 0,
VBlank = 1,
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct Attributes: u8 {
const PRIORITY = 0b1000_0000;
const Y_FLIP = 0b0100_0000;
const X_FLIP = 0b0010_0000;
const PALETTE_NO_0 = 0b0001_0000;
const BANK = 0b0000_1000;
}
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct LCDC: u8 {
// LCD & PPU enable: 0 = Off; 1 = On
const LCD_ENABLE = 0b1000_0000;
// Window tile map area: 0 = 9800–9BFF; 1 = 9C00–9FFF
const WINDOW_AREA = 0b0100_0000;
// Window enable: 0 = Off; 1 = On
const WINDOW_ENABLE = 0b0010_0000;
// BG & Window tile data area: 0 = 8800–97FF; 1 = 8000–8FFF
const TILE_DATA_AREA = 0b0001_0000;
// BG tile map area: 0 = 9800–9BFF; 1 = 9C00–9FFF
const BG_TILE_MAP_AREA = 0b0000_1000;
// OBJ size: 0 = 8×8; 1 = 8×16
const OBJ_SIZE = 0b0000_0100;
// OBJ enable: 0 = Off; 1 = On
const OBJ_ENABLE = 0b0000_0010;
// BG & Window enable (GB) / priority (CGB): 0 = Off; 1 = On
const WINDOW_PRIORITY = 0b0000_0001;
}
}

bitflags! {
#[derive(PartialEq, Copy, Clone)]
pub struct LCDS: u8 {
// LYC int select (Read/Write): If set, selects the LYC == LY condition for the STAT interrupt.
const LYC_SELECT = 0b0100_0000;
// Mode 2 int select (Read/Write): If set, selects the Mode 2 condition for the STAT interrupt.
const MODE_2_SELECT = 0b0010_0000;
// Mode 1 int select (Read/Write): If set, selects the Mode 1 condition for the STAT interrupt.
const MODE_1_SELECT = 0b0001_0000;
// Mode 0 int select (Read/Write): If set, selects the Mode 0 condition for the STAT interrupt.
const MODE_0_SELECT = 0b0000_1000;
// LYC == LY (Read-only): Set when LY contains the same value as LYC; it is constantly updated.
const LYC_EQUALS = 0b0000_0100;
// PPU mode (Read-only): Indicates the PPU’s current status.
}
}

0 comments on commit 010f9a0

Please sign in to comment.