diff --git a/Cargo.lock b/Cargo.lock index ffdcb85..0aca508 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,14 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "beneater" +version = "0.1.0" +dependencies = [ + "core", + "macroquad 0.4.14", +] + [[package]] name = "bitflags" version = "1.3.2" diff --git a/Cargo.toml b/Cargo.toml index 808b46d..d7dfc39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,8 @@ members = [ "core", "cli", - "macroquad" + "macroquad", + "beneater" ] resolver="2" @@ -15,3 +16,4 @@ clap = { version = "4.5", features = ["derive"] } # trevors_utilities = { git = "https://git.geekback.dev/tmerritt/trevors_utilities" } trevors_utilities = { path = "/home/tmerritt/Projects/trevors_utilities" } lipsum = "0.9" +macroquad = "0.4" diff --git a/beneater/Cargo.toml b/beneater/Cargo.toml new file mode 100644 index 0000000..8f06286 --- /dev/null +++ b/beneater/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "beneater" +version = "0.1.0" +edition = "2024" + +[dependencies] +core = { path = "../core" } +macroquad.workspace = true \ No newline at end of file diff --git a/beneater/src/bin/beneater.rs b/beneater/src/bin/beneater.rs new file mode 100644 index 0000000..fe408ff --- /dev/null +++ b/beneater/src/bin/beneater.rs @@ -0,0 +1,16 @@ +// This is the GUI for the BenEater PC +use macroquad::prelude::*; + +#[macroquad::main("Ben Eaters PC")] +async fn main() { + println!("Taxation is Theft"); + + let computer = BenEaterPC::new(); + + loop { + clear_background(BLUE); + + draw_text("Ben Eater", 20.0, 20.0, 30.0, BLACK); + next_frame().await + } +} diff --git a/beneater/src/lib.rs b/beneater/src/lib.rs new file mode 100644 index 0000000..fb9dd06 --- /dev/null +++ b/beneater/src/lib.rs @@ -0,0 +1 @@ +pub mod parts; diff --git a/beneater/src/parts/ben_eater_pc.rs b/beneater/src/parts/ben_eater_pc.rs new file mode 100644 index 0000000..7117b1e --- /dev/null +++ b/beneater/src/parts/ben_eater_pc.rs @@ -0,0 +1,25 @@ +use crate::parts::clock::Clock; +use core::mos6502cpu::Mos6502Cpu; + +struct BenEaterPC { + clock: Clock, + cpu: Mos6502Cpu, +} + +impl BenEaterPC { + pub fn new() -> Self { + BenEaterPC { + clock: Clock::new(), + cpu: Mos6502Cpu::default() + } + } + + pub fn tick_system(&mut self) { + let (address, data, rw) = self.cpu.tick(); + if self.cpu.microcode_step == 0 { + // tick the clock. + // tick the memory + // tick the VIA + } + } +} diff --git a/beneater/src/parts/clock.rs b/beneater/src/parts/clock.rs new file mode 100644 index 0000000..0c0caef --- /dev/null +++ b/beneater/src/parts/clock.rs @@ -0,0 +1,24 @@ +pub struct Clock { + ticks: u32 +} + +impl Clock { + pub fn new() -> Self { + + Clock { + ticks: 0 + } + } + + pub fn tick(&mut self) { + self.ticks += 1; + } + + pub fn ticks(&self) -> u32 { + self.ticks + } + + pub fn reset(&mut self) { + self.ticks = 0; + } +} diff --git a/beneater/src/parts/mod.rs b/beneater/src/parts/mod.rs new file mode 100644 index 0000000..2540ffd --- /dev/null +++ b/beneater/src/parts/mod.rs @@ -0,0 +1,3 @@ +pub mod clock; +mod ben_eater_pc; +mod via6522; diff --git a/beneater/src/parts/via6522.rs b/beneater/src/parts/via6522.rs new file mode 100644 index 0000000..4efe640 --- /dev/null +++ b/beneater/src/parts/via6522.rs @@ -0,0 +1,31 @@ +#[derive(Default)] +pub struct Via6522 { + port_a_state: u8, + port_b_data: u8, + port_a_direction: u8, + port_b_direction: u8, + memory_offset: u16, +} + +impl Via6522 { + pub fn new(offset: u16) -> Self { + Via6522 { + memory_offset: offset, + ..Default::default() + } + } + + pub fn set_a_direction(&mut self, new_direction: u8) { + + } + + // check for output pins and see what they say + pub fn update_pins(&mut self) { + + } + + // check for input mode pins and see what they say + pub fn read_pins(&self) { + + } +} \ No newline at end of file diff --git a/cli/src/bin/decode.rs b/cli/src/bin/decode.rs index b597f2f..fa5a43e 100644 --- a/cli/src/bin/decode.rs +++ b/cli/src/bin/decode.rs @@ -4,8 +4,8 @@ use core::address_mode::AddressMode; fn main() { println!("Taxation is Theft"); - Instruction::from_bytes(vec![0b11100011]); + // Instruction::from_bytes(vec![0b11100011]); - let instruction = Instruction::ADC(AddressMode::Immediate(0x45)); - println!("Instruction = {:?}", instruction.to_string()); + // let instruction = Instruction::ADC(AddressMode::Immediate); + // println!("Instruction = {:?}", instruction.to_string()); } diff --git a/core/src/address_mode.rs b/core/src/address_mode.rs index bf86d19..6c3ce0d 100644 --- a/core/src/address_mode.rs +++ b/core/src/address_mode.rs @@ -1,10 +1,4 @@ -use std::fmt::{Display, Formatter}; -use std::ops::Add; -use crate::address_mode::Operation::*; -use crate::constants::constants_isa_op::*; -use crate::constants::constants_isa_stub::*; -use crate::mos6502cpu::Mos6502Cpu; -use crate::operation::Operation; +use std::fmt::{Display}; #[derive(PartialEq, Debug, Copy, Clone)] pub enum AddressMode { diff --git a/core/src/computers/beneater/beneater.rs b/core/src/computers/beneater/beneater.rs new file mode 100644 index 0000000..aaadee8 --- /dev/null +++ b/core/src/computers/beneater/beneater.rs @@ -0,0 +1,9 @@ + +/// BenEater computer represents the 'Ben Eater' 6502 breadboard computer. +/// This was built along watching the video series where Ben builds a +/// 6502 on a breadboard and explains each step. +/// +pub struct BenEater { + +} + diff --git a/core/src/computers/beneater/mod.rs b/core/src/computers/beneater/mod.rs new file mode 100644 index 0000000..0188360 --- /dev/null +++ b/core/src/computers/beneater/mod.rs @@ -0,0 +1 @@ +pub mod beneater; diff --git a/core/src/computers/mod.rs b/core/src/computers/mod.rs new file mode 100644 index 0000000..ff5f773 --- /dev/null +++ b/core/src/computers/mod.rs @@ -0,0 +1,2 @@ +pub mod beneater; + diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs index 615e95c..094c7ce 100644 --- a/core/src/instruction_table.rs +++ b/core/src/instruction_table.rs @@ -1,5 +1,5 @@ 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_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_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::operation::Operation; use crate::operation::Operation::*; @@ -180,7 +180,6 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { length: 2, cycles: 2, }); - table[ISA_OP_BPL as usize] = Some(OpInfo { operation: Operation::BPL, mode: AddressMode::Implied, @@ -226,8 +225,8 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { table[ISA_OP_CLV as usize] = Some(OpInfo { operation: CLV, mode: AddressMode::Implied, - length: 2, - cycles: 1, + length: 1, + cycles: 2, }); table[ISA_OP_CMP_I as usize] = Some(OpInfo { @@ -382,7 +381,7 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { length: 3, cycles: 4, }); - table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo { + table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::AbsoluteY, length: 3, @@ -394,7 +393,7 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { length: 2, cycles: 6, }); - table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo { + table[ISA_OP_EOR_INDY as usize] = Some(OpInfo { operation: EOR, mode: AddressMode::IndirectY, length: 2, @@ -421,7 +420,7 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { }); table[ISA_OP_INC_ABSX as usize] = Some(OpInfo { operation: INC, - mode: AddressMode::ZeroPageX, + mode: AddressMode::AbsoluteX, length: 3, cycles: 7, }); @@ -537,13 +536,13 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { }); table[ISA_OP_LDY_I as usize] = Some(OpInfo { - operation: Operation::LDY, + operation: LDY, mode: AddressMode::Immediate, length: 2, cycles: 2, }); table[ISA_OP_LDY_ZP as usize] = Some(OpInfo { - operation: Operation::LDY, + operation: LDY, mode: AddressMode::ZeroPage, length: 2, cycles: 3, @@ -555,13 +554,13 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { cycles: 4, }); table[ISA_OP_LDY_ABS as usize] = Some(OpInfo { - operation: Operation::LDY, + operation: LDY, mode: AddressMode::Absolute, length: 3, cycles: 4, }); table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo { - operation: Operation::LDY, + operation: LDY, mode: AddressMode::AbsoluteX, length: 3, cycles: 4, @@ -574,13 +573,13 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { cycles: 2, }); table[ISA_OP_LSR_ZP as usize] = Some(OpInfo { - operation: Operation::LSR, + operation: LSR, mode: AddressMode::ZeroPage, length: 2, cycles: 5, }); table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo { - operation: Operation::LSR, + operation: LSR, mode: AddressMode::ZeroPageX, length: 2, cycles: 6, @@ -629,6 +628,13 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { length: 3, cycles: 4, }); + + table[ISA_OP_ORA_ABSX as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo { operation: Operation::ORA, mode: AddressMode::AbsoluteY, @@ -835,7 +841,7 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { cycles: 4, }); table[ISA_OP_STA_ABSX as usize] = Some(OpInfo { - operation: STA, + operation: Operation::STA, mode: AddressMode::AbsoluteX, length: 3, cycles: 5, @@ -936,3 +942,49 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { table }; + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_instruction_table_completeness() { + use INSTRUCTION_TABLE; // Adjust to your actual path + + let mut defined_count = 0; + let mut defined_opcodes = vec![]; + + for (i, entry) in INSTRUCTION_TABLE.iter().enumerate() { + if let Some(info) = entry { + defined_count += 1; + defined_opcodes.push(i); + // Optional: sanity check + assert!( + info.length > 0 && info.cycles > 0, + "Invalid OpInfo at opcode {:#04x?}", + i + ); + } + } + + println!("Defined opcodes: {}", defined_count); + for i in 0..256 { + if defined_opcodes.contains(&i) { + print!("{:02x} ", i); + } + } + println!("\nMissing opcodes:"); + for i in 0..256 { + if !defined_opcodes.contains(&i) { + print!("{:02X} ", i); + } + } + println!(); + + // The standard 6502 has 151 documented opcodes + assert_eq!( + defined_count, 151, + "Expected 151 opcodes, found {}", + defined_count + ); + } +} \ No newline at end of file diff --git a/core/src/lib.rs b/core/src/lib.rs index 4331b55..94ef2f8 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -1,9 +1,11 @@ +pub mod periph; pub mod address_mode; pub mod mos6502cpu; pub mod instruction; pub mod mos6502flags; pub mod constants; -mod operation; -mod op_info; -mod operand; -mod instruction_table; +pub mod operation; +pub mod op_info; +pub mod operand; +pub mod instruction_table; +pub mod computers; diff --git a/core/src/mos6502cpu.rs b/core/src/mos6502cpu.rs index 078f8b3..7ce38c1 100644 --- a/core/src/mos6502cpu.rs +++ b/core/src/mos6502cpu.rs @@ -1,6 +1,7 @@ use crate::mos6502flags::{Mos6502Flag, Mos6502Flags}; 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 { @@ -11,9 +12,28 @@ pub struct Mos6502Cpu { flags: Mos6502Flags, pc: u16, s: u8, - microcode_step: u8, + pub microcode_step: u8, address_bus: u16, - data_bus: u8 + data_bus: u8, + ir: u8 // Instruction Register +} + +impl Default for Mos6502Cpu { + fn default() -> Self { + Mos6502Cpu { + memory: [0x00; SIZE_64KB], + a: 0, + x: 0, + y: 0, + flags: Default::default(), + pc: 0, + s: 0, + microcode_step: 0, + address_bus: 0, + data_bus: 0, + ir: 0x00 + } + } } impl Mos6502Cpu { @@ -28,7 +48,8 @@ impl Mos6502Cpu { s: 0xfd, microcode_step: 0, address_bus: 0x0000, - data_bus: 0x00 + data_bus: 0x00, + ir: 0x00 } } @@ -70,12 +91,17 @@ impl Mos6502Cpu { self.y = new_y } - pub fn tick(&mut self) { - + /// Ticks the CPU + /// Returns + /// AddressBus, DataBus, RW flag + pub fn tick(&mut self) -> (u16, u8, bool) { + (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); } + + } diff --git a/core/src/periph/at28c256.rs b/core/src/periph/at28c256.rs new file mode 100644 index 0000000..9a5c1a5 --- /dev/null +++ b/core/src/periph/at28c256.rs @@ -0,0 +1,52 @@ +use crate::mos6502cpu::SIZE_32KB; +use crate::periph::rom_chip::RomChip; + +/// At28C256 +/// +/// Represents a single At28C256 Chip +/// +/// 256kbit storage +/// 32kbyte storage +pub struct At28C256 { + data: [u8; SIZE_32KB] +} + +impl RomChip for At28C256 { + fn read(&self, offset: &u16) -> u8 { + self.data[*offset as usize] + } + + fn program(new_data: &[u8; SIZE_32KB]) -> Self { + println!("Writing new chip."); + At28C256 { + data: *new_data + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn smoke() { + assert!(true) + } + + #[test] + fn programmed_data_reads_back_same() { + print!("Starting test..."); + let data_to_write = [0xea; SIZE_32KB]; + print!("allocated data for rom..."); + let chip: At28C256 = At28C256::program(&data_to_write); + println!("programmed chip..."); + print!("testing"); + for offset in 0..SIZE_32KB { + if offset.is_multiple_of(1000) { + print!("."); + }; + assert_eq!(0xea, chip.read(&(offset as u16))); + } + println!("passed!"); + } +} diff --git a/core/src/periph/mod.rs b/core/src/periph/mod.rs new file mode 100644 index 0000000..3c6c493 --- /dev/null +++ b/core/src/periph/mod.rs @@ -0,0 +1,3 @@ +pub mod rom_chip; + +pub mod at28c256; diff --git a/core/src/periph/rom_chip.rs b/core/src/periph/rom_chip.rs new file mode 100644 index 0000000..cff8ea8 --- /dev/null +++ b/core/src/periph/rom_chip.rs @@ -0,0 +1,17 @@ +use crate::mos6502cpu::SIZE_32KB; + +pub trait RomChip { + /// Read + /// + /// Reads a single byte from the specified address + fn read(&self, offset: &u16) -> u8; + /// Program + /// + /// Replaces all data in the ROM chip + fn program(new_data: &[u8; SIZE_32KB]) -> Self; +} + +pub trait RamChip: RomChip { + fn write(&mut self, offset: &u16, value: &u8); +} + diff --git a/macroquad/Cargo.toml b/macroquad/Cargo.toml index 0cd6edf..9aea351 100644 --- a/macroquad/Cargo.toml +++ b/macroquad/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] -macroquad = "0.4" \ No newline at end of file +macroquad.workspace = true \ No newline at end of file diff --git a/resources/beneater/roms/nop.bin b/resources/beneater/roms/nop.bin new file mode 100644 index 0000000..12f3be4 Binary files /dev/null and b/resources/beneater/roms/nop.bin differ