aboutsummaryrefslogtreecommitdiff
path: root/src/memory.rs
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-11 20:05:49 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-11 20:05:49 -0500
commit0edff96acccceb102fd97a9200f5504200d5fa50 (patch)
tree02216a47b2090175a48a8c207113adffb146ba3e /src/memory.rs
parenta600c658f7905e747bd9233b141de147972ef04c (diff)
...
Diffstat (limited to 'src/memory.rs')
-rw-r--r--src/memory.rs139
1 files changed, 123 insertions, 16 deletions
diff --git a/src/memory.rs b/src/memory.rs
index 852b837..f506a86 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,39 +1,146 @@
+use ppu::PPU;
+use mos6502::CPU;
+use cartridge::{MirrorType, Cartridge};
+use core::cell::{RefCell, RefMut};
+
pub trait VMem {
fn read(&self, addr: u16) -> u8;
fn write(&mut self, addr: u16, data: u8);
}
-pub struct CPUMemory {
- internal: [u8; 2048]
+pub struct CPUMemory<'a> {
+ internal: [u8; 2048],
+ ppu: *mut PPU<'a>,
+ cpu: *mut CPU<'a>,
+ mapper: &'a mut VMem
+}
+
+impl<'a> CPUMemory<'a> {
+ pub fn new(cpu: *mut CPU<'a>,
+ ppu: *mut PPU<'a>,
+ mapper: &'a mut VMem) -> Self {
+ CPUMemory{internal: [0; 2048],
+ cpu, ppu,
+ mapper}
+ }
+}
+
+impl<'a> VMem for CPUMemory<'a> {
+ fn read(&self, addr: u16) -> u8 {
+ match addr {
+ _ => if addr < 0x2000 {
+ self.internal[(addr & 0x07ff) as usize]
+ } else if addr < 0x4000 {
+ let ppu = unsafe {&mut *self.ppu};
+ match addr & 0x7 {
+ 0x2 => ppu.read_status(),
+ 0x4 => ppu.read_oamdata(),
+ 0x7 => ppu.read_data(),
+ _ => panic!("invalid ppu reg read access at 0x{:04x}", addr)
+ }
+ } else if addr < 0x4020 {
+ println!("feeding dummy data for 0x{:04x}", addr);
+ 0
+ } else {
+ self.mapper.read(addr)
+ }
+ }
+ }
+ fn write(&mut self, addr: u16, data: u8) {
+ let ppu = unsafe {&mut *self.ppu};
+ let cpu = unsafe {&mut *self.cpu};
+ if addr < 0x2000 {
+ self.internal[(addr & 0x07ff) as usize] = data;
+ } else if addr < 0x4000 {
+ match addr & 0x7 {
+ 0x0 => ppu.write_ctl(data),
+ 0x1 => ppu.write_mask(data),
+ 0x3 => ppu.write_oamaddr(data),
+ 0x4 => ppu.write_oamdata(data),
+ 0x5 => ppu.write_scroll(data),
+ 0x6 => ppu.write_addr(data),
+ 0x7 => ppu.write_data(data),
+ _ => panic!("invalid ppu reg write access at 0x{:04x}", addr)
+ }
+ } else if addr < 0x4020 {
+ match addr {
+ 0x4014 => ppu.write_oamdma(data, cpu),
+ _ => println!("ignore writing for 0x{:04x}", addr)
+ }
+ } else {
+ self.mapper.write(addr, data)
+ }
+ }
+}
+
+pub struct PPUMemory<'a> {
+ pattern_table: [u8; 0x2000],
+ nametable: [u8; 0x1000],
+ palette: [u8; 0x20],
+ cart: &'a Cartridge,
+ mapper: &'a mut VMem,
}
-impl CPUMemory {
- pub fn new() -> Self {
- CPUMemory{internal: [0; 2048]}
+impl<'a> PPUMemory<'a> {
+ pub fn new(mapper: &'a mut VMem,
+ cart: &'a Cartridge) -> Self {
+ PPUMemory{
+ pattern_table: [0; 0x2000],
+ nametable: [0; 0x1000],
+ palette: [0; 0x20],
+ cart,
+ mapper}
}
}
-impl<'a> VMem for CPUMemory {
+const MIRROR_IDX: [[u8; 4]; 5] = [
+ [0, 0, 1, 1],
+ [0, 1, 0, 1],
+ [0, 0, 0, 0],
+ [1, 1, 1, 1],
+ [0, 1, 2, 3],
+];
+
+fn get_mirror_addr(kind: MirrorType, mut addr: u16) -> u16 {
+ addr = (addr - 0x2000) & 0x0fff;
+ let table = addr >> 10;
+ let offset = addr & 0x03ff;
+ 0x2000 + ((MIRROR_IDX[kind as usize][table as usize] as u16) << 10) + offset
+}
+
+fn mirror_palette(addr: u16) -> u16 {
+ if addr >= 0x10 && addr & 3 == 0 {
+ addr - 0x10
+ } else { addr }
+}
+
+impl<'a> VMem for PPUMemory<'a> {
fn read(&self, addr: u16) -> u8 {
if addr < 0x2000 {
- self.internal[(addr & 0x07ff) as usize]
+ //self.pattern_table[addr as usize]
+ self.mapper.read(addr)
+ } else if addr < 0x3f00 {
+ let kind = self.cart.mirror_type;
+ self.nametable[(get_mirror_addr(kind, addr) & 0x07ff) as usize]
} else if addr < 0x4000 {
- match addr & 0x7 {
- _ => 0
- }
+ self.palette[mirror_palette(addr & 0x1f) as usize]
} else {
- panic!("invalid memory read access at 0x{:04x}", addr)
+ panic!("invalid ppu read access at 0x{:04x}", addr)
}
}
+
fn write(&mut self, addr: u16, data: u8) {
if addr < 0x2000 {
- self.internal[(addr & 0x07ff) as usize] = data;
+ //self.pattern_table[addr as usize] = data
+ self.mapper.write(addr, data)
+ } else if addr < 0x3f00 {
+ let kind = self.cart.mirror_type;
+ self.nametable[(get_mirror_addr(kind, addr) & 0x07ff) as usize] = data
} else if addr < 0x4000 {
- match addr & 0x7 {
- _ => ()
- }
+ self.palette[mirror_palette(addr & 0x1f) as usize] = data
} else {
- panic!("invalid memory write access at 0x{:04x}", addr)
+ panic!("invalid ppu read access at 0x{:04x}", addr)
}
}
+
}