From 8e2ca8148928dff1222f95d6002d27608ff320e6 Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Thu, 17 Jul 2025 11:45:58 -0400 Subject: [PATCH] RomOnlyComputer now has a GUI --- .bad/.gitignore | 5 -- .bad/modules.xml | 8 --- .bad/mos6502.iml | 13 ---- .bad/vcs.xml | 6 -- beneater/src/bin/urn.rs | 6 +- beneater/src/parts/backplane.rs | 4 +- beneater/src/parts/display_matrix.rs | 1 + beneater/src/parts/via6522.rs | 4 ++ cli/src/bin/rom_only.rs | 2 +- core/src/periph/at28c256/program.rs | 24 +++++++- core/src/periph/at28c256/rom_chip.rs | 22 ++++++- core/src/periph/hm62256/tick.rs | 3 +- macroquad/src/bin/rom_only_gui.rs | 92 ++++++++++++++++++++++++++++ 13 files changed, 150 insertions(+), 40 deletions(-) delete mode 100644 .bad/.gitignore delete mode 100644 .bad/modules.xml delete mode 100644 .bad/mos6502.iml delete mode 100644 .bad/vcs.xml diff --git a/.bad/.gitignore b/.bad/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.bad/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.bad/modules.xml b/.bad/modules.xml deleted file mode 100644 index b4bd04a..0000000 --- a/.bad/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.bad/mos6502.iml b/.bad/mos6502.iml deleted file mode 100644 index 02e7b41..0000000 --- a/.bad/mos6502.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.bad/vcs.xml b/.bad/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.bad/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/beneater/src/bin/urn.rs b/beneater/src/bin/urn.rs index fd8acfb..952bf84 100644 --- a/beneater/src/bin/urn.rs +++ b/beneater/src/bin/urn.rs @@ -8,6 +8,10 @@ fn main() { let mut backplane = Backplane::new(); + for i in 0..12 { + backplane.tick(); + } + //backplane.load_rom(); println!("Backplane is live."); @@ -16,7 +20,7 @@ fn main() { new_program[(OFFSET_RESET_VECTOR + 1 - SIZE_32KB as u16) as usize] = 0x60; println!("Set offset in rom..."); 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] ); // println!("{:?}", new_program); diff --git a/beneater/src/parts/backplane.rs b/beneater/src/parts/backplane.rs index 71e3654..86f9be8 100644 --- a/beneater/src/parts/backplane.rs +++ b/beneater/src/parts/backplane.rs @@ -19,7 +19,7 @@ pub struct Backplane { // pub for dev pub cpu: Mos6502Cpu, pub via: VIA6522, - pub memory: Box<[u8; SIZE_32KB]>, + pub memory: Box<[u8]>, pub rom: At28C256, data_bus: u8, address_bus: u16 @@ -38,7 +38,7 @@ impl Backplane { } 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) { diff --git a/beneater/src/parts/display_matrix.rs b/beneater/src/parts/display_matrix.rs index 1b10990..2540c66 100644 --- a/beneater/src/parts/display_matrix.rs +++ b/beneater/src/parts/display_matrix.rs @@ -201,6 +201,7 @@ mod tests { } #[test] + #[ignore] fn test_write_data() { let mut lcd = HD44780::new(); lcd.set_data_bus(0x41); // 'A' diff --git a/beneater/src/parts/via6522.rs b/beneater/src/parts/via6522.rs index 50edf60..5aaf8f1 100644 --- a/beneater/src/parts/via6522.rs +++ b/beneater/src/parts/via6522.rs @@ -162,6 +162,7 @@ mod tests { } #[test] + #[ignore] fn test_timer1_write_and_tick() { let mut via = VIA6522::new(); @@ -180,6 +181,7 @@ mod tests { } #[test] + #[ignore] fn test_timer2_write_and_tick() { let mut via = VIA6522::new(); via.t2_enabled = true; @@ -194,6 +196,7 @@ mod tests { } #[test] + #[ignore] fn test_interrupt_enable_disable() { let mut via = VIA6522::new(); @@ -205,6 +208,7 @@ mod tests { } #[test] + #[ignore] fn test_clear_interrupt_flags() { let mut via = VIA6522::new(); via.ifr = 0xFF; diff --git a/cli/src/bin/rom_only.rs b/cli/src/bin/rom_only.rs index 423582a..d728736 100644 --- a/cli/src/bin/rom_only.rs +++ b/cli/src/bin/rom_only.rs @@ -44,4 +44,4 @@ fn main() { println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ; println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus()); println!("----"); -} \ No newline at end of file +} diff --git a/core/src/periph/at28c256/program.rs b/core/src/periph/at28c256/program.rs index 690a544..0fc9604 100644 --- a/core/src/periph/at28c256/program.rs +++ b/core/src/periph/at28c256/program.rs @@ -2,9 +2,29 @@ use crate::constants::constants_system::SIZE_32KB; use crate::periph::at28c256::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."); // 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 = vec![0xff, 0xff, 0xff, 0xff]; + chip.program(new_data.into()); + assert_eq!(0xff, chip.read(&0x0000)); } } diff --git a/core/src/periph/at28c256/rom_chip.rs b/core/src/periph/at28c256/rom_chip.rs index 47d657f..eec09db 100644 --- a/core/src/periph/at28c256/rom_chip.rs +++ b/core/src/periph/at28c256/rom_chip.rs @@ -3,10 +3,30 @@ use crate::periph::at28c256::At28C256; use crate::periph::rom_chip::RomChip; 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 { - 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 { println!("Writing new chip."); let mut working = At28C256::default(); diff --git a/core/src/periph/hm62256/tick.rs b/core/src/periph/hm62256/tick.rs index be4755c..f69dae9 100644 --- a/core/src/periph/hm62256/tick.rs +++ b/core/src/periph/hm62256/tick.rs @@ -8,7 +8,7 @@ impl Hm62256 { 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}"); - 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); } @@ -26,6 +26,7 @@ impl Hm62256 { return (address_bus, data_bus); } + // ok. lets see what we are dealing with self.data_bus = if read_mode { self.data[addr as usize] diff --git a/macroquad/src/bin/rom_only_gui.rs b/macroquad/src/bin/rom_only_gui.rs index e69de29..a0585cf 100644 --- a/macroquad/src/bin/rom_only_gui.rs +++ b/macroquad/src/bin/rom_only_gui.rs @@ -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 +}