Tested and fixed all instructions

! something might still be bugged since the test program is failing,
although not in an obvious manner
This commit is contained in:
Steins7 2022-04-07 15:32:28 +02:00
parent 051cfe6611
commit 1b9c73c432
5 changed files with 165 additions and 59 deletions

5
.gitignore vendored
View File

@ -1,3 +1,6 @@
/target /target
.log *.log
*.bin
*.bin.*

View File

@ -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"),
}
}
}

View File

@ -4,7 +4,7 @@ use log::{debug, error, info, trace, warn};
use bitflags::bitflags; use bitflags::bitflags;
use crate::{ use crate::{
bus::Bus, bus::FileBus,
memory::Memory, memory::Memory,
}; };
@ -17,11 +17,11 @@ trait Input {
} }
trait RInput: Input { trait RInput: Input {
fn read(&self, acc: &u8, bus: &Bus) -> u8; fn read<M: Memory>(&self, acc: &u8, bus: &M) -> u8;
} }
trait WInput: Input { trait WInput: Input {
fn write(&mut self, acc: &mut u8, bus: &mut Bus, data: u8); fn write<M: Memory>(&mut self, acc: &mut u8, bus: &mut M, data: u8);
} }
trait RWInput: RInput + WInput {} trait RWInput: RInput + WInput {}
@ -33,11 +33,11 @@ impl Input for Accumulator {
} }
impl RInput for Accumulator { impl RInput for Accumulator {
fn read(&self, acc: &u8, _bus: &Bus) -> u8 { *acc } fn read<M: Memory>(&self, acc: &u8, _bus: &M) -> u8 { *acc }
} }
impl WInput for Accumulator { impl WInput for Accumulator {
fn write(&mut self, acc: &mut u8, _bus: &mut Bus, data: u8) { *acc = data } fn write<M: Memory>(&mut self, acc: &mut u8, _bus: &mut M, data: u8) { *acc = data }
} }
impl RWInput for Accumulator {} impl RWInput for Accumulator {}
@ -51,7 +51,7 @@ impl Input for Data {
} }
impl RInput for Data { impl RInput for Data {
fn read(&self, _acc: &u8, _bus: &Bus) -> u8 { self.data } fn read<M: Memory>(&self, _acc: &u8, _bus: &M) -> u8 { self.data }
} }
struct MemoryVal { struct MemoryVal {
@ -64,13 +64,13 @@ impl Input for MemoryVal {
} }
impl RInput for MemoryVal { impl RInput for MemoryVal {
fn read(&self, _acc: &u8, bus: &Bus) -> u8 { fn read<M: Memory>(&self, _acc: &u8, bus: &M) -> u8 {
bus.read_addr(self.addr) bus.read_addr(self.addr)
} }
} }
impl WInput for MemoryVal { impl WInput for MemoryVal {
fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) { fn write<M: Memory>(&mut self, _acc: &mut u8, bus: &mut M, data: u8) {
bus.write_addr(self.addr, data); bus.write_addr(self.addr, data);
} }
} }
@ -93,13 +93,13 @@ impl Input for MemoryValExtra {
} }
impl RInput for MemoryValExtra { impl RInput for MemoryValExtra {
fn read(&self, _acc: &u8, bus: &Bus) -> u8 { fn read<M: Memory>(&self, _acc: &u8, bus: &M) -> u8 {
bus.read_addr(self.addr) bus.read_addr(self.addr)
} }
} }
impl WInput for MemoryValExtra { impl WInput for MemoryValExtra {
fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) { fn write<M: Memory>(&mut self, _acc: &mut u8, bus: &mut M, data: u8) {
bus.write_addr(self.addr, data); bus.write_addr(self.addr, data);
self.extra_cycle = true; self.extra_cycle = true;
@ -145,7 +145,7 @@ pub struct Cpu {
pc: u16, pc: u16,
s: u8, s: u8,
p: StatusReg, p: StatusReg,
bus: Bus, bus: FileBus,
} }
impl fmt::Debug for Cpu { impl fmt::Debug for Cpu {
@ -167,14 +167,20 @@ impl fmt::Debug for Cpu {
impl Cpu { impl Cpu {
pub fn new() -> Self { 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 { Cpu {
a: 1, a: 0,
x: 1, //TODO temporary x: 0,
y: 2, //TODO temporary y: 0,
pc: 0, //TODO to be verified pc: (pc_lo | (pc_hi << 8)) + 3,
s: 0xFD, s: 0xFD,
p: StatusReg::from_bits(0x35).unwrap(), p: StatusReg::from_bits(0x34).unwrap(),
bus: Bus::new(), bus,
} }
} }
@ -186,6 +192,13 @@ impl Cpu {
fn execute(&mut self) { fn execute(&mut self) {
let opcode = self.read_pc_addr(); 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, let cycles = parse_opcode!(self, opcode,
0x69 => adc(mode_immediate), 0x69 => adc(mode_immediate),
0x65 => adc(mode_zero_page), 0x65 => adc(mode_zero_page),
@ -296,9 +309,9 @@ impl Cpu {
0xA0 => ldy(mode_immediate), 0xA0 => ldy(mode_immediate),
0xA4 => ldy(mode_zero_page), 0xA4 => ldy(mode_zero_page),
0xB4 => ldy(mode_zero_page_y), 0xB4 => ldy(mode_zero_page_x),
0xAC => ldy(mode_absolute), 0xAC => ldy(mode_absolute),
0xBC => ldy(mode_absolute_y), 0xBC => ldy(mode_absolute_x),
0x4A => lsr(mode_accumulator), 0x4A => lsr(mode_accumulator),
0x46 => lsr(mode_zero_page), 0x46 => lsr(mode_zero_page),
@ -372,10 +385,7 @@ impl Cpu {
0x8A => txa(mode_implicit), 0x8A => txa(mode_implicit),
0x9A => txs(mode_implicit), 0x9A => txs(mode_implicit),
0x98 => tya(mode_implicit), 0x98 => tya(mode_implicit),
); );
info!("0x{:X}: {} cycles", opcode, cycles);
} }
/// Implicit mode /// Implicit mode
@ -411,7 +421,7 @@ impl Cpu {
/// val = PEEK((arg + X) & 0xFF) /// val = PEEK((arg + X) & 0xFF)
fn mode_zero_page_x(&mut self) -> MemoryVal { fn mode_zero_page_x(&mut self) -> MemoryVal {
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, cycles: 4,
} }
} }
@ -421,7 +431,7 @@ impl Cpu {
/// val = PEEK((arg + Y) & 0xFF) /// val = PEEK((arg + Y) & 0xFF)
fn mode_zero_page_y(&mut self) -> MemoryVal { fn mode_zero_page_y(&mut self) -> MemoryVal {
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, cycles: 4,
} }
} }
@ -558,8 +568,8 @@ impl Cpu {
/// Increment PC, then read corresponding value in memory /// Increment PC, then read corresponding value in memory
fn read_pc_addr(&mut self) -> u8 { fn read_pc_addr(&mut self) -> u8 {
self.pc += 1;
let val = self.bus.read_addr(self.pc); let val = self.bus.read_addr(self.pc);
self.pc += 1;
val val
} }
@ -692,11 +702,12 @@ impl Cpu {
fn brk(&mut self, _: ()) -> u32 { fn brk(&mut self, _: ()) -> u32 {
// store PC on stack // store PC on stack
self.push_stack((self.pc >> 8) as u8); let pc = self.pc.wrapping_add(1);
self.push_stack(self.pc as u8); self.push_stack((pc >> 8) as u8);
self.push_stack(pc as u8);
// store status register // 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); self.push_stack(self.p.bits() as u8);
// load interrupt vector // load interrupt vector
@ -743,7 +754,7 @@ impl Cpu {
self.p.set(StatusReg::C, reg >= val); self.p.set(StatusReg::C, reg >= val);
self.p.set(StatusReg::Z, 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() input.get_cycles()
} }
@ -798,8 +809,8 @@ impl Cpu {
// compute // compute
self.a = (!self.a & val) | (self.a & !val); self.a = (!self.a & val) | (self.a & !val);
self.p.set(StatusReg::Z, self.y == 0); self.p.set(StatusReg::Z, self.a == 0);
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
input.get_cycles() input.get_cycles()
} }
@ -809,8 +820,8 @@ impl Cpu {
// compute // compute
val = val.wrapping_add(1); val = val.wrapping_add(1);
self.p.set(StatusReg::Z, self.y == 0); self.p.set(StatusReg::Z, val == 0);
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0);
// store result // store result
input.write(&mut self.a, &mut self.bus, val); input.write(&mut self.a, &mut self.bus, val);
@ -821,8 +832,8 @@ impl Cpu {
// compute // compute
self.x = self.x.wrapping_add(1); self.x = self.x.wrapping_add(1);
self.p.set(StatusReg::Z, self.y == 0); self.p.set(StatusReg::Z, self.x == 0);
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0); self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0);
2 2
} }
@ -845,8 +856,9 @@ impl Cpu {
fn jsr(&mut self, input: MemoryVal) -> u32 { fn jsr(&mut self, input: MemoryVal) -> u32 {
// store return point // store return point
self.push_stack((self.pc >> 8) as u8); let pc = self.pc.wrapping_sub(1);
self.push_stack(self.pc as u8); self.push_stack((pc >> 8) as u8);
self.push_stack(pc as u8);
// load target address // load target address
self.pc = input.addr; self.pc = input.addr;
@ -924,12 +936,18 @@ impl Cpu {
} }
fn php(&mut self, _: ()) -> u32 { 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 3
} }
fn pla(&mut self, _: ()) -> u32 { fn pla(&mut self, _: ()) -> u32 {
self.a = self.pop_stack(); self.a = self.pop_stack();
self.p.set(StatusReg::Z, self.a == 0);
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
4 4
} }
@ -952,6 +970,10 @@ impl Cpu {
} }
self.p.set(StatusReg::C, carry); 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 // store value
input.write(&mut self.a, &mut self.bus, val); input.write(&mut self.a, &mut self.bus, val);
input.get_cycles() + 2 input.get_cycles() + 2
@ -970,6 +992,10 @@ impl Cpu {
} }
self.p.set(StatusReg::C, carry); 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 // store value
input.write(&mut self.a, &mut self.bus, val); input.write(&mut self.a, &mut self.bus, val);
input.get_cycles() + 2 input.get_cycles() + 2
@ -979,7 +1005,7 @@ impl Cpu {
// load status register (B is cleared and I overrided) // load status register (B is cleared and I overrided)
self.p = StatusReg::from_bits_truncate(self.pop_stack()); 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 // load pc
let pc_lo = self.pop_stack() as u16; let pc_lo = self.pop_stack() as u16;
@ -995,6 +1021,7 @@ impl Cpu {
let pc_lo = self.pop_stack() as u16; let pc_lo = self.pop_stack() as u16;
let pc_hi = self.pop_stack() as u16; let pc_hi = self.pop_stack() as u16;
self.pc = pc_lo | (pc_hi << 8); self.pc = pc_lo | (pc_hi << 8);
self.pc = self.pc.wrapping_add(1);
6 6
} }

View File

@ -39,13 +39,15 @@ fn main() -> Result<(), &'static str> {
let vec: Vec<[u8; 4]> = (&buffer).into(); let vec: Vec<[u8; 4]> = (&buffer).into();
fb.update_buffer(&vec); fb.update_buffer(&vec);
let mut update = false;
let mut refresh = true;
let mut frame_counter = 0;
// event loop // event loop
fb.glutin_handle_basic_input(&mut event_loop, |fb, input| { fb.glutin_handle_basic_input(&mut event_loop, |fb, input| {
use winit::event::VirtualKeyCode; use winit::event::VirtualKeyCode;
// wait for input before updating // wait for input before updating
input.wait = true;
// close if escape is pressed // close if escape is pressed
if input.key_pressed(VirtualKeyCode::Escape) { if input.key_pressed(VirtualKeyCode::Escape) {
@ -55,15 +57,43 @@ fn main() -> Result<(), &'static str> {
// execute next cpu instruction (step mode) // execute next cpu instruction (step mode)
if input.key_pressed(VirtualKeyCode::S) { if input.key_pressed(VirtualKeyCode::S) {
cpu.tick(); 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(); let mut debug_str = String::new();
write!(debug_str, "{:#?}", cpu).unwrap(); write!(debug_str, "{:#?}", cpu).unwrap();
buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255)); buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255));
renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]); renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]);
}
let vec: Vec<[u8; 4]> = (&buffer).into(); let vec: Vec<[u8; 4]> = (&buffer).into();
fb.update_buffer(&vec); fb.update_buffer(&vec);
}
true true
}); });

View File

@ -16,17 +16,12 @@ pub struct Ram<const SIZE: usize> {
impl<const SIZE: usize> fmt::Debug for Ram<SIZE> { impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.buffer.iter().enumerate() for i in 0x100..=0x1FF {
.try_for_each(|(i, elem)| {
if i <= 0xFF {
if i%0x10 == 0 { if i%0x10 == 0 {
f.write_fmt(format_args!("\n {:0>4X}", i))?; f.write_fmt(format_args!("\n {:0>4X}", i))?;
} }
f.write_fmt(format_args!(" {:0>2X}", elem)) f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))?
} else {
Ok(())
} }
})?;
Ok(()) Ok(())
} }
@ -51,4 +46,19 @@ impl<const SIZE: usize> Ram<SIZE> {
buffer: [0u8; SIZE], 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,
}
}
} }