writes bins better now

This commit is contained in:
Trevor Merritt 2025-07-07 16:28:13 -04:00
parent 9c672741ed
commit 8c08555003
29 changed files with 1381 additions and 108 deletions

1028
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,14 +4,39 @@ use beneater::parts::ben_eater_pc::BenEaterPC;
use beneater::parts::cpu_display::CpuDisplay; use beneater::parts::cpu_display::CpuDisplay;
use macroquad::prelude::*; use macroquad::prelude::*;
use macroquad::telemetry::frame; use macroquad::telemetry::frame;
use core::mos6502cpu::cpu::Mos6502Cpu;
use core::periph::at28c256::At28C256;
use core::periph::hm62256::Hm62256;
use core::constants::constants_system::*;
/// 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 {
cpu: Mos6502Cpu,
ram: At28C256,
rom: Hm62256
}
impl BenEater {
pub fn new(rom: &[u8; SIZE_32KB]) -> BenEater {
}
}
#[macroquad::main("Ben Eaters PC")] #[macroquad::main("Ben Eaters PC")]
async fn main() { async fn main() {
println!("Taxation is Theft"); println!("Taxation is Theft");
let mut backplane = Backplane::new(); let rom_to_run = fs::read("resources/beneater/roms/ror.bin");
backplane.load_rom("resources/beneater/roms/ror.bin"); let mut pc = BenEater::new(&rom_to_run);
let mut dm = DisplayMatrix::new(200.0, 50.0); let mut backplane = Backplane::new();
// backplane.load_rom("resources/beneater/roms/ror.bin");
// let mut dm = DisplayMatrix::new(200.0, 50.0);
// dm.push_letter('T'); // dm.push_letter('T');
let mut frame_number: u32 = 0x00; let mut frame_number: u32 = 0x00;
@ -20,18 +45,18 @@ async fn main() {
clear_background(BLUE); clear_background(BLUE);
draw_text("Ben Eater", 20.0, 20.0, 30.0, BLACK); draw_text("Ben Eater", 20.0, 20.0, 30.0, BLACK);
dm.render(20.0, 40.0); // dm.render(20.0, 40.0);
// CpuDisplay::render(&computer.cpu, 20.0, 120.0); // CpuDisplay::render(&computer.cpu, 20.0, 120.0);
frame_number += 1; frame_number += 1;
if frame_number.is_multiple_of(60) { if frame_number.is_multiple_of(60) {
dm.push_letter('X'); // dm.push_letter('X');
computer.tick_system(); // computer.tick_system();
} }
if frame_number.is_multiple_of(60 * 6) { if frame_number.is_multiple_of(60 * 6) {
dm.clear_display() // dm.clear_display()
} }
next_frame().await next_frame().await

View File

@ -1,16 +1,46 @@
#![feature(slice_as_array)]
use core::constants::constants_system::SIZE_32KB; use core::constants::constants_system::SIZE_32KB;
use core::constants::constants_isa_op::*;
use std::fs; use std::fs;
use std::path::Path;
fn le_swap(to_swap: &[u8; SIZE_32KB]) -> [u8; 32768] {
let mut work: [u8; SIZE_32KB] = [0x00; SIZE_32KB];
for i in (0..SIZE_32KB).step_by(2) {
work[i] = to_swap[i+1];
work[i + 1] = to_swap[i];
}
work
}
fn main() { fn main() {
// make the rom data in memory. // make the rom data in memory.
// Fill with 0x6a -> ROR, A // Fill with 0xea -> NOP
let vec = vec![0x6a; SIZE_32KB]; let mut vec: [u8; SIZE_32KB] = [ISA_OP_NOP; 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 vec[0] = ISA_OP_LDA_I; // LDA #$ab
array[1] = 0xab; // 1010 1011 vec[1] = 0b1010_1011; // 1010 1011
vec[2] = 0x02; // --
vec[3] = 0x03; // --
vec[0x4000] = ISA_OP_LDA_I;
vec[0x4001] = 0b0101_0100;
vec[0x4002] = ISA_OP_JMP_ABS;
vec[0x4003] = 0x00;
vec[0x4004] = 0x40;
vec[0x4005] = ISA_OP_NOP;
vec[0x7ffc] = 0x12; // Reset Vector
vec[0x7ffd] = 0x34;
vec[0x7ffe] = 0x43; // Interrupt Vector
vec[0x7fff] = 0x21;
vec = le_swap(&vec);
// write the rom to disk // write the rom to disk
fs::write("outputfile.bin", array.as_slice()); fs::write("outputfile.bin", &vec[..]).expect("TODO: panic message");
} }

View File

@ -8,7 +8,7 @@ fn main() {
let mut backplane = Backplane::new(); let mut backplane = Backplane::new();
backplane.load_rom(); //backplane.load_rom();
println!("Backplane is live."); println!("Backplane is live.");
let mut new_program = [0x00u8; SIZE_32KB]; let mut new_program = [0x00u8; SIZE_32KB];
@ -21,9 +21,9 @@ fn main() {
); );
// println!("{:?}", new_program); // println!("{:?}", new_program);
backplane.rom.program(&new_program); // backplane.rom.program(&new_program);
backplane.cpu.pc = 0x6000; // backplane.cpu.pc = 0x6000;
backplane.memory[0x6000] = ISA_OP_LDA_I; // backplane.memory[0x6000] = ISA_OP_LDA_I;
backplane.memory[0x6001] = 0xab; // backplane.memory[0x6001] = 0xab;
backplane.tick(); // backplane.tick();
} }

View File

@ -1,3 +1,2 @@
pub mod parts; pub mod parts;
pub mod backplane; pub mod backplane;
mod backplane;

View File

@ -1,9 +1,10 @@
use crate::parts::mos6522_peripheral::Mos6522Peripheral; use crate::parts::mos6522_peripheral::Mos6522Peripheral;
use crate::parts::via6522::VIA6522; use crate::parts::via6522::VIA6522;
use core::constants::constants_system::*; use core::constants::constants_system::*;
use core::mos6502cpu::Mos6502Cpu; use core::mos6502cpu::cpu::Mos6502Cpu;
use core::periph::at28c256::At28C256; use core::periph::at28c256::At28C256;
use core::periph::rom_chip::RomChip; use core::periph::rom_chip::RomChip;
use core::constants::constants_via6522::*;
/// Backplane /// Backplane
/// ///
@ -60,7 +61,7 @@ impl Backplane {
// if we are reading // if we are reading
if rw { if rw {
println!("CPU HAS SET READ FLAG FOR ADDRESS {address:04x} with data 0x{data:02x}"); println!("CPU HAS SET READ FLAG FOR ADDRESS {:04x} with data 0x{:02x}", self.address_bus, self.data_bus);
match self.address_bus { match self.address_bus {
0x0000..=0x3fff => { 0x0000..=0x3fff => {
// read from ram // read from ram
@ -75,13 +76,13 @@ impl Backplane {
} }
} }
} else { } else {
println!("CPU HAS SET WRITE FLAG FOR ADDRESS 0x{address:04x} with data 0x{data:02x}"); println!("CPU HAS SET WRITE FLAG FOR ADDRESS 0x{:04x} with data 0x{:02x}", self.address_bus, self.data_bus);
match self.address_bus { match self.address_bus {
0x6000..=0x600f => { 0x6000..=0x600f => {
self.via.write((self.address_bus - 0x6000) as u8, self.data_bus); self.via.write((self.address_bus - 0x6000) as u8, self.data_bus);
}, },
0x0000..=0x3fff => { 0x0000..=0x3fff => {
self.memory[self.address_bus] = self.data_bus; self.memory[self.address_bus as usize] = self.data_bus;
} }
_ => { _ => {
println!("ATTEMPT TO WRITE OUTSIDE OF MEMORY"); println!("ATTEMPT TO WRITE OUTSIDE OF MEMORY");

View File

@ -1,6 +1,6 @@
use crate::parts::clock::Clock; use crate::parts::clock::Clock;
use core::constants::constants_system::*; use core::constants::constants_system::*;
use core::mos6502cpu::Mos6502Cpu; use core::mos6502cpu::cpu::Mos6502Cpu;
use std::fs; use std::fs;
use std::fs::File; use std::fs::File;
use std::io::{BufReader, Read}; use std::io::{BufReader, Read};

View File

@ -1,4 +1,4 @@
use core::mos6502cpu::Mos6502Cpu; use core::mos6502cpu::cpu::Mos6502Cpu;
use macroquad::color::{BLACK, Color}; use macroquad::color::{BLACK, Color};
use macroquad::prelude::*; use macroquad::prelude::*;
use macroquad::text::draw_text; use macroquad::text::draw_text;
@ -7,7 +7,7 @@ pub struct CpuDisplay {}
impl CpuDisplay { impl CpuDisplay {
pub fn render(cpu: &Mos6502Cpu, x_offset: f32, y_offset: f32) { pub fn render(cpu: &Mos6502Cpu, x_offset: f32, y_offset: f32) {
// get the data to display... // get the data to display...
let (pc, a, x, y, address_bus, data_bus, microsteps_remaining) = cpu.dump_data(); let (pc, a, x, y, address_bus, data_bus, microsteps_remaining, reset_vector, interrupt_vector) = cpu.dump_data();
// ...build the interface // ...build the interface
Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK); Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK);

18
cli/src/bin/rom_only.rs Normal file
View File

@ -0,0 +1,18 @@
use clap::Parser;
use core::computers::rom_only::backplane::Backplane;
#[derive(Parser)]
struct CliOptions {
offset: u16,
bytes: u16,
filename: String
}
fn main() {
println!("Taxation is theft");
let opts = CliOptions::parse();
let mut rom_only = Backplane::new();
rom_only.tick()
}

View File

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

View File

@ -1,5 +0,0 @@
/// 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 {}

View File

@ -3,7 +3,9 @@ use crate::periph::hm62256::Hm62256;
use crate::periph::rom_chip::RomChip; use crate::periph::rom_chip::RomChip;
pub struct Backplane { pub struct Backplane {
rom: Hm62256 rom: Hm62256,
data_bus: u8,
address_bus: u16
} }
impl Backplane { impl Backplane {
@ -13,7 +15,9 @@ impl Backplane {
pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane { pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane {
Backplane { Backplane {
rom: *Hm62256::program(rom) rom: *Hm62256::program(rom),
address_bus: 0x0000,
data_bus: 0x00
} }
} }

View File

@ -5,7 +5,3 @@ pub const SIZE_64KB: usize = SIZE_1KB * 64;
pub const OFFSET_RESET_VECTOR: u16 = 0xfffc; pub const OFFSET_RESET_VECTOR: u16 = 0xfffc;
pub const OFFSET_INT_VECTOR: u16 = 0xfffe; pub const OFFSET_INT_VECTOR: u16 = 0xfffe;
pub const VIA6522_ORB: u8 = 0;
pub const VIA6522_ORA: u8 = 1;
pub const VIA6522_DDRB: u8 = 2;
pub const VIA6522_DDRA: u8 = 3;

View File

@ -0,0 +1,20 @@
pub const VIA6522_ORB: u8 = 0b0000;
pub const VIA6522_ORA: u8 = 0b0001;
pub const VIA6522_DDRB: u8 = 0b0010;
pub const VIA6522_DDRA: u8 = 0b0011;
/// Timer 1 Write Latch
pub const VIA6522_T1WL: u8 = 0b0100;
/// Timer 1 Read Counter High
pub const VIA6522_T1CL: u8 = 0b0101;
pub const VIA6522_T1CH: u8 = 0b0110;
pub const VIA6522_T1LL: u8 = 0b0111;
pub const VIA6522_T1LH: u8 = 0b1000;
pub const VIA6522_T2LL: u8 = 0b1001;
pub const VIA6522_T2CH: u8 = 0b1010;
pub const VIA6522_SR: u8 = 0b1011;
pub const VIA6522_ACR: u8 = 0b1100;
pub const VIA6522_PCR: u8 = 0b1101;
pub const VIA6522_IFR: u8 = 0b1110;
pub const VIA6522_IER: u8 = 0b1111;

View File

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

View File

@ -31,11 +31,11 @@ use crate::op_info::OpInfo;
use crate::operation::Operation; use crate::operation::Operation;
use crate::operation::Operation::*; use crate::operation::Operation::*;
pub fn INSTRUCTION_CYCLES(instruction: u8) -> u8 { pub fn instruction_cycles(instruction: u8) -> u8 {
INSTRUCTION_TABLE[instruction as usize].unwrap().cycles INSTRUCTION_TABLE[instruction as usize].unwrap().cycles
} }
pub fn INSTRUCTION_LENGTH(instruction: u8) -> u8 { pub fn instruction_length(instruction: u8) -> u8 {
INSTRUCTION_TABLE[instruction as usize].unwrap().length INSTRUCTION_TABLE[instruction as usize].unwrap().length
} }

View File

@ -483,7 +483,7 @@ impl Mos6502Cpu {
mod test { mod test {
use super::*; use super::*;
use crate::constants::constants_isa_op::*; use crate::constants::constants_isa_op::*;
use crate::instruction_table::{INSTRUCTION_CYCLES, INSTRUCTION_TABLE}; use crate::instruction_table::{instruction_cycles, INSTRUCTION_TABLE};
#[test] #[test]
fn clc() { fn clc() {
@ -496,7 +496,7 @@ mod test {
cpu.pc = 0x6000; cpu.pc = 0x6000;
// Tick the CPU through the instruction // Tick the CPU through the instruction
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLC) { for _ in 0..instruction_cycles(ISA_OP_CLC) {
cpu.tick(); cpu.tick();
} }
@ -510,7 +510,7 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLD; cpu.memory[0x6000] = ISA_OP_CLD;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_CLD) { for _ in 0..instruction_cycles(ISA_OP_CLD) {
cpu.tick(); cpu.tick();
} }
@ -524,7 +524,7 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLI; cpu.memory[0x6000] = ISA_OP_CLI;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLI) { for _ in 0..=instruction_cycles(ISA_OP_CLI) {
cpu.tick(); cpu.tick();
} }
@ -538,7 +538,7 @@ mod test {
cpu.memory[0x6000] = ISA_OP_CLV; cpu.memory[0x6000] = ISA_OP_CLV;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_CLV) { for _ in 0..=instruction_cycles(ISA_OP_CLV) {
cpu.tick(); cpu.tick();
} }
@ -552,7 +552,7 @@ mod test {
cpu.memory[0x6001] = 0xab; cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_I) { for _ in 0..=instruction_cycles(ISA_OP_LDA_I) {
cpu.tick(); cpu.tick();
} }
@ -568,7 +568,7 @@ mod test {
cpu.memory[0x00ac] = 0xbe; cpu.memory[0x00ac] = 0xbe;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ZX) { for _ in 0..=instruction_cycles(ISA_OP_LDA_ZX) {
cpu.tick(); cpu.tick();
} }
@ -589,7 +589,7 @@ mod test {
cpu.memory[0x00ab] = 0xbe; cpu.memory[0x00ab] = 0xbe;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..INSTRUCTION_CYCLES(ISA_OP_LDA_Z) { for _ in 0..instruction_cycles(ISA_OP_LDA_Z) {
cpu.tick(); cpu.tick();
} }
@ -605,7 +605,7 @@ mod test {
cpu.memory[0x0eef] = 0xab; cpu.memory[0x0eef] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABS) { for _ in 0..=instruction_cycles(ISA_OP_LDA_ABS) {
cpu.tick(); cpu.tick();
} }
@ -622,7 +622,7 @@ mod test {
cpu.memory[0x0ef0] = 0xab; cpu.memory[0x0ef0] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSX) { for _ in 0..=instruction_cycles(ISA_OP_LDA_ABSX) {
cpu.tick(); cpu.tick();
} }
@ -639,7 +639,7 @@ mod test {
cpu.memory[0x0ef0] = 0xab; cpu.memory[0x0ef0] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_LDA_ABSY) { for _ in 0..=instruction_cycles(ISA_OP_LDA_ABSY) {
cpu.tick(); cpu.tick();
} }
@ -654,11 +654,11 @@ mod test {
cpu.memory[0x6001] = ISA_OP_INX; cpu.memory[0x6001] = ISA_OP_INX;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEX) { for _ in 0..=instruction_cycles(ISA_OP_DEX) {
cpu.tick(); cpu.tick();
} }
assert_eq!(0xaa, cpu.x); assert_eq!(0xaa, cpu.x);
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INX) { for _ in 0..=instruction_cycles(ISA_OP_INX) {
cpu.tick(); cpu.tick();
} }
assert_eq!(0xab, cpu.x); assert_eq!(0xab, cpu.x);
@ -672,11 +672,11 @@ mod test {
cpu.memory[0x6001] = ISA_OP_INY; cpu.memory[0x6001] = ISA_OP_INY;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_DEY) { for _ in 0..=instruction_cycles(ISA_OP_DEY) {
cpu.tick(); cpu.tick();
} }
assert_eq!(0xaa, cpu.peek_y()); assert_eq!(0xaa, cpu.peek_y());
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_INY) { for _ in 0..=instruction_cycles(ISA_OP_INY) {
cpu.tick(); cpu.tick();
} }
assert_eq!(0xab, cpu.peek_y()); assert_eq!(0xab, cpu.peek_y());
@ -690,11 +690,11 @@ mod test {
cpu.memory[0x6001] = ISA_OP_ROR_A; cpu.memory[0x6001] = ISA_OP_ROR_A;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_A) { for _ in 0..=instruction_cycles(ISA_OP_ROL_A) {
cpu.tick(); cpu.tick();
} }
assert_eq!(cpu.peek_a(), 0b0101_0101); assert_eq!(cpu.peek_a(), 0b0101_0101);
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROR_A) { for _ in 0..=instruction_cycles(ISA_OP_ROR_A) {
cpu.tick(); cpu.tick();
} }
assert_eq!(cpu.peek_a(), 0b1010_1010); assert_eq!(cpu.peek_a(), 0b1010_1010);
@ -708,7 +708,7 @@ mod test {
cpu.memory[0x6001] = 0xab; cpu.memory[0x6001] = 0xab;
cpu.pc = 0x6000; cpu.pc = 0x6000;
for _ in 0..=INSTRUCTION_CYCLES(ISA_OP_ROL_ZP) { for _ in 0..=instruction_cycles(ISA_OP_ROL_ZP) {
cpu.tick(); cpu.tick();
} }

View File

@ -1,6 +1,8 @@
pub mod default; pub mod default;
pub mod rom_chip; pub mod rom_chip;
pub mod tick; pub mod tick;
mod new;
mod program;
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;
@ -16,14 +18,6 @@ pub struct At28C256 {
data: Box<[u8; SIZE_32KB]>, data: Box<[u8; SIZE_32KB]>,
} }
impl At28C256 {
pub fn program(&mut self, new_program: &[u8; SIZE_32KB]) {
// panic!("FAIL. Cant program the chip.");
// println!("PROGRAMMING {:?}", new_program);
self.data = Box::new(*new_program);
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -0,0 +1,10 @@
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::at28c256::At28C256;
impl At28C256 {
pub fn new(data: &[u8; SIZE_32KB]) -> Self {
At28C256 {
data: (*data).into()
}
}
}

View File

@ -0,0 +1,10 @@
use crate::constants::constants_system::SIZE_32KB;
use crate::periph::at28c256::At28C256;
impl At28C256 {
pub fn program(&mut self, new_program: &[u8; SIZE_32KB]) {
// panic!("FAIL. Cant program the chip.");
// println!("PROGRAMMING {:?}", new_program);
self.data = Box::new(*new_program);
}
}

View File

@ -3,8 +3,10 @@ use crate::periph::hm62256::Hm62256;
impl At28C256 { impl At28C256 {
fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
if !read_mode { if read_mode {
// has to be read mode. its a rom. panic!("UNABLE TO WRITE TO ROM");
} else {
// has to be read mode. its a rom.
return (address_bus, data_bus) return (address_bus, data_bus)
} }
(address_bus, self.data[address_bus as usize]) (address_bus, self.data[address_bus as usize])

View File

@ -25,7 +25,9 @@ mod test {
fn write_to_memory_read_back_works_at_0() { fn write_to_memory_read_back_works_at_0() {
let mut ram = Hm62256::default(); let mut ram = Hm62256::default();
// load the data to ram
ram.tick(0x0000, 0xab, false); ram.tick(0x0000, 0xab, false);
// read the data back
let (_, new_data) = ram.tick(0x0000, 0x00, true); let (_, new_data) = ram.tick(0x0000, 0x00, true);
assert_eq!(new_data, 0xab); assert_eq!(new_data, 0xab);

View File

@ -3,3 +3,4 @@ pub mod rom_chip;
pub mod at28c256; pub mod at28c256;
pub mod hm62256; pub mod hm62256;
pub mod ram_chip; pub mod ram_chip;
pub mod mos6522;

View File

@ -0,0 +1,2 @@
pub mod mos6522;
mod registers;

View File

@ -0,0 +1,165 @@
use std::time::Instant;
use log::debug;
use crate::constants::constants_via6522::*;
#[derive(Default)]
pub struct Mos6522 {
/// data direction
dda: u8,
ddb: u8,
/// bottom 4 address bits
rs0: u8,
rs1: u8,
rs2: u8,
rs3: u8,
/// external data bus
data_bus: u8,
cs1: bool,
cs2: bool,
rw: bool,
/// reset circuit - true when reset inited
reset: bool,
/// IRQ - true when interrupt waiting
irq: bool,
ira: u8,
ora: u8,
porta: u8,
irb: u8,
orb: u8,
portb: u8,
ca1: bool,
ca2: bool,
cb1: bool,
cb2: bool,
}
impl Mos6522 {
pub fn new() -> Self {
Mos6522::default()
}
/// tick
///
/// data_bus -> 8 bits from the data bus
/// control -> 4 bits to identify which register to control
pub fn tick(&mut self, data_bus: u8, control: u8, rw: bool) -> (u8) {
println!("Mos6522 Tick Start -> 0x{data_bus:02x} / 0x{control:02x} / {rw}");
if rw {
// RW true = CPU is writing
self.data_bus = data_bus;
match control {
VIA6522_DDRA => {
debug!("Setting DDA to 0x{data_bus:02x}");
// setting the Data Direction for Port A
self.dda = data_bus;
},
VIA6522_DDRB => {
debug!("Setting DDB to 0x{data_bus:02x}");
// setting the data direction for port b
self.ddb = data_bus;
},
VIA6522_ORB => {
// writing data to ORB
let masked_data = data_bus & self.ddb;
debug!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
self.portb = masked_data;
},
VIA6522_ORA => {
// writing data to ORA
let masked_data = data_bus & self.dda;
debug!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}");
self.porta = masked_data;
},
_ => {}
}
} else {
// RW false = CPU is reading
self.data_bus = match control {
VIA6522_DDRA => {
self.dda
}
VIA6522_DDRB => {
self.ddb
}
VIA6522_ORA => {
self.porta & self.dda
}
VIA6522_ORB => {
self.portb & self.ddb
}
_ => {
debug!("VIA got request for b{:08b} / 0x{:02x}", control, control);
// do nothing. bad address for VIA
self.data_bus
}
}
}
(self.data_bus)
}
pub fn start_clocks(&mut self) {
loop {
let cycle_start = Instant::now();
// let duration = cycle_start.duration_since(self.clock);
// set the time to the new time.
// self.clock = cycle_start;
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn smoke() { assert!(true); }
#[test]
fn registers() {
let mut x = Mos6522::new();
x.tick(0b0000_0000, VIA6522_DDRA, true);
assert_eq!(x.dda, 0b0000_0000);
x.tick(0b1111_1111, VIA6522_DDRA, true);
assert_eq!(x.dda, 0b1111_1111);
x.tick(0b0000_0000, VIA6522_DDRB, true);
assert_eq!(x.ddb, 0b0000_0000);
x.tick(0b1111_1111, VIA6522_DDRB, true);
assert_eq!(x.ddb, 0b1111_1111);
x.tick(0b0000_0000, VIA6522_ORA, true);
assert_eq!(x.porta, 0b0000_0000);
x.tick(0b1111_1111, VIA6522_ORA, true);
assert_eq!(x.porta, 0b1111_1111);
x.tick(0b0000_0000, VIA6522_ORB, true);
assert_eq!(x.portb, 0b0000_0000);
x.tick(0b1111_1111, VIA6522_ORB, true);
assert_eq!(x.portb, 0b1111_1111);
}
#[test]
fn partial_output_porta() {
let mut x = Mos6522::new();
x.tick(0b1010_1010, VIA6522_DDRA, true);
x.tick(0b1111_1111, VIA6522_ORA, true);
assert_eq!(x.porta, 0b1010_1010);
}
#[test]
fn partial_output_portb() {
let mut x = Mos6522::new();
x.tick(0b0101_0101, VIA6522_DDRB, true);
x.tick(0b1111_1111, VIA6522_ORB, true);
assert_eq!(x.portb, 0b0101_0101);
}
}

View File

@ -0,0 +1,12 @@
pub enum Via6522Registers {
ORA,
ORB,
DDRA,
DDRB,
T1WL,
T1CL,
T1CH,
T1LL,
T2LL,
T2CH,
}

View File

@ -5,4 +5,5 @@ edition = "2024"
[dependencies] [dependencies]
macroquad.workspace = true macroquad.workspace = true
core = { path = "../core" } core = { path = "../core" }
egui-macroquad = "0.17"

View File

@ -1,31 +0,0 @@
use macroquad::prelude::*;
use core::computers::rom_only::backplane::Backplane;
pub struct UiState {
display_offset: u16,
current_offset: u16
}
#[macroquad::main("Rom_Only")]
async fn main() {
let mut backplane = Backplane::new();
let mut state = UiState { display_offset: 0x00, current_offset: 0x00 };
loop {
clear_background(BLUE);
draw_text("ROM ONLY", 20.0, 20.0, 30.0, DARKGRAY);
backplane.tick();
draw_text(
format!("Display Offset: 0x{:04x}", state.display_offset).as_str(), 20.0, 60.0, 30.0, DARKGRAY
);
draw_text(
format!("Current Offset: 0x{:04x}", state.current_offset).as_str(), 20.0, 100.0, 30.0, DARKGRAY
);
next_frame().await
}
}

View File