decodes all instructions i think.
start of a beneater pc
This commit is contained in:
parent
57544589b3
commit
d89fc1cd2b
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
8
beneater/Cargo.toml
Normal file
8
beneater/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "beneater"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
macroquad.workspace = true
|
||||
16
beneater/src/bin/beneater.rs
Normal file
16
beneater/src/bin/beneater.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
1
beneater/src/lib.rs
Normal file
1
beneater/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod parts;
|
||||
25
beneater/src/parts/ben_eater_pc.rs
Normal file
25
beneater/src/parts/ben_eater_pc.rs
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
24
beneater/src/parts/clock.rs
Normal file
24
beneater/src/parts/clock.rs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
3
beneater/src/parts/mod.rs
Normal file
3
beneater/src/parts/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod clock;
|
||||
mod ben_eater_pc;
|
||||
mod via6522;
|
||||
31
beneater/src/parts/via6522.rs
Normal file
31
beneater/src/parts/via6522.rs
Normal file
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
9
core/src/computers/beneater/beneater.rs
Normal file
9
core/src/computers/beneater/beneater.rs
Normal file
@ -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 {
|
||||
|
||||
}
|
||||
|
||||
1
core/src/computers/beneater/mod.rs
Normal file
1
core/src/computers/beneater/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod beneater;
|
||||
2
core/src/computers/mod.rs
Normal file
2
core/src/computers/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod beneater;
|
||||
|
||||
@ -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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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<OpInfo>; 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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
52
core/src/periph/at28c256.rs
Normal file
52
core/src/periph/at28c256.rs
Normal file
@ -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!");
|
||||
}
|
||||
}
|
||||
3
core/src/periph/mod.rs
Normal file
3
core/src/periph/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod rom_chip;
|
||||
|
||||
pub mod at28c256;
|
||||
17
core/src/periph/rom_chip.rs
Normal file
17
core/src/periph/rom_chip.rs
Normal file
@ -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);
|
||||
}
|
||||
|
||||
@ -4,4 +4,4 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
macroquad = "0.4"
|
||||
macroquad.workspace = true
|
||||
BIN
resources/beneater/roms/nop.bin
Normal file
BIN
resources/beneater/roms/nop.bin
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user