start of rom_only PC
This commit is contained in:
parent
b9242b1943
commit
9c672741ed
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -366,6 +366,7 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
|||||||
name = "macroquad"
|
name = "macroquad"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"core",
|
||||||
"macroquad 0.4.14",
|
"macroquad 0.4.14",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
0
beneater/src/backplane/mod.rs
Normal file
0
beneater/src/backplane/mod.rs
Normal file
@ -1 +1,3 @@
|
|||||||
pub mod parts;
|
pub mod parts;
|
||||||
|
pub mod backplane;
|
||||||
|
mod backplane;
|
||||||
|
|||||||
@ -40,10 +40,6 @@ impl Backplane {
|
|||||||
self.rom.program(to_load);
|
self.rom.program(to_load);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
// is the CPU in read or write state
|
// is the CPU in read or write state
|
||||||
self.address_bus = self.cpu.address_bus();
|
self.address_bus = self.cpu.address_bus();
|
||||||
|
|||||||
@ -4,4 +4,4 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rand = "0.9.0"
|
rand = "0.9.0"
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
pub mod beneater;
|
pub mod beneater;
|
||||||
|
pub mod rom_only;
|
||||||
|
|||||||
25
core/src/computers/rom_only/backplane.rs
Normal file
25
core/src/computers/rom_only/backplane.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB};
|
||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
use crate::periph::rom_chip::RomChip;
|
||||||
|
|
||||||
|
pub struct Backplane {
|
||||||
|
rom: Hm62256
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backplane {
|
||||||
|
pub fn new() -> Backplane {
|
||||||
|
Backplane::program(&[0x00; SIZE_32KB])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn program(rom: &[u8; SIZE_32KB]) -> Backplane {
|
||||||
|
Backplane {
|
||||||
|
rom: *Hm62256::program(rom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(&mut self) {
|
||||||
|
println!("Preparing to tick.");
|
||||||
|
|
||||||
|
println!("Done ticking.");
|
||||||
|
}
|
||||||
|
}
|
||||||
1
core/src/computers/rom_only/mod.rs
Normal file
1
core/src/computers/rom_only/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod backplane;
|
||||||
@ -1,5 +1,5 @@
|
|||||||
pub mod address_mode;
|
|
||||||
pub mod computers;
|
pub mod computers;
|
||||||
|
pub mod address_mode;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod instruction_table;
|
pub mod instruction_table;
|
||||||
|
|||||||
@ -11,30 +11,32 @@ use crate::operation::Operation;
|
|||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
pub struct Mos6502Cpu {
|
pub struct Mos6502Cpu {
|
||||||
memory: [u8; SIZE_64KB],
|
pub(crate) memory: [u8; SIZE_64KB],
|
||||||
/// accumulator
|
/// accumulator
|
||||||
a: u8,
|
pub(crate) a: u8,
|
||||||
/// x register
|
/// x register
|
||||||
x: u8,
|
pub(crate) x: u8,
|
||||||
/// y register
|
/// y register
|
||||||
y: u8,
|
pub(crate) y: u8,
|
||||||
/// cpu flags
|
/// cpu flags
|
||||||
flags: Mos6502Flags,
|
pub(crate) flags: Mos6502Flags,
|
||||||
/// program counter
|
/// program counter
|
||||||
pub pc: u16,
|
pub pc: u16,
|
||||||
/// stack offset
|
/// stack offset
|
||||||
s: u8,
|
pub(crate) s: u8,
|
||||||
pub microcode_step: u8,
|
pub microcode_step: u8,
|
||||||
address_bus: u16,
|
pub(crate) address_bus: u16,
|
||||||
data_bus: u8,
|
pub(crate) data_bus: u8,
|
||||||
ir: Instruction, // Instruction Register
|
pub(crate) ir: Instruction, // Instruction Register
|
||||||
oi: OpInfo,
|
pub(crate) oi: OpInfo,
|
||||||
has_reset: bool,
|
pub(crate) has_reset: bool,
|
||||||
iv: u16, // Interrupt Vector
|
pub(crate) iv: u16, // Interrupt Vector
|
||||||
cycle_carry: u16, // Value to hold between microsteps
|
pub(crate) cycle_carry: u16, // Value to hold between microsteps
|
||||||
ir_bytes: [u8; 4],
|
pub(crate) ir_bytes: [u8; 4],
|
||||||
/// CPU Read signal
|
/// CPU Read signal
|
||||||
pub read_signal: bool,
|
pub read_signal: bool,
|
||||||
|
pub(crate) reset_vector: u16,
|
||||||
|
pub(crate) int_vector: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mos6502Cpu {
|
impl Mos6502Cpu {
|
||||||
@ -71,6 +73,8 @@ impl Default for Mos6502Cpu {
|
|||||||
cycle_carry: 0x0000,
|
cycle_carry: 0x0000,
|
||||||
ir_bytes: [0x00; 4],
|
ir_bytes: [0x00; 4],
|
||||||
read_signal: true,
|
read_signal: true,
|
||||||
|
reset_vector: 0x0000,
|
||||||
|
int_vector: 0x0000
|
||||||
};
|
};
|
||||||
working.reset_cpu();
|
working.reset_cpu();
|
||||||
working
|
working
|
||||||
@ -86,43 +90,17 @@ impl Mos6502Cpu {
|
|||||||
self.data_bus
|
self.data_bus
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Mos6502Cpu {
|
//
|
||||||
let array = [0x00u8; SIZE_64KB];
|
// fn read_word(&self, offset: &u16) -> u16 {
|
||||||
let mut working = Mos6502Cpu {
|
// println!("READING OFFSET 0x{offset:04x} and 0x{:04x}", offset + 1);
|
||||||
memory: array,
|
// let low = self.memory[*offset as usize];
|
||||||
ir_bytes: [0x00; 4],
|
// let high = self.memory[*offset as usize + 1];
|
||||||
..Default::default()
|
// println!("LOW = 0x{low:02x} HIGH = 0x{high:02x}");
|
||||||
};
|
// let result = (high as u16) << 8 | low as u16;
|
||||||
working.reset_cpu();
|
// // println!("MEMORY: {:?}", self.memory);
|
||||||
working
|
// println!("READ {result:04x}");
|
||||||
}
|
// result
|
||||||
|
// }
|
||||||
fn reset_cpu(&mut self) {
|
|
||||||
// self = &mut Mos6502Cpu::default();
|
|
||||||
println!("Should tick 7 times.");
|
|
||||||
// read the value at 0xfffc 0xfffd for our reset vector.
|
|
||||||
// read the value at 0xfffe 0xffff for our int vector
|
|
||||||
self.pc = self.read_word(&OFFSET_RESET_VECTOR);
|
|
||||||
println!("READ FROM {OFFSET_RESET_VECTOR} AND GOT {}", self.pc);
|
|
||||||
self.iv = self.read_word(&OFFSET_INT_VECTOR);
|
|
||||||
self.address_bus = self.pc;
|
|
||||||
self.read_signal = true;
|
|
||||||
println!(
|
|
||||||
"PC and IV are now set from ROM addresses / AB = {:016b}",
|
|
||||||
self.address_bus
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_word(&self, offset: &u16) -> u16 {
|
|
||||||
println!("READING OFFSET 0x{offset:04x} and 0x{:04x}", offset + 1);
|
|
||||||
let low = self.memory[*offset as usize];
|
|
||||||
let high = self.memory[*offset as usize + 1];
|
|
||||||
println!("LOW = 0x{low:02x} HIGH = 0x{high:02x}");
|
|
||||||
let result = (high as u16) << 8 | low as u16;
|
|
||||||
// println!("MEMORY: {:?}", self.memory);
|
|
||||||
println!("READ {result:04x}");
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn peek_flag(&self, flag_to_read: Mos6502Flag) -> bool {
|
pub fn peek_flag(&self, flag_to_read: Mos6502Flag) -> bool {
|
||||||
self.flags.flag(flag_to_read)
|
self.flags.flag(flag_to_read)
|
||||||
@ -145,15 +123,16 @@ impl Mos6502Cpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek_a(&self) -> u8 {
|
pub fn peek_a(&self) -> u8 {
|
||||||
|
println!("Readding register A => 0x{:02x}", self.a);
|
||||||
self.a
|
self.a
|
||||||
}
|
}
|
||||||
pub fn poke_a(&mut self, new_a: u8) {
|
pub fn poke_a(&mut self, new_a: u8) {
|
||||||
println!("Updating register A from [{}] to [{}]", self.a, new_a);
|
println!("Updating register A from [{}] to [{}]", self.a, new_a);
|
||||||
|
|
||||||
self.a = new_a;
|
self.a = new_a;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn peek_x(&self) -> u8 {
|
pub fn peek_x(&self) -> u8 {
|
||||||
|
println!("Readding register X => 0x{}", self.x);
|
||||||
self.x
|
self.x
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,36 +477,6 @@ impl Mos6502Cpu {
|
|||||||
self.microcode_step -= 1;
|
self.microcode_step -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump(&self) {
|
|
||||||
println!(
|
|
||||||
"CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}",
|
|
||||||
self.pc,
|
|
||||||
self.a,
|
|
||||||
self.x,
|
|
||||||
self.y,
|
|
||||||
self.address_bus,
|
|
||||||
self.data_bus,
|
|
||||||
self.microcode_step,
|
|
||||||
self.flags.dump()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// dump_data
|
|
||||||
///
|
|
||||||
/// returns
|
|
||||||
/// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step
|
|
||||||
pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8) {
|
|
||||||
(
|
|
||||||
self.pc,
|
|
||||||
self.a,
|
|
||||||
self.x,
|
|
||||||
self.y,
|
|
||||||
self.address_bus,
|
|
||||||
self.data_bus,
|
|
||||||
self.microcode_step,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
35
core/src/mos6502cpu/dbg.rs
Normal file
35
core/src/mos6502cpu/dbg.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||||
|
|
||||||
|
impl Mos6502Cpu {
|
||||||
|
/// dump_data
|
||||||
|
///
|
||||||
|
/// returns
|
||||||
|
/// PC, A, X, Y, Address_Bus, Data_Bus, Microcode_Step
|
||||||
|
pub fn dump_data(&self) -> (u16, u8, u8, u8, u16, u8, u8, u16, u16) {
|
||||||
|
(
|
||||||
|
self.pc,
|
||||||
|
self.a,
|
||||||
|
self.x,
|
||||||
|
self.y,
|
||||||
|
self.address_bus,
|
||||||
|
self.data_bus,
|
||||||
|
self.microcode_step,
|
||||||
|
self.reset_vector,
|
||||||
|
self.int_vector
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump(&self) {
|
||||||
|
println!(
|
||||||
|
"CPU State: PC: {:04x} / A: {:02x} / X: {:02x} / Y: {:02x} / ADDRESS: {:04x} / DATA: {:02x} / MICROSTEPS: {:02x} / S: {}",
|
||||||
|
self.pc,
|
||||||
|
self.a,
|
||||||
|
self.x,
|
||||||
|
self.y,
|
||||||
|
self.address_bus,
|
||||||
|
self.data_bus,
|
||||||
|
self.microcode_step,
|
||||||
|
self.flags.dump()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
core/src/mos6502cpu/mod.rs
Normal file
6
core/src/mos6502cpu/mod.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub mod cpu;
|
||||||
|
pub mod new;
|
||||||
|
|
||||||
|
pub mod tick2;
|
||||||
|
mod dbg;
|
||||||
|
mod tick_stages;
|
||||||
26
core/src/mos6502cpu/new.rs
Normal file
26
core/src/mos6502cpu/new.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use crate::constants::constants_system::{OFFSET_RESET_VECTOR, SIZE_64KB};
|
||||||
|
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||||
|
|
||||||
|
impl Mos6502Cpu {
|
||||||
|
pub fn new() -> Mos6502Cpu {
|
||||||
|
let array = [0x00u8; SIZE_64KB];
|
||||||
|
let mut working = Mos6502Cpu {
|
||||||
|
memory: array,
|
||||||
|
ir_bytes: [0x00; 4],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
working.reset_cpu();
|
||||||
|
working
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub(crate) fn reset_cpu(&mut self) {
|
||||||
|
self.microcode_step = 7 + 4;
|
||||||
|
// self = &mut Mos6502Cpu::default();
|
||||||
|
println!("Should tick 7 times, then 4 cycles to read the reset and int vectors.");
|
||||||
|
// read the value at 0xfffc 0xfffd for our reset vector.
|
||||||
|
// read the value at 0xfffe 0xffff for our int vector
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
64
core/src/mos6502cpu/tick2.rs
Normal file
64
core/src/mos6502cpu/tick2.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use crate::constants::constants_system::{OFFSET_INT_VECTOR, OFFSET_RESET_VECTOR};
|
||||||
|
use crate::mos6502cpu::cpu::Mos6502Cpu;
|
||||||
|
|
||||||
|
impl Mos6502Cpu {
|
||||||
|
/// AccurateTick
|
||||||
|
///
|
||||||
|
/// In: address_bus > Address of data operationm
|
||||||
|
/// data_bus > Data read or written
|
||||||
|
/// State:
|
||||||
|
/// read_bus > Flag for if cpu is reading or writing the data bus
|
||||||
|
/// cycle_step > Index for what step of the Decode->Load->Execute cycle we are in
|
||||||
|
/// Out: address_bus > address for operation
|
||||||
|
/// data_bus > data for the operation
|
||||||
|
/// read_bus > lets rest of the computer know if the CPU is reading from the address
|
||||||
|
/// provided or if we are writing to the address
|
||||||
|
pub fn tick2(&mut self, address_bus: u16, data_bus: u8) -> (u16, u8, bool) {
|
||||||
|
if self.has_reset {
|
||||||
|
// we have completed the reset cycle
|
||||||
|
if self.read_signal {
|
||||||
|
// we should see new data in the data_bus for us
|
||||||
|
let read_data = data_bus;
|
||||||
|
} else {
|
||||||
|
// we are writing to the bus.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("Reset microstep {}", self.microcode_step);
|
||||||
|
// we need to do the reset steps
|
||||||
|
// reduce the number of remaining microsteps
|
||||||
|
self.read_signal = true;
|
||||||
|
match self.microcode_step {
|
||||||
|
4 => {
|
||||||
|
// read first byte of reset vector
|
||||||
|
self.address_bus = OFFSET_RESET_VECTOR;
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
// at this point data holds the upper byte of our reset vector
|
||||||
|
self.reset_vector = (data_bus as u16) << 8;
|
||||||
|
// read secondd byte of reset vector
|
||||||
|
self.address_bus = OFFSET_RESET_VECTOR + 1;
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
self.reset_vector |= data_bus as u16;
|
||||||
|
println!("Loaded reset vector of 0x{:04x}", self.reset_vector);
|
||||||
|
// read first byte of interrupt vector
|
||||||
|
self.address_bus = OFFSET_INT_VECTOR;
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
// read second byte of interrupt vector
|
||||||
|
self.address_bus = OFFSET_INT_VECTOR + 1;
|
||||||
|
}
|
||||||
|
0 => {
|
||||||
|
self.int_vector |= data_bus as u16;
|
||||||
|
println!("Loaded interrupt vector of 0x{:04x}", self.int_vector);
|
||||||
|
self.pc = self.reset_vector;
|
||||||
|
println!("Set PC to Reset Vector. Giddy-up!");
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.microcode_step -= 1;
|
||||||
|
}
|
||||||
|
(self.address_bus, self.data_bus, self.read_signal)
|
||||||
|
}
|
||||||
|
}
|
||||||
19
core/src/mos6502cpu/tick_stages.rs
Normal file
19
core/src/mos6502cpu/tick_stages.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
/// Mos6502TickStates
|
||||||
|
///
|
||||||
|
/// The set of what a tick can be doing
|
||||||
|
///
|
||||||
|
enum Mos6502TickStates {
|
||||||
|
/// Loading the first byte into the IR
|
||||||
|
LoadingInstruction,
|
||||||
|
/// Loading an 8 bit parameter
|
||||||
|
Loading8BitParameter,
|
||||||
|
/// Loading the MSB 8 bits
|
||||||
|
Loading16BitParameter1,
|
||||||
|
/// Loading the LSB 8 bits
|
||||||
|
Loading16BitParameter2,
|
||||||
|
/// Stalling for accurate emulation
|
||||||
|
Stall(u8),
|
||||||
|
/// Completed the instruction
|
||||||
|
Complete
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
mod default;
|
pub mod default;
|
||||||
mod rom_chip;
|
pub mod rom_chip;
|
||||||
|
pub mod tick;
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
31
core/src/periph/at28c256/tick.rs
Normal file
31
core/src/periph/at28c256/tick.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::periph::at28c256::At28C256;
|
||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
|
||||||
|
impl At28C256 {
|
||||||
|
fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
||||||
|
if !read_mode {
|
||||||
|
// has to be read mode. its a rom.
|
||||||
|
return (address_bus, data_bus)
|
||||||
|
}
|
||||||
|
(address_bus, self.data[address_bus as usize])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smoke() { assert!(true); }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_to_memory_read_back_works_at_0() {
|
||||||
|
let mut rom = At28C256::default();
|
||||||
|
|
||||||
|
rom.tick(0x0000, 0xab, false);
|
||||||
|
let (_, new_data) = rom.tick(0x0000, 0x00, true);
|
||||||
|
|
||||||
|
assert_eq!(new_data, 0xab);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,13 @@
|
|||||||
// HM62256 Static Ram
|
// HM62256 Static Ram
|
||||||
|
|
||||||
|
pub mod ramchip;
|
||||||
|
pub mod romchip;
|
||||||
|
pub mod tick;
|
||||||
|
|
||||||
use crate::constants::constants_system::SIZE_32KB;
|
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;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
pub struct Hm62256 {
|
pub struct Hm62256 {
|
||||||
pub(crate) base_offset: u16,
|
pub(crate) base_offset: u16,
|
||||||
pub(crate) data: Box<[u8]>,
|
pub(crate) data: Box<[u8]>,
|
||||||
@ -23,27 +26,6 @@ impl Default for Hm62256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RomChip for Hm62256 {
|
|
||||||
fn read(&self, offset: &u16) -> u8 {
|
|
||||||
// loops memory around past 32k
|
|
||||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
|
||||||
self.data[effective as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn program(_: &[u8; SIZE_32KB]) -> Box<Self> {
|
|
||||||
debug!("Dont program ram.");
|
|
||||||
Hm62256::default().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RamChip for Hm62256 {
|
|
||||||
fn write(&mut self, offset: &u16, value: &u8) {
|
|
||||||
let effective = *offset as i32 % SIZE_32KB as i32;
|
|
||||||
println!("Writing at E[{effective:04x}] / O[{offset:04x}]");
|
|
||||||
self.data[effective as usize] = *value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -61,7 +43,7 @@ mod test {
|
|||||||
// 100,000 random read/writes to ram that all read back right
|
// 100,000 random read/writes to ram that all read back right
|
||||||
for _ in 0..100_000 {
|
for _ in 0..100_000 {
|
||||||
let mut offset: u16 = random();
|
let mut offset: u16 = random();
|
||||||
println!("SIze = {SIZE_32KB}");
|
println!("Size = {SIZE_32KB}");
|
||||||
let value: u8 = random();
|
let value: u8 = random();
|
||||||
println!("Wrote [{value:02x}] to [{offset:04x}]");
|
println!("Wrote [{value:02x}] to [{offset:04x}]");
|
||||||
ram.write(&offset, &value);
|
ram.write(&offset, &value);
|
||||||
12
core/src/periph/hm62256/ramchip.rs
Normal file
12
core/src/periph/hm62256/ramchip.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
use crate::periph::ram_chip::RamChip;
|
||||||
|
|
||||||
|
impl RamChip for Hm62256 {
|
||||||
|
fn write(&mut self, offset: &u16, value: &u8) {
|
||||||
|
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||||
|
println!("Writing at E[{effective:04x}] / O[{offset:04x}]");
|
||||||
|
self.data[effective as usize] = *value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
19
core/src/periph/hm62256/romchip.rs
Normal file
19
core/src/periph/hm62256/romchip.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use log::debug;
|
||||||
|
use crate::constants::constants_system::SIZE_32KB;
|
||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
use crate::periph::rom_chip::RomChip;
|
||||||
|
|
||||||
|
impl RomChip for Hm62256 {
|
||||||
|
|
||||||
|
|
||||||
|
fn read(&self, offset: &u16) -> u8 {
|
||||||
|
// loops memory around past 32k
|
||||||
|
let effective = *offset as i32 % SIZE_32KB as i32;
|
||||||
|
self.data[effective as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn program(_: &[u8; SIZE_32KB]) -> Box<Self> {
|
||||||
|
debug!("Dont program ram.");
|
||||||
|
Hm62256::default().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
33
core/src/periph/hm62256/tick.rs
Normal file
33
core/src/periph/hm62256/tick.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use crate::periph::hm62256::Hm62256;
|
||||||
|
|
||||||
|
impl Hm62256 {
|
||||||
|
fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) {
|
||||||
|
let new_data_bus = if read_mode {
|
||||||
|
// reading from ram
|
||||||
|
self.data[address_bus as usize]
|
||||||
|
} else {
|
||||||
|
// writing to ram
|
||||||
|
self.data[address_bus as usize] = data_bus.into();
|
||||||
|
data_bus
|
||||||
|
};
|
||||||
|
(address_bus, new_data_bus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smoke() { assert!(true); }
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn write_to_memory_read_back_works_at_0() {
|
||||||
|
let mut ram = Hm62256::default();
|
||||||
|
|
||||||
|
ram.tick(0x0000, 0xab, false);
|
||||||
|
let (_, new_data) = ram.tick(0x0000, 0x00, true);
|
||||||
|
|
||||||
|
assert_eq!(new_data, 0xab);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,4 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
macroquad.workspace = true
|
macroquad.workspace = true
|
||||||
|
core = { path = "../core" }
|
||||||
31
macroquad/src/bin/rom_only.rs
Normal file
31
macroquad/src/bin/rom_only.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user