diff --git a/doc/nes_architecture b/doc/nes_architecture
new file mode 100644
index 0000000..0da7a16
--- /dev/null
+++ b/doc/nes_architecture
@@ -0,0 +1 @@
+7VvbcqM4EP0aqmYeMgXiYvzoS7JTtfFuKs5sdh4Vo9hMMPIK2bHn61eAxE2YYGOMJ5OnWE1LQPfp090SUfTRcvsHgavFBDvIU4DqbBV9rACgaT2d/Qklu1jSA1YsmBPX4UqpYOr+RFyocunadVCQU6QYe9Rd5YUz7PtoRnMySAh+zas9Yy9/1xWcI0kwnUFPlj66Dl2I97L66YWvyJ0v+K1t0IsvLKFQ5m8SLKCDXzMi/VrRRwRjGv9abkfIC40n7BLPu9lzNXkwgnxaZ4L3aNkb76/5K/J3wx9TePsyxFfhhOjh6E68MXKYAfgQE7rAc+xD7zqVDgle+w4Kl1XZKNW5xXjFhBoT/kCU7rg34ZpiJlrQpcevoq1L/w2nfwEmH37nq4W/x9vsYCcGPiW77Kxw/D17MZ0XjcTEgEJCByEWmMDHPhKyG9fzEh2CXxIPM98MY7uExthrby4K8JrMUIWRBW4hmSNa5YwEFSycEF4i9hZsHkEepO4m/xyQ43qe6PGp7EXhLqOwwq5Pg8zKd6GAKfAQtTk8eXxaBRAVtI1+lTr7Ed9ejDLvkYoiXB6CUf0DoxeDUe0XAKmtnh+kuhHfcgO9NTcCdBxSitxb+MSyZA5t0HPnPvs9Y45DhAk2iFCXpaEBv7B0HScGNgrcn/ApWi9EBTcdW9wcKuY4QUW4ANrm3MFzJJ+cZqYsXioiUHY6X56B3TCsnMkFng6DRepJoYKfnwOGx7z7TuOwj8x3OaxiXj6pgL55dlLRJE4Z3X2TYBu8uksPRs7dG/qS8/YGs563iia49DWtfoGQLTKFb2LOMv/kgvfgSJWsMKi2QgRxHoKMumqaZb8H9trKKNjKkG2lgRJbJcKT2woY3bLaUaR2PKfNPBgE7qxAa9ppSQzULY26IDGzgEG7msU0vUq9pfrd6hKTWhaRadZ9C5Q5SGbS7qVm2togbVq/N6Mn+wMKFwMFuwu+sgpVl2ZWE1ZR39B7lfo9UKnfUvNnSSXKO2r+9uAkaf408/KbPbXUF53wznG0cxDr7C+L8sTTUaHUDfFYeWIQTcxe4inoG2b/DETSk4jEgRS+DyLR1XK/J0Si2ma+xwaXzitActdd6w26Uew6a3foaltdpzisy9jhig2ZLUYP97cKsDz2CMMnlhCtOY2sEEscd1MUBSvoCxlfYzKY/ikus8fLamTEJWvVW376MHj4Nm3xBuPBw6DF5Qfj8f2ByxfwybBIy4nEQ8+0GY2EWTGIE2Saf0bYwyStjp9ZfiqIasXJIYdoYpV87Ohy6PRLIqe9rS1NcsbvuV3Tal1i1qxLmm7gNIKCKVHo4/1gwiSfwMvnllMKsN5OKcnmZjYwrLYCw5as8c/ZrCG1kJohW8MqsUa/tfwqHwTkckTGFtZ/6/CDkmHI6Vecxln2USMmT65WpRUfsocOOT04Pmmd9IEgpcR9WlMUxfAFPdgKeoxnD36c2tn3FGX82fNv9W5Bvr4vSb9aWeVqtnZcYn7k31NnW+1c5yXNKi85376fThvsOU/ny1+pX3SRUkSOUy690+51GqnKETt4mvLL7eDVjt2mp0in2cLjQVx3C6+w5dfSFp78ucIs6DbL5D410uqBt0maqXXo1RVym24+Nyvk5Q3DETMScUMTnLerKevx9LKPVUCvtbZG/mbyjuA5gUsmvP970tgiB52Ai1640PzV/KSnvd5PPltkkIEzKmx0wxtj+wSN8QkMlnTG3XXL8iFKez0gdb2wL41rx4voSkHkGqAC04pgsbU/K/H/qXw0qnJgNdgpLuUBvTVUy1ti2cBXP+EVdcMCoRsW0IrHpTV3EFtjAeGcjL0mcLViMO2EJLW3WbLs5OEI87Bh+k9lcVWb/muefv0/
\ No newline at end of file
diff --git a/src/bus.rs b/src/bus.rs
index 36722e6..1d06327 100644
--- a/src/bus.rs
+++ b/src/bus.rs
@@ -1,15 +1,24 @@
-use std::fmt;
+use std::{
+ fmt,
+ rc::Rc,
+ cell::RefCell,
+};
-use crate::peripherals::{Peripheral, Ram};
+use crate::peripherals::{
+ Peripheral,
+ Ram,
+ Mapper,
+ Ppu,
+};
-pub struct Bus {
+pub struct Bus {
ram: Ram<0x800>,
- ppu: Ram<0x8>,
- apu: Ram<0x1F>,
- cartridge: Ram<0xBFE0>,
+ ppu: Ppu,
+ apu: Ram<0x1F>,//TODO
+ cartridge: Rc>,
}
-impl fmt::Debug for Bus {
+impl fmt::Debug for Bus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Bus")
@@ -18,7 +27,7 @@ impl fmt::Debug for Bus {
}
}
-impl Peripheral for Bus {
+impl Peripheral for Bus {
fn read_addr(&self, addr: u16) -> u8 {
@@ -26,7 +35,7 @@ impl Peripheral for Bus {
0x0000..=0x1FFF => self.ram.read_addr(addr % 0x0800), //RAM is mirrored 3 times
0x2000..=0x3FFF => self.ppu.read_addr(addr % 0x8), //PPU is mirrored every 8 bytes
0x4000..=0x401F => self.apu.read_addr(addr),
- 0x4020..=0xFFFF => self.cartridge.read_addr(addr),
+ 0x4020..=0xFFFF => self.cartridge.borrow().read_addr(addr),
}
}
@@ -36,14 +45,14 @@ impl Peripheral for Bus {
0x0000..=0x1FFF => self.ram.write_addr(addr % 0x0800, data),
0x2000..=0x3FFF => self.ppu.write_addr(addr % 0x8, data),
0x4000..=0x401F => self.apu.write_addr(addr, data),
- 0x4020..=0xFFFF => self.cartridge.write_addr(addr, data),
+ 0x4020..=0xFFFF => self.cartridge.borrow_mut().write_addr(addr, data),
};
}
}
-impl Bus {
+impl Bus {
- pub fn new() -> Self {
+ pub fn new(mapper: Rc>) -> Self {
let mut ram = Ram::<0x800>::new();
@@ -106,9 +115,9 @@ impl Bus {
Bus {
ram,
- ppu: Ram::<0x8>::new(),
+ ppu: Ppu::new(mapper.clone()),
apu: Ram::<0x1F>::new(),
- cartridge: Ram::<0xBFE0>::new(),
+ cartridge: mapper,
}
}
}
diff --git a/src/cpu.rs b/src/cpu.rs
index 648d1be..e2ef460 100644
--- a/src/cpu.rs
+++ b/src/cpu.rs
@@ -1,14 +1,18 @@
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
+use std::{
+ fmt,
+ rc::Rc,
+ cell::RefCell,
+};
use bitflags::bitflags;
use crate::{
- bus::FileBus,
- peripherals::Peripheral,
+ bus::Bus,
+ peripherals::{Peripheral, Mapper},
};
-use std::fmt;
//--------------------------------------------------------------------------------------------------
@@ -138,17 +142,17 @@ bitflags! {
}
}
-pub struct Cpu {
+pub struct Cpu {
a: u8,
x: u8,
y: u8,
pc: u16,
s: u8,
p: StatusReg,
- bus: FileBus,
+ bus: Bus,
}
-impl fmt::Debug for Cpu {
+impl fmt::Debug for Cpu {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Cpu")
@@ -164,12 +168,12 @@ impl fmt::Debug for Cpu {
}
-impl Cpu {
+impl Cpu {
- pub fn new() -> Self {
+ pub fn new(mapper: Rc>) -> Self {
// read initial PC value from reset vector
- let bus = FileBus::new();
+ let bus = Bus::new(mapper);
let pc_lo = bus.read_addr(0xFFFC) as u16;
let pc_hi = bus.read_addr(0xFFFD) as u16;
diff --git a/src/main.rs b/src/main.rs
index df9fb12..3dde190 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,6 +6,7 @@ use cpu::Cpu;
mod bus;
mod peripherals;
+use peripherals::mapper::Nrom;
mod utils;
fn main() -> Result<(), &'static str> {
@@ -15,7 +16,11 @@ fn main() -> Result<(), &'static str> {
dpi::LogicalSize,
};
use mini_gl_fb::config;
- use std::fmt::Write;
+ use std::{
+ fmt::Write,
+ rc::Rc,
+ cell::RefCell,
+ };
// setup
setup_logger().map_err(|_| "Failed to setup logger")?;
@@ -31,7 +36,8 @@ fn main() -> Result<(), &'static str> {
let mut renderer = FontRenderer::new(20.0, [0u8, 0, 0]);
// first image
- let mut cpu = Cpu::new();
+ let mapper = Rc::new(RefCell::new(Nrom::new()));
+ let mut cpu = Cpu::new(mapper);
let mut debug_str = String::new();
write!(debug_str, "{:#?}", cpu).unwrap();
buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255));
diff --git a/src/peripherals.rs b/src/peripherals.rs
index ed1e0e9..83db315 100644
--- a/src/peripherals.rs
+++ b/src/peripherals.rs
@@ -1,4 +1,11 @@
-use std::fmt;
+
+mod ram;
+mod ppu;
+pub mod mapper;
+
+pub use ram::Ram;
+pub use ppu::Ppu;
+pub use mapper::Mapper;
//--------------------------------------------------------------------------------------------------
pub trait Peripheral {
@@ -8,57 +15,3 @@ pub trait Peripheral {
fn write_addr(&mut self, addr: u16, data: u8);
}
-//--------------------------------------------------------------------------------------------------
-pub struct Ram {
- pub buffer: [u8; SIZE],
-}
-
-impl fmt::Debug for Ram {
-
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- for i in 0x100..=0x1FF {
- if i%0x10 == 0 {
- f.write_fmt(format_args!("\n {:0>4X}", i))?;
- }
- f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))?
- }
-
- Ok(())
- }
-}
-
-impl Peripheral for Ram {
-
- fn read_addr(&self, addr: u16) -> u8 {
- self.buffer[addr as usize]
- }
-
- fn write_addr(&mut self, addr: u16, data: u8) {
- self.buffer[addr as usize] = data;
- }
-}
-
-impl Ram {
-
- pub fn new() -> Self {
-
- Ram {
- buffer: [0u8; SIZE],
- }
- }
-
- pub fn from_file(file: &str) -> Self {
- use std::{
- fs::File,
- io::Read,
- };
-
- let mut f = File::open(file).unwrap();
- let mut buffer = [0u8; SIZE];
- f.read_exact(&mut buffer).unwrap();
-
- Ram {
- buffer,
- }
- }
-}
diff --git a/src/peripherals/mapper.rs b/src/peripherals/mapper.rs
new file mode 100644
index 0000000..a25a5a2
--- /dev/null
+++ b/src/peripherals/mapper.rs
@@ -0,0 +1,42 @@
+use super::Peripheral;
+
+//--Mapper struct-----------------------------------------------------------------------------------
+///A trait used as API for the different implementations of mappers in cartridges
+///
+///A Mapper is a special `Peripheral` that can also be read by the `Ppu`. The exact memory layout
+///is defined by the implementation
+pub trait Mapper: Peripheral {
+
+ ///read the specified 16 bits address using the ppu bus
+ fn ppu_read_addr(&self, addr: u16) -> u8;
+}
+
+pub struct Nrom {
+
+}
+
+impl Peripheral for Nrom {
+
+ fn read_addr(&self, _addr: u16) -> u8 {
+ unimplemented!();
+ }
+
+ fn write_addr(&mut self, _addr: u16, _data: u8) {
+ unimplemented!();
+ }
+}
+
+impl Mapper for Nrom {
+
+ fn ppu_read_addr(&self, _addr: u16) -> u8 {
+ unimplemented!();
+ }
+}
+
+impl Nrom {
+
+ pub fn new() -> Self {
+ unimplemented!();
+ }
+}
+
diff --git a/src/peripherals/ppu.rs b/src/peripherals/ppu.rs
new file mode 100644
index 0000000..306d4c9
--- /dev/null
+++ b/src/peripherals/ppu.rs
@@ -0,0 +1,78 @@
+use std::{
+ rc::Rc,
+ cell::RefCell,
+};
+
+use bitflags::bitflags;
+
+use crate::{
+ peripherals::{Peripheral, Ram, Mapper},
+};
+
+//--------------------------------------------------------------------------------------------------
+bitflags! {
+ struct Ctrl: u8 {
+ const Nl = 0x1 << 0;
+ const Nh = 0x1 << 1;
+ const I = 0x1 << 2;
+ const S = 0x1 << 3;
+ const B = 0x1 << 4;
+ const H = 0x1 << 5;
+ const P = 0x1 << 6;
+ const V = 0x1 << 7;
+ }
+}
+
+bitflags! {
+ struct Mask: u8 {
+ const Gr = 0x1 << 0;
+ const m = 0x1 << 1;
+ const M = 0x1 << 2;
+ const b = 0x1 << 3;
+ const s = 0x1 << 4;
+ const R = 0x1 << 5;
+ const G = 0x1 << 6;
+ const B = 0x1 << 7;
+ }
+}
+
+bitflags! {
+ struct Status: u8 {
+ const O = 0x1 << 5;
+ const S = 0x1 << 6;
+ const V = 0x1 << 7;
+ }
+}
+
+pub struct Ppu {
+ vbus: Rc>,
+ ctrl: Ctrl,
+ mask: Mask,
+ status: Status,
+ scroll: u8,
+ addr: u8,
+ data: u8,
+ oam_addr: u8,
+ oam_data: u8,
+ oam_dma: u8,
+ oam: Ram<0x100>,
+ blanking: bool,
+}
+
+impl Peripheral for Ppu {
+
+ fn read_addr(&self, _addr: u16) -> u8 {
+ unimplemented!();
+ }
+
+ fn write_addr(&mut self, _addr: u16, _data: u8) {
+ unimplemented!();
+ }
+}
+
+impl Ppu {
+
+ pub fn new(_mapper: Rc>) -> Self {
+ unimplemented!();
+ }
+}
diff --git a/src/peripherals/ram.rs b/src/peripherals/ram.rs
new file mode 100644
index 0000000..e56e975
--- /dev/null
+++ b/src/peripherals/ram.rs
@@ -0,0 +1,59 @@
+use std::fmt;
+
+use super::Peripheral;
+
+//--------------------------------------------------------------------------------------------------
+pub struct Ram {
+ pub buffer: [u8; SIZE],
+}
+
+impl fmt::Debug for Ram {
+
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ for i in 0x100..=0x1FF {
+ if i%0x10 == 0 {
+ f.write_fmt(format_args!("\n {:0>4X}", i))?;
+ }
+ f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))?
+ }
+
+ Ok(())
+ }
+}
+
+impl Peripheral for Ram {
+
+ fn read_addr(&self, addr: u16) -> u8 {
+ self.buffer[addr as usize]
+ }
+
+ fn write_addr(&mut self, addr: u16, data: u8) {
+ self.buffer[addr as usize] = data;
+ }
+}
+
+impl Ram {
+
+ pub fn new() -> Self {
+
+ Ram {
+ buffer: [0u8; SIZE],
+ }
+ }
+
+ pub fn from_file(file: &str) -> Self {
+ use std::{
+ fs::File,
+ io::Read,
+ };
+
+ let mut f = File::open(file).unwrap();
+ let mut buffer = [0u8; SIZE];
+ f.read_exact(&mut buffer).unwrap();
+
+ Ram {
+ buffer,
+ }
+ }
+}
+