Compare commits

..

2 Commits

Author SHA1 Message Date
1a53f1d782 more instructions and tests passing. 2025-07-01 16:58:59 -04:00
9b9462c98c fixed size from 32mb to 32kb 2025-07-01 13:14:01 -04:00
9 changed files with 121 additions and 47 deletions

View File

@ -4,8 +4,6 @@ use macroquad::prelude::*;
use macroquad::telemetry::frame;
use beneater::parts::ben_eater_pc::BenEaterPC;
use beneater::parts::display_matrix::DisplayMatrix;
#[macroquad::main("Ben Eaters PC")]
async fn main() {
println!("Taxation is Theft");

View File

@ -1,4 +1,4 @@
pub const SIZE_1KB: usize = 1024 * 1024;
pub const SIZE_1KB: usize = 1024;
pub const SIZE_32KB: usize = SIZE_1KB * 32;
pub const SIZE_64KB: usize = SIZE_1KB * 64;

View File

@ -42,7 +42,6 @@ impl Instruction {
}
}
#[cfg(test)]
mod test {
use crate::address_mode::AddressMode::*;

View File

@ -102,6 +102,7 @@ impl Mos6502Cpu {
// 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);
println!("PC and IV are now set from ROM addresses");
}
fn read_word(&self, offset: &u16) -> u16 {
@ -137,6 +138,7 @@ impl Mos6502Cpu {
}
pub fn poke_x(&mut self, new_x: u8) {
println!("Updating register X from [{}] to [{}]", self.x, new_x);
self.x = new_x
}
@ -174,7 +176,7 @@ impl Mos6502Cpu {
// set the counter to the number of steps left
} else {
// run 1 microcode step
println!("Microstep {}", self.microcode_step);
println!("Microstep {} for {:?}", self.microcode_step, self.ir.op);
match self.ir.op {
Operation::ADC => {
}
@ -207,19 +209,32 @@ impl Mos6502Cpu {
Operation::CPY => {}
Operation::DEC => {}
Operation::DEX => {
(self.x, _) = self.x.overflowing_sub(1) ;
if self.microcode_step == 1 {
let (new_x, new_carry) = self.x.overflowing_sub(1);
self.poke_x(new_x);
self.poke_flag(Carry, new_carry);
}
}
Operation::DEY => {
(self.y, _) = self.y.overflowing_sub(1);
if self.microcode_step == 1 {
(self.y, _) = self.y.overflowing_sub(1);
}
}
Operation::EOR => { }
Operation::INC => { }
Operation::INX => {
self.x += 1;
if self.microcode_step == 1 {
let (new_x, new_carry) = self.x.overflowing_add(1);
self.poke_x(new_x);
self.poke_flag(Carry, new_carry);
}
}
Operation::INY => {
self.y += 1;
}
if self.microcode_step == 1 {
let (new_y, new_carry) = self.y.overflowing_add(1);
self.poke_y(new_y);
self.poke_flag(Carry, new_carry);
} }
Operation::JMP => {
match self.ir.operand {
Operand::Word(offset) => {
@ -274,11 +289,15 @@ impl Mos6502Cpu {
Operation::PLA => {}
Operation::PLP => {}
Operation::ROL => {
self.a = self.a.rotate_left(1);
if self.microcode_step == 1 {
self.a = self.a.rotate_left(1);
}
}
Operation::ROR => {
// rotate A
self.a = self.a.rotate_right(1);
if self.microcode_step == 1 {
self.a = self.a.rotate_right(1);
}
}
Operation::RTI => {}
Operation::RTS => {}
@ -470,14 +489,44 @@ mod test {
}
#[test]
fn dex() {
fn dex_inx() {
let mut cpu = Mos6502Cpu::default();
cpu.a = 0xab;
cpu.x = 0xab;
cpu.memory[0x6000] = ISA_OP_DEX;
cpu.memory[0x6001] = ISA_OP_INX;
cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_TABLE[ISA_OP_DEX as usize].unwrap().cycles { cpu.tick(); }
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_DEX as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(0xaa, cpu.x);
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_INX as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(0xab, cpu.x);
}
assert_eq!(0xaa, cpu.a);
#[test]
fn dey_iny() {
let mut cpu = Mos6502Cpu::default();
cpu.poke_y(0xab);
cpu.memory[0x6000] = ISA_OP_DEY;
cpu.memory[0x6001] = ISA_OP_INY;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_DEY as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(0xaa, cpu.peek_y());
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_INY as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(0xab, cpu.peek_y());
}
#[test]
fn rol_a_ror_a() {
let mut cpu = Mos6502Cpu::default();
cpu.poke_a(0b1010_1010); // 0xaa
cpu.memory[0x6000] = ISA_OP_ROL_A;
cpu.memory[0x6001] = ISA_OP_ROR_A;
cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_ROL_A as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(cpu.peek_a(), 0b0101_0101);
for _ in 0..=INSTRUCTION_TABLE[ISA_OP_ROR_A as usize].unwrap().cycles { cpu.tick(); }
assert_eq!(cpu.peek_a(), 0b1010_1010);
}
}

View File

@ -0,0 +1,22 @@
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::at28c256::At28C256;
use crate::periph::hm62256::Hm62256;
impl Default for At28C256 {
fn default() -> Self {
let vec = vec![0xea; SIZE_32KB];
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");
At28C256 {
data: boxed_array,
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() { assert!(true); }
}

View File

@ -1,3 +1,6 @@
mod default;
mod rom_chip;
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::rom_chip::RomChip;
@ -11,31 +14,6 @@ pub struct At28C256 {
data: Box<[u8; SIZE_32KB]>,
}
impl Default for At28C256 {
fn default() -> Self {
let vec = vec![0x00; SIZE_32KB];
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");
At28C256 {
data: boxed_array,
}
}
}
impl RomChip for At28C256 {
fn read(&self, offset: &u16) -> u8 {
self.data[*offset as usize]
}
fn program(new_data: Box<[u8; 33554432]>) -> Box<At28C256> {
println!("Writing new chip.");
let mut working = At28C256::default();
working.data = Box::new(*new_data);
working.into()
}
}
#[cfg(test)]
mod test {
use crate::constants::constants_system::SIZE_1KB;

View File

@ -0,0 +1,27 @@
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::at28c256::At28C256;
use crate::periph::rom_chip::RomChip;
impl RomChip for At28C256 {
fn read(&self, offset: &u16) -> u8 {
self.data[*offset as usize]
}
fn program(new_data: Box<[u8; SIZE_32KB]>) -> Box<At28C256> {
println!("Writing new chip.");
let mut working = At28C256::default();
working.data = Box::new(*new_data);
working.into()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() { assert!(true); }
}

View File

@ -5,9 +5,9 @@ use crate::constants::constants_system::SIZE_32KB;
use crate::periph::ram_chip::RamChip;
use crate::periph::rom_chip::RomChip;
struct Hm62256 {
base_offset: u16,
data: Box<[u8]>
pub struct Hm62256 {
pub(crate) base_offset: u16,
pub(crate) data: Box<[u8]>
}
impl Default for Hm62256 {
@ -24,8 +24,9 @@ impl Default for Hm62256 {
impl RomChip for Hm62256 {
fn read(&self, offset: &u16) -> u8 {
//println!("READING FROM RAM AT [{offset:04x}]");
self.data[*offset as usize]
// loops memory around past 32k
let effective = *offset as i32 % SIZE_32KB as i32;
self.data[effective as usize]
}
fn program(_: Box<[u8; SIZE_32KB]>) -> Box<Self> {

View File

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