removes sccache
updates display of ben eater pc doesnt blow up when creating a rom chip anymore doesnt blow up when creating a pc anymore
This commit is contained in:
parent
d89fc1cd2b
commit
e5c2319803
@ -1,5 +1,2 @@
|
|||||||
[alias]
|
[alias]
|
||||||
coverage = "tarpaulin --out Html --skip-clean --output-dir coverage"
|
coverage = "tarpaulin --out Html --skip-clean --output-dir coverage"
|
||||||
|
|
||||||
[build]
|
|
||||||
rustc-wrapper = "sccache"
|
|
||||||
|
|||||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -75,9 +75,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "beneater"
|
name = "beneater"
|
||||||
|
|||||||
@ -1,5 +1,10 @@
|
|||||||
// This is the GUI for the BenEater PC
|
// This is the GUI for the BenEater PC
|
||||||
|
use beneater::parts::cpu_display::CpuDisplay;
|
||||||
use macroquad::prelude::*;
|
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")]
|
#[macroquad::main("Ben Eaters PC")]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -7,10 +12,32 @@ async fn main() {
|
|||||||
|
|
||||||
let computer = BenEaterPC::new();
|
let computer = BenEaterPC::new();
|
||||||
|
|
||||||
|
|
||||||
|
let mut dm = DisplayMatrix::new(200.0, 50.0);
|
||||||
|
let message_to_show = "Taxation is theft";
|
||||||
|
let mut message_index = 0;
|
||||||
|
|
||||||
|
dm.push_letter('T');
|
||||||
|
let mut frame_number: u32 = 0x00;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
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);
|
||||||
|
CpuDisplay::render(&computer.cpu, 20.0, 120.0);
|
||||||
|
|
||||||
|
frame_number += 1;
|
||||||
|
|
||||||
|
if frame_number.is_multiple_of(60) {
|
||||||
|
dm.push_letter('X');
|
||||||
|
}
|
||||||
|
|
||||||
|
if frame_number.is_multiple_of(60 * 6) {
|
||||||
|
dm.clear_display()
|
||||||
|
}
|
||||||
|
|
||||||
next_frame().await
|
next_frame().await
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
beneater/src/parts/address_bus.rs
Normal file
9
beneater/src/parts/address_bus.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub struct AddressBus {
|
||||||
|
pub address: u16
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddressBus {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
AddressBus { address: 0x0000 }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,17 @@
|
|||||||
use crate::parts::clock::Clock;
|
use crate::parts::clock::Clock;
|
||||||
use core::mos6502cpu::Mos6502Cpu;
|
use core::mos6502cpu::Mos6502Cpu;
|
||||||
|
|
||||||
struct BenEaterPC {
|
pub struct BenEaterPC {
|
||||||
clock: Clock,
|
clock: Clock,
|
||||||
cpu: Mos6502Cpu,
|
// pub because i am rendering it.
|
||||||
|
// there should be a proper interface to get the data
|
||||||
|
// for ui out of this.
|
||||||
|
pub cpu: Mos6502Cpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BenEaterPC {
|
impl BenEaterPC {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
println!("New BENEATERPC");
|
||||||
BenEaterPC {
|
BenEaterPC {
|
||||||
clock: Clock::new(),
|
clock: Clock::new(),
|
||||||
cpu: Mos6502Cpu::default()
|
cpu: Mos6502Cpu::default()
|
||||||
|
|||||||
28
beneater/src/parts/cpu_display.rs
Normal file
28
beneater/src/parts/cpu_display.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use macroquad::color::{BLACK, Color};
|
||||||
|
use macroquad::prelude::*;
|
||||||
|
use macroquad::text::draw_text;
|
||||||
|
use core::mos6502cpu::Mos6502Cpu;
|
||||||
|
|
||||||
|
pub struct CpuDisplay {}
|
||||||
|
impl CpuDisplay {
|
||||||
|
pub fn render(cpu: &Mos6502Cpu, x_offset: f32, y_offset: f32) {
|
||||||
|
// get the data to display...
|
||||||
|
let (pc, a, x, y, address_bus, data_bus) = cpu.dump_data();
|
||||||
|
|
||||||
|
// ...build the interface
|
||||||
|
Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK);
|
||||||
|
|
||||||
|
draw_text(format!("PC: 0x{:04x} / {}", pc, pc).as_str(), x_offset + 5.0, y_offset + 18.0, 15.0, BLACK);
|
||||||
|
draw_text(format!("A: 0x{:02x} X: 0x{:02x} Y: 0x{:02x}", a, x, y).as_str(), x_offset + 5.0, y_offset + 35.0, 15.0, BLACK);
|
||||||
|
draw_text(format!("Address: {:016b} | {:04x}", address_bus, address_bus).as_str(), x_offset + 5.0, y_offset + 55.0, 15.0, BLACK);
|
||||||
|
draw_text(format!("Data: {:08b} | {:02x}", data_bus, data_bus).as_str(), x_offset + 5.0, y_offset + 75.0, 15.0, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
|
||||||
|
// println!("Square from {x1:2.0}x{y1:2.0} to {x2:2.0}x{y2:2.0} with {:?}", color);
|
||||||
|
draw_line(x1, y1, x2, y1, 1.0, color);
|
||||||
|
draw_line(x1, y1, x1, y2, 1.0, color);
|
||||||
|
draw_line(x1, y2, x2, y2, 1.0, color);
|
||||||
|
draw_line(x2, y1, x2, y2, 1.0, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
beneater/src/parts/data_bus.rs
Normal file
9
beneater/src/parts/data_bus.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub struct DataBus {
|
||||||
|
pub data: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataBus {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
DataBus { data: 0x00 }
|
||||||
|
}
|
||||||
|
}
|
||||||
79
beneater/src/parts/display_matrix.rs
Normal file
79
beneater/src/parts/display_matrix.rs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
use macroquad::prelude::*;
|
||||||
|
use crate::parts::address_bus::AddressBus;
|
||||||
|
use crate::parts::data_bus::DataBus;
|
||||||
|
|
||||||
|
pub struct DisplayMatrix {
|
||||||
|
width: f32,
|
||||||
|
height: f32,
|
||||||
|
text_buffer: String,
|
||||||
|
data_bus: DataBus,
|
||||||
|
rs: bool,
|
||||||
|
rw: bool,
|
||||||
|
cursor_position: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayMatrix {
|
||||||
|
pub fn new(width: f32, height: f32) -> DisplayMatrix {
|
||||||
|
DisplayMatrix {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
text_buffer: String::from(""),
|
||||||
|
data_bus: DataBus::new(),
|
||||||
|
rs: false,
|
||||||
|
rw: false,
|
||||||
|
cursor_position: 0x00
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tick
|
||||||
|
///
|
||||||
|
/// Checks the data bus and sees what the setup is.
|
||||||
|
///
|
||||||
|
/// 0 0 0 0 0 0 0 1 -> Clear Display
|
||||||
|
/// 0 0 0 0 0 0 1 - -> Return Home
|
||||||
|
/// 0 0 0 0 0 0 A B -> Sets cursor move direction and shift
|
||||||
|
/// A -> 0 = Insert, 1 = Delete
|
||||||
|
/// B -> Scroll bool
|
||||||
|
/// 0 0 0 0 1 D C B -> Sets display mode
|
||||||
|
/// D -> Display On/Off
|
||||||
|
/// C -> Cursor On/Off
|
||||||
|
/// B -> Blink
|
||||||
|
pub fn tick(&mut self) {
|
||||||
|
// parse whats on the data bus.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_busses(&mut self, address_bus: &mut AddressBus, data_bus: &mut DataBus) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_letter(&mut self, letter_to_push: char) {
|
||||||
|
self.cursor_position += 1;
|
||||||
|
self.text_buffer.push(letter_to_push)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_display(&mut self) {
|
||||||
|
self.cursor_position = 0;
|
||||||
|
self.text_buffer.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, x_offset: f32, y_offset: f32) {
|
||||||
|
DisplayMatrix::draw_square(x_offset,
|
||||||
|
y_offset,
|
||||||
|
x_offset + self.width ,
|
||||||
|
y_offset + self.height,
|
||||||
|
BLACK);
|
||||||
|
|
||||||
|
let mut tmp = self.text_buffer.clone();
|
||||||
|
tmp.push('#');
|
||||||
|
draw_text(&*tmp, x_offset + 5.0, y_offset + 20.0, 20.0, BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
|
||||||
|
// println!("Square from {x1:2.0}x{y1:2.0} to {x2:2.0}x{y2:2.0} with {:?}", color);
|
||||||
|
draw_line(x1, y1, x2, y1, 1.0, color);
|
||||||
|
draw_line(x1, y1, x1, y2, 1.0, color);
|
||||||
|
draw_line(x1, y2, x2, y2, 1.0, color);
|
||||||
|
draw_line(x2, y1, x2, y2, 1.0, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,8 @@
|
|||||||
pub mod clock;
|
pub mod clock;
|
||||||
mod ben_eater_pc;
|
pub mod ben_eater_pc;
|
||||||
mod via6522;
|
pub mod via6522;
|
||||||
|
pub mod display_matrix;
|
||||||
|
pub mod address_bus;
|
||||||
|
pub mod data_bus;
|
||||||
|
pub mod cpu_display;
|
||||||
|
mod ram_display;
|
||||||
|
|||||||
20
beneater/src/parts/ram_display.rs
Normal file
20
beneater/src/parts/ram_display.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use macroquad::prelude::*;
|
||||||
|
|
||||||
|
pub struct RamDisplay {}
|
||||||
|
|
||||||
|
impl RamDisplay {
|
||||||
|
pub fn render(ram: &Box<[u8]>, x_offset: f32, y_offset: f32) {
|
||||||
|
Self::draw_square(x_offset, y_offset, x_offset + 200.0, y_offset + 300.0, BLACK);
|
||||||
|
|
||||||
|
draw_text("RAM", x_offset + 5.0, y_offset + 5.0, 15.0, BLACK);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_square(x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
|
||||||
|
// println!("Square from {x1:2.0}x{y1:2.0} to {x2:2.0}x{y2:2.0} with {:?}", color);
|
||||||
|
draw_line(x1, y1, x2, y1, 1.0, color);
|
||||||
|
draw_line(x1, y1, x1, y2, 1.0, color);
|
||||||
|
draw_line(x1, y2, x2, y2, 1.0, color);
|
||||||
|
draw_line(x2, y1, x2, y2, 1.0, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,12 +19,12 @@ impl Via6522 {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for output pins and see what they say
|
/// check for output pins and see what they say
|
||||||
pub fn update_pins(&mut self) {
|
pub fn update_pins(&mut self) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for input mode pins and see what they say
|
/// check for input mode pins and see what they say
|
||||||
pub fn read_pins(&self) {
|
pub fn read_pins(&self) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,8 @@ pub const SIZE_32KB: usize = SIZE_1KB * 32;
|
|||||||
pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
pub const SIZE_64KB: usize = SIZE_1KB * 64;
|
||||||
|
|
||||||
pub struct Mos6502Cpu {
|
pub struct Mos6502Cpu {
|
||||||
memory: [u8; SIZE_64KB],
|
// this is public for rendering quickly.
|
||||||
|
pub memory: Box<[u8]>,
|
||||||
a: u8,
|
a: u8,
|
||||||
x: u8,
|
x: u8,
|
||||||
y: u8,
|
y: u8,
|
||||||
@ -13,20 +14,24 @@ pub struct Mos6502Cpu {
|
|||||||
pc: u16,
|
pc: u16,
|
||||||
s: u8,
|
s: u8,
|
||||||
pub microcode_step: u8,
|
pub microcode_step: u8,
|
||||||
address_bus: u16,
|
pub address_bus: u16,
|
||||||
data_bus: u8,
|
pub data_bus: u8,
|
||||||
ir: u8 // Instruction Register
|
ir: u8 // Instruction Register
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Mos6502Cpu {
|
impl Default for Mos6502Cpu {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
let vec = vec![0x00; SIZE_64KB];
|
||||||
|
let boxed_slize: Box<[u8]> = vec.into_boxed_slice();
|
||||||
|
let boxed_array: Box<[u8; SIZE_64KB]> = boxed_slize.try_into().expect("Failed to allocate system memory");
|
||||||
|
|
||||||
Mos6502Cpu {
|
Mos6502Cpu {
|
||||||
memory: [0x00; SIZE_64KB],
|
memory: boxed_array,
|
||||||
a: 0,
|
a: 0,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
pc: 0,
|
pc: 0xfffd,
|
||||||
s: 0,
|
s: 0,
|
||||||
microcode_step: 0,
|
microcode_step: 0,
|
||||||
address_bus: 0,
|
address_bus: 0,
|
||||||
@ -38,8 +43,11 @@ impl Default for Mos6502Cpu {
|
|||||||
|
|
||||||
impl Mos6502Cpu {
|
impl Mos6502Cpu {
|
||||||
pub fn new() -> Mos6502Cpu {
|
pub fn new() -> Mos6502Cpu {
|
||||||
|
let vec = vec![0x00; SIZE_64KB];
|
||||||
|
let boxed_slize: Box<[u8]> = vec.into_boxed_slice();
|
||||||
|
let boxed_array: Box<[u8; SIZE_64KB]> = boxed_slize.try_into().expect("Failed to allocate system memory");
|
||||||
Mos6502Cpu {
|
Mos6502Cpu {
|
||||||
memory: [0; SIZE_64KB],
|
memory: boxed_array,
|
||||||
a: 0,
|
a: 0,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
@ -103,5 +111,7 @@ impl Mos6502Cpu {
|
|||||||
self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus);
|
self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8) {
|
||||||
|
(self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::mos6502cpu::SIZE_32KB;
|
use crate::mos6502cpu::{SIZE_32KB, SIZE_64KB};
|
||||||
use crate::periph::rom_chip::RomChip;
|
use crate::periph::rom_chip::RomChip;
|
||||||
|
|
||||||
/// At28C256
|
/// At28C256
|
||||||
@ -8,24 +8,37 @@ use crate::periph::rom_chip::RomChip;
|
|||||||
/// 256kbit storage
|
/// 256kbit storage
|
||||||
/// 32kbyte storage
|
/// 32kbyte storage
|
||||||
pub struct At28C256 {
|
pub struct At28C256 {
|
||||||
data: [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 {
|
impl RomChip for At28C256 {
|
||||||
|
|
||||||
fn read(&self, offset: &u16) -> u8 {
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
self.data[*offset as usize]
|
self.data[*offset as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn program(new_data: &[u8; SIZE_32KB]) -> Self {
|
fn program(new_data: Box<[u8; 33554432]>) -> Box<At28C256> {
|
||||||
println!("Writing new chip.");
|
println!("Writing new chip.");
|
||||||
At28C256 {
|
let mut working = At28C256::default();
|
||||||
data: *new_data
|
working.data = Box::new(*new_data);
|
||||||
}
|
working.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::mos6502cpu::SIZE_1KB;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -36,16 +49,18 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn programmed_data_reads_back_same() {
|
fn programmed_data_reads_back_same() {
|
||||||
print!("Starting test...");
|
print!("Starting test...");
|
||||||
let data_to_write = [0xea; SIZE_32KB];
|
let mut data = At28C256::default();
|
||||||
|
for i in 0..SIZE_32KB {
|
||||||
|
data.data[i] = 0xea;
|
||||||
|
}
|
||||||
print!("allocated data for rom...");
|
print!("allocated data for rom...");
|
||||||
let chip: At28C256 = At28C256::program(&data_to_write);
|
|
||||||
println!("programmed chip...");
|
println!("programmed chip...");
|
||||||
print!("testing");
|
print!("testing");
|
||||||
for offset in 0..SIZE_32KB {
|
for offset in 0..SIZE_32KB {
|
||||||
if offset.is_multiple_of(1000) {
|
if offset.is_multiple_of(SIZE_1KB) {
|
||||||
print!(".");
|
print!(".");
|
||||||
};
|
};
|
||||||
assert_eq!(0xea, chip.read(&(offset as u16)));
|
assert_eq!(0xea, data.read(&(offset as u16)));
|
||||||
}
|
}
|
||||||
println!("passed!");
|
println!("passed!");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,9 @@ pub trait RomChip {
|
|||||||
/// Program
|
/// Program
|
||||||
///
|
///
|
||||||
/// Replaces all data in the ROM chip
|
/// Replaces all data in the ROM chip
|
||||||
fn program(new_data: &[u8; SIZE_32KB]) -> Self;
|
fn program(new_data: Box<[u8; SIZE_32KB]>) -> Box<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RamChip: RomChip {
|
pub trait RamChip: RomChip {
|
||||||
fn write(&mut self, offset: &u16, value: &u8);
|
fn write(&mut self, offset: &u16, value: &u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user