diff --git a/core/src/cpu/disassembler.rs b/core/src/cpu/disassembler.rs index 7ffd516..ede8a22 100644 --- a/core/src/cpu/disassembler.rs +++ b/core/src/cpu/disassembler.rs @@ -2,14 +2,14 @@ use crate::cpu::op::AddressingMode::*; use crate::cpu::op::{AddressingMode, Instruction}; use crate::cpu::Cpu; -impl Cpu<'_> { +impl Cpu { pub fn disassemble_next_instr(&self) { let registers = self.registers; - let op_code = self.memory_bus.get_byte(registers.pc); + let op_code = self.memory_bus.borrow().get_byte(registers.pc) as usize; let instr: Instruction = Self::INSTRUCTIONS[op_code]; let operation = instr.op().to_string(); - let addr_mode = self.disassemble_addr_mode(instr.addr_mode()); + let addr_mode = self.disassemble_addr_mode(instr.addr_mode(), registers.pc); dbg!( "DIS {:#04x} - {:#02x} {:?} {:?} - A {:#02x}, X {:#02x}, Y {:#02x}, SP: {:#02x}, F: {:#02x}", @@ -26,7 +26,7 @@ impl Cpu<'_> { } fn disassemble_addr_mode(&self, addr_mode: AddressingMode, pc: u16) -> String { - let word_peek = self.memory_bus.get_word(pc); + let word_peek = self.memory_bus.borrow().get_word(pc); let byte_peek = (word_peek & 0xFF) as u8; match addr_mode { diff --git a/core/src/cpu/mod.rs b/core/src/cpu/mod.rs index cf7f2a1..31bb372 100644 --- a/core/src/cpu/mod.rs +++ b/core/src/cpu/mod.rs @@ -2,6 +2,7 @@ mod disassembler; mod op; mod operations; +use std::cell::RefCell; use crate::memory::MemoryBus; use crate::Clock; use bitflags::bitflags; @@ -9,18 +10,18 @@ use bitflags::bitflags; const STACK_ADDR: u16 = 0x0100; /// Represents a 6502 CPU -struct Cpu<'a> { +pub struct Cpu { /// The registers of the CPU registers: CpuRegisters, /// The memory bus accessible by the CPU - memory_bus: &'a MemoryBus, + memory_bus: RefCell, /// The number of cycles ran on the CPU - cycle: u32, + cycle: usize, /// The amount of cycles the CPU will be busy for (won't execute any instruction) - busy_cycle_count: u16, + busy_cycle_count: usize, /// Whether an OAM DMA was triggered (data transfer to the PPU OAM memory) oam_dma_triggered: bool, @@ -131,8 +132,8 @@ pub trait CpuInternals { fn stack_pop_context(&mut self); } -impl<'a> Cpu<'a> { - pub fn new(memory_bus: &mut MemoryBus) -> Self { +impl Cpu { + pub fn new(memory_bus: RefCell) -> Self { Cpu { registers: CpuRegisters { pc: 0x8000, @@ -151,9 +152,9 @@ impl<'a> Cpu<'a> { } } -impl CpuInternals for Cpu<'_> { +impl CpuInternals for Cpu { fn get_status_flag(&self, flag: CpuStatus) -> bool { - *self.registers.status & flag + self.registers.status & flag.bits() > 0 } fn get_status_flag_u8(&self, flag: CpuStatus) -> u8 { @@ -166,14 +167,14 @@ impl CpuInternals for Cpu<'_> { } fn program_get_next_byte(&mut self) -> u8 { - let byte = self.memory_bus.get_byte(self.registers.pc); + let byte = self.memory_bus.borrow().get_byte(self.registers.pc); self.registers.pc += 1; byte } fn program_get_next_word(&mut self) -> u16 { - let word = self.memory_bus.get_word(self.registers.pc); + let word = self.memory_bus.borrow().get_word(self.registers.pc); self.registers.pc += 2; word @@ -181,9 +182,9 @@ impl CpuInternals for Cpu<'_> { fn set_status_flag(&mut self, flag: CpuStatus, set: bool) { if set { - *self.registers.status |= flag; + self.registers.status |= flag.bits(); } else { - *self.registers.status &= !flag; + self.registers.status &= !flag.bits(); } } @@ -196,7 +197,7 @@ impl CpuInternals for Cpu<'_> { assert!(self.registers.sp > 0); let addr = STACK_ADDR | self.registers.sp as u16; - self.memory_bus.set_byte(addr, value); + self.memory_bus.borrow_mut().set_byte(addr, value); self.registers.sp -= 1; } @@ -211,7 +212,7 @@ impl CpuInternals for Cpu<'_> { self.registers.sp += 1; let addr = STACK_ADDR | self.registers.sp as u16; - self.memory_bus.get_byte(addr) + self.memory_bus.borrow().get_byte(addr) } fn stack_pop_word(&mut self) -> u16 { @@ -240,7 +241,7 @@ impl CpuInternals for Cpu<'_> { } } -impl Clock for Cpu<'_> { +impl Clock for Cpu { fn cycle(&mut self) { self.cycle += 1; @@ -252,7 +253,7 @@ impl Clock for Cpu<'_> { self.disassemble_next_instr(); let op_code = self.program_get_next_byte(); - let instr = Self::INSTRUCTIONS[op_code]; + let instr = Self::INSTRUCTIONS[op_code as usize]; self.busy_cycle_count = instr.cycles(); self.exec_instruction(instr); diff --git a/core/src/cpu/op.rs b/core/src/cpu/op.rs index f0a5ff0..5c6d0a9 100644 --- a/core/src/cpu/op.rs +++ b/core/src/cpu/op.rs @@ -31,13 +31,10 @@ use OperationType::{ }; /// CPU Instruction. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Instruction(u8, AddressingMode, OperationType, usize); impl Instruction { - pub const fn opcode(&self) -> u8 { - self.0 - } - pub const fn addr_mode(&self) -> AddressingMode { self.1 } @@ -69,7 +66,7 @@ impl Operand { self.value as u8 } - pub const fn is_address(&self) -> bool { + pub fn is_address(&self) -> bool { self.operand_type == OperandType::Address } @@ -79,7 +76,7 @@ impl Operand { OperandType::Immediate => self.value_u8(), OperandType::Address => { let addr = self.value; - cpu.memory_bus.get_byte(addr) + cpu.memory_bus.borrow().get_byte(addr) } } } @@ -89,7 +86,7 @@ impl Operand { OperandType::Accumulator => cpu.registers.a = value, OperandType::Address => { let addr = self.value; - cpu.memory_bus.set_byte(addr, value); + cpu.memory_bus.borrow_mut().set_byte(addr, value); } OperandType::Immediate => unreachable!("Cannot write to immediate operand"), } @@ -97,7 +94,7 @@ impl Operand { } // Operands -impl Cpu<'_> { +impl Cpu { /// 16x16 grid of 6502 opcodes. Matches datasheet matrix for easy lookup #[rustfmt::skip] pub const INSTRUCTIONS: [Instruction; 256] = [ @@ -119,13 +116,6 @@ impl Cpu<'_> { Instruction(0xF0, REL, BEQ, 2), Instruction(0xF1, IDY, SBC, 5), Instruction(0xF2, IMP, STP, 2), Instruction(0xF3, IDY, ISB, 8), Instruction(0xF4, ZPX, NOP, 4), Instruction(0xF5, ZPX, SBC, 4), Instruction(0xF6, ZPX, INC, 6), Instruction(0xF7, ZPX, ISB, 6), Instruction(0xF8, IMP, SED, 2), Instruction(0xF9, ABY, SBC, 4), Instruction(0xFA, IMP, NOP, 2), Instruction(0xFB, ABY, ISB, 7), Instruction(0xFC, ABX, NOP, 4), Instruction(0xFD, ABX, SBC, 4), Instruction(0xFE, ABX, INC, 7), Instruction(0xFF, ABX, ISB, 7), ]; - pub fn read_next_instruction(&mut self) -> Instruction { - let op_code = self.program_get_next_byte(); - let instruction = Instruction[op_code]; - - instruction - } - /// Decodes the next operand in memory /// /// # Arguments @@ -226,11 +216,11 @@ impl Cpu<'_> { if ref_addr & 0xFF == 0xFF { // Error in NES CPU for JMP op - let low = self.memory_bus.get_byte(ref_addr) as u16; - let high = self.memory_bus.get_byte(ref_addr & 0xFF00) as u16; + let low = self.memory_bus.borrow().get_byte(ref_addr) as u16; + let high = self.memory_bus.borrow().get_byte(ref_addr & 0xFF00) as u16; low + (high << 8) } else { - self.memory_bus.get_word(ref_addr) + self.memory_bus.borrow().get_word(ref_addr) } } @@ -239,17 +229,17 @@ impl Cpu<'_> { let mut ref_addr = self.program_get_next_byte() as u16; ref_addr += self.registers.x as u16; - let low = self.memory_bus.get_byte(ref_addr & 0xFF) as u16; - let high = self.memory_bus.get_byte((ref_addr + 1) & 0xFF) as u16; + let low = self.memory_bus.borrow().get_byte(ref_addr & 0xFF) as u16; + let high = self.memory_bus.borrow().get_byte((ref_addr + 1) & 0xFF) as u16; low + (high << 8) } /// (d),y - PEEK(byte) + Y fn operand_addr_indy(&mut self, page_crossed: &mut bool) -> u16 { - let mut ref_addr = self.program_get_next_byte() as u16; + let ref_addr = self.program_get_next_byte() as u16; - let low = self.memory_bus.get_byte(ref_addr) as u16; - let high = self.memory_bus.get_byte((ref_addr + 1) & 0xFF) as u16; + let low = self.memory_bus.borrow().get_byte(ref_addr) as u16; + let high = self.memory_bus.borrow().get_byte((ref_addr + 1) & 0xFF) as u16; let addr = low + (high << 8); let incr_addr = addr + self.registers.y as u16; @@ -265,7 +255,7 @@ impl Cpu<'_> { // The offset is signed let positive_offset = offset & 0x7F; - if offset & 0x80 { + if offset & 0x80 > 0 { base_addr.wrapping_sub(positive_offset) } else { base_addr.wrapping_add(positive_offset) diff --git a/core/src/cpu/operations.rs b/core/src/cpu/operations.rs index 5501d28..477e875 100644 --- a/core/src/cpu/operations.rs +++ b/core/src/cpu/operations.rs @@ -7,7 +7,7 @@ fn is_sign_overflow(val1: u8, val2: u8, result: u8) -> bool { (val1 & 0x80 == val2 & 0x80) && (val1 & 0x80 != result & 0x80) } -impl Cpu<'_> { +impl Cpu { pub fn exec_instruction(&mut self, instr: Instruction) { let operand = self.operand_decode(instr.addr_mode()); if operand.is_page_crossing { @@ -322,6 +322,11 @@ impl Cpu<'_> { self.set_status_flag(CpuStatus::Carry, false); } + /// Clear decimal flag + fn op_cld(&mut self, operand: Operand) { + self.set_status_flag(CpuStatus::Decimal, false); + } + /// Clear interrupt disable flag fn op_cli(&mut self, operand: Operand) { self.set_status_flag(CpuStatus::InterruptDisable, false); @@ -470,7 +475,7 @@ impl Cpu<'_> { value } else { assert_eq!(addr_mode, AddressingMode::IND); - self.memory_bus.get_word(value) + self.memory_bus.borrow().get_word(value) }; self.registers.pc = target_addr; @@ -840,6 +845,13 @@ impl Cpu<'_> { self.set_common_flags(x); } + /// Transfer X to stack pointer + fn op_txs(&mut self, operand: Operand) { + let x = self.registers.x; + + self.registers.sp = x; + } + /// Transfer Y to A fn op_tya(&mut self, operand: Operand) { let y = self.registers.y; diff --git a/core/src/rom/mod.rs b/core/src/rom/mod.rs index ac6d57f..ecfda45 100644 --- a/core/src/rom/mod.rs +++ b/core/src/rom/mod.rs @@ -99,7 +99,7 @@ impl Rom { } } -enum RomReadError { +pub enum RomReadError { FormatNotSupported, Io(std::io::Error), InvalidHeader(String),