From 1b9c73c43213d254dc02a0e8f9b44766499cb154 Mon Sep 17 00:00:00 2001 From: Steins7 Date: Thu, 7 Apr 2022 15:32:28 +0200 Subject: [PATCH] Tested and fixed all instructions ! something might still be bugged since the test program is failing, although not in an obvious manner --- .gitignore | 5 ++- src/bus.rs | 36 +++++++++++++++++ src/cpu.rs | 107 +++++++++++++++++++++++++++++++------------------- src/main.rs | 42 +++++++++++++++++--- src/memory.rs | 34 ++++++++++------ 5 files changed, 165 insertions(+), 59 deletions(-) diff --git a/.gitignore b/.gitignore index 866259d..a6efd65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ /target -.log +*.log +*.bin +*.bin.* + diff --git a/src/bus.rs b/src/bus.rs index ef8ee76..054a8ee 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -112,3 +112,39 @@ impl Bus { } } } + +/// special Bus only used for testing the emulator +pub struct FileBus { + mem: Ram<0x10000>, +} + +impl fmt::Debug for FileBus { + + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Bus") + .field("mem", &self.mem) + .finish() + } +} + +impl Memory for FileBus { + + fn read_addr(&self, addr: u16) -> u8 { + self.mem.read_addr(addr) //RAM is mirrored 3 times + } + + fn write_addr(&mut self, addr: u16, data: u8) { + self.mem.write_addr(addr % 0x0800, data) + } +} + +impl FileBus { + + pub fn new() -> Self { + FileBus { + mem: Ram::from_file("6502_functional_test.bin"), + } + } +} + + diff --git a/src/cpu.rs b/src/cpu.rs index ef805a4..28972e8 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -4,7 +4,7 @@ use log::{debug, error, info, trace, warn}; use bitflags::bitflags; use crate::{ - bus::Bus, + bus::FileBus, memory::Memory, }; @@ -17,11 +17,11 @@ trait Input { } trait RInput: Input { - fn read(&self, acc: &u8, bus: &Bus) -> u8; + fn read(&self, acc: &u8, bus: &M) -> u8; } trait WInput: Input { - fn write(&mut self, acc: &mut u8, bus: &mut Bus, data: u8); + fn write(&mut self, acc: &mut u8, bus: &mut M, data: u8); } trait RWInput: RInput + WInput {} @@ -33,11 +33,11 @@ impl Input for Accumulator { } impl RInput for Accumulator { - fn read(&self, acc: &u8, _bus: &Bus) -> u8 { *acc } + fn read(&self, acc: &u8, _bus: &M) -> u8 { *acc } } impl WInput for Accumulator { - fn write(&mut self, acc: &mut u8, _bus: &mut Bus, data: u8) { *acc = data } + fn write(&mut self, acc: &mut u8, _bus: &mut M, data: u8) { *acc = data } } impl RWInput for Accumulator {} @@ -51,7 +51,7 @@ impl Input for Data { } impl RInput for Data { - fn read(&self, _acc: &u8, _bus: &Bus) -> u8 { self.data } + fn read(&self, _acc: &u8, _bus: &M) -> u8 { self.data } } struct MemoryVal { @@ -64,13 +64,13 @@ impl Input for MemoryVal { } impl RInput for MemoryVal { - fn read(&self, _acc: &u8, bus: &Bus) -> u8 { + fn read(&self, _acc: &u8, bus: &M) -> u8 { bus.read_addr(self.addr) } } impl WInput for MemoryVal { - fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) { + fn write(&mut self, _acc: &mut u8, bus: &mut M, data: u8) { bus.write_addr(self.addr, data); } } @@ -93,13 +93,13 @@ impl Input for MemoryValExtra { } impl RInput for MemoryValExtra { - fn read(&self, _acc: &u8, bus: &Bus) -> u8 { + fn read(&self, _acc: &u8, bus: &M) -> u8 { bus.read_addr(self.addr) } } impl WInput for MemoryValExtra { - fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) { + fn write(&mut self, _acc: &mut u8, bus: &mut M, data: u8) { bus.write_addr(self.addr, data); self.extra_cycle = true; @@ -145,7 +145,7 @@ pub struct Cpu { pc: u16, s: u8, p: StatusReg, - bus: Bus, + bus: FileBus, } impl fmt::Debug for Cpu { @@ -167,14 +167,20 @@ impl fmt::Debug for Cpu { impl Cpu { pub fn new() -> Self { + + // read initial PC value from reset vector + let bus = FileBus::new(); + let pc_lo = bus.read_addr(0xFFFC) as u16; + let pc_hi = bus.read_addr(0xFFFD) as u16; + Cpu { - a: 1, - x: 1, //TODO temporary - y: 2, //TODO temporary - pc: 0, //TODO to be verified + a: 0, + x: 0, + y: 0, + pc: (pc_lo | (pc_hi << 8)) + 3, s: 0xFD, - p: StatusReg::from_bits(0x35).unwrap(), - bus: Bus::new(), + p: StatusReg::from_bits(0x34).unwrap(), + bus, } } @@ -184,8 +190,15 @@ impl Cpu { } fn execute(&mut self) { - + let opcode = self.read_pc_addr(); +// if self.pc-1 > 0x36D0 && self.pc-1 < 0x36D8 { +// println!("{:#?}", self); +// } +// if (self.pc-1) != 0x36D8 { +// println!("0x{:0>4X}: {:0>2X}", self.pc-1, opcode); +// } + let cycles = parse_opcode!(self, opcode, 0x69 => adc(mode_immediate), 0x65 => adc(mode_zero_page), @@ -296,9 +309,9 @@ impl Cpu { 0xA0 => ldy(mode_immediate), 0xA4 => ldy(mode_zero_page), - 0xB4 => ldy(mode_zero_page_y), + 0xB4 => ldy(mode_zero_page_x), 0xAC => ldy(mode_absolute), - 0xBC => ldy(mode_absolute_y), + 0xBC => ldy(mode_absolute_x), 0x4A => lsr(mode_accumulator), 0x46 => lsr(mode_zero_page), @@ -372,10 +385,7 @@ impl Cpu { 0x8A => txa(mode_implicit), 0x9A => txs(mode_implicit), 0x98 => tya(mode_implicit), - ); - - info!("0x{:X}: {} cycles", opcode, cycles); } /// Implicit mode @@ -411,7 +421,7 @@ impl Cpu { /// val = PEEK((arg + X) & 0xFF) fn mode_zero_page_x(&mut self) -> MemoryVal { MemoryVal { - addr: (self.read_pc_addr() + self.x) as u16 & 0x00FF, + addr: (self.read_pc_addr().wrapping_add(self.x)) as u16 & 0x00FF, cycles: 4, } } @@ -421,7 +431,7 @@ impl Cpu { /// val = PEEK((arg + Y) & 0xFF) fn mode_zero_page_y(&mut self) -> MemoryVal { MemoryVal { - addr: (self.read_pc_addr() + self.y) as u16 & 0x00FF, + addr: (self.read_pc_addr().wrapping_add(self.y)) as u16 & 0x00FF, cycles: 4, } } @@ -558,8 +568,8 @@ impl Cpu { /// Increment PC, then read corresponding value in memory fn read_pc_addr(&mut self) -> u8 { - self.pc += 1; let val = self.bus.read_addr(self.pc); + self.pc += 1; val } @@ -692,11 +702,12 @@ impl Cpu { fn brk(&mut self, _: ()) -> u32 { // store PC on stack - self.push_stack((self.pc >> 8) as u8); - self.push_stack(self.pc as u8); + let pc = self.pc.wrapping_add(1); + self.push_stack((pc >> 8) as u8); + self.push_stack(pc as u8); // store status register - self.p.set(StatusReg::B, true); + self.p.set(StatusReg::B | StatusReg::U, true); self.push_stack(self.p.bits() as u8); // load interrupt vector @@ -743,7 +754,7 @@ impl Cpu { self.p.set(StatusReg::C, reg >= val); self.p.set(StatusReg::Z, reg == val); - self.p.set(StatusReg::N, ((reg - val) & (0x1 << 7)) != 0); + self.p.set(StatusReg::N, ((reg.wrapping_sub(val)) & (0x1 << 7)) != 0); input.get_cycles() } @@ -798,8 +809,8 @@ impl Cpu { // compute self.a = (!self.a & val) | (self.a & !val); - self.p.set(StatusReg::Z, self.y == 0); - self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); + self.p.set(StatusReg::Z, self.a == 0); + self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0); input.get_cycles() } @@ -809,8 +820,8 @@ impl Cpu { // compute val = val.wrapping_add(1); - self.p.set(StatusReg::Z, self.y == 0); - self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); + self.p.set(StatusReg::Z, val == 0); + self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0); // store result input.write(&mut self.a, &mut self.bus, val); @@ -821,8 +832,8 @@ impl Cpu { // compute self.x = self.x.wrapping_add(1); - self.p.set(StatusReg::Z, self.y == 0); - self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); + self.p.set(StatusReg::Z, self.x == 0); + self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0); 2 } @@ -845,8 +856,9 @@ impl Cpu { fn jsr(&mut self, input: MemoryVal) -> u32 { // store return point - self.push_stack((self.pc >> 8) as u8); - self.push_stack(self.pc as u8); + let pc = self.pc.wrapping_sub(1); + self.push_stack((pc >> 8) as u8); + self.push_stack(pc as u8); // load target address self.pc = input.addr; @@ -924,12 +936,18 @@ impl Cpu { } fn php(&mut self, _: ()) -> u32 { - self.push_stack(self.p.bits() as u8); + let mut p = self.p; + p.set(StatusReg::B | StatusReg::U, true); + self.push_stack(p.bits() as u8); 3 } fn pla(&mut self, _: ()) -> u32 { + self.a = self.pop_stack(); + self.p.set(StatusReg::Z, self.a == 0); + self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0); + 4 } @@ -952,6 +970,10 @@ impl Cpu { } self.p.set(StatusReg::C, carry); + // update status bits + self.p.set(StatusReg::Z, val == 0); + self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0); + // store value input.write(&mut self.a, &mut self.bus, val); input.get_cycles() + 2 @@ -970,6 +992,10 @@ impl Cpu { } self.p.set(StatusReg::C, carry); + // update status bits + self.p.set(StatusReg::Z, val == 0); + self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0); + // store value input.write(&mut self.a, &mut self.bus, val); input.get_cycles() + 2 @@ -979,7 +1005,7 @@ impl Cpu { // load status register (B is cleared and I overrided) self.p = StatusReg::from_bits_truncate(self.pop_stack()); - self.p.set(StatusReg::B, false); + self.p.set(StatusReg::B | StatusReg::U, false); // load pc let pc_lo = self.pop_stack() as u16; @@ -995,6 +1021,7 @@ impl Cpu { let pc_lo = self.pop_stack() as u16; let pc_hi = self.pop_stack() as u16; self.pc = pc_lo | (pc_hi << 8); + self.pc = self.pc.wrapping_add(1); 6 } diff --git a/src/main.rs b/src/main.rs index 2cd3240..f83d071 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,13 +39,15 @@ fn main() -> Result<(), &'static str> { let vec: Vec<[u8; 4]> = (&buffer).into(); fb.update_buffer(&vec); + let mut update = false; + let mut refresh = true; + let mut frame_counter = 0; // event loop fb.glutin_handle_basic_input(&mut event_loop, |fb, input| { use winit::event::VirtualKeyCode; // wait for input before updating - input.wait = true; // close if escape is pressed if input.key_pressed(VirtualKeyCode::Escape) { @@ -55,16 +57,44 @@ fn main() -> Result<(), &'static str> { // execute next cpu instruction (step mode) if input.key_pressed(VirtualKeyCode::S) { cpu.tick(); - + refresh = true; + } + + if input.key_pressed(VirtualKeyCode::R) { + update = true; + } + + if input.key_pressed(VirtualKeyCode::C) { + update = false; + refresh = true; + } + + if update { + cpu.tick(); + + frame_counter += 1; + if frame_counter > 1000 { + frame_counter = 0; + refresh = true; + } + + input.wait = false; + } else { + input.wait = true; + } + + if refresh { + refresh = false; + let mut debug_str = String::new(); write!(debug_str, "{:#?}", cpu).unwrap(); buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255)); renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]); - } - let vec: Vec<[u8; 4]> = (&buffer).into(); - fb.update_buffer(&vec); - + let vec: Vec<[u8; 4]> = (&buffer).into(); + fb.update_buffer(&vec); + } + true }); diff --git a/src/memory.rs b/src/memory.rs index bb760cf..3097156 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -16,18 +16,13 @@ pub struct Ram { impl fmt::Debug for Ram { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.buffer.iter().enumerate() - .try_for_each(|(i, elem)| { - if i <= 0xFF { - if i%0x10 == 0 { - f.write_fmt(format_args!("\n {:0>4X}", i))?; - } - f.write_fmt(format_args!(" {:0>2X}", elem)) - } else { - Ok(()) - } - })?; - + for i in 0x100..=0x1FF { + if i%0x10 == 0 { + f.write_fmt(format_args!("\n {:0>4X}", i))?; + } + f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))? + } + Ok(()) } } @@ -51,4 +46,19 @@ impl Ram { buffer: [0u8; SIZE], } } + + pub fn from_file(file: &str) -> Self { + use std::{ + fs::File, + io::Read, + }; + + let mut f = File::open(file).unwrap(); + let mut buffer = [0u8; SIZE]; + f.read_exact(&mut buffer).unwrap(); + + Ram { + buffer, + } + } }