rustfmt cleanup

This commit is contained in:
Trevor Merritt 2025-07-06 13:38:55 -04:00
parent cf14804df2
commit b9242b1943
39 changed files with 1695 additions and 551 deletions

View File

@ -1,9 +1,9 @@
// This is the GUI for the BenEater PC // This is the GUI for the BenEater PC
use beneater::parts::backplane::Backplane;
use beneater::parts::ben_eater_pc::BenEaterPC;
use beneater::parts::cpu_display::CpuDisplay; use beneater::parts::cpu_display::CpuDisplay;
use macroquad::prelude::*; use macroquad::prelude::*;
use macroquad::telemetry::frame; use macroquad::telemetry::frame;
use beneater::parts::ben_eater_pc::BenEaterPC;
use beneater::parts::backplane::Backplane;
#[macroquad::main("Ben Eaters PC")] #[macroquad::main("Ben Eaters PC")]
async fn main() { async fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");

View File

@ -1,5 +1,5 @@
use std::fs;
use core::constants::constants_system::SIZE_32KB; use core::constants::constants_system::SIZE_32KB;
use std::fs;
fn main() { fn main() {
// make the rom data in memory. // make the rom data in memory.

View File

@ -1,20 +1,24 @@
use beneater::parts::backplane::Backplane;
use core::constants::constants_isa_op::*;
use core::constants::constants_system::*;
use std::fs; use std::fs;
use std::ops::Index; use std::ops::Index;
use beneater::parts::backplane::Backplane;
use core::constants::constants_system::*;
use core::constants::constants_isa_op::*;
fn main() { fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");
let mut backplane = Backplane::new(); let mut backplane = Backplane::new();
backplane.load_rom();
println!("Backplane is live."); println!("Backplane is live.");
let mut new_program = [0x00u8; SIZE_32KB]; let mut new_program = [0x00u8; SIZE_32KB];
new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize] = 0x00; new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize] = 0x00;
new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60; new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60;
println!("Set offset in rom..."); println!("Set offset in rom...");
println!("VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ", new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize]); println!(
"VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ",
new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize]
);
// println!("{:?}", new_program); // println!("{:?}", new_program);
backplane.rom.program(&new_program); backplane.rom.program(&new_program);
@ -22,5 +26,4 @@ fn main() {
backplane.memory[0x6000] = ISA_OP_LDA_I; backplane.memory[0x6000] = ISA_OP_LDA_I;
backplane.memory[0x6001] = 0xab; backplane.memory[0x6001] = 0xab;
backplane.tick(); backplane.tick();
} }

View File

@ -1,5 +1,5 @@
pub struct AddressBus { pub struct AddressBus {
pub address: u16 pub address: u16,
} }
impl AddressBus { impl AddressBus {

View File

@ -1,15 +1,27 @@
use core::mos6502cpu::Mos6502Cpu;
use crate::parts::mos6522_peripheral::Mos6522Peripheral; use crate::parts::mos6522_peripheral::Mos6522Peripheral;
use crate::parts::via6522::VIA6522; use crate::parts::via6522::VIA6522;
use core::constants::constants_system::*; use core::constants::constants_system::*;
use core::mos6502cpu::Mos6502Cpu;
use core::periph::at28c256::At28C256; use core::periph::at28c256::At28C256;
use core::periph::rom_chip::RomChip; use core::periph::rom_chip::RomChip;
/// Backplane
///
/// A Backplane hold and coordinates the cpu with the
/// rest of the peripherals.
///
/// This system has
/// -> VIA6522 for peripherals
/// -> 322KB RAM
/// -> 32KB ROM
pub struct Backplane { pub struct Backplane {
// pub for dev // pub for dev
pub cpu: Mos6502Cpu, pub cpu: Mos6502Cpu,
pub via: VIA6522, pub via: VIA6522,
pub memory: Box<[u8; SIZE_64KB]>, pub memory: Box<[u8; SIZE_32KB]>,
pub rom: At28C256 pub rom: At28C256,
data_bus: u8,
address_bus: u16
} }
impl Backplane { impl Backplane {
@ -17,8 +29,10 @@ impl Backplane {
Backplane { Backplane {
cpu: Mos6502Cpu::default(), cpu: Mos6502Cpu::default(),
via: VIA6522::default(), via: VIA6522::default(),
memory: Box::new([0x00; SIZE_64KB]), memory: Box::new([0x00; SIZE_32KB]),
rom: At28C256::default() rom: At28C256::default(),
data_bus: 0x00,
address_bus: 0x0000
} }
} }
@ -26,48 +40,91 @@ impl Backplane {
self.rom.program(to_load); self.rom.program(to_load);
} }
pub fn tick(&mut self) { pub fn tick(&mut self) {
// is the CPU in read or write state // is the CPU in read or write state
let address = self.cpu.address_bus(); self.address_bus = self.cpu.address_bus();
let data = self.cpu.data_bus(); self.data_bus = self.cpu.data_bus();
let rw = self.cpu.read_signal; let rw = self.cpu.read_signal;
println!("- TICK START:"); println!("- TICK START:");
println!("| CPU: Address: 0b{address:016b} Data: 0b{data:08b} CPU RW: {rw}"); println!("| CPU: Address: 0b{:016b} Data: 0b{:08b} CPU RW: {rw}", self.address_bus, self.data_bus);
// via state // via state
println!("| VIA 0b{:08b}/0b{:08b}/0b{:08b}/0b{:08b}/", println!(
"| VIA 0b{:08b}/0b{:08b}/0b{:08b}/0b{:08b}/",
self.via.read(VIA6522_ORA), self.via.read(VIA6522_ORA),
self.via.read(VIA6522_ORA), self.via.read(VIA6522_ORA),
self.via.read(VIA6522_DDRB), self.via.read(VIA6522_DDRB),
self.via.read(VIA6522_DDRA), self.via.read(VIA6522_DDRA),
); );
println!("| LCD"); println!("| LCD");
match address {
/// VIA
0x6000..0x6010 => { // if we are reading
if self.cpu.read_signal { if rw {
self.cpu.set_data_bus(self.via.read((address - 0x6000) as u8)); println!("CPU HAS SET READ FLAG FOR ADDRESS {address:04x} with data 0x{data:02x}");
} else { match self.address_bus {
self.via.write((address - 0x6000) as u8, self.cpu.data_bus());
}
self.via.tick();
}
/// RAM
0x0000..=0x3fff => { 0x0000..=0x3fff => {
if self.cpu.read_signal { // read from ram
self.cpu.set_data_bus(self.memory[address as usize]);
} else { },
self.memory[address as usize] = data;
}
}
/// ROM
0x4000..=0x7fff => { 0x4000..=0x7fff => {
self.rom.read(&(address - 0x4000)); // read from ROM
} }
/// The ether. Scarrrrrrrryyyy......
_ => { _ => {
println!("Lost READ:?{} to {:04x}", self.cpu.read_signal, address); println!("READ OUTSIDE DATA RANGE");
} }
} }
} else {
println!("CPU HAS SET WRITE FLAG FOR ADDRESS 0x{address:04x} with data 0x{data:02x}");
match self.address_bus {
0x6000..=0x600f => {
self.via.write((self.address_bus - 0x6000) as u8, self.data_bus);
},
0x0000..=0x3fff => {
self.memory[self.address_bus] = self.data_bus;
}
_ => {
println!("ATTEMPT TO WRITE OUTSIDE OF MEMORY");
}
}
}
//
//
// match address {
// /// VIA
// 0x6000..=0x600f => {
// if self.cpu.read_signal {
// self.cpu
// .set_data_bus(self.via.read((address - 0x6000) as u8));
// } else {
// self.via
// .write((address - 0x6000) as u8, self.cpu.data_bus());
// }
// self.via.tick();
// }
// /// RAM
// 0x0000..=0x3fff => {
// if self.cpu.read_signal {
// self.cpu.set_data_bus(self.memory[address as usize]);
// } else {
// self.memory[address as usize] = data;
// }
// }
// /// ROM
// 0x4000..=0x7fff => {
// println!("ROM READ AT {address:04x} / ROM OFFSET {:04x}", address - 0x4000);
// self.rom.read(&(address - 0x4000));
// }
// /// The ether. Scarrrrrrrryyyy......
// _ => {
// println!("XXXXLost READ:?{} to {:04x}", self.cpu.read_signal, address);
// }
// }
println!("- TICK DONE"); println!("- TICK DONE");
} }
} }

