From 4c61fe990679768eb53dcc69fcb50e69c1568bcd Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Mon, 27 Jun 2022 22:17:14 -0500 Subject: [PATCH] WIP Bus implementation --- snes-core/src/bus.rs | 120 +++++++++++++++++++++++++++++++++++++++++++ snes-core/src/cpu.rs | 6 +-- snes-core/src/lib.rs | 1 + 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/snes-core/src/bus.rs b/snes-core/src/bus.rs index e69de29..825d6da 100644 --- a/snes-core/src/bus.rs +++ b/snes-core/src/bus.rs @@ -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); + } +} + diff --git a/snes-core/src/cpu.rs b/snes-core/src/cpu.rs index 5859b65..87a02f6 100644 --- a/snes-core/src/cpu.rs +++ b/snes-core/src/cpu.rs @@ -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!"), } } } diff --git a/snes-core/src/lib.rs b/snes-core/src/lib.rs index 3bfb62f..b3d151d 100644 --- a/snes-core/src/lib.rs +++ b/snes-core/src/lib.rs @@ -1 +1,2 @@ pub mod cpu; +pub mod bus;