Compare commits
2 Commits
f9c938757f
...
1a53f1d782
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a53f1d782 | |||
| 9b9462c98c |
@ -4,8 +4,6 @@ use macroquad::prelude::*;
|
|||||||
use macroquad::telemetry::frame;
|
use macroquad::telemetry::frame;
|
||||||
use beneater::parts::ben_eater_pc::BenEaterPC;
|
use beneater::parts::ben_eater_pc::BenEaterPC;
|
||||||
use beneater::parts::display_matrix::DisplayMatrix;
|
use beneater::parts::display_matrix::DisplayMatrix;
|
||||||
|
|
||||||
|
|
||||||
#[macroquad::main("Ben Eaters PC")]
|
#[macroquad::main("Ben Eaters PC")]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("Taxation is Theft");
|
println!("Taxation is Theft");
|
||||||
|
|||||||
@ -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_32KB: usize = SIZE_1KB * 32;
|
||||||
pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
||||||
|
|
||||||
|
|||||||
@ -42,7 +42,6 @@ impl Instruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::address_mode::AddressMode::*;
|
use crate::address_mode::AddressMode::*;
|
||||||
|
|||||||
@ -102,6 +102,7 @@ impl Mos6502Cpu {
|
|||||||
// read the value at 0xfffe 0xffff for our int vector
|
// read the value at 0xfffe 0xffff for our int vector
|
||||||
self.pc = self.read_word(&OFFSET_RESET_VECTOR);
|
self.pc = self.read_word(&OFFSET_RESET_VECTOR);
|
||||||
self.iv = self.read_word(&OFFSET_INT_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 {
|
fn read_word(&self, offset: &u16) -> u16 {
|
||||||
@ -137,6 +138,7 @@ impl Mos6502Cpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poke_x(&mut self, new_x: u8) {
|
pub fn poke_x(&mut self, new_x: u8) {
|
||||||
|
println!("Updating register X from [{}] to [{}]", self.x, new_x);
|
||||||
self.x = new_x
|
self.x = new_x
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +176,7 @@ 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 {}", self.microcode_step);
|
println!("Microstep {} for {:?}", self.microcode_step, self.ir.op);
|
||||||
match self.ir.op {
|
match self.ir.op {
|
||||||
Operation::ADC => {
|
Operation::ADC => {
|
||||||
}
|
}
|
||||||
@ -207,19 +209,32 @@ impl Mos6502Cpu {
|
|||||||
Operation::CPY => {}
|
Operation::CPY => {}
|
||||||
Operation::DEC => {}
|
Operation::DEC => {}
|
||||||
Operation::DEX => {
|
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 => {
|
Operation::DEY => {
|
||||||
(self.y, _) = self.y.overflowing_sub(1);
|
if self.microcode_step == 1 {
|
||||||
|
(self.y, _) = self.y.overflowing_sub(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Operation::EOR => { }
|
Operation::EOR => { }
|
||||||
Operation::INC => { }
|
Operation::INC => { }
|
||||||
Operation::INX => {
|
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 => {
|
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 => {
|
Operation::JMP => {
|
||||||
match self.ir.operand {
|
match self.ir.operand {
|
||||||
Operand::Word(offset) => {
|
Operand::Word(offset) => {
|
||||||
@ -274,11 +289,15 @@ impl Mos6502Cpu {
|
|||||||
Operation::PLA => {}
|
Operation::PLA => {}
|
||||||
Operation::PLP => {}
|
Operation::PLP => {}
|
||||||
Operation::ROL => {
|
Operation::ROL => {
|
||||||
self.a = self.a.rotate_left(1);
|
if self.microcode_step == 1 {
|
||||||
|
self.a = self.a.rotate_left(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Operation::ROR => {
|
Operation::ROR => {
|
||||||
// rotate A
|
// rotate A
|
||||||
self.a = self.a.rotate_right(1);
|
if self.microcode_step == 1 {
|
||||||
|
self.a = self.a.rotate_right(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Operation::RTI => {}
|
Operation::RTI => {}
|
||||||
Operation::RTS => {}
|
Operation::RTS => {}
|
||||||
@ -470,14 +489,44 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn dex() {
|
fn dex_inx() {
|
||||||
let mut cpu = Mos6502Cpu::default();
|
let mut cpu = Mos6502Cpu::default();
|
||||||
cpu.a = 0xab;
|
cpu.x = 0xab;
|
||||||
cpu.memory[0x6000] = ISA_OP_DEX;
|
cpu.memory[0x6000] = ISA_OP_DEX;
|
||||||
|
cpu.memory[0x6001] = ISA_OP_INX;
|
||||||
cpu.pc = 0x6000;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
22
core/src/periph/at28c256/default.rs
Normal file
22
core/src/periph/at28c256/default.rs
Normal 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); }
|
||||||
|
}
|
||||||
@ -1,3 +1,6 @@
|
|||||||
|
mod default;
|
||||||
|
mod rom_chip;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -11,31 +14,6 @@ pub struct At28C256 {
|
|||||||
data: Box<[u8; SIZE_32KB]>,
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::constants::constants_system::SIZE_1KB;
|
use crate::constants::constants_system::SIZE_1KB;
|
||||||
27
core/src/periph/at28c256/rom_chip.rs
Normal file
27
core/src/periph/at28c256/rom_chip.rs
Normal 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); }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,9 +5,9 @@ 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;
|
||||||
|
|
||||||
struct Hm62256 {
|
pub struct Hm62256 {
|
||||||
base_offset: u16,
|
pub(crate) base_offset: u16,
|
||||||
data: Box<[u8]>
|
pub(crate) data: Box<[u8]>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Hm62256 {
|
impl Default for Hm62256 {
|
||||||
@ -24,8 +24,9 @@ impl Default for Hm62256 {
|
|||||||
|
|
||||||
impl RomChip for Hm62256 {
|
impl RomChip for Hm62256 {
|
||||||
fn read(&self, offset: &u16) -> u8 {
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
//println!("READING FROM RAM AT [{offset:04x}]");
|
// loops memory around past 32k
|
||||||
self.data[*offset as usize]
|
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||||
|
self.data[effective as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn program(_: Box<[u8; SIZE_32KB]>) -> Box<Self> {
|
fn program(_: Box<[u8; SIZE_32KB]>) -> Box<Self> {
|
||||||
|
|||||||
@ -2,5 +2,5 @@ pub mod rom_chip;
|
|||||||
|
|
||||||
pub mod at28c256;
|
pub mod at28c256;
|
||||||
pub mod ram_chip;
|
pub mod ram_chip;
|
||||||
mod hm62256;
|
pub mod hm62256;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user