View File

@ -1,10 +1,10 @@
use crate::parts::clock::Clock;
use core::constants::constants_system::*;
use core::mos6502cpu::Mos6502Cpu;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};
use std::path::Path; use std::path::Path;
use crate::parts::clock::Clock;
use core::mos6502cpu::Mos6502Cpu;
use core::constants::constants_system::*;
pub struct BenEaterPC { pub struct BenEaterPC {
clock: Clock, clock: Clock,
@ -19,7 +19,7 @@ impl BenEaterPC {
println!("New BENEATERPC"); println!("New BENEATERPC");
BenEaterPC { BenEaterPC {
clock: Clock::new(), clock: Clock::new(),
cpu: Mos6502Cpu::default() cpu: Mos6502Cpu::default(),
} }
} }

View File

@ -1,13 +1,10 @@
pub struct Clock { pub struct Clock {
ticks: u32 ticks: u32,
} }
impl Clock { impl Clock {
pub fn new() -> Self { pub fn new() -> Self {
Clock { ticks: 0 }
Clock {
ticks: 0
}
} }
pub fn tick(&mut self) { pub fn tick(&mut self) {

View File

@ -1,7 +1,7 @@
use core::mos6502cpu::Mos6502Cpu;
use macroquad::color::{BLACK, Color}; use macroquad::color::{BLACK, Color};
use macroquad::prelude::*; use macroquad::prelude::*;
use macroquad::text::draw_text; use macroquad::text::draw_text;
use core::mos6502cpu::Mos6502Cpu;
pub struct CpuDisplay {} pub struct CpuDisplay {}
impl CpuDisplay { impl CpuDisplay {
@ -12,11 +12,41 @@ impl CpuDisplay {
// ...build the interface // ...build the interface
Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK); Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK);
draw_text(format!("PC: 0x{:04x} / {}", pc, pc).as_str(), x_offset + 5.0, y_offset + 18.0, 15.0, BLACK); draw_text(
draw_text(format!("A: 0x{:02x} X: 0x{:02x} Y: 0x{:02x}", a, x, y).as_str(), x_offset + 5.0, y_offset + 35.0, 15.0, BLACK); format!("PC: 0x{:04x} / {}", pc, pc).as_str(),
draw_text(format!("Address: {:016b} | {:04x}", address_bus, address_bus).as_str(), x_offset + 5.0, y_offset + 55.0, 15.0, BLACK); x_offset + 5.0,
draw_text(format!("Data: {:08b} | {:02x}", data_bus, data_bus).as_str(), x_offset + 5.0, y_offset + 75.0, 15.0, BLACK); y_offset + 18.0,
draw_text(format!("MS: {:02x}", microsteps_remaining).as_str(), x_offset + 5.0, y_offset + 95.0, 15.0, BLACK); 15.0,
BLACK,
);
draw_text(
format!("A: 0x{:02x} X: 0x{:02x} Y: 0x{:02x}", a, x, y).as_str(),
x_offset + 5.0,
y_offset + 35.0,
15.0,
BLACK,
);
draw_text(
format!("Address: {:016b} | {:04x}", address_bus, address_bus).as_str(),
x_offset + 5.0,
y_offset + 55.0,
15.0,
BLACK,
);
draw_text(
format!("Data: {:08b} | {:02x}", data_bus, data_bus).as_str(),
x_offset + 5.0,
y_offset + 75.0,
15.0,
BLACK,
);
draw_text(
format!("MS: {:02x}", microsteps_remaining).as_str(),
x_offset + 5.0,
y_offset + 95.0,
15.0,
BLACK,
);
} }
fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) { fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {

View File

@ -1,5 +1,5 @@
pub struct DataBus { pub struct DataBus {
pub data: u8 pub data: u8,
} }
impl DataBus { impl DataBus {

View File

@ -1,5 +1,5 @@
use std::time::{Duration, Instant};
use crate::parts::mos6522_peripheral::Mos6522Peripheral; use crate::parts::mos6522_peripheral::Mos6522Peripheral;
use std::time::{Duration, Instant};
#[derive(Debug)] #[derive(Debug)]
pub struct HD44780 { pub struct HD44780 {
@ -46,7 +46,7 @@ impl Mos6522Peripheral for HD44780 {
self.write_control_lines( self.write_control_lines(
control & 1 << 2 == 0, control & 1 << 2 == 0,
control & 1 << 1 == 0, control & 1 << 1 == 0,
control & 1 == 0 control & 1 == 0,
); );
} }

View File

@ -1,10 +1,10 @@
pub mod clock;
pub mod ben_eater_pc;
pub mod via6522;
pub mod display_matrix;
pub mod address_bus; pub mod address_bus;
pub mod data_bus;
pub mod cpu_display;
pub mod ram_display;
pub mod mos6522_peripheral;
pub mod backplane; pub mod backplane;
pub mod ben_eater_pc;
pub mod clock;
pub mod cpu_display;
pub mod data_bus;
pub mod display_matrix;
pub mod mos6522_peripheral;
pub mod ram_display;
pub mod via6522;

View File

@ -4,10 +4,15 @@ pub struct RamDisplay {}
impl RamDisplay { impl RamDisplay {
pub fn render(ram: &Box<[u8]>, x_offset: f32, y_offset: f32) { pub fn render(ram: &Box<[u8]>, x_offset: f32, y_offset: f32) {
Self::draw_square(x_offset, y_offset, x_offset + 200.0, y_offset + 300.0, BLACK); Self::draw_square(
x_offset,
y_offset,
x_offset + 200.0,
y_offset + 300.0,
BLACK,
);
draw_text("RAM", x_offset + 5.0, y_offset + 5.0, 15.0, BLACK); draw_text("RAM", x_offset + 5.0, y_offset + 5.0, 15.0, BLACK);
} }
fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) { fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {

View File

@ -57,7 +57,6 @@ impl VIA6522 {
} }
} }
pub fn read(&self, addr: u8) -> u8 { pub fn read(&self, addr: u8) -> u8 {
match (addr & 0x0F) { match (addr & 0x0F) {
VIA6522_ORB => self.orb, VIA6522_ORB => self.orb,

View File

@ -1,5 +1,5 @@
use core::instruction::Instruction;
use core::address_mode::AddressMode; use core::address_mode::AddressMode;
use core::instruction::Instruction;
use core::operand::Operand; use core::operand::Operand;
use core::operation::Operation; use core::operation::Operation;
@ -11,7 +11,8 @@ fn main() {
op: Operation::NOP, op: Operation::NOP,
mode: AddressMode::Implied, mode: AddressMode::Implied,
operand: Operand::None, operand: Operand::None,
}, &[0xea] },
&[0xea],
)]; )];
for (op, bytes) in instructions { for (op, bytes) in instructions {

View File

@ -1,7 +1,5 @@
use core::mos6502cpu::Mos6502Cpu; use core::mos6502cpu::Mos6502Cpu;
fn main() { fn main() {
let x = Mos6502Cpu::default(); let x = Mos6502Cpu::default();
} }

View File

@ -1,4 +1,3 @@
/// Represents the various addressing modes of the 6502 CPU. /// Represents the various addressing modes of the 6502 CPU.
#[derive(PartialEq, Debug, Copy, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
pub enum AddressMode { pub enum AddressMode {

View File

@ -1,9 +1,5 @@
/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer. /// BenEater computer represents the 'Ben Eater' 6502 breadboard computer.
/// This was built along watching the video series where Ben builds a /// This was built along watching the video series where Ben builds a
/// 6502 on a breadboard and explains each step. /// 6502 on a breadboard and explains each step.
/// ///
pub struct BenEater { pub struct BenEater {}
}

View File

@ -1,2 +1 @@
pub mod beneater; pub mod beneater;

View File

@ -107,7 +107,6 @@ pub const ISA_OP_LDY_ZP: u8 = 0xa4;
pub const ISA_OP_LDY_ZPX: u8 = 0xb4; pub const ISA_OP_LDY_ZPX: u8 = 0xb4;
pub const ISA_OP_LDY_ABS: u8 = 0xac; pub const ISA_OP_LDY_ABS: u8 = 0xac;
pub const ISA_OP_LDY_ABSX: u8 = 0xbc; pub const ISA_OP_LDY_ABSX: u8 = 0xbc;
pub const ISA_OP_LSR_A: u8 = 0x4a; pub const ISA_OP_LSR_A: u8 = 0x4a;
pub const ISA_OP_LSR_ZP: u8 = 0x46; pub const ISA_OP_LSR_ZP: u8 = 0x46;
pub const ISA_OP_LSR_ZPX: u8 = 0x56; pub const ISA_OP_LSR_ZPX: u8 = 0x56;

View File

@ -5,7 +5,6 @@ pub const SIZE_64KB: usize = SIZE_1KB * 64;
pub const OFFSET_RESET_VECTOR: u16 = 0xfffc; pub const OFFSET_RESET_VECTOR: u16 = 0xfffc;
pub const OFFSET_INT_VECTOR: u16 = 0xfffe; pub const OFFSET_INT_VECTOR: u16 = 0xfffe;
pub const VIA6522_ORB: u8 = 0; pub const VIA6522_ORB: u8 = 0;
pub const VIA6522_ORA: u8 = 1; pub const VIA6522_ORA: u8 = 1;
pub const VIA6522_DDRB: u8 = 2; pub const VIA6522_DDRB: u8 = 2;

View File

@ -1,3 +1,3 @@
pub mod constants_isa_stub;
pub mod constants_isa_op; pub mod constants_isa_op;
pub mod constants_isa_stub;
pub mod constants_system; pub mod constants_system;

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
use log::debug;
use crate::address_mode::AddressMode::*;
use crate::constants::constants_isa_op::*;
fn join_word(low: u8, high: u8) -> u16 {
((high as u16) << 8) | low as u16
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_join_word() {
let low: u8 = 0xcd;
let high: u8 = 0xab;
assert_eq!(
join_word(low, high),
0xabcd
);
}
}

View File

@ -1,7 +0,0 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::*;
use crate::mos6502flags::Mos6502Flag::*;
mod from_bytes;
mod to_bytes;
mod to_string;

View File

@ -1,38 +0,0 @@
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY};
use crate::constants::constants_isa_op::*;
fn split_word_hl(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(high, low)
}
fn split_word_lh(to_split: u16) -> (u8, u8) {
let low = (to_split & 0xff) as u8;
let high = ((to_split & 0xff00) >> 8) as u8;
(low, high)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn split_le() {
let value = 0xabcd;
let (high, low) = split_word_hl(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
#[test]
fn split_be() {
let value = 0xabcd;
let (low, high) = split_word_lh(value);
assert_eq!(low, 0xcd);
assert_eq!(high, 0xab);
}
}

View File

@ -1,18 +0,0 @@
fn format(mode: &AddressMode, prefix: &str) -> String {
// let suffix = match mode {
// AddressMode::Implied => "",
// AddressMode::Accumulator => " A",
// AddressMode::Immediate(value) => &*format!(" #${value:02x}"),
// AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"),
// AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"),
// AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"),
// AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"),
// AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"),
// AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"),
// AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"),
// AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y")
// };
// format!("{}{}", prefix, suffix)
prefix.to_string()
}

View File

@ -1,10 +1,36 @@
use crate::address_mode::AddressMode; use crate::address_mode::AddressMode;
use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA}; use crate::constants::constants_isa_op::{
ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX,
ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY,
ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A,
ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS,
ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK,
ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS,
ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY,
ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS,
ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX,
ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I,
ISA_OP_EOR_INDX, ISA_OP_EOR_INDY, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS,
ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS,
ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I,
ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY,
ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I,
ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP,
ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSX, ISA_OP_ORA_ABSY, ISA_OP_ORA_I,
ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP,
ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP,
ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX,
ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I,
ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED,
ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY,
ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS,
ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS,
ISA_OP_TYA,
};
use crate::op_info::OpInfo; use crate::op_info::OpInfo;
use crate::operation::Operation; use crate::operation::Operation;
use crate::operation::Operation::*; use crate::operation::Operation::*;
pub fn INSTRUCTION_CYCLES(instruction: u8) -> u8 { pub fn INSTRUCTION_CYCLES(instruction: u8) -> u8 {
INSTRUCTION_TABLE[instruction as usize].unwrap().cycles INSTRUCTION_TABLE[instruction as usize].unwrap().cycles
} }
@ -723,7 +749,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
operation: Operation::ROR, operation: Operation::ROR,
mode: AddressMode::Accumulator, mode: AddressMode::Accumulator,
length: 1, length: 1,
cycles: 2 cycles: 2,
}); });
table[ISA_OP_ROR_ZP as usize] = Some(OpInfo { table[ISA_OP_ROR_ZP as usize] = Some(OpInfo {
operation: Operation::ROR, operation: Operation::ROR,

View File

@ -1,11 +1,11 @@
pub mod periph;
pub mod address_mode; pub mod address_mode;
pub mod mos6502cpu; pub mod computers;
pub mod instruction;
pub mod mos6502flags;
pub mod constants; pub mod constants;
pub mod operation; pub mod instruction;
pub mod instruction_table;
pub mod mos6502cpu;
pub mod mos6502flags;
pub mod op_info; pub mod op_info;
pub mod operand; pub mod operand;
pub mod instruction_table; pub mod operation;
pub mod computers; pub mod periph;

View File

@ -1,14 +1,14 @@
use log::trace;
use crate::address_mode::AddressMode; use crate::address_mode::AddressMode;
use crate::constants::constants_isa_op::ISA_OP_NOP; use crate::constants::constants_isa_op::ISA_OP_NOP;
use crate::constants::constants_system::*;
use crate::instruction::Instruction; use crate::instruction::Instruction;
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags}; use crate::instruction_table::INSTRUCTION_TABLE;
use crate::mos6502flags::Mos6502Flag::*; use crate::mos6502flags::Mos6502Flag::*;
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags};
use crate::op_info::OpInfo; use crate::op_info::OpInfo;
use crate::operand::Operand; use crate::operand::Operand;
use crate::operation::Operation; use crate::operation::Operation;
use crate::constants::constants_system::*; use log::trace;
use crate::instruction_table::INSTRUCTION_TABLE;
pub struct Mos6502Cpu { pub struct Mos6502Cpu {
memory: [u8; SIZE_64KB], memory: [u8; SIZE_64KB],
@ -34,11 +34,10 @@ pub struct Mos6502Cpu {
cycle_carry: u16, // Value to hold between microsteps cycle_carry: u16, // Value to hold between microsteps
ir_bytes: [u8; 4], ir_bytes: [u8; 4],
/// CPU Read signal /// CPU Read signal
pub read_signal: bool pub read_signal: bool,
} }
impl Mos6502Cpu { impl Mos6502Cpu {
/// set_data_bus /// set_data_bus
/// ///
/// Sets data on the data bus. /// Sets data on the data bus.
@ -71,7 +70,7 @@ impl Default for Mos6502Cpu {
iv: 0xfffe, iv: 0xfffe,
cycle_carry: 0x0000, cycle_carry: 0x0000,
ir_bytes: [0x00; 4], ir_bytes: [0x00; 4],
read_signal: true read_signal: true,
}; };
working.reset_cpu(); working.reset_cpu();
working working
@ -108,7 +107,10 @@ impl Mos6502Cpu {
self.iv = self.read_word(&OFFSET_INT_VECTOR); self.iv = self.read_word(&OFFSET_INT_VECTOR);
self.address_bus = self.pc; self.address_bus = self.pc;
self.read_signal = true; self.read_signal = true;
println!("PC and IV are now set from ROM addresses / AB = {:016b}", self.address_bus); println!(
"PC and IV are now set from ROM addresses / AB = {:016b}",
self.address_bus
);
} }
fn read_word(&self, offset: &u16) -> u16 { fn read_word(&self, offset: &u16) -> u16 {
@ -126,7 +128,11 @@ impl Mos6502Cpu {
self.flags.flag(flag_to_read) self.flags.flag(flag_to_read)
} }
pub fn poke_flag(&mut self, flag_to_set: Mos6502Flag, new_value: bool) { pub fn poke_flag(&mut self, flag_to_set: Mos6502Flag, new_value: bool) {
if new_value { self.flags.set_flag(flag_to_set) } else { self.flags.clear_flag(flag_to_set) } if new_value {
self.flags.set_flag(flag_to_set)
} else {
self.flags.clear_flag(flag_to_set)
}
} }
pub fn peek(&self, offset: u16) -> u8 { pub fn peek(&self, offset: u16) -> u8 {
@ -142,7 +148,6 @@ impl Mos6502Cpu {
self.a self.a
} }
pub fn poke_a(&mut self, new_a: u8) { pub fn poke_a(&mut self, new_a: u8) {
println!("Updating register A from [{}] to [{}]", self.a, new_a); println!("Updating register A from [{}] to [{}]", self.a, new_a);
self.a = new_a; self.a = new_a;
@ -175,7 +180,6 @@ impl Mos6502Cpu {
/// Ticks the CPU /// Ticks the CPU
pub fn tick(&mut self) { pub fn tick(&mut self) {
println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc); println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc);
if self.microcode_step == 0 { if self.microcode_step == 0 {
println!("OUT OF MICROSTEPS. Decoding the next instruction"); println!("OUT OF MICROSTEPS. Decoding the next instruction");
@ -190,12 +194,13 @@ impl Mos6502Cpu {
// set the counter to the number of steps left // set the counter to the number of steps left
} else { } else {
// run 1 microcode step // run 1 microcode step
println!("Microstep {}/{} for {:?}", self.microcode_step, self.oi.cycles, self.ir.op); println!(
"Microstep {}/{} for {:?}",
self.microcode_step, self.oi.cycles, self.ir.op
);
match self.ir.op { match self.ir.op {
Operation::ADC => { Operation::ADC => match self.microcode_step {
match self.microcode_step { 1 => match self.ir.mode {
1 => {
match self.ir.mode {
AddressMode::Immediate => {} AddressMode::Immediate => {}
AddressMode::ZeroPage => {} AddressMode::ZeroPage => {}
AddressMode::ZeroPageX => {} AddressMode::ZeroPageX => {}
@ -206,12 +211,10 @@ impl Mos6502Cpu {
AddressMode::IndirectX => {} AddressMode::IndirectX => {}
AddressMode::IndirectY => {} AddressMode::IndirectY => {}
_ => {} _ => {}
}
}, },
2 => {}, 2 => {}
_ => {} _ => {}
} },
}
Operation::AND => {} Operation::AND => {}
Operation::ASL => {} Operation::ASL => {}
Operation::BCC => {} Operation::BCC => {}
@ -247,10 +250,8 @@ impl Mos6502Cpu {
AddressMode::ZeroPage => { AddressMode::ZeroPage => {
// read from // read from
let offset = match self.ir.operand { let offset = match self.ir.operand {
Operand::Byte(z) => { Operand::Byte(z) => z,
z _ => 0x00,
}
_ => { 0x00 }
}; };
trace!("READING FROM MEMORY AT 0x{offset:04x}"); trace!("READING FROM MEMORY AT 0x{offset:04x}");
self.memory[offset as usize] self.memory[offset as usize]
@ -258,37 +259,29 @@ impl Mos6502Cpu {
} }
AddressMode::ZeroPageX => { AddressMode::ZeroPageX => {
let offset = match self.ir.operand { let offset = match self.ir.operand {
Operand::Byte(z) => { Operand::Byte(z) => z,
z _ => 0x00,
}
_ => { 0x00 }
}; };
// self.memory.peek(offset + self.x); // self.memory.peek(offset + self.x);
self.memory[offset as usize] self.memory[offset as usize]
} }
AddressMode::Absolute => { AddressMode::Absolute => {
let offset = match self.ir.operand { let offset = match self.ir.operand {
Operand::Word(offset) => { Operand::Word(offset) => offset,
offset _ => 0x00,
}
_ => { 0x00 }
}; };
// self.memory.peek(offset) // self.memory.peek(offset)
self.memory[offset as usize] self.memory[offset as usize]
} }
AddressMode::AbsoluteX => { AddressMode::AbsoluteX => {
let offset = match self.ir.operand { let offset = match self.ir.operand {
Operand::Word(offset) => { Operand::Word(offset) => offset,
offset _ => 0x00,
}
_ => { 0x00 }
}; };
// self.memory.peek(offset + self.x); // self.memory.peek(offset + self.x);
self.memory[offset as usize] self.memory[offset as usize]
} }
_ => { _ => 0x00,
0x00
}
}; };
} }
// DEC write memory // DEC write memory
@ -310,8 +303,8 @@ impl Mos6502Cpu {
(self.y, _) = self.y.overflowing_sub(1); (self.y, _) = self.y.overflowing_sub(1);
} }
} }
Operation::EOR => { } Operation::EOR => {}
Operation::INC => { } Operation::INC => {}
Operation::INX => { Operation::INX => {
if self.microcode_step == 1 { if self.microcode_step == 1 {
let (new_x, new_carry) = self.x.overflowing_add(1); let (new_x, new_carry) = self.x.overflowing_add(1);
@ -328,56 +321,47 @@ impl Mos6502Cpu {
self.poke_flag(Carry, new_carry); self.poke_flag(Carry, new_carry);
self.address_bus = self.pc; self.address_bus = self.pc;
self.data_bus = 0x00; self.data_bus = 0x00;
} } }
Operation::JMP => { }
match self.ir.operand { Operation::JMP => match self.ir.operand {
Operand::Word(offset) => { Operand::Word(offset) => {
self.pc = offset; self.pc = offset;
self.address_bus = self.pc; self.address_bus = self.pc;
self.data_bus = 0x00; self.data_bus = 0x00;
} }
_ => {} _ => {}
} },
}
Operation::JSR => { Operation::JSR => {
// push pc to stack. // push pc to stack.
// jump to the subroutine. // jump to the subroutine.
} }
Operation::LDA => { Operation::LDA => match self.oi.mode {
match self.oi.mode { AddressMode::Immediate => match self.ir.operand {
AddressMode::Immediate => {
match self.ir.operand {
Operand::Byte(value) => { Operand::Byte(value) => {
println!("Loading 0x{value:02x} ({value}) into A"); println!("Loading 0x{value:02x} ({value}) into A");
self.a = value; self.a = value;
} }
_ => {} _ => {}
} },
} AddressMode::ZeroPage => match self.ir.operand {
AddressMode::ZeroPage => {
match self.ir.operand {
Operand::Byte(value) => { Operand::Byte(value) => {
println!("Loading from zero page at 0x{value:02x} ({value})"); println!("Loading from zero page at 0x{value:02x} ({value})");
self.a = self.memory[value as usize]; self.a = self.memory[value as usize];
} }
_ => {} _ => {}
} },
} AddressMode::ZeroPageX => match self.ir.operand {
AddressMode::ZeroPageX => {
match self.ir.operand {
Operand::Byte(value) => { Operand::Byte(value) => {
let x_offset = self.x; let x_offset = self.x;
self.a = self.memory[(value + x_offset) as usize]; self.a = self.memory[(value + x_offset) as usize];
} }
_ => {} _ => {}
} },
}
AddressMode::Absolute => { AddressMode::Absolute => {
if let Operand::Word(offset) = self.ir.operand { if let Operand::Word(offset) = self.ir.operand {
println!("Loading from absolute address 0x{offset:04x}"); println!("Loading from absolute address 0x{offset:04x}");
self.a = self.memory[offset as usize]; self.a = self.memory[offset as usize];
} }
} }
AddressMode::AbsoluteX => { AddressMode::AbsoluteX => {
if let Operand::Word(offset) = self.ir.operand { if let Operand::Word(offset) = self.ir.operand {
@ -386,6 +370,8 @@ impl Mos6502Cpu {
} }
AddressMode::AbsoluteY => { AddressMode::AbsoluteY => {
if let Operand::Word(offset) = self.ir.operand { if let Operand::Word(offset) = self.ir.operand {
let real_offset = offset + self.y as u16;
println!("offset: {offset:04x} + {:02x}", self.y);
self.a = self.memory[(offset + self.y as u16) as usize]; self.a = self.memory[(offset + self.y as u16) as usize];
} }
} }
@ -395,8 +381,7 @@ impl Mos6502Cpu {
_ => { _ => {
println!("INVALID ADDRESS MODE FOR LDA"); println!("INVALID ADDRESS MODE FOR LDA");
} }
} },
}
Operation::LDX => {} Operation::LDX => {}
Operation::LDY => {} Operation::LDY => {}
Operation::LSR => {} Operation::LSR => {}
@ -501,13 +486,11 @@ impl Mos6502Cpu {
Operation::TAY => { Operation::TAY => {
self.y = self.a; self.y = self.a;
} }
Operation::TSX => { Operation::TSX => {}
}
Operation::TXA => { Operation::TXA => {
self.a = self.x; self.a = self.x;
} }
Operation::TXS => { Operation::TXS => {}
}
Operation::TYA => { Operation::TYA => {
self.y = self.a; self.y = self.a;
} }
@ -517,25 +500,41 @@ impl Mos6502Cpu {
} }
pub fn dump(&self) { pub fn dump(&self) {
println!("CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}", println!(
self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step, self.flags.dump()); "CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}",
self.pc,
self.a,
self.x,
self.y,
self.address_bus,
self.data_bus,
self.microcode_step,
self.flags.dump()
);
} }
/// dump_data /// dump_data
/// ///
/// returns /// returns
/// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step /// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step
pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8, u8) { pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8) {
(self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus, self.microcode_step) (
self.pc,
self.a,
self.x,
self.y,
self.address_bus,
self.data_bus,
self.microcode_step,
)
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*;
use crate::constants::constants_isa_op::*; use crate::constants::constants_isa_op::*;
use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE}; use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE};
use super::*;
#[test] #[test]
fn clc() { fn clc() {
@ -548,7 +547,9 @@ mod test {
cpu.pc = 0x6000; cpu.pc = 0x6000;
// Tick the CPU through the instruction // Tick the CPU through the instruction
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLC as usize].unwrap().cycles { cpu.tick(); } for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLC) {
cpu.tick();
}
assert!(!cpu.peek_flag(Carry)); assert!(!cpu.peek_flag(Carry));
} }
@ -560,7 +561,9 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLD; cpu.memory[0x6000] = ISA_OP_CLD;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLD as usize].unwrap().cycles { cpu.tick(); } for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLD) {
cpu.tick();
}
assert!(!cpu.peek_flag(Decimal)); assert!(!cpu.peek_flag(Decimal));
} }
@ -572,10 +575,11 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLI; cpu.memory[0x6000] = ISA_OP_CLI;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) {
cpu.tick();
}
assert!(!cpu.peek_flag(Interrupt)); assert!(!cpu.peek_flag(Interrupt));
} }
#[test] #[test]
@ -585,7 +589,9 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLV; cpu.memory[0x6000] = ISA_OP_CLV;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) {
cpu.tick();
}
assert!(!cpu.peek_flag(Overflow)); assert!(!cpu.peek_flag(Overflow));
} }
@ -597,7 +603,9 @@ mod test {
cpu.memory[0x6001] = 0xab; cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab); assert_eq!(cpu.a, 0xab);
} }
@ -611,7 +619,9 @@ mod test {
cpu.memory[0x00ac] = 0xbe; cpu.memory[0x00ac] = 0xbe;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) { cpu.tick(); }; for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) {
cpu.tick();
}
// println!("MEMORY AT 0x00aa, ab, ac, ad, ae -> {:02x} {:02x} {:02x} {:02x} {:02x}", cpu.memory[0x00aa], cpu.memory[0x00ab], cpu.memory[0x00ac], cpu.memory[0x00ad], cpu.memory[0x00ae]); // println!("MEMORY AT 0x00aa, ab, ac, ad, ae -> {:02x} {:02x} {:02x} {:02x} {:02x}", cpu.memory[0x00aa], cpu.memory[0x00ab], cpu.memory[0x00ac], cpu.memory[0x00ad], cpu.memory[0x00ae]);
// cpu.dump(); // cpu.dump();
@ -630,7 +640,9 @@ mod test {
cpu.memory[0x00ab] = 0xbe; cpu.memory[0x00ab] = 0xbe;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) { cpu.tick(); } for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) {
cpu.tick();
}
assert_eq!(cpu.a, 0xbe); assert_eq!(cpu.a, 0xbe);
} }
@ -644,7 +656,9 @@ mod test {
cpu.memory[0x0eef] = 0xab; cpu.memory[0x0eef] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab); assert_eq!(cpu.a, 0xab);
} }
@ -659,7 +673,9 @@ mod test {
cpu.memory[0x0ef0] = 0xab; cpu.memory[0x0ef0] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab); assert_eq!(cpu.a, 0xab);
} }
@ -669,12 +685,14 @@ mod test {
let mut cpu = Mos6502Cpu::default(); let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_ABSY; cpu.memory[0x6000] = ISA_OP_LDA_ABSY;
cpu.memory[0x6001] = 0xef; cpu.memory[0x6001] = 0xef;
cpu.memory[0x6002] = 0xbe; cpu.memory[0x6002] = 0x0e;
cpu.poke_y(0x01); cpu.poke_y(0x01);
cpu.memory[0x0ef0] = 0xab; cpu.memory[0x0ef0] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) {
cpu.tick();
}
assert_eq!(cpu.a, 0xab); assert_eq!(cpu.a, 0xab);
} }
@ -687,9 +705,13 @@ mod test {
cpu.memory[0x6001] = ISA_OP_INX; cpu.memory[0x6001] = ISA_OP_INX;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) {
cpu.tick();
}
assert_eq!(0xaa, cpu.x); assert_eq!(0xaa, cpu.x);
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) {
cpu.tick();
}
assert_eq!(0xab, cpu.x); assert_eq!(0xab, cpu.x);
} }
@ -701,9 +723,13 @@ mod test {
cpu.memory[0x6001] = ISA_OP_INY; cpu.memory[0x6001] = ISA_OP_INY;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) {
cpu.tick();
}
assert_eq!(0xaa, cpu.peek_y()); assert_eq!(0xaa, cpu.peek_y());
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) {
cpu.tick();
}
assert_eq!(0xab, cpu.peek_y()); assert_eq!(0xab, cpu.peek_y());
} }
@ -715,9 +741,28 @@ mod test {
cpu.memory[0x6001] = ISA_OP_ROR_A; cpu.memory[0x6001] = ISA_OP_ROR_A;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) {
cpu.tick();
}
assert_eq!(cpu.peek_a(), 0b0101_0101); assert_eq!(cpu.peek_a(), 0b0101_0101);
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) { cpu.tick(); } for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) {
cpu.tick();
}
assert_eq!(cpu.peek_a(), 0b1010_1010); assert_eq!(cpu.peek_a(), 0b1010_1010);
} }
#[test]
fn rol_zp_ror_zp() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x00ab] = 0b0101_0101;
cpu.memory[0x6000] = ISA_OP_ROL_ZP;
cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_ZP) {
cpu.tick();
}
assert_eq!(cpu.memory[0xab], 0b1010_1010);;
}
} }

