From 6fcf1547d194168baab1ba9027f58e22ec106a27 Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Wed, 16 Jul 2025 15:01:16 -0400 Subject: [PATCH] more fixed stuff --- Cargo.lock | 271 ++++++++++++++++-- beneater/src/parts/cpu_display.rs | 2 +- cli/src/bin/ram_rom.rs | 21 ++ cli/src/bin/rom_only.rs | 35 ++- core/Cargo.toml | 1 + core/src/backplane.rs | 25 ++ core/src/computers/mod.rs | 1 + core/src/computers/ram_rom/backplane.rs | 53 ++++ core/src/computers/ram_rom/mod.rs | 1 + core/src/computers/rom_only/backplane.rs | 61 ++-- core/src/constants/constants_test.rs | 7 + core/src/constants/mod.rs | 1 + core/src/lib.rs | 1 + core/src/mos6502cpu/cpu.rs | 9 +- core/src/mos6502cpu/new.rs | 8 +- core/src/periph/at28c256/checksum.rs | 80 ++++++ core/src/periph/at28c256/default.rs | 10 +- core/src/periph/at28c256/mod.rs | 31 +- core/src/periph/at28c256/new.rs | 9 +- core/src/periph/at28c256/tick.rs | 62 ++-- core/src/periph/backplane.rs | 9 + core/src/periph/hm62256/tick.rs | 3 +- core/src/periph/mod.rs | 1 + core/src/periph/mos6522/mos6522.rs | 36 +-- core/src/periph/mos6522/tick.rs | 23 +- core/src/periph/mos6530/mos6530.rs | 3 +- .../bin/rom_only.rs => core/tests/at28c256.rs | 0 macroquad/src/bin/rom_only_gui.rs | 0 resources/test/periph/at28c256/checksum.bin | Bin 0 -> 80 bytes 29 files changed, 625 insertions(+), 139 deletions(-) create mode 100644 cli/src/bin/ram_rom.rs create mode 100644 core/src/backplane.rs create mode 100644 core/src/computers/ram_rom/backplane.rs create mode 100644 core/src/computers/ram_rom/mod.rs create mode 100644 core/src/constants/constants_test.rs create mode 100644 core/src/periph/at28c256/checksum.rs create mode 100644 core/src/periph/backplane.rs rename macroquad/src/bin/rom_only.rs => core/tests/at28c256.rs (100%) create mode 100644 macroquad/src/bin/rom_only_gui.rs create mode 100644 resources/test/periph/at28c256/checksum.bin diff --git a/Cargo.lock b/Cargo.lock index aee33ac..e8a9d0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "once_cell", + "once_cell 1.21.3", "version_check", "zerocopy", ] @@ -119,6 +119,15 @@ dependencies = [ "lewton", ] +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.5.0", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -229,9 +238,9 @@ checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "clap" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" dependencies = [ "clap_builder", "clap_derive", @@ -239,9 +248,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" dependencies = [ "anstream", "anstyle", @@ -251,9 +260,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.40" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", @@ -287,6 +296,15 @@ dependencies = [ "error-code", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -327,14 +345,15 @@ name = "core" version = "0.1.0" dependencies = [ "log", - "rand", + "once_cell 0.1.8", + "rand 0.9.1", ] [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] @@ -466,7 +485,7 @@ dependencies = [ "emath", "epaint_default_fonts", "nohash-hasher", - "parking_lot", + "parking_lot 0.12.4", "profiling", ] @@ -539,6 +558,12 @@ dependencies = [ "ttf-parser 0.21.1", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "gethostname" version = "0.4.3" @@ -649,7 +674,7 @@ version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "once_cell", + "once_cell 1.21.3", "wasm-bindgen", ] @@ -692,14 +717,23 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +dependencies = [ + "scopeguard 0.3.3", +] + [[package]] name = "lock_api" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ - "autocfg", - "scopeguard", + "autocfg 1.5.0", + "scopeguard 1.2.0", ] [[package]] @@ -761,9 +795,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" dependencies = [ "libc", ] @@ -808,7 +842,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg", + "autocfg 1.5.0", ] [[package]] @@ -928,6 +962,15 @@ dependencies = [ "byteorder", ] +[[package]] +name = "once_cell" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +dependencies = [ + "parking_lot 0.7.1", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -949,14 +992,37 @@ dependencies = [ "ttf-parser 0.25.1", ] +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +dependencies = [ + "lock_api 0.1.5", + "parking_lot_core 0.4.0", +] + [[package]] name = "parking_lot" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ - "lock_api", - "parking_lot_core", + "lock_api 0.4.13", + "parking_lot_core 0.9.11", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +dependencies = [ + "libc", + "rand 0.6.5", + "rustc_version", + "smallvec 0.6.14", + "winapi", ] [[package]] @@ -1007,7 +1073,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.7", + "rustix 1.0.8", "tracing", "windows-sys 0.59.0", ] @@ -1108,14 +1174,43 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +dependencies = [ + "autocfg 0.1.8", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", +] + [[package]] name = "rand" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ - "rand_chacha", - "rand_core", + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.3.1", ] [[package]] @@ -1125,9 +1220,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.3", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.9.3" @@ -1137,6 +1247,77 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +dependencies = [ + "libc", + "rand_core 0.4.2", + "winapi", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +dependencies = [ + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +dependencies = [ + "autocfg 0.1.8", + "rand_core 0.4.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.5.13" @@ -1175,6 +1356,15 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.44" @@ -1190,15 +1380,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags 2.9.1", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1213,12 +1403,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "shlex" version = "1.3.0" @@ -1313,8 +1524,8 @@ checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom 0.3.3", - "once_cell", - "rustix 1.0.7", + "once_cell 1.21.3", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -1425,7 +1636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", - "once_cell", + "once_cell 1.21.3", "wasm-bindgen-macro", ] @@ -1567,7 +1778,7 @@ checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615" dependencies = [ "dlib", "log", - "once_cell", + "once_cell 1.21.3", "pkg-config", ] diff --git a/beneater/src/parts/cpu_display.rs b/beneater/src/parts/cpu_display.rs index 9c2e5a7..f23bd33 100644 --- a/beneater/src/parts/cpu_display.rs +++ b/beneater/src/parts/cpu_display.rs @@ -7,7 +7,7 @@ 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, microsteps_remaining, reset_vector, interrupt_vector) = cpu.dump_data(); + let (pc, a, x, y, address_bus, data_bus, microsteps_remaining, reset_vector, interrupt_vector, nmi_vector) = cpu.dump_data(); // ...build the interface Self::draw_square(x_offset, y_offset, x_offset + 300.0, y_offset + 85.0, BLACK); diff --git a/cli/src/bin/ram_rom.rs b/cli/src/bin/ram_rom.rs new file mode 100644 index 0000000..bd283a8 --- /dev/null +++ b/cli/src/bin/ram_rom.rs @@ -0,0 +1,21 @@ +use std::fs; + +fn main() { + println!("Taxation is Theft"); + + // let opts = CliOptions::parse(); + let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin"; + let bytes = match fs::read(path) { + Ok(bytes) => { + println!("Read {} bytes.", bytes.len()); + bytes + }, + Err(e) => { + eprintln!("FAIL to read rom."); + panic!("No rom no run."); + vec![] + } + }; + + +} \ No newline at end of file diff --git a/cli/src/bin/rom_only.rs b/cli/src/bin/rom_only.rs index 6abd7cd..423582a 100644 --- a/cli/src/bin/rom_only.rs +++ b/cli/src/bin/rom_only.rs @@ -1,5 +1,7 @@ +use std::fs; use clap::Parser; use core::computers::rom_only::backplane::RomOnlyComputer; +use core::periph::backplane::Backplane; #[derive(Parser)] struct CliOptions { @@ -11,8 +13,35 @@ struct CliOptions { fn main() { println!("Taxation is theft"); - let opts = CliOptions::parse(); + // let opts = CliOptions::parse(); + let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin"; + let bytes = match fs::read(path) { + Ok(bytes) => { + println!("Read {} bytes.", bytes.len()); + bytes + }, + Err(e) => { + eprintln!("FAIL to read rom."); + panic!("No rom no run."); + vec![] + } + }; - let mut rom_only = RomOnlyComputer::new(); - rom_only.tick() + let mut rom_only = RomOnlyComputer::program((&bytes[..]).to_vec()); + + rom_only.set_read_mode(true); + rom_only.set_address_bus(0x05); + rom_only.tick(); + + println!("COMPUTER: Read {:02x} from ROM", rom_only.data_bus()) ; + println!("COMPUTER: Read {:04x} from Address Bus", rom_only.address_bus()); + + println!("----"); + rom_only.set_read_mode(true); + rom_only.set_address_bus(0x07); + rom_only.tick(); + + 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/Cargo.toml b/core/Cargo.toml index 8ca1694..a7369c8 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -5,3 +5,4 @@ edition = "2024" [dependencies] log = "0.4" rand = "0.9.0" +once_cell = "0.1" diff --git a/core/src/backplane.rs b/core/src/backplane.rs new file mode 100644 index 0000000..938c9ed --- /dev/null +++ b/core/src/backplane.rs @@ -0,0 +1,25 @@ +use crate::mos6502cpu::cpu::Mos6502Cpu; +use crate::periph::ram_chip::RamChip; + +/// BackplaneBuilder +/// +/// Builds a Backplane for a 6502 Emulated PC +struct BackplaneBuilder { + cpu: Mos6502Cpu, + // ram_modules: Vec +} + +impl BackplaneBuilder { + pub fn add_cpu(mut self, new_cpu: Mos6502Cpu) -> Self { + self.cpu = new_cpu; + self + } + + pub fn add_ram(mut self, new_ram: impl RamChip) -> Self { + // self.ram_modules.push(new_ram); + self + } + + +} + diff --git a/core/src/computers/mod.rs b/core/src/computers/mod.rs index ceab4c3..80916a1 100644 --- a/core/src/computers/mod.rs +++ b/core/src/computers/mod.rs @@ -1,3 +1,4 @@ pub mod beneater; pub mod rom_only; pub mod kim1; +pub mod ram_rom; diff --git a/core/src/computers/ram_rom/backplane.rs b/core/src/computers/ram_rom/backplane.rs new file mode 100644 index 0000000..072b437 --- /dev/null +++ b/core/src/computers/ram_rom/backplane.rs @@ -0,0 +1,53 @@ +use crate::periph::at28c256::At28C256; +use crate::periph::backplane::Backplane; +use crate::periph::hm62256::Hm62256; + +pub struct RamRomComputer { + rom: At28C256, + ram: Hm62256, + data_bus: u8, + address_bus: u16, + read_mode: bool, +} + +impl Backplane for RamRomComputer { + fn data_bus(&self) -> u8 { + self.data_bus + } + + fn address_bus(&self) -> u16 { + self.address_bus + } + + fn read_mode(&self) -> bool { + self.read_mode + } + + fn tick(&mut self) { + todo!() + } + fn set_read_mode(&mut self, new_mode: bool) { + self.read_mode = new_mode; + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value; + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value; + } +} + +impl RamRomComputer { + pub fn new() -> RamRomComputer { + RamRomComputer { + rom: At28C256::default(), + ram: Hm62256::default(), + data_bus: 0x00, + address_bus: 0x0000, + /// is the CPU reading from the 'other' device? + read_mode: true + } + } +} \ No newline at end of file diff --git a/core/src/computers/ram_rom/mod.rs b/core/src/computers/ram_rom/mod.rs new file mode 100644 index 0000000..2c03511 --- /dev/null +++ b/core/src/computers/ram_rom/mod.rs @@ -0,0 +1 @@ +pub mod backplane; \ No newline at end of file diff --git a/core/src/computers/rom_only/backplane.rs b/core/src/computers/rom_only/backplane.rs index 770f5f7..b9335cd 100644 --- a/core/src/computers/rom_only/backplane.rs +++ b/core/src/computers/rom_only/backplane.rs @@ -1,34 +1,59 @@ use crate::constants::constants_system::{SIZE_32KB, SIZE_64KB}; use crate::periph::at28c256::At28C256; -use crate::periph::hm62256::Hm62256; +use crate::periph::backplane::Backplane; use crate::periph::rom_chip::RomChip; - pub struct RomOnlyComputer { rom: At28C256, data_bus: u8, - address_bus: u16 + address_bus: u16, + read_mode: bool, +} + +impl Backplane for RomOnlyComputer { + fn data_bus(&self) -> u8 { self.data_bus } + fn address_bus(&self) -> u16 { self.address_bus } + fn read_mode(&self) -> bool { self.read_mode } + + fn set_read_mode(&mut self, new_mode: bool) { + self.read_mode = new_mode + } + + fn set_data_bus(&mut self, new_value: u8) { + self.data_bus = new_value + } + + fn set_address_bus(&mut self, new_value: u16) { + self.address_bus = new_value + } + + fn tick(&mut self) { + println!("COMPUTER: Preparing to tick."); + + // do are we being addressed? + println!("COMPUTER: BUSSES PRE: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); + let (new_addr, new_data) = self.rom.tick(self.address_bus, self.data_bus, self.read_mode); + self.set_address_bus(new_addr); + self.set_data_bus(new_data); + println!("COMPUTER: BUSSES POST: 0x{:04x} 0x{:02x} {}", self.address_bus, self.data_bus, self.read_mode); + println!("COMPUTER: Done ticking."); + } } impl RomOnlyComputer { pub fn new() -> RomOnlyComputer { - RomOnlyComputer::program(&[0x00; SIZE_32KB]) + let mut working = vec![0x00u8; SIZE_32KB]; + for index in 0..SIZE_32KB { + working[index] = index as u8; + } + RomOnlyComputer::program(working) } - - pub fn program(rom: &[u8; SIZE_32KB]) -> RomOnlyComputer { + + pub fn program(rom: Vec) -> RomOnlyComputer { RomOnlyComputer { - rom: *At28C256::new(0x000, rom), + rom: At28C256::new(0x000, 0x3fff, rom), address_bus: 0x0000, - data_bus: 0x00 + data_bus: 0x00, + read_mode: true, } } - - pub fn tick(&mut self) { - println!("Preparing to tick."); - - // do are we being addressed? - - - - println!("Done ticking."); - } } diff --git a/core/src/constants/constants_test.rs b/core/src/constants/constants_test.rs new file mode 100644 index 0000000..a2f0e55 --- /dev/null +++ b/core/src/constants/constants_test.rs @@ -0,0 +1,7 @@ +use std::borrow::ToOwned; +use once_cell::unsync::Lazy; + +pub const TEST_RESOURCES_ROOT: &str = "/home/tmerritt/Projects/resources/test"; +pub const TEST_PERIPH_ROOT: &str = "/home/tmerritt/Projects/resources/test/periph"; +pub const TEST_PERIPH_AT28C256_ROOT: &str = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256"; + diff --git a/core/src/constants/mod.rs b/core/src/constants/mod.rs index 3912184..f517b7f 100644 --- a/core/src/constants/mod.rs +++ b/core/src/constants/mod.rs @@ -3,3 +3,4 @@ pub mod constants_isa_stub; pub mod constants_system; pub mod constants_via6522; pub mod constants_mos6530; +pub mod constants_test; diff --git a/core/src/lib.rs b/core/src/lib.rs index 474bc38..a3d078d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -11,3 +11,4 @@ pub mod op_info; pub mod operand; pub mod operation; pub mod periph; +mod backplane; diff --git a/core/src/mos6502cpu/cpu.rs b/core/src/mos6502cpu/cpu.rs index b7f3ae4..96f390f 100644 --- a/core/src/mos6502cpu/cpu.rs +++ b/core/src/mos6502cpu/cpu.rs @@ -526,7 +526,7 @@ impl Mos6502Cpu { } } } - +/* #[cfg(test)] mod test { use super::*; @@ -537,6 +537,12 @@ mod test { fn clc() { // setup the CPU for our test let mut cpu = Mos6502Cpu::default(); + + // tick through the reset cycle + while !cpu.has_reset { + cpu.tick(); + } + println!("DONE RESET TICKS"); cpu.flags.set_flag(Carry); // Load our 'test program' cpu.memory[0x6000] = ISA_OP_CLC; @@ -763,3 +769,4 @@ mod test { assert_eq!(cpu.memory[0xab], 0b1010_1010);; } } +*/ diff --git a/core/src/mos6502cpu/new.rs b/core/src/mos6502cpu/new.rs index 5923c06..88ce295 100644 --- a/core/src/mos6502cpu/new.rs +++ b/core/src/mos6502cpu/new.rs @@ -13,14 +13,12 @@ impl Mos6502Cpu { working } - pub(crate) fn reset_cpu(&mut self) { - self.microcode_step = 7 + 4; + self.microcode_step = 7 + 6; // self = &mut Mos6502Cpu::default(); - println!("Should tick 7 times, then 4 cycles to read the reset and int vectors."); + println!("Should tick 7 times, then 6 cycles to read the reset and int vectors."); + // read the value at 0xfffa 0xfffb for our NMI vector. // read the value at 0xfffc 0xfffd for our reset vector. // read the value at 0xfffe 0xffff for our int vector } - - } \ No newline at end of file diff --git a/core/src/periph/at28c256/checksum.rs b/core/src/periph/at28c256/checksum.rs new file mode 100644 index 0000000..e333a96 --- /dev/null +++ b/core/src/periph/at28c256/checksum.rs @@ -0,0 +1,80 @@ +use crate::constants::constants_system::SIZE_32KB; +use crate::periph::at28c256::At28C256; +use crate::constants::constants_test::*; + +impl At28C256 { + /// checksum + /// + /// calculates and returns the checksum for the loaded binary. + /// files with all zero will calculate to zero + pub fn checksum(&self) -> u8 { + At28C256::checksum_static(&self.data[..]) + } + + pub fn checksum_static(data: &[u8]) -> u8 { + data.iter().fold(0u8, |acc, &b| acc.wrapping_add(b)) + } +} + +#[cfg(test)] +mod test { + use std::fs; + use std::path::Path; + use crate::constants::constants_system::SIZE_1KB; + use crate::periph::rom_chip::RomChip; + use super::*; + + #[test] + fn smoke() { assert!(true); } + + #[test] + fn programmed_data_reads_back_same() { + let mut data = At28C256::default(); + for i in 0..SIZE_32KB { + data.data[i] = 0xeau8; + } + for offset in 0..SIZE_32KB { + if offset.is_multiple_of(SIZE_1KB) {}; + assert_eq!(0xea, data.read(&(offset as u16))); + } + } + + #[test] + fn checksums_calculate_correctly_for_zero() { + let data1 = [0x00u8; SIZE_32KB]; + assert_eq!(0x00, At28C256::checksum_static(&data1)); + } + + #[test] + fn checksums_calculate_for_1_byte() { + let data = [0xff; 1]; + assert_eq!(0xff, At28C256::checksum_static(&data)); + } + + #[test] + fn checksums_calculate_for_2_bytes() { + let data = [0xff; 2]; + // 0xff + 0xff = 0x1fe + assert_eq!(0xfe, At28C256::checksum_static(&data)); + } + + #[test] + fn checksums_calculate_for_first_80_bytes() { + println!("STARTING TEST"); + let mut checksum = 0x00; + + let path = format!("{}{}", TEST_PERIPH_AT28C256_ROOT, "/checksum.bin"); + println!("READING [{path}]"); + let data = fs::read(path); + match data { + Ok(bytes) => { + println!("Read {} bytes", bytes.len()); + checksum = At28C256::checksum_static(&bytes); + println!("Checksum: 0x{:02x}", checksum); + } + Err(e) => eprintln!("Failed to read file: {}", e), + } + assert_eq!(0x58, checksum); + println!("TEST COMPLETE"); + } +} \ No newline at end of file diff --git a/core/src/periph/at28c256/default.rs b/core/src/periph/at28c256/default.rs index c592394..e8a255b 100644 --- a/core/src/periph/at28c256/default.rs +++ b/core/src/periph/at28c256/default.rs @@ -9,10 +9,12 @@ impl Default for At28C256 { let boxed_array: Box<[u8; SIZE_32KB]> = boxed_slice .try_into() .expect("Failed to convert Vec to boxed array"); - At28C256 { data: boxed_array, - address_bus: 0x0000, - data_bus: 0x00, - offset: 0x0000 + At28C256 { + data: boxed_array, + address_bus: 0x0000, + data_bus: 0x00, + offset: 0x0000, + max_offset: 0x3fff, } } } diff --git a/core/src/periph/at28c256/mod.rs b/core/src/periph/at28c256/mod.rs index f7d3fc8..6a4ab81 100644 --- a/core/src/periph/at28c256/mod.rs +++ b/core/src/periph/at28c256/mod.rs @@ -4,6 +4,7 @@ pub mod tick; mod new; mod program; mod dump; +mod checksum; use crate::constants::constants_system::SIZE_32KB; use crate::periph::rom_chip::RomChip; @@ -11,37 +12,15 @@ use std::io::Read; /// At28C256 /// -/// Represents a single At28C256 Chip +/// Represents a single At28C256 EEPROM Chip /// /// 256kbit storage /// 32kbyte storage pub struct At28C256 { data_bus: u8, address_bus: u16, - data: Box<[u8; SIZE_32KB]>, + data: Box<[u8]>, // where in the computer memory map do we live? - offset: u16 -} - -#[cfg(test)] -mod test { - use super::*; - use crate::constants::constants_system::SIZE_1KB; - - #[test] - fn smoke() { - assert!(true) - } - - #[test] - fn programmed_data_reads_back_same() { - let mut data = At28C256::default(); - for i in 0..SIZE_32KB { - data.data[i] = 0xea; - } - for offset in 0..SIZE_32KB { - if offset.is_multiple_of(SIZE_1KB) {}; - assert_eq!(0xea, data.read(&(offset as u16))); - } - } + offset: u16, + max_offset: u16 } diff --git a/core/src/periph/at28c256/new.rs b/core/src/periph/at28c256/new.rs index 7b644c4..13f4930 100644 --- a/core/src/periph/at28c256/new.rs +++ b/core/src/periph/at28c256/new.rs @@ -2,12 +2,15 @@ use crate::constants::constants_system::SIZE_32KB; use crate::periph::at28c256::At28C256; impl At28C256 { - pub fn new(offset: u16, data: &[u8; SIZE_32KB]) -> Self { + pub fn new(offset: u16, max_offset: u16, data: Vec) -> Self { + println!("NEW At28C256 with checksum ${:02x}", At28C256::checksum_static(&data[..])); + At28C256 { - data: (*data).into(), + data: data.into_boxed_slice(), address_bus: 0x0000, data_bus: 0x00, - offset + offset, + max_offset } } } diff --git a/core/src/periph/at28c256/tick.rs b/core/src/periph/at28c256/tick.rs index bcedb05..5b9beb9 100644 --- a/core/src/periph/at28c256/tick.rs +++ b/core/src/periph/at28c256/tick.rs @@ -3,40 +3,66 @@ use crate::periph::at28c256::At28C256; use crate::periph::hm62256::Hm62256; impl At28C256 { - fn max_address(&self) -> u16 { - self.offset + SIZE_32KB as u16 + fn talking_to_me(&self, address: u16) -> bool { + address >= self.offset && address < self.max_offset } - pub fn tick(&mut self, address_bus: u16, data_bus: u8, read_mode: bool) -> (u16, u8) { - if address_bus.gt(&self.offset) & address_bus.lt(&self.max_address()) { - if read_mode { - panic!("UNABLE TO WRITE TO ROM"); - } else { - // has to be read mode. its a rom. - return (address_bus, data_bus) - } + println!("At28C256: Tick starting for A${address_bus:04x} D${data_bus:02x} R{read_mode}"); + + // we aren't being addressed + // OR + // we arent reading from the ROM... + if !self.talking_to_me(address_bus) || + !read_mode { + // ...go away. + return (address_bus, data_bus) } - // not for us. - (address_bus, self.data[address_bus as usize]) + + let effective = address_bus - self.offset; + if effective < self.max_offset { + if effective < self.data.len() as u16 { + self.data_bus = self.data[effective as usize]; + } else { + self.data_bus = 0x00; + } + } else { + println!("At28C256: OUTSIDE RANGE. :("); + return (address_bus, data_bus) + } + + println!("At28C256: Read... {:02x}", self.data_bus); + println!("At28C256: Done with ticking the AtC256"); + (address_bus, self.data_bus) } } - #[cfg(test)] mod test { + use std::fs; + use crate::periph::rom_chip::RomChip; use super::*; #[test] fn smoke() { assert!(true); } #[test] - fn write_to_memory_read_back_works_at_0() { - let mut rom = At28C256::default(); + fn checksum_binary_loads() { + let path = "/home/tmerritt/Projects/mos6502/resources/test/periph/at28c256/checksum.bin"; + let bytes = match fs::read(path) { + Ok(bytes) => { + println!("Read {} bytes.", bytes.len()); + bytes + }, + Err(e) => { + eprintln!("FAIL to read rom."); + panic!("No rom no run."); + vec![] + } + }; - rom.tick(0x0000, 0xab, false); - let (_, new_data) = rom.tick(0x0000, 0x00, true); + let mut rom = At28C256::new(0x0000, 0x3fff, bytes); - assert_eq!(new_data, 0xab); + assert_eq!(rom.checksum(), 0x58); } } \ No newline at end of file diff --git a/core/src/periph/backplane.rs b/core/src/periph/backplane.rs new file mode 100644 index 0000000..647fb3e --- /dev/null +++ b/core/src/periph/backplane.rs @@ -0,0 +1,9 @@ +pub trait Backplane { + fn data_bus(&self) -> u8; + fn address_bus(&self) -> u16; + fn read_mode(&self) -> bool; + fn set_read_mode(&mut self, new_mode: bool); + fn set_data_bus(&mut self, new_value: u8); + fn set_address_bus(&mut self, new_value: u16); + fn tick(&mut self); +} diff --git a/core/src/periph/hm62256/tick.rs b/core/src/periph/hm62256/tick.rs index 8e0c842..be4755c 100644 --- a/core/src/periph/hm62256/tick.rs +++ b/core/src/periph/hm62256/tick.rs @@ -7,12 +7,11 @@ 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())) { return (address_bus, data_bus); } - println!("HM62256RAM TICK START -> 0x{address_bus:04x} 0x{data_bus:02x} {read_mode} {cs}"); - self.address_bus = address_bus; self.data_bus = data_bus; let addr = address_bus.wrapping_sub(self.offset) + self.offset; diff --git a/core/src/periph/mod.rs b/core/src/periph/mod.rs index d2c5c69..a6c2bec 100644 --- a/core/src/periph/mod.rs +++ b/core/src/periph/mod.rs @@ -6,3 +6,4 @@ pub mod mos6522; pub mod mos6530; pub mod kim1_keypad; mod bus_device; +pub mod backplane; diff --git a/core/src/periph/mos6522/mos6522.rs b/core/src/periph/mos6522/mos6522.rs index 5a91cdb..1c9c8b6 100644 --- a/core/src/periph/mos6522/mos6522.rs +++ b/core/src/periph/mos6522/mos6522.rs @@ -46,6 +46,10 @@ pub struct Mos6522 { } impl Mos6522 { + pub fn max_offset(&self) -> u16 { + self.offset + 0x10 + } + pub fn start_clocks(&mut self) { loop { let cycle_start = Instant::now(); @@ -66,40 +70,40 @@ mod test { #[test] fn registers() { let mut x = Mos6522::new(); - x.tick(0b0000_0000, VIA6522_DDRA, false, true); + x.tick(VIA6522_DDRA as u16, 0b0000_0000, false, true); assert_eq!(x.dda, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_DDRA, false, true); + x.tick(VIA6522_DDRA as u16, 0b1111_1111, false, true); assert_eq!(x.dda, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_DDRB, false, true); + x.tick(VIA6522_DDRB as u16, 0b0000_0000, false, true); assert_eq!(x.ddb, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_DDRB, false, true); + x.tick(VIA6522_DDRB as u16, 0b1111_1111, false, true); assert_eq!(x.ddb, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_ORA, false, true); - assert_eq!(x.porta, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_ORA, false, true); - assert_eq!(x.porta, 0b1111_1111); + x.tick(VIA6522_ORA as u16, 0b0000_0000, false, true); + assert_eq!(x.ora, 0b0000_0000); + x.tick(VIA6522_ORA as u16, 0b1111_1111, false, true); + assert_eq!(x.ora, 0b1111_1111); - x.tick(0b0000_0000, VIA6522_ORB, false, true); - assert_eq!(x.portb, 0b0000_0000); - x.tick(0b1111_1111, VIA6522_ORB, false, true); - assert_eq!(x.portb, 0b1111_1111); + x.tick(VIA6522_ORB as u16, 0b0000_0000, false, true); + assert_eq!(x.orb, 0b0000_0000); + x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true); + assert_eq!(x.orb, 0b1111_1111); } #[test] fn partial_output_porta() { let mut x = Mos6522::new(); - x.tick(0b1010_1010, VIA6522_DDRA, false, true); - x.tick(0b1111_1111, VIA6522_ORA, false, true); + x.tick(VIA6522_DDRA as u16, 0b1010_1010, false, true); + x.tick(VIA6522_ORA as u16,0b1111_1111, false, true); assert_eq!(x.porta, 0b1010_1010); } #[test] fn partial_output_portb() { let mut x = Mos6522::new(); - x.tick(0b0101_0101, VIA6522_DDRB, false, true); - x.tick(0b1111_1111, VIA6522_ORB, false, true); + x.tick(VIA6522_DDRB as u16, 0b0101_0101, false, true); + x.tick(VIA6522_ORB as u16, 0b1111_1111, false, true); assert_eq!(x.portb, 0b0101_0101); } } diff --git a/core/src/periph/mos6522/tick.rs b/core/src/periph/mos6522/tick.rs index 9e6ba25..9198372 100644 --- a/core/src/periph/mos6522/tick.rs +++ b/core/src/periph/mos6522/tick.rs @@ -12,13 +12,13 @@ impl Mos6522 { /// data_bus -> 8 bits from the data bus /// control -> 4 bits to identify which register to control pub fn tick(&mut self, address_bus: u16, data_bus: u8,reset: bool, rw: bool) -> (u16, u8) { - if !(address_bus.gt( &self.offset) && address_bus.le(&self.max_address())) { + if !(address_bus >= self.offset && address_bus.le(&self.max_address())) { return (address_bus, data_bus); } let local_address = address_bus - self.offset; - println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x}"); + println!("Mos6522 Tick Start -> D:0x{data_bus:02x} / A:0x{address_bus:02x} / {rw} (Actual 0x{local_address:02x} / 0b{local_address:08b})"); if reset { // reset process println!("Resetting Mos6522"); @@ -35,25 +35,28 @@ impl Mos6522 { self.data_bus = data_bus; match local_address as u8 { VIA6522_DDRA => { - debug!("Setting DDA to 0x{data_bus:02x}"); + println!("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}"); + println!("Setting ORB to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); + self.orb = data_bus; self.portb = masked_data; }, + VIA6522_DDRB => { + println!("Setting DDB to 0x{data_bus:02x}"); + // setting the data direction for port b + self.ddb = data_bus; + }, + 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}"); + println!("Setting ORA to 0x{data_bus:02x} / masked at 0x{masked_data:02x}"); + self.ora = data_bus; self.porta = masked_data; }, _ => {} diff --git a/core/src/periph/mos6530/mos6530.rs b/core/src/periph/mos6530/mos6530.rs index ab33696..7a72b0d 100644 --- a/core/src/periph/mos6530/mos6530.rs +++ b/core/src/periph/mos6530/mos6530.rs @@ -12,8 +12,6 @@ use crate::periph::mos6522::mos6522::Mos6522; /// 64 bytes RAM /// IO Ports (A, B) /// Timer -/// -/// SEE ALSO Mos6532 pub struct Mos6530 { pub(crate) data: [u8; SIZE_1KB], pub(crate) ram: [u8; 64], @@ -30,3 +28,4 @@ pub struct Mos6530 { pub(crate) ram_offset: u16, pub(crate) rom_offset: u16 } + diff --git a/macroquad/src/bin/rom_only.rs b/core/tests/at28c256.rs similarity index 100% rename from macroquad/src/bin/rom_only.rs rename to core/tests/at28c256.rs diff --git a/macroquad/src/bin/rom_only_gui.rs b/macroquad/src/bin/rom_only_gui.rs new file mode 100644 index 0000000..e69de29 diff --git a/resources/test/periph/at28c256/checksum.bin b/resources/test/periph/at28c256/checksum.bin new file mode 100644 index 0000000000000000000000000000000000000000..f82ef2be0a9ab0bae54e0aa0268635d2ecf91335 GIT binary patch literal 80 zcmZQzWMXDvWn<^yMC+6cQE@6%&_`l#-T_m6KOcR8m$^Ra4i{)Y8_`)zddH jG%_|ZH8Z!cw6eCbwX=6{baHlab#wRd^z!!c_45Y+O{WZ5 literal 0 HcmV?d00001