From e66085eb25d6aabe77dea0d7c6181aa80136af00 Mon Sep 17 00:00:00 2001 From: PeronTheDuck Date: Mon, 13 Jan 2020 00:44:09 -0300 Subject: [PATCH] +10000 lines changed: First commit --- .gitignore | 2 + Cargo.lock | 429 +++++++++++++++ Cargo.toml | 13 + src/color.hex | Bin 0 -> 65536 bytes src/emulator/addr | 32 ++ src/emulator/addressing_modes.rs | 24 + src/emulator/emulator.rs | 145 +++++ src/emulator/error.rs | 25 + src/emulator/mod.rs | 8 + src/emulator/opcodes.rs | 883 +++++++++++++++++++++++++++++++ src/emulator/ops | 56 ++ src/error.rs | 24 + src/graphic/mod.rs | 75 +++ src/main.rs | 169 ++++++ src/ui.glade | 114 ++++ src/ui.glade~ | 114 ++++ 16 files changed, 2113 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/color.hex create mode 100644 src/emulator/addr create mode 100644 src/emulator/addressing_modes.rs create mode 100644 src/emulator/emulator.rs create mode 100644 src/emulator/error.rs create mode 100644 src/emulator/mod.rs create mode 100644 src/emulator/opcodes.rs create mode 100644 src/emulator/ops create mode 100644 src/error.rs create mode 100644 src/graphic/mod.rs create mode 100644 src/main.rs create mode 100644 src/ui.glade create mode 100644 src/ui.glade~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53eaa21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a1091d3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,429 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "atk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atk-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cairo-rs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crustacean_6502_emulator" +version = "0.1.0" +dependencies = [ + "cairo-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-executor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gdk" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-pixbuf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pango 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gdk-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gio-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glib" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glib-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gobject-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gtk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-pixbuf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gtk-sys 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pango 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gtk-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gdk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pango" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pango-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro-hack" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum atk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "444daefa55f229af145ea58d77efd23725024ee1f6f3102743709aa6b18c663e" +"checksum atk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e552c1776737a4c80110d06b36d099f47c727335f9aaa5d942a72b6863a8ec6f" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum cairo-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b528aca2ef1026235d0122495dbaee0b09479f77c51f6df8d9bb9cb1c6d6f87" +"checksum cairo-sys-rs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff65ba02cac715be836f63429ab00a767d48336efc5497c5637afb53b4f14d63" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +"checksum gdk 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2739c12374f83bad563ee839c2b3ea5c60391465a254fd4a54b6e3e9648dc61f" +"checksum gdk-pixbuf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e248220c46b329b097d4b158d2717f8c688f16dd76d0399ace82b3e98062bdd7" +"checksum gdk-pixbuf-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d8991b060a9e9161bafd09bf4a202e6fd404f5b4dd1a08d53a1e84256fb34ab0" +"checksum gdk-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6adf679e91d1bff0c06860287f80403e7db54c2d2424dce0a470023b56c88fbb" +"checksum gio 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "879a5eb1a91623819d658669104fb587c1ae68695d50947f3e4949a00c6bc218" +"checksum gio-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4fad225242b9eae7ec8a063bb86974aca56885014672375e5775dc0ea3533911" +"checksum glib 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "121c502fc6895e62d2ce084e677d3289ccbdd7f56edd4ac9a5ab8bd95d4a8670" +"checksum glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2" +"checksum gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9" +"checksum gtk 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7cd1d646cc9a2cb795f33b538779a3f22e71dc172f2aba08a41e84a2f72c0dec" +"checksum gtk-sys 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum pango 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9c6b728f1be8edb5f9f981420b651d5ea30bdb9de89f1f1262d0084a020577" +"checksum pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86b93d84907b3cf0819bff8f13598ba72843bee579d5ebc2502e4b0367b4be7d" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +"checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d4d1abf --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "crustacean_6502_emulator" +version = "0.1.0" +authors = ["PeronTheDuck "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +gtk = "0.8.0" +glib = "0.9.0" +gio = "*" +cairo-rs = "*" \ No newline at end of file diff --git a/src/color.hex b/src/color.hex new file mode 100644 index 0000000000000000000000000000000000000000..a2a0712031a0022dfdba976e8b2f59ae109abd12 GIT binary patch literal 65536 zcmeIuK>+|D48*Ww57c1 uses X|Y +a => x / y \ No newline at end of file diff --git a/src/emulator/addressing_modes.rs b/src/emulator/addressing_modes.rs new file mode 100644 index 0000000..6228147 --- /dev/null +++ b/src/emulator/addressing_modes.rs @@ -0,0 +1,24 @@ +pub fn get_size(addr_mode: AddressingMode) -> usize { + OP_SIZES[addr_mode as usize] +} + +//A,abs,absX,absY,imm,impl,ind,indX,indY,rel,zpg,zpgX,zpgY +//1, 3, 3, 3, 2, 1, 3, 2, 2, 2, 2, 2, 2 +pub static OP_SIZES: [usize; 13] = [1, 3, 3, 3, 2, 1, 3, 2, 2, 2, 2, 2, 2]; + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum AddressingMode { + A = 0, // LSR A + ABS, // LDA $1234 + ABSX, // STA $3000,X + ABSY, // AND $4000,Y + IMM, // LDA #$10 + IMPL, // CLC + IND, // JMP ($FFFC) + INDX, // LDA ($40,X) + INDY, // LDA ($40),Y + REL, // LABEL // +4 + ZPG, // LDA $10 + ZPGX, // LDA $10,X + ZPGY, // LDA $10,Y +} diff --git a/src/emulator/emulator.rs b/src/emulator/emulator.rs new file mode 100644 index 0000000..34aca5b --- /dev/null +++ b/src/emulator/emulator.rs @@ -0,0 +1,145 @@ +use super::error; +use super::opcodes; +use super::OpcodeType; +use super::{addressing_modes::get_size, AddressingMode}; + +fn invalid_mode(mode_used: AddressingMode) -> T { + panic!("The addressign mode used ({:?}) is either not valid for this opcode, or expects an argument which was not provided",mode_used) +} + +macro_rules! fetch { + ($self:ident PC+$off:expr) => { + $self.ram[$self.cpu.PC as usize + $off] + }; + ($self:ident $addr:expr) => { + $self.ram[$addr as usize] + }; + ($self:ident D $addr:expr) => { + ($self.ram[$addr as usize + 1] as u16) << 8 | $self.ram[$addr as usize] as u16 + }; +} + +pub struct Emulator { + pub cycles: usize, + pub ram: [u8; 0x10000], + pub cpu: Cpu, +} +impl Emulator { + pub fn new() -> Self { + Self { + cycles: 0, + ram: [0x00; 0x10000], + cpu: Cpu::default(), + } + } + pub fn step(&mut self) -> Result<(), error::EmulatorError> { + println!("Step on {:04X}", self.cpu.PC); + let code = self.ram[self.cpu.PC as usize]; + let code = match opcodes::from_code(code) { + None => return Err(error::EmulatorError::UnknownOp(code)), + Some(v) => v, + }; + println!(" Opcode {:?}", code.name); + let arg: Option = match code.addr_mode { + AddressingMode::IMPL => None, + AddressingMode::A => None, + AddressingMode::IMM => { + let addr = fetch!(self PC+1); + Some(addr as u16) + } + AddressingMode::ABS => { + let addr = self.cpu.PC as usize + 1; + Some(fetch!(self D addr) as u16) + } + AddressingMode::ZPG => { + let addr = self.cpu.PC as usize + 1; + Some(fetch!(self addr) as u16) + } + _ => { + unimplemented!("Unimplemented addressing mode {:?}", code.addr_mode); + } + }; + println!(" Argument: {:#04X?}", arg); + match code.name { + OpcodeType::BRK => { + println!("Stepped on break. Ending"); + println!("{:#?}", self.cpu); + return Err(error::EmulatorError::Break); + } + OpcodeType::LDA => match code.addr_mode { + AddressingMode::IMM => { + self.cpu.A = arg.unwrap_or_else(|| invalid_mode(code.addr_mode)) as u8 + } + AddressingMode::ABS => { + self.cpu.A = fetch!(self arg.unwrap_or_else(||invalid_mode(code.addr_mode))) + } + AddressingMode::ZPG => { + self.cpu.A = fetch!(self arg.unwrap_or_else(||invalid_mode(code.addr_mode))) + } + _ => panic!("Invalid addressing mode for {:?}", code.name), + }, + OpcodeType::STA => match code.addr_mode { + AddressingMode::ABS => { + self.ram[arg.unwrap_or_else(|| invalid_mode(code.addr_mode)) as usize] = + self.cpu.A + } + _ => panic!("Invalid addressing mode for {:?}", code.name), + }, + OpcodeType::ADC => match code.addr_mode { + AddressingMode::IMM => { + self.cpu.A += arg.unwrap_or_else(|| invalid_mode(code.addr_mode)) as u8 + } + _ => panic!("Invalid addressing mode for {:?}", code.name), + }, + OpcodeType::JMP => match code.addr_mode { + AddressingMode::ABS => { + self.cpu.PC = arg.unwrap_or_else(|| invalid_mode(code.addr_mode)) as u16 + } + _ => panic!("Invalid addressing mode for {:?}", code.name), + }, + _ => { + unimplemented!( + "Unimplemented opcode {:?} with {:?}", + code.name, + code.addr_mode + ); + } + } + if code.name != OpcodeType::JMP { + self.cpu.PC += get_size(code.addr_mode) as u16; + } + Ok(()) + } + pub fn restart(&mut self) { + self.cycles = 0; + self.ram = [0x00; 0x10000]; + self.cpu = Cpu::default(); + } +} + +#[allow(non_snake_case)] +pub struct Cpu { + A: u8, + X: u8, + Y: u8, + PC: u16, +} +impl std::default::Default for Cpu { + fn default() -> Self { + Self { + A: 0x00, + X: 0x00, + Y: 0x00, + PC: 0x0600, + } + } +} +impl std::fmt::Debug for Cpu { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + write!( + f, + "Registers: \n PC: {:04X}\n A: {:02X} X: {:02X} Y: {:02X}\n", + self.PC, self.A, self.X, self.Y, + ) + } +} diff --git a/src/emulator/error.rs b/src/emulator/error.rs new file mode 100644 index 0000000..1ea0bb6 --- /dev/null +++ b/src/emulator/error.rs @@ -0,0 +1,25 @@ +use std::boxed::Box; +use std::error::Error; +use std::fmt::{Display, Error as FmtError, Formatter}; + +#[derive(Debug)] +pub enum EmulatorError { + UnknownOp(u8), + Break, + Suberror(Box), +} + +impl Display for EmulatorError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "Emulator Error: {}", + match self { + EmulatorError::Suberror(e) => e.description().to_string(), + EmulatorError::Break => "Emulator Terminated".to_string(), + EmulatorError::UnknownOp(code) => format!("Unknown OP with code {:02X}", code), + } + ) + } +} +impl Error for EmulatorError {} diff --git a/src/emulator/mod.rs b/src/emulator/mod.rs new file mode 100644 index 0000000..2164023 --- /dev/null +++ b/src/emulator/mod.rs @@ -0,0 +1,8 @@ +pub mod error; + +mod addressing_modes; +use addressing_modes::AddressingMode; +mod opcodes; +use opcodes::OpcodeType; +mod emulator; +pub use emulator::Emulator; diff --git a/src/emulator/opcodes.rs b/src/emulator/opcodes.rs new file mode 100644 index 0000000..5e3c160 --- /dev/null +++ b/src/emulator/opcodes.rs @@ -0,0 +1,883 @@ +use super::addressing_modes::AddressingMode; + +pub const OPCODES: [Option; 0x100] = [ + Some(OpcodeData { + name: OpcodeType::BRK, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::INDX, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::ASL, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::PHP, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::ASL, + addr_mode: AddressingMode::A, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::ASL, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BPL, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::ASL, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::CLC, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ORA, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::ASL, + addr_mode: AddressingMode::ABSX, + }), + None, + Some(OpcodeData { + name: OpcodeType::JSR, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::INDX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::BIT, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::ROL, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::PLP, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::ROL, + addr_mode: AddressingMode::A, + }), + None, + Some(OpcodeData { + name: OpcodeType::BIT, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::ROL, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BMI, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::ROL, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::SEC, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::AND, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::ROL, + addr_mode: AddressingMode::ABSX, + }), + None, + Some(OpcodeData { + name: OpcodeType::RTI, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::INDX, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::LSR, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::PHA, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::LSR, + addr_mode: AddressingMode::A, + }), + None, + Some(OpcodeData { + name: OpcodeType::JMP, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::LSR, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BVC, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::LSR, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::CLI, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::EOR, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::LSR, + addr_mode: AddressingMode::ABSX, + }), + None, + Some(OpcodeData { + name: OpcodeType::RTS, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::INDX, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::ROR, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::PLA, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::ROR, + addr_mode: AddressingMode::A, + }), + None, + Some(OpcodeData { + name: OpcodeType::JMP, + addr_mode: AddressingMode::IND, + }), + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::ROR, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BVS, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::ROR, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::SEI, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::ADC, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::ROR, + addr_mode: AddressingMode::ABSX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::INDX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::STY, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::STX, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::DEY, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::TXA, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::STY, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::STX, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BCC, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::INDY, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::STY, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::STX, + addr_mode: AddressingMode::ZPGY, + }), + None, + Some(OpcodeData { + name: OpcodeType::TYA, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::ABSY, + }), + Some(OpcodeData { + name: OpcodeType::TXS, + addr_mode: AddressingMode::IMPL, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::STA, + addr_mode: AddressingMode::ABSX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::LDY, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::INDX, + }), + Some(OpcodeData { + name: OpcodeType::LDX, + addr_mode: AddressingMode::IMM, + }), + None, + Some(OpcodeData { + name: OpcodeType::LDY, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::LDX, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::TAY, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::TAX, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::LDY, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::LDX, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BCS, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::INDY, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::LDY, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::LDX, + addr_mode: AddressingMode::ZPGY, + }), + None, + Some(OpcodeData { + name: OpcodeType::CLV, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::ABSY, + }), + Some(OpcodeData { + name: OpcodeType::TSX, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::LDY, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::LDA, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::LDX, + addr_mode: AddressingMode::ABSY, + }), + None, + Some(OpcodeData { + name: OpcodeType::CPY, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::INDX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::CPY, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::DEC, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::INY, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::DEX, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::CPY, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::DEC, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BNE, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::DEC, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::CLD, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::CMP, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::DEC, + addr_mode: AddressingMode::ABSX, + }), + None, + Some(OpcodeData { + name: OpcodeType::CPX, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::INDX, + }), + None, + None, + Some(OpcodeData { + name: OpcodeType::CPX, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::ZPG, + }), + Some(OpcodeData { + name: OpcodeType::INC, + addr_mode: AddressingMode::ZPG, + }), + None, + Some(OpcodeData { + name: OpcodeType::INX, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::IMM, + }), + Some(OpcodeData { + name: OpcodeType::NOP, + addr_mode: AddressingMode::IMPL, + }), + None, + Some(OpcodeData { + name: OpcodeType::CPX, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::ABS, + }), + Some(OpcodeData { + name: OpcodeType::INC, + addr_mode: AddressingMode::ABS, + }), + None, + Some(OpcodeData { + name: OpcodeType::BEQ, + addr_mode: AddressingMode::REL, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::INDY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::ZPGX, + }), + Some(OpcodeData { + name: OpcodeType::INC, + addr_mode: AddressingMode::ZPGX, + }), + None, + Some(OpcodeData { + name: OpcodeType::SED, + addr_mode: AddressingMode::IMPL, + }), + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::ABSY, + }), + None, + None, + None, + Some(OpcodeData { + name: OpcodeType::SBC, + addr_mode: AddressingMode::ABSX, + }), + Some(OpcodeData { + name: OpcodeType::INC, + addr_mode: AddressingMode::ABSX, + }), + None, +]; +/* pub fn get_code(name: OpcodeType, addr_mode: AddressingMode) -> Result { + for (i, opcode) in OPCODES.iter().enumerate() { + match opcode { + None => continue, + Some(ref opcode) => { + if opcode.name == name && opcode.addr_mode == addr_mode { + return Ok((i & 0xFF) as u8); + } + } + } + } + Err(Error::UnkownOpcode { name: name.into() }) +} */ + +#[derive(Debug, PartialEq, Copy, Clone)] +pub enum OpcodeType { + ADC, + AND, + ASL, + BCC, // Branch ops + BCS, // Branch ops + BEQ, // Branch ops + BIT, + BMI, // Branch ops + BNE, // Branch ops + BPL, // Branch ops + BRK, + BVC, // Branch ops + BVS, // Branch ops + CLC, + CLD, + CLI, + CLV, + CMP, + CPX, + CPY, + DEC, + DEX, + DEY, + EOR, + INC, + INX, + INY, + JMP, + JSR, + LDA, + LDX, + LDY, + LSR, + NOP, + ORA, + PHA, + PHP, + PLA, + PLP, + ROL, + ROR, + RTI, + RTS, + SBC, + SEC, + SED, + SEI, + STA, + STX, + STY, + TAX, + TAY, + TSX, + TXA, + TXS, + TYA, +} +impl OpcodeType { + pub fn identify<'s, S: std::ops::Deref>( + string: &S, + ) -> Result { + match **string { + "ADC" => Ok(OpcodeType::ADC), + "AND" => Ok(OpcodeType::AND), + "ASL" => Ok(OpcodeType::ASL), + "BCC" => Ok(OpcodeType::BCC), + "BCS" => Ok(OpcodeType::BCS), + "BEQ" => Ok(OpcodeType::BEQ), + "BIT" => Ok(OpcodeType::BIT), + "BMI" => Ok(OpcodeType::BMI), + "BNE" => Ok(OpcodeType::BNE), + "BPL" => Ok(OpcodeType::BPL), + "BRK" => Ok(OpcodeType::BRK), + "BVC" => Ok(OpcodeType::BVC), + "BVS" => Ok(OpcodeType::BVS), + "CLC" => Ok(OpcodeType::CLC), + "CLD" => Ok(OpcodeType::CLD), + "CLI" => Ok(OpcodeType::CLI), + "CLV" => Ok(OpcodeType::CLV), + "CMP" => Ok(OpcodeType::CMP), + "CPX" => Ok(OpcodeType::CPX), + "CPY" => Ok(OpcodeType::CPY), + "DEC" => Ok(OpcodeType::DEC), + "DEX" => Ok(OpcodeType::DEX), + "DEY" => Ok(OpcodeType::DEY), + "EOR" => Ok(OpcodeType::EOR), + "INC" => Ok(OpcodeType::INC), + "INX" => Ok(OpcodeType::INX), + "INY" => Ok(OpcodeType::INY), + "JMP" => Ok(OpcodeType::JMP), + "JSR" => Ok(OpcodeType::JSR), + "LDA" => Ok(OpcodeType::LDA), + "LDX" => Ok(OpcodeType::LDX), + "LDY" => Ok(OpcodeType::LDY), + "LSR" => Ok(OpcodeType::LSR), + "NOP" => Ok(OpcodeType::NOP), + "ORA" => Ok(OpcodeType::ORA), + "PHA" => Ok(OpcodeType::PHA), + "PHP" => Ok(OpcodeType::PHP), + "PLA" => Ok(OpcodeType::PLA), + "PLP" => Ok(OpcodeType::PLP), + "ROL" => Ok(OpcodeType::ROL), + "ROR" => Ok(OpcodeType::ROR), + "RTI" => Ok(OpcodeType::RTI), + "RTS" => Ok(OpcodeType::RTS), + "SBC" => Ok(OpcodeType::SBC), + "SEC" => Ok(OpcodeType::SEC), + "SED" => Ok(OpcodeType::SED), + "SEI" => Ok(OpcodeType::SEI), + "STA" => Ok(OpcodeType::STA), + "STX" => Ok(OpcodeType::STX), + "STY" => Ok(OpcodeType::STY), + "TAX" => Ok(OpcodeType::TAX), + "TAY" => Ok(OpcodeType::TAY), + "TSX" => Ok(OpcodeType::TSX), + "TXA" => Ok(OpcodeType::TXA), + "TXS" => Ok(OpcodeType::TXS), + "TYA" => Ok(OpcodeType::TYA), + _ => Err(()), + } + } + pub fn is_branch_op(self) -> bool { + use OpcodeType::*; + let branch_ops = [BCC, BCS, BEQ, BMI, BNE, BPL, BVC, BVS]; + branch_ops.contains(&self) + } +} +impl std::convert::Into for OpcodeType { + fn into(self) -> String { + format!("{:?}", self) + } +} +#[derive(Debug, Copy, Clone)] +pub struct OpcodeData { + pub name: OpcodeType, + pub addr_mode: AddressingMode, +} + +pub fn from_code(code: u8) -> Option { + OPCODES[code as usize] +} + +mod test { + #[test] + fn test_opcode_name() { + use super::OpcodeType; + let strings = vec![("LDA", true), ("STA", true), ("JMP", true), ("xd", false)]; + for (string, is_ok) in strings.iter() { + let res = OpcodeType::identify(&string); + println!("{} -> {:?}", string, res); + assert_eq!(res.is_ok(), *is_ok); + } + } +} diff --git a/src/emulator/ops b/src/emulator/ops new file mode 100644 index 0000000..0f61576 --- /dev/null +++ b/src/emulator/ops @@ -0,0 +1,56 @@ +ADC 011A AA01 +AND 001A AA01 +ASL 000A AA10 +BCC 1001 0000 +BCS 1011 0000 +BEQ 1111 0000 +BIT 0010 A100 +BMI 0011 0000 +BNE 1101 0000 +BPL 0001 0000 +BRK 0000 0000 +BVC 0101 0000 +BVS 0111 0000 +CLC 0001 1000 +CLD 1101 1000 +CLI 0101 1000 +CLV 1011 1000 +CMP 110A AA01 +CPA 1110 AA00 +CPY 1100 AA00 +DEC 110A A110 +DEA 1100 1010 +DEY 1000 1000 +EOR 010A AA01 +INC 111A A110 +INA 1110 1000 +INY 1100 1000 +JMP 01A0 1100 +JSR 0010 0000 +LDA 10AA AA01 +LDA 101A AA10 +LDY 101A AA00 +LSR 010A AA10 +NOP 1110 1010 +ORA 000A AA01 +PHA 0100 1000 +PHP 0000 1000 +PLA 0110 1000 +PLP 0010 1000 +ROL 001A AA10 +ROR 011A AA10 +RTI 0100 0000 +RTS 0110 0000 +SBC 111A AA01 +SEC 0011 1000 +SED 1111 1000 +SEI 0111 0000 +STA 100A AA01 +STA 100A A110 +STY 100A A100 +TAA 1010 1010 +TAY 1010 1000 +TSA 1011 1010 +TAA 1000 1010 +TAS 1001 1010 +TYA 1001 1000 \ No newline at end of file diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..5be2f6e --- /dev/null +++ b/src/error.rs @@ -0,0 +1,24 @@ +use std::error::Error; + +#[derive(Debug)] +pub struct ProgErr(Box); +impl std::fmt::Display for ProgErr { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(fmt, "Error:\n\t{}", self.0) + } +} +impl std::error::Error for ProgErr {} + +macro_rules! prog_err { + ( $( $type: ty ),* ) => { + $( + impl std::convert::From<$type> for ProgErr { + fn from(e: $type) -> Self { + Self(Box::from(e)) + } + } + )* + }; +} + +prog_err!(glib::BoolError, crate::emulator::error::EmulatorError); diff --git a/src/graphic/mod.rs b/src/graphic/mod.rs new file mode 100644 index 0000000..1142d27 --- /dev/null +++ b/src/graphic/mod.rs @@ -0,0 +1,75 @@ +pub struct Image { + pub pixels: std::boxed::Box<[Color]>, + pub width: usize, + pub height: usize, +} +#[derive(Copy, Clone, Debug)] +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, +} +impl Image { + pub fn new() -> Self { + let width: usize = 16; + let height: usize = 16; + let pixels: Vec<_> = (0..(width * height)).map(|_| Color::from(0i32)).collect(); + let pixels = pixels.into_boxed_slice(); + Self { + pixels, + width, + height, + } + } + pub fn draw(&self, cr: &cairo::Context) { + println!("Started drawing"); + cr.scale(self.width as f64, self.height as f64); + cr.set_source_rgb(0.0, 0.0, 0.0); + cr.paint(); + for y in 0..self.height { + for x in 0..self.width { + let (r, g, b): (f64, _, _) = self + .pixels + .get(y * self.width + x) + .expect("Out of bounds") + .into(); + cr.set_source_rgb(r, g, b); + cr.rectangle( + x as f64 / self.width as f64, + y as f64 / self.height as f64, + 1., + 1., + ); + cr.fill(); + } + } + } +} +impl std::convert::From<(u8, u8, u8)> for Color { + fn from(color: (u8, u8, u8)) -> Self { + Color { + r: color.0, + g: color.1, + b: color.2, + } + } +} +impl std::convert::From for Color { + fn from(num: i32) -> Self { + let num = num & 0x00_FF_FF_FF; // Remove alpha + Color { + r: (num >> 16) as u8, + g: (num >> 8) as u8, + b: (num) as u8, + } + } +} +impl std::convert::Into<(f64, f64, f64)> for &Color { + fn into(self) -> (f64, f64, f64) { + ( + (self.r as f64) / 255.0, + (self.g as f64) / 255.0, + (self.b as f64) / 255.0, + ) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e99cfbd --- /dev/null +++ b/src/main.rs @@ -0,0 +1,169 @@ +mod error; +use error::ProgErr; + +use cairo; +use gio::prelude::*; +use gtk::prelude::*; +use gtk::Builder; + +mod emulator; +use emulator::Emulator; +mod graphic; +use graphic::{Color, Image}; + +#[derive(Copy, Clone, Debug, PartialEq)] +enum Cmd { + Step, + Run, + Stop, + Reset, +} +impl std::convert::From<&str> for Cmd { + fn from(text: &str) -> Self { + match text { + "Step" => Self::Step, + "Run" => Self::Run, + "Stop" => Self::Stop, + "Reset" => Self::Reset, + _ => panic!("???"), + } + } +} + +pub fn init(app: >k::Application) { + let img = Image::new(); + let (img_width, img_height) = (img.width, img.height); + use std::sync::{Arc, Mutex}; + let img_m = Arc::from(Mutex::from(img)); + + let (tcmd, rcmd) = std::sync::mpsc::channel::(); + let (tdata, rdata) = glib::MainContext::channel(glib::source::Priority::default()); + let emulator = Arc::from(Mutex::from(Emulator::new())); + { + let emulator_clone = emulator.clone(); + std::thread::spawn(move || { + let emulator = emulator_clone; + loop { + if let Ok(cmd) = rcmd.recv() { + let mut emulator = match emulator.try_lock() { + Err(_) => continue, + Ok(v) => v, + }; + match cmd { + Cmd::Step => { + if let Err(e) = emulator.step() { + println!("{:#?}", e); + } + } + Cmd::Reset => { + emulator.restart(); + emulator.ram = *include_bytes!("color.hex"); + } + Cmd::Run => loop { + if let Ok(cmd) = rcmd.recv_timeout(std::time::Duration::from_millis(1)) + { + break; + } else { + emulator.step(); + println!("Tick {}", emulator.cycles); + let page_02 = Vec::from(&emulator.ram[0x200..0x300]); + tdata.send(page_02); + } + }, + _ => {} + }; + println!("Tick {}", emulator.cycles); + let page_02 = Vec::from(&emulator.ram[0x200..0x300]); + tdata.send(page_02); + } + } + }); + } + let builder: Builder = Builder::new_from_string(include_str!("ui.glade")); + let window: gtk::ApplicationWindow = builder.get_object("Window").unwrap(); + let da: gtk::DrawingArea = builder.get_object("Display").unwrap(); + + { + da.set_size_request(img_width as i32, img_height as i32); + let img_m = img_m.clone(); + da.connect_draw(move |_: >k::DrawingArea, ctx: &cairo::Context| { + let img: Result<_, _> = img_m.try_lock(); + if let Ok(img) = img { + println!("Redrawing!"); + img.draw(&ctx); + } + glib::signal::Inhibit(false) + }); + } + + for widget_name in &["Step", "Reset", "Run"] { + let tcmd_clone = tcmd.clone(); + let widget: gtk::Button = builder.get_object(widget_name).expect("Not found"); + widget.connect_clicked(move |s: >k::Button| { + let name = s.get_widget_name().unwrap(); + let name = name.as_str(); + println!("Sending from {}", name); + let cmd = Cmd::from(name); + tcmd_clone.send(cmd).expect("Couldn't send cmd"); + }); + } + + let registers: gtk::Label = builder.get_object("Registers").unwrap(); + let registers = Mutex::from(registers); + + { + let emulator = emulator.clone(); + let img_m = img_m.clone(); + rdata.attach(None, move |data: Vec<_>| { + let img: Result<_, _> = img_m.try_lock(); + println!("Received page"); + for line in data.chunks(16) { + println!( + "{}", + line.iter() + .map(|h| format!("{:02X}", h)) + .collect::() + ) + } + if let Ok(mut img) = img { + println!("Updating image"); + let (w, h) = (img.width, img.height); + let pixels: &mut [Color] = &mut img.pixels; + let palette = [ + Color::from(0x00_00_00), + Color::from(0xFF_00_00), + Color::from(0x00_FF_00), + Color::from(0xFF_FF_00), + Color::from(0x00_00_FF), + Color::from(0xFF_00_FF), + Color::from(0x00_FF_FF), + Color::from(0xFF_FF_FF), + ]; + for x in 0..w { + for y in 0..h { + let i = y * w + x; + pixels[i] = palette[data[i] as usize & 0b111]; + } + } + } + if let Ok(registers) = registers.try_lock() { + if let Ok(emulator) = emulator.try_lock() { + registers.set_text(&format!("{:#?}", emulator.cpu)); + } + } + da.queue_draw(); + glib::Continue(true) + }); + } + + window.set_application(Some(app)); + window.show_all(); +} + +fn main() -> Result<(), ProgErr> { + let app: gtk::Application = + gtk::Application::new(Some("com.ducklings_corp.emulator"), Default::default())?; + app.connect_activate(move |app| init(app)); + app.run(&std::env::args().collect::>()); + Ok(()) +} diff --git a/src/ui.glade b/src/ui.glade new file mode 100644 index 0000000..25fddc1 --- /dev/null +++ b/src/ui.glade @@ -0,0 +1,114 @@ + + + + + + False + 800 + 600 + + + + + + True + False + True + True + + + True + False + vertical + + + Reset + Reset + True + True + True + + + False + True + 0 + + + + + Run + Run + True + True + True + + + False + True + 1 + + + + + Step + Step + True + True + True + + + False + True + 2 + + + + + 1 + 1 + + + + + True + False + True + True + + + 0 + 1 + + + + + True + False + True + 6502 Emulator + + + 0 + 0 + 2 + + + + + Registers + True + False + A: 0x00 X: 0x00 Y: 0x00 PC: 0x000 + + + 0 + 2 + + + + + + + + + diff --git a/src/ui.glade~ b/src/ui.glade~ new file mode 100644 index 0000000..25fddc1 --- /dev/null +++ b/src/ui.glade~ @@ -0,0 +1,114 @@ + + + + + + False + 800 + 600 + + + + + + True + False + True + True + + + True + False + vertical + + + Reset + Reset + True + True + True + + + False + True + 0 + + + + + Run + Run + True + True + True + + + False + True + 1 + + + + + Step + Step + True + True + True + + + False + True + 2 + + + + + 1 + 1 + + + + + True + False + True + True + + + 0 + 1 + + + + + True + False + True + 6502 Emulator + + + 0 + 0 + 2 + + + + + Registers + True + False + A: 0x00 X: 0x00 Y: 0x00 PC: 0x000 + + + 0 + 2 + + + + + + + + +