From 677a584ba7fab8e76b010f90bd2cf5dbdd083c99 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Wed, 23 Dec 2020 21:24:27 -0600 Subject: [PATCH] chore: stub vram, start work on ppu, fix set_register bug --- src/bus.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/cpu.rs | 4 ++-- src/lib.rs | 1 + src/ppu.rs | 42 ++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 9 deletions(-) create mode 100644 src/ppu.rs diff --git a/src/bus.rs b/src/bus.rs index 1cc4ac6..596cda8 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -2,8 +2,9 @@ use super::cartridge::Cartridge; #[derive(Debug, Clone)] pub struct Bus { - boot: Option<[u8; 256]>, + boot: Option<[u8; 256]>, // Boot ROM is 256b long cartridge: Option, + vram: [u8; 8192], // 8KB of VRAM } impl Default for Bus { @@ -11,6 +12,7 @@ impl Default for Bus { Self { boot: Some(include_bytes!("../bin/DMG_ROM.bin").to_owned()), cartridge: None, + vram: [0; 8192], } } } @@ -23,7 +25,7 @@ impl Bus { pub fn without_boot() -> Self { Self { boot: None, - cartridge: None, + ..Default::default() } } @@ -54,7 +56,7 @@ impl Bus { }, 0x8000..=0x9FFF => { // 8KB Video RAM - unimplemented!("Unable to read {:#06X} in Video RAM", addr); + self.vram[(addr - 0x8000) as usize] } 0xA000..=0xBFFF => { // 8KB External RAM @@ -87,13 +89,62 @@ impl Bus { } 0xFFFF => { // Interupts Enable Register - unimplemented!("Unable to read Interrupt Enable Register {:#06X} ", addr); + unimplemented!("Unable to read IE Register {:#06X} ", addr); } } } pub fn write_byte(&mut self, addr: u16, byte: u8) { - unimplemented!("Can't write {:#04x} to {:#06X}", byte, addr) + match addr { + 0x0000..=0x3FFF => { + // 16KB ROM bank 00 + panic!("Tried to write to {:#06X} in ROM Bank 00", addr); + } + 0x4000..=0x7FFF => { + // 16KB ROM Bank 01 -> NN (switchable via MB) + panic!("Tried to write to {:#06X} in ROM Bank 01 -> NN", addr); + } + 0x8000..=0x9FFF => { + // 8KB Video RAM + self.vram[(addr - 0x8000) as usize] = byte; + } + 0xA000..=0xBFFF => { + // 8KB External RAM + unimplemented!("Unable to write to {:#06X} in Extermal RAM", addr); + } + 0xC000..=0xCFFF => { + // 4KB Work RAM Bank 0 + unimplemented!("Unable to write to {:#06X} in Work RAM Bank 0", addr); + } + 0xD000..=0xDFFF => { + // 4KB Work RAM Bank 1 -> N + unimplemented!("Unable to write to {:#06X} in Work RAM Bank N", addr); + } + 0xE000..=0xFDFF => { + // Mirror of 0xC000 to 0xDDFF + unimplemented!("Unable to write to {:#06X} in Restricted Mirror", addr); + } + 0xFE00..=0xFE9F => { + // Sprite Attrbute Table + unimplemented!( + "Unable to write to {:#06X} in the Sprite Attribute Table", + addr + ); + } + 0xFEA0..=0xFEFF => unimplemented!("{:#06X} is not allowed to be used", addr), + 0xFF00..=0xFF7F => { + // IO Registers + unimplemented!("Unable to write to {:#06X} in I/O Registers", addr); + } + 0xFF80..=0xFFFE => { + // High RAM + unimplemented!("Unable to write to {:#06X} in High RAM", addr); + } + 0xFFFF => { + // Interupts Enable Register + unimplemented!("Unable to write to IE Register {:#06X} ", addr); + } + } } pub fn read_word(&self, addr: u16) -> u16 { @@ -117,7 +168,8 @@ impl Bus { }, 0x8000..=0x9FFF => { // 8KB Video RAM - unimplemented!("Unable to read {:#06X} in Video RAM", addr); + (self.vram[((addr + 1) - 0x8000) as usize] as u16) << 8 + | self.vram[(addr - 0x8000) as usize] as u16 } 0xA000..=0xBFFF => { // 8KB External RAM @@ -150,7 +202,7 @@ impl Bus { } 0xFFFF => { // Interupts Enable Register - unimplemented!("Unable to read Interrupt Enable Register {:#06X} ", addr); + unimplemented!("Unable to read IE Register {:#06X} ", addr); } } } diff --git a/src/cpu.rs b/src/cpu.rs index 4bfac7e..150f482 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -77,7 +77,7 @@ impl Cpu { } pub fn write_byte(&mut self, addr: u16, byte: u8) { - self.bus.write_byte(addr, byte) + self.bus.write_byte(addr, byte); } pub fn read_word(&mut self, addr: u16) -> u16 { @@ -116,7 +116,7 @@ impl Cpu { Register::E => self.reg.e = value, Register::H => self.reg.h = value, Register::L => self.reg.l = value, - Register::Flag => self.reg.a = value, + Register::Flag => self.flags = value.into(), } } diff --git a/src/lib.rs b/src/lib.rs index c10e6ae..021a1aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,3 +2,4 @@ mod bus; mod cartridge; pub mod cpu; mod instruction; +mod ppu; diff --git a/src/ppu.rs b/src/ppu.rs new file mode 100644 index 0000000..5bd1076 --- /dev/null +++ b/src/ppu.rs @@ -0,0 +1,42 @@ +struct PPU { + lcdc: LCDControl, +} + +struct LCDControl { + lcd_enable: bool, // Bit 7 + window_tile_map_select: bool, + window_enable: bool, + tile_data_select: bool, + bg_tile_map_select: bool, + sprite_size: bool, + sprite_enable: bool, + display_priority: bool, // Bit 0 +} + +impl From for LCDControl { + fn from(byte: u8) -> Self { + Self { + lcd_enable: (byte >> 7) == 0x01, + window_tile_map_select: ((byte >> 6) & 0x01) == 0x01, + window_enable: ((byte >> 5) & 0x01) == 0x01, + tile_data_select: ((byte >> 4) & 0x01) == 0x01, + bg_tile_map_select: ((byte >> 3) & 0x01) == 0x01, + sprite_size: ((byte >> 2) & 0x01) == 0x01, + sprite_enable: ((byte >> 1) & 0x01) == 0x01, + display_priority: (byte & 0x01) == 0x01, + } + } +} + +impl From for u8 { + fn from(lcdc: LCDControl) -> Self { + (lcdc.lcd_enable as u8) << 7 + | (lcdc.window_tile_map_select as u8) << 6 + | (lcdc.window_enable as u8) << 5 + | (lcdc.tile_data_select as u8) << 4 + | (lcdc.bg_tile_map_select as u8) << 3 + | (lcdc.sprite_size as u8) << 2 + | (lcdc.sprite_enable as u8) << 1 + | lcdc.display_priority as u8 + } +}