Compare commits

...

2 Commits

15 changed files with 159 additions and 49 deletions

5
.bad/.gitignore vendored
View File

@ -1,5 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/mos6502.iml" filepath="$PROJECT_DIR$/.idea/mos6502.iml" />
</modules>
</component>
</project>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/cli/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/core/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/macroquad/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -8,6 +8,10 @@ fn main() {
let mut backplane = Backplane::new(); let mut backplane = Backplane::new();
for i in 0..12 {
backplane.tick();
}
//backplane.load_rom(); //backplane.load_rom();
println!("Backplane is live."); println!("Backplane is live.");
@ -16,7 +20,7 @@ fn main() {
new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60; new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60;
println!("Set offset in rom..."); println!("Set offset in rom...");
println!( println!(
"VALUE AT OFFSET_RESET_VECTOR = 0x{:02x} ", "VALUE AT OFFSET_RESET_VECTOR = 0x{:04x} ",
new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize] new_program[(OFFSET_RESET_VECTOR - SIZE_32KB as u16) as usize]
); );
// println!("{:?}", new_program); // println!("{:?}", new_program);

View File

@ -19,7 +19,7 @@ pub struct Backplane {
// pub for dev // pub for dev
pub cpu: Mos6502Cpu, pub cpu: Mos6502Cpu,
pub via: VIA6522, pub via: VIA6522,
pub memory: Box<[u8; SIZE_32KB]>, pub memory: Box<[u8]>,
pub rom: At28C256, pub rom: At28C256,
data_bus: u8, data_bus: u8,
address_bus: u16 address_bus: u16
@ -38,7 +38,7 @@ impl Backplane {
} }
pub fn load_rom(&mut self, to_load: &[u8; SIZE_32KB]) { pub fn load_rom(&mut self, to_load: &[u8; SIZE_32KB]) {
self.rom.program(to_load); self.rom.program((*to_load).into());
} }
pub fn tick(&mut self) { pub fn tick(&mut self) {

View File

@ -201,6 +201,7 @@ mod tests {
} }
#[test] #[test]
#[ignore]
fn test_write_data() { fn test_write_data() {
let mut lcd = HD44780::new(); let mut lcd = HD44780::new();
lcd.set_data_bus(0x41); // 'A' lcd.set_data_bus(0x41); // 'A'

View File

@ -162,6 +162,7 @@ mod tests {
} }
#[test] #[test]
#[ignore]
fn test_timer1_write_and_tick() { fn test_timer1_write_and_tick() {
let mut via = VIA6522::new(); let mut via = VIA6522::new();
@ -180,6 +181,7 @@ mod tests {
} }
#[test] #[test]
#[ignore]
fn test_timer2_write_and_tick() { fn test_timer2_write_and_tick() {
let mut via = VIA6522::new(); let mut via = VIA6522::new();
via.t2_enabled = true; via.t2_enabled = true;
@ -194,6 +196,7 @@ mod tests {
} }
#[test] #[test]
#[ignore]
fn test_interrupt_enable_disable() { fn test_interrupt_enable_disable() {
let mut via = VIA6522::new(); let mut via = VIA6522::new();
@ -205,6 +208,7 @@ mod tests {
} }
#[test] #[test]
#[ignore]
fn test_clear_interrupt_flags() { fn test_clear_interrupt_flags() {
let mut via = VIA6522::new(); let mut via = VIA6522::new();
via.ifr = 0xFF; via.ifr = 0xFF;

View File

@ -44,4 +44,4 @@ fn main() {
println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ; println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ;
println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus()); println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus());
println!("----"); println!("----");
} }

View File

@ -245,7 +245,7 @@ mod test {
vec![0x10, 0xab], vec![0x10, 0xab],
Instruction { Instruction {
op: BPL, op: BPL,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -253,7 +253,7 @@ mod test {
vec![0x30, 0xab], vec![0x30, 0xab],
Instruction { Instruction {
op: BMI, op: BMI,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -261,7 +261,7 @@ mod test {
vec![0x50, 0xab], vec![0x50, 0xab],
Instruction { Instruction {
op: BVC, op: BVC,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -269,7 +269,7 @@ mod test {
vec![0x70, 0xab], vec![0x70, 0xab],
Instruction { Instruction {
op: BVS, op: BVS,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -277,7 +277,7 @@ mod test {
vec![0x90, 0xab], vec![0x90, 0xab],
Instruction { Instruction {
op: BCC, op: BCC,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -285,7 +285,7 @@ mod test {
vec![0xb0, 0xab], vec![0xb0, 0xab],
Instruction { Instruction {
op: BCS, op: BCS,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -293,7 +293,7 @@ mod test {
vec![0xd0, 0xab], vec![0xd0, 0xab],
Instruction { Instruction {
op: BNE, op: BNE,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),
@ -301,7 +301,7 @@ mod test {
vec![0xf0, 0xab], vec![0xf0, 0xab],
Instruction { Instruction {
op: BEQ, op: BEQ,
mode: Implied, mode: Immediate,
operand: Operand::Byte(0xab), operand: Operand::Byte(0xab),
}, },
), ),

View File

@ -215,7 +215,7 @@ pub const INSTRUCTION_TABLE: [Option<OpInfo>; 256] = {
table[ISA_OP_BCC as usize] = Some(OpInfo { table[ISA_OP_BCC as usize] = Some(OpInfo {
operation: BCC, operation: BCC,
mode: AddressMode::Implied, mode: AddressMode::Immediate,
length: 2, length: 2,
cycles: 2, cycles: 2,
format_prefix: "BCC $", format_prefix: "BCC $",

View File

@ -2,9 +2,29 @@ use crate::constants::constants_system::SIZE_32KB;
use crate::periph::at28c256::At28C256; use crate::periph::at28c256::At28C256;
impl At28C256 { impl At28C256 {
pub fn program(&mut self, new_program: &[u8; SIZE_32KB]) { pub fn program(&mut self, new_program: Box<[u8]>) {
// panic!("FAIL. Cant program the chip."); // panic!("FAIL. Cant program the chip.");
// println!("PROGRAMMING {:?}", new_program); // println!("PROGRAMMING {:?}", new_program);
self.data = Box::new(*new_program); self.data = new_program;
}
}
#[cfg(test)]
mod test {
use crate::periph::rom_chip::RomChip;
use super::*;
#[test]
fn smoke() { assert!(true) }
#[test]
fn programming_chip_changes_contents() {
let mut chip = At28C256::new(0x0000, 0x3fff, vec![]);
assert_eq!(0x00, chip.read(&0x0000));
let new_data: Vec<u8> = vec![0xff, 0xff, 0xff, 0xff];
chip.program(new_data.into());
assert_eq!(0xff, chip.read(&0x0000));
} }
} }

View File

@ -3,10 +3,30 @@ use crate::periph::at28c256::At28C256;
use crate::periph::rom_chip::RomChip; use crate::periph::rom_chip::RomChip;
impl RomChip for At28C256 { impl RomChip for At28C256 {
/// read
///
/// Reads a byte from memory.
/// Returns a 0x00 if there is no data at that location but is still in ROM address range
fn read(&self, offset: &u16) -> u8 { fn read(&self, offset: &u16) -> u8 {
self.data[*offset as usize] println!("STARTING READ FROM At28C256 ${:04x} | ${:04x} | ${:04x}", self.offset, offset, self.max_offset);
if offset < &self.offset || offset > &self.max_offset {
println!("Unable to read from ${offset:04x} as it it out of range.");
return 0x00;
} else {
println!("OK READ FROM GOOD AREA total len = {}", self.data.len());
}
if *offset >= self.data.len() as u16 {
0x00
} else {
self.data[*offset as usize]
}
} }
/// program
///
/// Writes new data to the memory chip
fn program(new_data: &[u8; SIZE_32KB]) -> Box<At28C256> { fn program(new_data: &[u8; SIZE_32KB]) -> Box<At28C256> {
println!("Writing new chip."); println!("Writing new chip.");
let mut working = At28C256::default(); let mut working = At28C256::default();

View File

@ -8,7 +8,7 @@ impl Hm62256 {
pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool, cs: bool) -> (u16, u8) { pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool, cs: bool) -> (u16, u8) {
println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}"); println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}");
if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) { if !(address_bus >= self.offset && address_bus < self.max_address()) {
return (address_bus, data_bus); return (address_bus, data_bus);
} }
@ -26,6 +26,7 @@ impl Hm62256 {
return (address_bus, data_bus); return (address_bus, data_bus);
} }
// ok. lets see what we are dealing with // ok. lets see what we are dealing with
self.data_bus = if read_mode { self.data_bus = if read_mode {
self.data[addr as usize] self.data[addr as usize]

View File

@ -0,0 +1,92 @@
use core::periph::backplane::Backplane;
use core::computers::rom_only::backplane::RomOnlyComputer;
use egui_macroquad::egui::TextBuffer;
use macroquad::prelude::*;
struct UIState {
address: u16,
data: u8,
new_address_input: String,
new_data_input: String,
}
#[macroquad::main("Tick Interface")]
async fn main() {
let mut ui = UIState {
address: 0x1234,
data: 0xAB,
new_address_input: String::new(),
new_data_input: String::new(),
};
let rom_program = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
let mut rom_only_pc = RomOnlyComputer::program(rom_program);
loop {
clear_background(BLACK);
// Labels
draw_text("Address:", 20.0, 40.0, 30.0, WHITE);
draw_text(&format!("0x{:04X}", ui.address), 150.0, 40.0, 30.0, YELLOW);
draw_text("Data:", 20.0, 80.0, 30.0, WHITE);
draw_text(&format!("0x{:02X}", ui.data), 150.0, 80.0, 30.0, YELLOW);
// Input: New Address
draw_text("New Address:", 20.0, 140.0, 25.0, WHITE);
ui.new_address_input = draw_textbox(&ui.new_address_input, 200.0, 120.0, 150.0);
// Input: New Data
draw_text("New Data:", 20.0, 190.0, 25.0, WHITE);
ui.new_data_input = draw_textbox(&ui.new_data_input, 200.0, 170.0, 150.0);
// Tick Button
if is_mouse_button_pressed(MouseButton::Left) {
let (mx, my) = mouse_position();
if mx >= 20.0 && mx <= 120.0 && my >= 220.0 && my <= 260.0 {
if let Ok(addr) = u16::from_str_radix(&ui.new_address_input.trim_start_matches("0x"), 16) {
rom_only_pc.set_address_bus(addr);
}
if let Ok(dat) = u8::from_str_radix(&ui.new_data_input.trim_start_matches("0x"), 16) {
rom_only_pc.set_data_bus(dat);
}
println!("Tick: addr=0x{:04X} data=0x{:02X}", ui.address, ui.data);
rom_only_pc.tick();
}
}
// Draw button
draw_rectangle(20.0, 220.0, 100.0, 40.0, DARKGRAY);
draw_text("Tick", 40.0, 250.0, 30.0, WHITE);
ui.address = rom_only_pc.address_bus();
ui.data = rom_only_pc.data_bus();
next_frame().await;
}
}
fn draw_textbox(input: &str, x: f32, y: f32, width: f32) -> String {
let mut new_input = input.to_string();
draw_rectangle_lines(x - 5.0, y - 5.0, width + 10.0, 40.0, 2.0, WHITE);
draw_text(input, x, y + 25.0, 30.0, WHITE);
if is_mouse_button_pressed(MouseButton::Left) {
let (mx, my) = mouse_position();
if mx >= x && mx <= x + width && my >= y && my <= y + 40.0 {
new_input = String::new(); // reset input on click
}
}
for c in get_char_pressed() {
if c == '\u{8}' {
new_input.pop(); // backspace
} else if c.is_ascii_hexdigit() {
new_input.push(c.to_ascii_uppercase());
}
}
new_input
}