View File

@ -1,4 +1,6 @@
use crate::mos6502flags::Mos6502Flag::{Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero}; use crate::mos6502flags::Mos6502Flag::{
Break, Carry, Decimal, Interrupt, Negative, Overflow, Zero,
};
pub const BIT_NEGATIVE: u8 = 7; pub const BIT_NEGATIVE: u8 = 7;
pub const BIT_OVERFLOW: u8 = 6; pub const BIT_OVERFLOW: u8 = 6;
@ -59,7 +61,7 @@ impl Mos6502Flag {
Decimal => BIT_DECIMAL, Decimal => BIT_DECIMAL,
Break => BIT_BREAK, Break => BIT_BREAK,
Overflow => BIT_OVERFLOW, Overflow => BIT_OVERFLOW,
Negative => BIT_NEGATIVE Negative => BIT_NEGATIVE,
} }
} }
} }
@ -77,7 +79,8 @@ pub struct Mos6502Flags {
impl Mos6502Flags { impl Mos6502Flags {
pub fn dump(&self) -> String { pub fn dump(&self) -> String {
format!("{}{}{}{}{}{}{}", format!(
"{}{}{}{}{}{}{}",
if self.carry { 'C' } else { 'c' }, if self.carry { 'C' } else { 'c' },
if self.zero { 'Z' } else { 'z' }, if self.zero { 'Z' } else { 'z' },
if self.interrupt { 'I' } else { 'i' }, if self.interrupt { 'I' } else { 'i' },
@ -113,7 +116,8 @@ impl Mos6502Flags {
Break => self.break_flag = false, Break => self.break_flag = false,
Overflow => self.overflow = false, Overflow => self.overflow = false,
Negative => self.negative = false, Negative => self.negative = false,
} } }
}
fn change_flag(&mut self, flag_to_change: Mos6502Flag, new_value: bool) { fn change_flag(&mut self, flag_to_change: Mos6502Flag, new_value: bool) {
if new_value { if new_value {
@ -139,20 +143,32 @@ impl Mos6502Flags {
pub fn as_byte(&self) -> u8 { pub fn as_byte(&self) -> u8 {
let mut working = 0x00; let mut working = 0x00;
if self.flag(Negative) { working += 1 << Negative.index(); } if self.flag(Negative) {
if self.flag(Overflow) { working += 1 << Overflow.index(); } working += 1 << Negative.index();
}
if self.flag(Overflow) {
working += 1 << Overflow.index();
}
working += 1 << 5; // Always Set working += 1 << 5; // Always Set
if self.flag(Break) { working += 1 << Break.index(); } if self.flag(Break) {
if self.flag(Decimal) { working += 1 << Decimal.index(); } working += 1 << Break.index();
if self.flag(Interrupt) { working += 1 << Interrupt.index(); } }
if self.flag(Zero) { working += 1 << Zero.index(); } if self.flag(Decimal) {
if self.flag(Carry) { working += 1 << Carry.index(); } working += 1 << Decimal.index();
}
if self.flag(Interrupt) {
working += 1 << Interrupt.index();
}
if self.flag(Zero) {
working += 1 << Zero.index();
}
if self.flag(Carry) {
working += 1 << Carry.index();
}
working working
} }
pub fn from_byte(src: u8) -> Self { pub fn from_byte(src: u8) -> Self {
let mut working = Self::default(); let mut working = Self::default();
@ -182,14 +198,15 @@ impl Mos6502Flags {
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
#[test] #[test]
fn smoke() { assert!(true); } fn smoke() {
assert!(true);
}
#[test] #[test]
fn sanity() { fn sanity() {

View File

@ -356,5 +356,4 @@ pub enum Operation {
/// ///
/// Addressing Modes: Implied /// Addressing Modes: Implied
TYA, TYA,
} }

View File

@ -6,10 +6,10 @@ impl Default for At28C256 {
fn default() -> Self { fn default() -> Self {
let vec = vec![0xea; SIZE_32KB]; let vec = vec![0xea; SIZE_32KB];
let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); let boxed_slice: Box<[u8]> = vec.into_boxed_slice();
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Failed to convert Vec to boxed array"); let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice
At28C256 { .try_into()
data: boxed_array, .expect("Failed to convert Vec to boxed array");
} At28C256 { data: boxed_array }
} }
} }
@ -18,5 +18,7 @@ mod test {
use super::*; use super::*;
#[test] #[test]
fn smoke() { assert!(true); } fn smoke() {
assert!(true);
}
} }

View File

@ -1,9 +1,9 @@
mod default; mod default;
mod rom_chip; mod rom_chip;
use std::io::Read;
use crate::constants::constants_system::SIZE_32KB; use crate::constants::constants_system::SIZE_32KB;
use crate::periph::rom_chip::RomChip; use crate::periph::rom_chip::RomChip;
use std::io::Read;
/// At28C256 /// At28C256
/// ///
@ -25,8 +25,8 @@ impl At28C256 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::constants::constants_system::SIZE_1KB;
use super::*; use super::*;
use crate::constants::constants_system::SIZE_1KB;
#[test] #[test]
fn smoke() { fn smoke() {
@ -40,8 +40,7 @@ mod test {
data.data[i] = 0xea; data.data[i] = 0xea;
} }
for offset in 0..SIZE_32KB { for offset in 0..SIZE_32KB {
if offset.is_multiple_of(SIZE_1KB) { if offset.is_multiple_of(SIZE_1KB) {};
};
assert_eq!(0xea, data.read(&(offset as u16))); assert_eq!(0xea, data.read(&(offset as u16)));
} }
} }

View File

@ -3,7 +3,6 @@ use crate::periph::at28c256::At28C256;
use crate::periph::rom_chip::RomChip; use crate::periph::rom_chip::RomChip;
impl RomChip for At28C256 { impl RomChip for At28C256 {
fn read(&self, offset: &u16) -> u8 { fn read(&self, offset: &u16) -> u8 {
self.data[*offset as usize] self.data[*offset as usize]
} }
@ -21,7 +20,7 @@ mod test {
use super::*; use super::*;
#[test] #[test]
fn smoke() { assert!(true); } fn smoke() {
assert!(true);
}
} }

View File

@ -1,23 +1,24 @@
// HM62256 Static Ram // HM62256 Static Ram
use log::debug;
use crate::constants::constants_system::SIZE_32KB; use crate::constants::constants_system::SIZE_32KB;
use crate::periph::ram_chip::RamChip; use crate::periph::ram_chip::RamChip;
use crate::periph::rom_chip::RomChip; use crate::periph::rom_chip::RomChip;
use log::debug;
pub struct Hm62256 { pub struct Hm62256 {
pub(crate) base_offset: u16, pub(crate) base_offset: u16,
pub(crate) data: Box<[u8]> pub(crate) data: Box<[u8]>,
} }
impl Default for Hm62256 { impl Default for Hm62256 {
fn default() -> Self { fn default() -> Self {
let vec = vec![0x00; SIZE_32KB]; let vec = vec![0x00; SIZE_32KB];
let boxed_slice: Box<[u8]> = vec.into_boxed_slice(); let boxed_slice: Box<[u8]> = vec.into_boxed_slice();
let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice.try_into().expect("Unable to box the ram"); let boxed_array: Box<[u8; SIZE_32KB]> =
boxed_slice.try_into().expect("Unable to box the ram");
Hm62256 { Hm62256 {
base_offset: 0x0000, base_offset: 0x0000,
data: boxed_array data: boxed_array,
} }
} }
} }
@ -45,11 +46,13 @@ impl RamChip for Hm62256 {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use rand::random;
use super::*; use super::*;
use rand::random;
#[test] #[test]
fn smoke() { assert!(true) } fn smoke() {
assert!(true)
}
#[test] #[test]
fn written_data_comes_back() { fn written_data_comes_back() {
@ -59,7 +62,7 @@ mod test {
for _ in 0..100_000 { for _ in 0..100_000 {
let mut offset: u16 = random(); let mut offset: u16 = random();
println!("SIze = {SIZE_32KB}"); println!("SIze = {SIZE_32KB}");
let value: u8 =random(); let value: u8 = random();
println!("Wrote [{value:02x}] to [{offset:04x}]"); println!("Wrote [{value:02x}] to [{offset:04x}]");
ram.write(&offset, &value); ram.write(&offset, &value);

View File

@ -1,6 +1,5 @@
pub mod rom_chip; pub mod rom_chip;
pub mod at28c256; pub mod at28c256;
pub mod ram_chip;
pub mod hm62256; pub mod hm62256;
pub mod ram_chip;

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@