writes bins better now
This commit is contained in:
parent
9c672741ed
commit
8c08555003
1028
Cargo.lock
generated
1028
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -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
|
||||||
|
|||||||
@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,2 @@
|
|||||||
pub mod parts;
|
pub mod parts;
|
||||||
pub mod backplane;
|
pub mod backplane;
|
||||||
mod backplane;
|
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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
18
cli/src/bin/rom_only.rs
Normal 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()
|
||||||
|
}
|
||||||
@ -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();
|
||||||
|
|||||||
@ -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 {}
|
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
|
|||||||
20
core/src/constants/constants_via6522.rs
Normal file
20
core/src/constants/constants_via6522.rs
Normal 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;
|
||||||
|
|
||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
10
core/src/periph/at28c256/new.rs
Normal file
10
core/src/periph/at28c256/new.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
core/src/periph/at28c256/program.rs
Normal file
10
core/src/periph/at28c256/program.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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])
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
2
core/src/periph/mos6522/mod.rs
Normal file
2
core/src/periph/mos6522/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod mos6522;
|
||||||
|
mod registers;
|
||||||
165
core/src/periph/mos6522/mos6522.rs
Normal file
165
core/src/periph/mos6522/mos6522.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
core/src/periph/mos6522/registers.rs
Normal file
12
core/src/periph/mos6522/registers.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
pub enum Via6522Registers {
|
||||||
|
ORA,
|
||||||
|
ORB,
|
||||||
|
DDRA,
|
||||||
|
DDRB,
|
||||||
|
T1WL,
|
||||||
|
T1CL,
|
||||||
|
T1CH,
|
||||||
|
T1LL,
|
||||||
|
T2LL,
|
||||||
|
T2CH,
|
||||||
|
}
|
||||||
@ -5,4 +5,5 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
macroquad.workspace = true
|
macroquad.workspace = true
|
||||||
core = { path = "../core" }
|
core = { path = "../core" }
|
||||||
|
egui-macroquad = "0.17"
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
resources/beneater/asm/nop_1.asm
Normal file
0
resources/beneater/asm/nop_1.asm
Normal file
Loading…
x
Reference in New Issue
Block a user