diff --git a/src/bus.rs b/src/bus.rs index d08a577..38608ef 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -104,6 +104,8 @@ impl Bus { 0xFF24 => self.sound.control.channel.into(), 0xFF25 => self.sound.control.select.into(), 0xFF26 => self.sound.control.status.into(), + 0xFF40 => self.ppu.lcd_control.into(), + 0xFF47 => self.ppu.monochrome.bg_palette.into(), _ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr), } } @@ -166,6 +168,8 @@ impl Bus { 0xFF24 => self.sound.control.channel = byte.into(), 0xFF25 => self.sound.control.select = byte.into(), 0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here? + 0xFF40 => self.ppu.lcd_control = byte.into(), + 0xFF47 => self.ppu.monochrome.bg_palette = byte.into(), _ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr), }; } diff --git a/src/ppu.rs b/src/ppu.rs index 42c6c1e..87b7b15 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -1,20 +1,27 @@ #[derive(Debug, Clone)] pub struct PPU { - lcdc: LCDControl, + pub lcd_control: LCDControl, + pub monochrome: Monochrome, pub vram: Box<[u8]>, } impl Default for PPU { fn default() -> Self { Self { - lcdc: Default::default(), + lcd_control: Default::default(), + monochrome: Default::default(), vram: vec![0; 8192].into_boxed_slice(), } } } +#[derive(Debug, Clone, Copy, Default)] +pub struct Monochrome { + pub bg_palette: BackgroundPalette, +} + #[derive(Debug, Default, Clone, Copy)] -struct LCDControl { +pub struct LCDControl { lcd_enable: bool, // Bit 7 window_tile_map_select: bool, window_enable: bool, @@ -52,3 +59,70 @@ impl From for u8 { | lcdc.display_priority as u8 } } + +#[derive(Debug, Clone, Copy)] +enum GrayShade { + White, + LightGray, + DarkGray, + Black, +} + +impl Default for GrayShade { + fn default() -> Self { + Self::White + } +} + +impl From for GrayShade { + fn from(byte: u8) -> Self { + match byte { + 0b00 => GrayShade::White, + 0b01 => GrayShade::LightGray, + 0b10 => GrayShade::DarkGray, + 0b11 => GrayShade::Black, + _ => unreachable!("{:#04X} is not a valid Shade of Gray", byte), + } + } +} + +impl From for u8 { + fn from(shade: GrayShade) -> Self { + match shade { + GrayShade::White => 0b00, + GrayShade::LightGray => 0b01, + GrayShade::DarkGray => 0b10, + GrayShade::Black => 0b11, + } + } +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct BackgroundPalette { + color3: GrayShade, + color2: GrayShade, + color1: GrayShade, + color0: GrayShade, +} + +impl From for BackgroundPalette { + fn from(byte: u8) -> Self { + Self { + color3: (byte >> 6).into(), + color2: ((byte >> 4) & 0x03).into(), + color1: ((byte >> 2) & 0x03).into(), + color0: (byte & 0x03).into(), + } + } +} + +impl From for u8 { + fn from(palette: BackgroundPalette) -> Self { + let color0: u8 = palette.color0.into(); + let color1: u8 = palette.color1.into(); + let color2: u8 = palette.color2.into(); + let color3: u8 = palette.color0.into(); + + color3 << 6 | color2 << 4 | color1 << 2 | color0 + } +}