Compare commits

...

3 Commits

Author SHA1 Message Date
f9c938757f box swap 2025-07-01 13:08:23 -04:00
d97774e97b some instructions have code and tests 2025-06-30 13:55:35 -04:00
9e0e8b5910 closer to ticking.
has microsteps in the UI
decodes from a NOP only binary
some basic instructions are starting to move data around
2025-06-30 08:50:18 -04:00
19 changed files with 769 additions and 920 deletions

View File

@ -10,8 +10,8 @@ use beneater::parts::display_matrix::DisplayMatrix;
async fn main() {
println!("Taxation is Theft");
let computer = BenEaterPC::new();
let mut computer = BenEaterPC::new();
computer.load_rom("resources/beneater/roms/ror.bin");
let mut dm = DisplayMatrix::new(200.0, 50.0);
let message_to_show = "Taxation is theft";
@ -31,6 +31,7 @@ async fn main() {
if frame_number.is_multiple_of(60) {
dm.push_letter('X');
computer.tick_system();
}
if frame_number.is_multiple_of(60 * 6) {

View File

@ -0,0 +1,16 @@
use std::fs;
use core::constants::constants_system::SIZE_32KB;
fn main() {
// make the rom data in memory.
// Fill with 0x6a -> ROR, A
let vec = vec![0x6a; SIZE_32KB];
let slice: Box<[u8]> = vec.into_boxed_slice();
let mut array: Box<[u8; SIZE_32KB]> = slice.try_into().expect("Unable to make rom in ram");
array[0] = 0xa9; // LDA #$ab
array[1] = 0xab; // 1010 1011
// write the rom to disk
fs::write("outputfile.bin", array.as_slice());
}

View File

@ -1,3 +1,7 @@
use std::fs;
use std::fs::File;
use std::io::{BufReader, Read};
use std::path::Path;
use crate::parts::clock::Clock;
use core::mos6502cpu::Mos6502Cpu;
@ -28,4 +32,24 @@ impl BenEaterPC {
self.cpu.tick();
}
}
pub fn load_rom(&mut self, rom_to_load: &str) {
println!("Preparing to load {rom_to_load}");
let file = File::open(rom_to_load).unwrap();
let mut reader = BufReader::new(file);
let mut chunks = Vec::new();
loop {
let mut buffer = vec![0u8; 1];
let bytes_read = reader.read(&mut buffer).unwrap_or(0);
if bytes_read == 0 {
break;
}
buffer.truncate(bytes_read);
chunks.push(buffer[0]);
}
println!("Loaded {}b of data.", chunks.len());
self.cpu.memory = chunks.into();
}
}

View File

@ -7,7 +7,7 @@ pub struct CpuDisplay {}
impl CpuDisplay {
pub fn render(cpu: &Mos6502Cpu, x_offset: f32, y_offset: f32) {
// get the data to display...
let (pc, a, x, y, address_bus, data_bus) = cpu.dump_data();
let (pc, a, x, y, address_bus, data_bus, microsteps_remaining) = cpu.dump_data();
// ...build the interface
Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK);
@ -16,6 +16,7 @@ impl CpuDisplay {
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) {

View File

@ -5,4 +5,4 @@ pub mod display_matrix;
pub mod address_bus;
pub mod data_bus;
pub mod cpu_display;
mod ram_display;
pub mod ram_display;

7
cli/src/bin/ticker.rs Normal file
View File

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

View File

@ -1,16 +1,77 @@
/// Represents the various addressing modes of the 6502 CPU.
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum AddressMode {
/// Implied
///
/// No operand is needed; the instruction implicitly operates on a register or flag.
/// Example: `CLC` (Clear Carry Flag)
Implied,
/// Accumulator
///
/// Operates directly on the accumulator register.
/// Example: `ASL A` (Arithmetic Shift Left on Accumulator)
Accumulator,
/// Immediate
///
/// Operand is a constant 8-bit value.
/// Example: `LDA #$01` loads the value 0x01 into the accumulator.
Immediate,
/// Zero Page
///
/// Operand is an address in the first 256 bytes of memory (0x00000x00FF).
/// Example: `LDA $10` reads from address 0x0010.
ZeroPage,
/// Zero Page X
///
/// Zero page address offset by the X register.
/// Example: If X = 0x10, `LDA $23,X` reads from 0x33.
ZeroPageX,
/// Zero Page Y
///
/// Zero page address offset by the Y register.
/// Used only by a few instructions like `LDX` and `STX`.
/// Example: If Y = 0x10, `LDX $23,Y` reads from 0x33.
ZeroPageY,
/// Absolute
///
/// Full 16-bit address is provided as the operand.
/// Example: `LDA $1234` reads from address 0x1234.
Absolute,
/// Absolute X
///
/// Absolute address offset by the X register.
/// Example: If X = 0x10, `LDA $1234,X` reads from 0x1244.
AbsoluteX,
/// Absolute Y
///
/// Absolute address offset by the Y register.
/// Example: If Y = 0x10, `LDA $1234,Y` reads from 0x1244.
AbsoluteY,
/// Indirect
///
/// Only used by `JMP`. Operand is a 16-bit address pointing to another 16-bit address.
/// Example: `JMP ($1234)` jumps to the address stored at 0x1234/0x1235.
Indirect,
/// Indirect X (Indexed Indirect)
///
/// Operand is a zero-page address. Add X to it, then fetch the 16-bit address from that location.
/// Example: If X = 0x04 and operand = $20, `LDA ($20,X)` reads from the address at $24/$25.
IndirectX,
/// Indirect Y (Indirect Indexed)
///
/// Operand is a zero-page address. Fetch the 16-bit address from that location, then add Y.
/// Example: If Y = 0x10 and ($20) = $3000, `LDA ($20),Y` reads from $3010.
IndirectY,
}

View File

@ -0,0 +1,7 @@
pub const SIZE_1KB: usize = 1024 * 1024;
pub const SIZE_32KB: usize = SIZE_1KB * 32;
pub const SIZE_64KB: usize = SIZE_1KB * 64;
pub const OFFSET_RESET_VECTOR: u16 = 0xfffc;
pub const OFFSET_INT_VECTOR: u16 = 0xfffe;

View File

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

View File

@ -1,10 +1,12 @@
use log::trace;
use crate::address_mode::AddressMode;
use crate::address_mode::AddressMode::*;
use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Accumulator, Immediate, Implied, Indirect, IndirectX, IndirectY, ZeroPage, ZeroPageX};
use crate::address_mode::AddressMode::*;
use crate::instruction_table::INSTRUCTION_TABLE;
use crate::op_info::OpInfo;
use crate::operand::Operand;
use crate::operation::Operation;
use crate::operation::Operation::{ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRK, BVC, BVS, CLC, CLD, CLI, CLV, CMP, CPX, CPY, DEC, DEX, DEY, EOR, INC, INX, JMP, JSR, LDA, LDX, LDY, NOP, ORA, PHA, PHP, PLA, PLP, ROL, ROR, RTI, RTS, SBC, SEC, SED, SEI, STA, STX, STY, TAX, TAY, TSX, TXA, TXS, TYA};
use crate::operation::Operation::*;
#[derive(Debug, PartialEq)]
pub struct Instruction {
@ -14,30 +16,29 @@ pub struct Instruction {
}
impl Instruction {
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
println!("DECODING : {bytes:?}");
pub fn opinfo(bytes: &[u8]) -> Option<OpInfo> {
trace!("DECODING : {bytes:?}");
let opcode = bytes.get(0).copied()?;
let info = INSTRUCTION_TABLE[opcode as usize]?;
Some(INSTRUCTION_TABLE[opcode as usize])?
}
pub fn decode(bytes: &[u8]) -> Option<Instruction> {
let info = Instruction::opinfo(bytes)?;
let operand = match info.length {
2 => Operand::Byte(bytes.get(1).copied()?),
3 => {
let lo = *bytes.get(1)?;
let hi = *bytes.get(2)?;
Operand::Word(u16::from_le_bytes([lo, hi]))
}
2 => Operand::Byte(*bytes.get(1)?),
3 => Operand::Word(u16::from_le_bytes([*bytes.get(1)?, *bytes.get(2)?])),
_ => Operand::None,
};
let return_value = Some(Instruction {
let instruction = Instruction {
op: info.operation,
mode: info.mode,
operand,
});
};
println!("RETURNING: {:?}", return_value);
return_value
trace!("RETURNING: {:?}", instruction);
Some(instruction)
}
}
@ -46,7 +47,7 @@ impl Instruction {
mod test {
use crate::address_mode::AddressMode::*;
use crate::instruction::Instruction;
use crate::operation::Operation::{ADC, INY, LSR};
use crate::operation::Operation::*;
use super::*;
#[test]

View File

@ -1,13 +1,11 @@
use crate::address_mode::AddressMode;
use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR, SIZE_64KB};
use crate::instruction::Instruction;
use crate::mos6502flags::{Mos6502Flag, Mos6502Flags};
use crate::mos6502flags::Mos6502Flag::{Carry, Decimal, Interrupt, Overflow};
use crate::op_info::OpInfo;
use crate::operand::Operand;
use crate::operation::Operation;
use crate::operation::Operation::NOP;
pub const SIZE_1KB: usize = 1024 * 1024;
pub const SIZE_32KB: usize = SIZE_1KB * 32;
pub const SIZE_64KB: usize = SIZE_1KB * 64;
pub struct Mos6502Cpu {
// this is public for rendering quickly.
@ -21,7 +19,10 @@ pub struct Mos6502Cpu {
pub microcode_step: u8,
pub address_bus: u16,
pub data_bus: u8,
ir: Instruction // Instruction Register
ir: Instruction, // Instruction Register
oi: OpInfo,
has_reset: bool,
iv: u16 // Interrupt Vector
}
impl Default for Mos6502Cpu {
@ -30,7 +31,7 @@ impl Default for Mos6502Cpu {
let boxed_slize: Box<[u8]> = vec.into_boxed_slice();
let boxed_array: Box<[u8; SIZE_64KB]> = boxed_slize.try_into().expect("Failed to allocate system memory");
Mos6502Cpu {
let mut working = Mos6502Cpu {
memory: boxed_array,
a: 0,
x: 0,
@ -45,8 +46,18 @@ impl Default for Mos6502Cpu {
op: Operation::NOP,
mode: AddressMode::Implied,
operand: Operand::None,
}
}
},
oi: OpInfo {
operation: Operation::NOP,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
},
has_reset: false,
iv: 0xfffe
};
working.reset_cpu();
working
}
}
@ -55,7 +66,7 @@ impl Mos6502Cpu {
let vec = vec![0x00; SIZE_64KB];
let boxed_slize: Box<[u8]> = vec.into_boxed_slice();
let boxed_array: Box<[u8; SIZE_64KB]> = boxed_slize.try_into().expect("Failed to allocate system memory");
Mos6502Cpu {
let mut working = Mos6502Cpu {
memory: boxed_array,
a: 0,
x: 0,
@ -70,8 +81,33 @@ impl Mos6502Cpu {
op: Operation::NOP,
mode: AddressMode::Implied,
operand: Operand::None,
},
oi: OpInfo {
operation: Operation::NOP,
mode: AddressMode::Implied,
length: 1,
cycles: 2,
},
has_reset: false,
iv: 0xfffe
};
working.reset_cpu();
working
}
fn reset_cpu(&mut self) {
// self = &mut Mos6502Cpu::default();
println!("Should tick 7 times.");
// read the value at 0xfffc 0xfffd for our reset vector.
// read the value at 0xfffe 0xffff for our int vector
self.pc = self.read_word(&OFFSET_RESET_VECTOR);
self.iv = self.read_word(&OFFSET_INT_VECTOR);
}
fn read_word(&self, offset: &u16) -> u16 {
let low = self.memory[*offset as usize];
let high = self.memory[*offset as usize + 1];
(high as u16) << 8 | low as u16
}
pub fn peek_flag(&self, flag_to_read: Mos6502Flag) -> bool {
@ -112,38 +148,336 @@ impl Mos6502Cpu {
self.y = new_y
}
fn advance_pc(&mut self, how_far: u16) {
self.pc += how_far;
}
fn set_pc_to(&mut self, new_pc: u16) {
self.pc = new_pc;
}
/// Ticks the CPU
/// Returns
/// AddressBus, DataBus, RW flag
pub fn tick(&mut self) -> (u16, u8, bool) {
println!("PREPARiNG TO TICK CPU AT {:04x}", self.pc);
let mut num_microsteps_left = 0;
if num_microsteps_left == 0 {
println!("OUT OF MICROSTEPS. Time To do something that isnt microstep.");
println!("PREPARiNG TO TICK CPU AT PC 0x{:04x}", self.pc);
if self.microcode_step == 0 {
println!("OUT OF MICROSTEPS. Decoding the next instruction");
let offset = self.pc as usize;
// TODO: this calls opinfo 2x
self.oi = Instruction::opinfo(&self.memory[offset..offset + 4]).unwrap();
self.ir = Instruction::decode(&self.memory[offset..offset + 4]).unwrap();
self.microcode_step = self.oi.cycles;
println!("Decoded [[{:?}]]", self.ir);
self.advance_pc(self.oi.length as u16);
// load the microstep buffer with what steps to run
// set the counter to the number of steps left
} else {
// run 1 microcode step
println!("Microstep {num_microsteps_left}");
num_microsteps_left -= 1;
println!("Microstep {}", self.microcode_step);
match self.ir.op {
Operation::ADC => {
}
Operation::AND => {}
Operation::ASL => {}
Operation::BCC => {}
Operation::BCS => {}
Operation::BEQ => {}
Operation::BIT => {}
Operation::BMI => {}
Operation::BNE => {}
Operation::BPL => {}
Operation::BRK => {}
Operation::BVC => {}
Operation::BVS => {}
Operation::CLC => {
self.flags.clear_flag(Carry);
}
Operation::CLD => {
self.flags.clear_flag(Decimal);
}
Operation::CLI => {
self.flags.clear_flag(Interrupt);
}
Operation::CLV => {
self.flags.clear_flag(Overflow);
}
Operation::CMP => {}
Operation::CPX => {}
Operation::CPY => {}
Operation::DEC => {}
Operation::DEX => {
(self.x, _) = self.x.overflowing_sub(1) ;
}
Operation::DEY => {
(self.y, _) = self.y.overflowing_sub(1);
}
Operation::EOR => { }
Operation::INC => { }
Operation::INX => {
self.x += 1;
}
Operation::INY => {
self.y += 1;
}
Operation::JMP => {
match self.ir.operand {
Operand::Word(offset) => {
self.pc = offset;
}
_ => {}
}
}
Operation::JSR => {}
Operation::LDA => {
match self.oi.mode {
AddressMode::Immediate => {
match self.ir.operand {
Operand::Byte(value) => {
println!("Loading 0x{value:02x} ({value}) into A");
self.a = value;
}
_ => {}
}
}
AddressMode::ZeroPage => {
match self.ir.operand {
Operand::Byte(value) => {
println!("Loading from zero page at 0x{value:02x} ({value})");
self.a = self.memory[value as usize];
}
_ => {}
}
}
AddressMode::ZeroPageX => {}
AddressMode::ZeroPageY => {}
AddressMode::Absolute => {}
AddressMode::AbsoluteX => {}
AddressMode::AbsoluteY => {}
AddressMode::Indirect => {}
AddressMode::IndirectX => {}
AddressMode::IndirectY => {}
_ => {
println!("INVALID ADDRESS MODE FOR LDA");
}
}
}
Operation::LDX => {}
Operation::LDY => {}
Operation::LSR => {}
Operation::NOP => {
// do nothing.
}
Operation::ORA => {}
Operation::PHA => {}
Operation::PHP => {}
Operation::PLA => {}
Operation::PLP => {}
Operation::ROL => {
self.a = self.a.rotate_left(1);
}
Operation::ROR => {
// rotate A
self.a = self.a.rotate_right(1);
}
Operation::RTI => {}
Operation::RTS => {}
Operation::SBC => {}
Operation::SEC => {
self.flags.set_flag(Carry);
}
Operation::SED => {
self.flags.set_flag(Decimal);
}
Operation::SEI => {
self.flags.set_flag(Interrupt);
}
Operation::STA => {
match self.oi.mode {
AddressMode::ZeroPage => {
// write to the zero page.
match self.ir.operand {
Operand::Byte(target) => {
self.memory[target as usize] = self.a;
}
_ => {
// Invalid parameter
}
}
}
AddressMode::ZeroPageX => {
match self.ir.operand {
Operand::Byte(target) => {
let x = self.x;
self.memory[(x + target) as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::Absolute => {
// write from A to the specified memory location
match self.ir.operand {
Operand::Word(offset) => {
self.memory[offset as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::AbsoluteX => {
match self.ir.operand {
Operand::Word(offset) => {
self.memory[(offset + self.x as u16) as usize] = self.a;
}
_ => {
// Invalid Parameter
}
}
}
AddressMode::AbsoluteY => {}
AddressMode::IndirectX => {}
AddressMode::IndirectY => {}
_ => {
// invalid memory mode
}
}
}
Operation::STX => {}
Operation::STY => {}
Operation::TAX => {
self.x = self.a;
}
Operation::TAY => {
self.y = self.a;
}
Operation::TSX => {
}
Operation::TXA => {
self.a = self.x;
}
Operation::TXS => {
}
Operation::TYA => {
self.y = self.a;
}
}
self.microcode_step -= 1;
}
(0,0,false)
}
pub fn dump(&self) {
println!("CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x}",
self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus);
println!("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());
}
pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8) {
(self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus)
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)
}
fn run_microstep(&self, instruction: Instruction, step: u8) {
}
}
#[cfg(test)]
mod test {
use crate::constants::constants_isa_op::*;
use crate::instruction_table::INSTRUCTION_TABLE;
use super::*;
#[test]
fn clc() {
// setup the CPU for our test
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Carry);
// Load our 'test program'
cpu.memory[0x6000] = ISA_OP_CLC;
// Start the PC at our program
cpu.pc = 0x6000;
// Tick the CPU through the instruction
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLC as usize].unwrap().cycles { cpu.tick(); }
assert!(!cpu.peek_flag(Carry));
}
#[test]
fn cld() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Decimal);
cpu.memory[0x6000] = ISA_OP_CLD;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLD as usize].unwrap().cycles { cpu.tick(); }
assert!(!cpu.peek_flag(Decimal));
}
#[test]
fn cli() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Interrupt);
cpu.memory[0x6000] = ISA_OP_CLI;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLI as usize].unwrap().cycles { cpu.tick(); }
assert!(!cpu.peek_flag(Interrupt));
}
#[test]
fn clv() {
let mut cpu = Mos6502Cpu::default();
cpu.flags.set_flag(Overflow);
cpu.memory[0x6000] = ISA_OP_CLV;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_CLV as usize].unwrap().cycles { cpu.tick(); }
assert!(!cpu.peek_flag(Overflow));
}
#[test]
fn lda_immediate() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_I;
cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_LDA_I as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(cpu.a, 0xab);
}
#[test]
fn lda_zeropage() {
let mut cpu = Mos6502Cpu::default();
cpu.memory[0x6000] = ISA_OP_LDA_Z;
cpu.memory[0x6001] = 0xab;
cpu.memory[0x00ab] = 0xbe;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_LDA_Z as usize].unwrap().cycles + 1 { cpu.tick(); }
assert_eq!(cpu.a, 0xbe);
}
#[test]
fn dex() {
let mut cpu = Mos6502Cpu::default();
cpu.a = 0xab;
cpu.memory[0x6000] = ISA_OP_DEX;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_DEX as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(0xaa, cpu.a);
}
}

View File

@ -1,12 +1,45 @@
/// Represents the status flags in the 6502 processor's status register (P).
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Mos6502Flag {
/// Carry Flag (C)
///
/// Set if an arithmetic operation results in a carry out of the most significant bit (for addition),
/// or a borrow (for subtraction). Also used for bit shifts and rotates.
Carry,
/// Zero Flag (Z)
///
/// Set if the result of an operation is zero.
Zero,
/// Interrupt Disable Flag (I)
///
/// When set, disables maskable interrupts (IRQ).
Interrupt,
/// Decimal Mode Flag (D)
///
/// When set, arithmetic operations use Binary-Coded Decimal (BCD) mode.
/// Note: Not supported on all 6502 variants (e.g., not on the NES CPU).
Decimal,
/// Break Command Flag (B)
///
/// Set when a BRK (break) instruction is executed.
/// Used to distinguish software interrupts from hardware ones.
Break,
/// Overflow Flag (V)
///
/// Set when an arithmetic operation results in a signed overflow.
/// For example, adding two positive numbers results in a negative.
Overflow,
Negative
/// Negative Flag (N)
///
/// Set if the result of an operation has bit 7 set (i.e., the result is negative in two's complement).
Negative,
}
#[derive(Default)]
@ -20,6 +53,20 @@ pub struct Mos6502Flags {
negative: bool,
}
impl Mos6502Flags {
pub fn dump(&self) -> String {
format!("{}{}{}{}{}{}{}",
if self.carry { 'C' } else { 'c' },
if self.zero { 'Z' } else { 'z' },
if self.interrupt { 'I' } else { 'i' },
if self.decimal { 'D' } else { 'd' },
if self.break_flag { 'B' } else { 'b' },
if self.overflow { 'O' } else { 'o' },
if self.negative { 'N' } else { 'n' }
)
}
}
impl Mos6502Flags {
pub fn set_flag(&mut self, flag_to_set: Mos6502Flag) {

View File

@ -3,8 +3,12 @@ use crate::operation::Operation;
#[derive(Debug, Copy, Clone)]
pub struct OpInfo {
/// What is the operation
pub operation: Operation,
/// How does this operation access memory
pub mode: AddressMode,
/// Bytes to represent the instruction and parameters
pub length: u8,
/// CPU Cycles to complete the instruction
pub cycles: u8,
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
use crate::mos6502cpu::{SIZE_32KB};
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::rom_chip::RomChip;
/// At28C256
@ -38,7 +38,7 @@ impl RomChip for At28C256 {
#[cfg(test)]
mod test {
use crate::mos6502cpu::SIZE_1KB;
use crate::constants::constants_system::SIZE_1KB;
use super::*;
#[test]

View File

@ -1,7 +1,7 @@
// HM62256 Static Ram
use log::debug;
use crate::mos6502cpu::SIZE_32KB;
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::ram_chip::RamChip;
use crate::periph::rom_chip::RomChip;

View File

@ -1,4 +1,4 @@
use crate::mos6502cpu::SIZE_32KB;
use crate::constants::constants_system::SIZE_32KB;
pub trait RomChip {
/// Read

Binary file not shown.

File diff suppressed because one or more lines are too long