WIP Bus implementation

This commit is contained in:
2022-06-27 22:17:14 -05:00
parent c7a38ecc95
commit 4c61fe9906
3 changed files with 124 additions and 3 deletions
+120
View File
@@ -0,0 +1,120 @@
pub struct Bus {
wram: [u8; 0x10000],
}
#[derive(PartialEq, Debug)]
pub enum MemoryMap {
WRAM,
PPU,
CPU,
Joypad,
Cartridge,
}
impl Bus {
pub fn new() -> Self {
Self {
wram: [0; 0x10000],
}
}
fn read_wram(&self, address: u32) -> u8 {
return self.wram[(address & 0xFFFF) as usize];
}
fn write_wram(&mut self, address: u32, value: u8) {
self.wram[(address & 0xFFFF) as usize] = value;
}
pub fn map_address(address: u32) -> MemoryMap {
let (bank, sub_address) = {
let bank = (address >> 16) as u8;
let sub_address = address as u16;
(bank, sub_address)
};
match bank {
0x7E..=0x7F => MemoryMap::WRAM,
0x80..=0xBF | 0x00..=0x3F => match sub_address {
0x0000..=0x1FFF => MemoryMap::WRAM,
0x2100..=0x21FF => MemoryMap::PPU,
0x4016..=0x4017 => MemoryMap::Joypad,
0x4200..=0x43FF => MemoryMap::CPU,
_ => MemoryMap::Cartridge,
},
_ => MemoryMap::Cartridge,
}
}
pub fn read(&self, address: u32) -> u8 {
let section = Bus::map_address(address);
match section {
MemoryMap::WRAM => self.read_wram(address),
_ => todo!("Implement other memory sections"),
}
}
pub fn write(&mut self, address: u32, value: u8) {
let section = Bus::map_address(address);
match section {
MemoryMap::WRAM => self.write_wram(address, value),
_ => todo!("Implement other memory sections"),
}
}
}
#[cfg(test)]
mod bus_tests {
use super::*;
#[test]
fn memory_map() {
assert_eq!(Bus::map_address(0x7E0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x7F0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x7E0500), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x000000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x3F0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x3F1FFF), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x3F0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x800000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0xBF0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0xBF1FFF), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x3F0000), MemoryMap::WRAM);
assert_eq!(Bus::map_address(0x002100), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x0021FF), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x3F2100), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x3F21FF), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x802100), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x8021FF), MemoryMap::PPU);
assert_eq!(Bus::map_address(0xBF2100), MemoryMap::PPU);
assert_eq!(Bus::map_address(0xBF21FF), MemoryMap::PPU);
assert_eq!(Bus::map_address(0x004200), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x0042FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x3F4200), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x3F42FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x804200), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x8042FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0xBF4200), MemoryMap::CPU);
assert_eq!(Bus::map_address(0xBF42FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x004300), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x0043FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x3F4300), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x3F43FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x804300), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x8043FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0xBF4300), MemoryMap::CPU);
assert_eq!(Bus::map_address(0xBF43FF), MemoryMap::CPU);
assert_eq!(Bus::map_address(0x004016), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0x004017), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0x3F4016), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0x3F4017), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0x804016), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0x804017), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0xBF4016), MemoryMap::Joypad);
assert_eq!(Bus::map_address(0xBF4017), MemoryMap::Joypad);
}
}
+3 -3
View File
@@ -129,10 +129,10 @@ impl CPU {
}
pub fn adc_const(&mut self, value: u16) {
self.registers.pc.wrapping_add(2);
self.registers.pc = self.registers.pc.wrapping_add(2);
self.cycles += 2;
if self.registers.get_memory_select_flag() {
self.registers.pc.wrapping_add(1);
self.registers.pc = self.registers.pc.wrapping_add(1);
self.cycles += 1;
}
if self.registers.get_decimal_mode_flag() {
@@ -144,7 +144,7 @@ impl CPU {
pub fn decode_instruction(&mut self, opcode: u8) {
match opcode {
0x69 => self.adc_const(0x00), // TODO: read value from Bus
_ => (),
_ => todo!("Opcode missing!"),
}
}
}
+1
View File
@@ -1 +1,2 @@
pub mod cpu;
pub mod bus;