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
.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 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<M: Memory>(&self, acc: &u8, bus: &M) -> u8;
}
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 {}
@ -33,11 +33,11 @@ impl Input 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 {
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 {}
@ -51,7 +51,7 @@ impl Input 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 {
@ -64,13 +64,13 @@ impl Input 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)
}
}
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);
}
}
@ -93,13 +93,13 @@ impl Input 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)
}
}
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);
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
}

View File

@ -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
});

View File

@ -16,18 +16,13 @@ pub struct Ram<const SIZE: usize> {
impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
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<const SIZE: usize> Ram<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,
}
}
}