diff --git a/snes-core/src/cpu/bus.rs b/snes-core/src/cpu/bus.rs index 997cf3f..1870a0c 100644 --- a/snes-core/src/cpu/bus.rs +++ b/snes-core/src/cpu/bus.rs @@ -56,6 +56,22 @@ impl Bus { } } + /// This function is meant to be used by external parts of the code, + /// for example, to render register info without mutating them + pub fn read_external(&self, address: u32) -> u8 { + let section = Bus::map_address(address); + match section { + MemoryMap::WRAM => self.read_wram(address), + MemoryMap::PPU => self.ppu.registers.read_external(address as u16), + MemoryMap::CPU => self.internal_registers.read_external( + address as u16, + &self.ppu.registers, + ), + MemoryMap::Joypad => 0x00, // TODO: Placeholder + MemoryMap::Cartridge => self.rom.read(address), + } + } + pub fn read(&mut self, address: u32) -> u8 { let section = Bus::map_address(address); match section { diff --git a/snes-core/src/cpu/internal_registers.rs b/snes-core/src/cpu/internal_registers.rs index 48aec25..4178cb2 100644 --- a/snes-core/src/cpu/internal_registers.rs +++ b/snes-core/src/cpu/internal_registers.rs @@ -24,18 +24,31 @@ impl InternalRegisters { self.registers[(address - INTERNAL_REGISTERS_ADDRESS) as usize] = value } - pub fn read(&self, address: u16, ppu_registers: &mut PPURegisters) -> u8 { + pub fn read_external(&self, address: u16, ppu_registers: &PPURegisters) -> u8 { match address { RDNMI => self.read_vblank_nmi(ppu_registers), _ => self._read(address), } } + pub fn read(&self, address: u16, ppu_registers: &mut PPURegisters) -> u8 { + match address { + RDNMI => self.read_vblank_nmi_mut(ppu_registers), + _ => self._read(address), + } + } + pub fn write(&mut self, address: u16, value: u8) { self._write(address, value); } - fn read_vblank_nmi(&self, ppu_registers: &mut PPURegisters) -> u8 { + fn read_vblank_nmi(&self, ppu_registers: &PPURegisters) -> u8 { + let byte = self._read(RDNMI); + let result = (byte & 0x7F) | ((ppu_registers.vblank_nmi as u8) << 7); + result + } + + fn read_vblank_nmi_mut(&self, ppu_registers: &mut PPURegisters) -> u8 { let byte = self._read(RDNMI); // When register is read, bit 7 is cleared let result = (byte & 0x7F) | ((ppu_registers.vblank_nmi as u8) << 7); diff --git a/snes-core/src/ppu/registers.rs b/snes-core/src/ppu/registers.rs index 34d3b46..ced96ac 100644 --- a/snes-core/src/ppu/registers.rs +++ b/snes-core/src/ppu/registers.rs @@ -164,6 +164,10 @@ impl PPURegisters { self.data[(address as usize) - 0x2100] = value; } + pub fn read_external(&self, address: u16) -> u8 { + self._read(address) + } + pub fn read(&mut self, address: u16) -> u8 { let result = self._read(address); match address { diff --git a/snes-frontend/src/cpu.rs b/snes-frontend/src/cpu.rs index 1138371..364711a 100644 --- a/snes-frontend/src/cpu.rs +++ b/snes-frontend/src/cpu.rs @@ -7,22 +7,21 @@ pub struct CPUDisassembler { } impl CPUDisassembler { - // TODO FIXME: please do not mutate the emulator state to fetch upcoming instructions - pub fn get_next_instruction(emulator: &mut Emulator) -> String { - let opcode = emulator.bus.read(emulator.cpu.registers.get_pc_address()); + pub fn get_next_instruction(emulator: &Emulator) -> String { + let opcode = emulator.bus.read_external(emulator.cpu.registers.get_pc_address()); let is_cpu_16bit = emulator.cpu.registers.is_16bit_mode(); let is_index_16bit = emulator.cpu.registers.is_16bit_index(); - let next_byte = emulator.bus.read(emulator.cpu.registers.get_pc_address() + 1); - let next_second_byte = emulator.bus.read(emulator.cpu.registers.get_pc_address() + 2); - let next_third_byte = emulator.bus.read(emulator.cpu.registers.get_pc_address() + 3); + let next_byte = emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 1); + let next_second_byte = emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 2); + let next_third_byte = emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 3); let next_word = { - (emulator.bus.read(emulator.cpu.registers.get_pc_address() + 1) as u16) | - ((emulator.bus.read(emulator.cpu.registers.get_pc_address() + 2) as u16) << 8) + (emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 1) as u16) | + ((emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 2) as u16) << 8) }; let next_word_long = { - (emulator.bus.read(emulator.cpu.registers.get_pc_address() + 1) as u32) | - ((emulator.bus.read(emulator.cpu.registers.get_pc_address() + 2) as u32) << 8) | - ((emulator.bus.read(emulator.cpu.registers.get_pc_address() + 3) as u32) << 16) + (emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 1) as u32) | + ((emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 2) as u32) << 8) | + ((emulator.bus.read_external(emulator.cpu.registers.get_pc_address() + 3) as u32) << 16) }; match opcode { // ADC diff --git a/snes-frontend/src/main.rs b/snes-frontend/src/main.rs index e4ab121..ea0ca82 100644 --- a/snes-frontend/src/main.rs +++ b/snes-frontend/src/main.rs @@ -404,7 +404,7 @@ fn main() { let mut address_row = format!("{:04X} | ", address); for page in (page_start..=page_end).rev() { let bus_address = ((page as u32) << 16) | (address as u32); - address_row = format!("{}{:02X} ", address_row, emulator.bus.read(bus_address)); + address_row = format!("{}{:02X} ", address_row, emulator.bus.read_external(bus_address)); } ui.text(address_row); }