much better cli! more ergonomic screen struct! window screen type still broken but working on it!

This commit is contained in:
august kline 2024-06-30 22:49:54 -04:00
parent 8890853656
commit ac4619406d
9 changed files with 931 additions and 440 deletions

549
Cargo.lock generated
View File

@ -39,12 +39,30 @@ version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cc"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2755ff20a1d93490d26ba33a6f092a38a508398a5320df5d4b3014fcccce9410"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -57,7 +75,7 @@ version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.5.0",
"crossterm_winapi", "crossterm_winapi",
"libc", "libc",
"mio", "mio",
@ -76,12 +94,132 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "dlib"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [
"libloading",
]
[[package]]
name = "downcast-rs"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "fastrand"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "georgeemu" name = "georgeemu"
version = "0.1.0" version = "0.1.0"
@ -89,6 +227,7 @@ dependencies = [
"anyhow", "anyhow",
"bdf", "bdf",
"crossterm", "crossterm",
"minifb",
"serde", "serde",
"toml", "toml",
] ]
@ -109,12 +248,66 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "js-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.155" version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libloading"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
dependencies = [
"cfg-if",
"windows-targets 0.52.5",
]
[[package]]
name = "libredox"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
"bitflags 2.5.0",
"libc",
"redox_syscall 0.4.1",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.12" version = "0.4.12"
@ -137,6 +330,41 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "minifb"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c470a74618b43cd182c21b3dc1e6123501249f3bad9a0085e95d1304ca2478"
dependencies = [
"cc",
"dlib",
"futures",
"instant",
"js-sys",
"lazy_static",
"libc",
"orbclient",
"raw-window-handle",
"serde",
"serde_derive",
"tempfile",
"wasm-bindgen-futures",
"wayland-client",
"wayland-cursor",
"wayland-protocols",
"winapi",
"x11-dl",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.11" version = "0.8.11"
@ -146,7 +374,37 @@ dependencies = [
"libc", "libc",
"log", "log",
"wasi", "wasi",
"windows-sys", "windows-sys 0.48.0",
]
[[package]]
name = "nix"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
"libc",
"memoffset",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "orbclient"
version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166"
dependencies = [
"libc",
"libredox",
"sdl2",
"sdl2-sys",
] ]
[[package]] [[package]]
@ -167,11 +425,29 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall", "redox_syscall 0.5.2",
"smallvec", "smallvec",
"windows-targets 0.52.5", "windows-targets 0.52.5",
] ]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.86" version = "1.0.86"
@ -190,21 +466,78 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.2" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.5.0",
] ]
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sdl2"
version = "0.35.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a"
dependencies = [
"bitflags 1.3.2",
"lazy_static",
"libc",
"sdl2-sys",
]
[[package]]
name = "sdl2-sys"
version = "0.35.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0"
dependencies = [
"cfg-if",
"libc",
"version-compare",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.203" version = "1.0.203"
@ -264,6 +597,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"
@ -281,6 +623,18 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "tempfile"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",
"rustix",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.61" version = "1.0.61"
@ -341,12 +695,167 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version-compare"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "wayland-client"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
dependencies = [
"bitflags 1.3.2",
"downcast-rs",
"libc",
"nix",
"scoped-tls",
"wayland-commons",
"wayland-scanner",
"wayland-sys",
]
[[package]]
name = "wayland-commons"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
dependencies = [
"nix",
"once_cell",
"smallvec",
"wayland-sys",
]
[[package]]
name = "wayland-cursor"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
dependencies = [
"nix",
"wayland-client",
"xcursor",
]
[[package]]
name = "wayland-protocols"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"
dependencies = [
"bitflags 1.3.2",
"wayland-client",
"wayland-commons",
"wayland-scanner",
]
[[package]]
name = "wayland-scanner"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"
dependencies = [
"proc-macro2",
"quote",
"xml-rs",
]
[[package]]
name = "wayland-sys"
version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"
dependencies = [
"dlib",
"lazy_static",
"pkg-config",
]
[[package]]
name = "web-sys"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -378,6 +887,15 @@ dependencies = [
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.5",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.48.5" version = "0.48.5"
@ -507,3 +1025,26 @@ checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "x11-dl"
version = "2.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f"
dependencies = [
"libc",
"once_cell",
"pkg-config",
]
[[package]]
name = "xcursor"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911"
[[package]]
name = "xml-rs"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193"

View File

@ -9,6 +9,7 @@ edition = "2021"
anyhow = "1.0.81" anyhow = "1.0.81"
bdf = "0.6.0" bdf = "0.6.0"
crossterm = "0.27.0" crossterm = "0.27.0"
minifb = "0.27.0"
# minifb = "0.25.0" # minifb = "0.25.0"
# ratatui = "0.26.3" # ratatui = "0.26.3"
serde = { version = "1.0.197", features = ["serde_derive", "derive"] } serde = { version = "1.0.197", features = ["serde_derive", "derive"] }

View File

@ -7,116 +7,163 @@ use std::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::memory::Mem; use crate::video::ScreenType;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
struct Config { struct ConfigBuilder {
rom: Option<String>,
char_rom: Option<String>, char_rom: Option<String>,
rom: String, screen: ScreenType,
} }
pub fn get_input(memory: &mut Mem) { impl ConfigBuilder {
let args: Vec<String> = env::args().collect(); fn new() -> Self {
Self {
rom: None,
char_rom: None,
screen: ScreenType::default(),
}
}
match args.len() { fn build(self) -> Config {
0 => { let rom = match self.rom {
println!("george-emu must be run in the terminal, don't know what went wrong here!"); Some(rom) => rom,
exit(1) None => {
println!("no rom was provided :(");
exit(1);
}
};
let char_rom = self.char_rom;
let screen = self.screen;
Config {
rom,
screen,
char_rom,
} }
1 => { }
let config: Config = match File::open("./george.toml") { }
Ok(mut file) => {
let mut string = String::new(); pub struct Config {
file.read_to_string(&mut string).unwrap(); pub rom: String,
toml::from_str(string.as_str()).unwrap() pub screen: ScreenType,
} pub char_rom: Option<String>,
Err(_) => { }
println!("couldn't find a `george.toml` in the current directory!");
exit(1); fn help(command: Option<String>) {
} let executable: String = env::args().next().unwrap();
}; if let Some(command) = command {
let rom = match std::fs::File::open(config.rom) { match &command as &str {
Ok(file) => file, "rom" | "--rom" | "-r" => {
Err(error) => panic!("Couldn't open main rom! {:?}", error), println!("{executable} {command} <path>\n\nload a rom/binary from path");
}; exit(0);
if let Err(error) = memory.load_rom(rom) { }
println!("{:?}", error); "screen" | "--screen" | "-s" => {
}; println!("{executable} {command} <path>\n\nload a rom/binary from path");
} exit(0);
2 => match &args[1] as &str { }
"help" => { "help" | "--help" | "-h" => {
println!("ʕ·ᴥ·ʔ- george-emu is an emulator for george:"); println!("{executable} {command} <command>\n\nshow help info for a given command");
println!("https://git.augustkline.com/august/george\n");
println!("commands:");
println!(" help: print this help screen");
println!(" help <command>: print help info for any command");
println!(" rom <path>: load a rom/binary from path\n");
println!("configuration:");
println!(" george-emu searches for a `george.toml` in the current directory. in `george.toml` you can specify a path for the character rom using the key `char_rom` and the main rom/binary with the key `rom`");
exit(0); exit(0);
} }
_ => { _ => {
println!( println!(
"{:?} isn't a valid command!\n\nuse `{} help` to see all valid commands", "{command:?} isn't a valid command!\n\nuse `{executable} help` to see all valid commands",
&args[1], &args[0]
); );
exit(1); exit(1);
} }
},
3 => match &args[1] as &str {
"help" => match &args[2] as &str {
"rom" => {
println!("{} rom <path>\n\nload a rom/binary from path", &args[0]);
exit(0);
}
_ => {
println!(
"{:?} isn't a valid command!\n\nuse `{} help` to see all valid commands",
&args[2], &args[0]
);
exit(1);
}
},
"rom" => {
let rom = match std::fs::File::open(&args[2]) {
Ok(file) => file,
Err(error) => {
match error.kind() {
ErrorKind::NotFound => {
println!("couldn't find the rom at {:?}", &args[2]);
}
ErrorKind::PermissionDenied => {
println!(
"didn't have sufficient permissions to open the rom at {:?}",
&args[2]
);
}
_ => {
println!("something went wrong! try again in a moment? really not sure why you're getting this error");
}
}
exit(1);
}
};
if let Err(error) = memory.load_rom(rom) {
println!("oh no! this rom couldn't be loaded: {:?}", error);
exit(1);
};
}
_ => {
println!(
"{:?} isn't a valid command!\n\nuse `{} help` to see all valid commands",
&args[1], &args[0]
);
exit(1);
}
},
_ => {
println!(
"too many arguments were provided!\n\nuse `{} help` to see all valid commands",
&args[0]
);
exit(1);
} }
} else {
println!("ʕ·ᴥ·ʔ- {executable} is an emulator for george:");
println!("https://git.augustkline.com/august/george\n");
println!("commands:");
println!(" help, -h, --help <command>: print help info for any command");
println!(" rom, -r, --rom <path>: load a rom/binary from path");
println!(" screen, -s, --screen <type>: use the \"terminal\" or \"window\" display type");
println!("\nconfiguration:");
println!(" george-emu searches for a `george.toml` in the current directory.\n in `george.toml` you can specify a path for the character rom using the key `char_rom` and the main rom/binary with the key `rom`");
exit(0);
} }
} }
pub fn get_input() -> Config {
let executable: String = env::args().next().unwrap();
let mut config = ConfigBuilder::new();
let len = env::args().len();
if len == 1 {
config = match File::open("./george.toml") {
Ok(mut file) => {
let mut string = String::new();
file.read_to_string(&mut string).unwrap();
toml::from_str(string.as_str()).unwrap()
}
Err(_) => {
println!("couldn't find a `george.toml` in the current directory!");
exit(1);
}
};
return config.build();
}
let mut args = env::args().skip(1);
while let Some(arg) = args.next() {
match &arg[..] {
"--help" | "-h" | "help" => help(args.next()),
"--rom" | "-r" | "rom" => {
if let Some(path) = args.next() {
match std::fs::File::open(&path) {
Ok(_) => {
config.rom = Some(path);
}
Err(error) => {
match error.kind() {
ErrorKind::NotFound => {
println!("couldn't find the rom at {path:?}");
}
ErrorKind::PermissionDenied => {
println!(
"didn't have sufficient permissions to open the rom at {path:?}"
);
}
_ => {
println!("something went wrong! try again in a moment? really not sure why you're getting this error");
}
}
exit(1);
}
};
} else {
println!("no rom specified!");
exit(1);
}
}
"--screen" | "-s" | "screen" => {
let kind = args.next();
match kind {
Some(kind) => match &kind as &str {
"terminal" | "Terminal" | "TERMINAL" | "t" | "term" => {}
"window" | "Window" | "WINDOW" | "w" | "win" => {
config.screen = ScreenType::Window
}
_ => {
println!("{kind:?} isn't a valid screen type!\n\nuse \"{executable} --help screen\" to see all valid screen types");
exit(1);
}
},
None => {
println!("no screen type was provided!\n\nuse \"{executable} --help screen\" to see all valid screen types");
exit(1);
}
}
}
_ => {
println!("{arg:?} isn't a valid command!\n\nuse \"{executable} help\" to see all valid commands");
exit(1);
}
}
}
config.build()
}

View File

@ -1,5 +1,5 @@
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
// use minifb::{InputCallback, Key}; use minifb::{InputCallback, Key};
use crate::memory::{MemHandle, MemoryWriter}; use crate::memory::{MemHandle, MemoryWriter};
@ -18,56 +18,61 @@ impl Keyboard {
let mut row3 = 0; let mut row3 = 0;
let mut row4 = 0; let mut row4 = 0;
let mut row5 = 0; let mut row5 = 0;
if key.kind == KeyEventKind::Press || key.kind == KeyEventKind::Repeat { match key.modifiers {
match key.modifiers { KeyModifiers::SHIFT => row2 ^= 0b1000_0000,
KeyModifiers::SHIFT => row2 ^= 0b1000_0000, KeyModifiers::CONTROL => row3 ^= 0b1000_0000,
KeyModifiers::CONTROL => row3 ^= 0b1000_0000, KeyModifiers::ALT => row4 ^= 0b1000_0000,
KeyModifiers::ALT => row4 ^= 0b1000_0000, KeyModifiers::META => row5 ^= 0b1000_0000,
KeyModifiers::META => row5 ^= 0b1000_0000, KeyModifiers::SUPER => row5 ^= 0b0010_0000,
KeyModifiers::SUPER => row5 ^= 0b0010_0000, _ => {}
_ => {} };
};
match key.code { match key.code {
KeyCode::Esc => row0 ^= 0b1000_0000, KeyCode::Esc => row0 ^= 0b1000_0000,
KeyCode::Char('w') => row0 ^= 0b0100_0000, KeyCode::Char('w') => row0 ^= 0b0100_0000,
KeyCode::Char('e') => row0 ^= 0b0010_0000, KeyCode::Char('e') => row0 ^= 0b0010_0000,
KeyCode::Char('r') => row0 ^= 0b0001_0000, KeyCode::Char('r') => row0 ^= 0b0001_0000,
KeyCode::Char('t') => row0 ^= 0b0000_1000, KeyCode::Char('t') => row0 ^= 0b0000_1000,
KeyCode::Char('u') => row0 ^= 0b0000_0100, KeyCode::Char('u') => row0 ^= 0b0000_0100,
KeyCode::Char('o') => row0 ^= 0b0000_0010, KeyCode::Char('o') => row0 ^= 0b0000_0010,
KeyCode::Backspace => row0 ^= 0b0000_0001, KeyCode::Backspace => row0 ^= 0b0000_0001,
KeyCode::Tab => row1 ^= 0b1000_0000, KeyCode::Tab => row1 ^= 0b1000_0000,
KeyCode::Char('q') => row1 ^= 0b0100_0000, KeyCode::Char('q') => row1 ^= 0b0100_0000,
KeyCode::Char('s') => row1 ^= 0b0010_0000, KeyCode::Char('s') => row1 ^= 0b0010_0000,
KeyCode::Char('g') => row1 ^= 0b0001_0000, KeyCode::Char('g') => row1 ^= 0b0001_0000,
KeyCode::Char('y') => row1 ^= 0b0000_1000, KeyCode::Char('y') => row1 ^= 0b0000_1000,
KeyCode::Char('i') => row1 ^= 0b0000_0100, KeyCode::Char('i') => row1 ^= 0b0000_0100,
KeyCode::Char('p') => row1 ^= 0b0000_0010, KeyCode::Char('p') => row1 ^= 0b0000_0010,
KeyCode::Enter => row1 ^= 0b0000_0001, KeyCode::Enter => row1 ^= 0b0000_0001,
KeyCode::Char('d') => row2 ^= 0b0100_0000, KeyCode::Char('d') => row2 ^= 0b0100_0000,
KeyCode::Char('v') => row2 ^= 0b0010_0000, KeyCode::Char('v') => row2 ^= 0b0010_0000,
KeyCode::Char('h') => row2 ^= 0b0001_0000, KeyCode::Char('h') => row2 ^= 0b0001_0000,
KeyCode::Char('k') => row2 ^= 0b0000_1000, KeyCode::Char('k') => row2 ^= 0b0000_1000,
KeyCode::Char('\'') => row2 ^= 0b0000_0100, KeyCode::Char('\'') => row2 ^= 0b0000_0100,
KeyCode::Char('/') => row2 ^= 0b0000_0010, KeyCode::Char('/') => row2 ^= 0b0000_0010,
KeyCode::Char('a') => row2 ^= 0b0000_0001, KeyCode::Char('a') => row2 ^= 0b0000_0001,
KeyCode::Char('z') => row3 ^= 0b0100_0000, KeyCode::Char('z') => row3 ^= 0b0100_0000,
KeyCode::Char('f') => row3 ^= 0b0010_0000, KeyCode::Char('f') => row3 ^= 0b0010_0000,
KeyCode::Char('b') => row3 ^= 0b0001_0000, KeyCode::Char('b') => row3 ^= 0b0001_0000,
KeyCode::Char('j') => row3 ^= 0b0000_1000, KeyCode::Char('j') => row3 ^= 0b0000_1000,
KeyCode::Char('l') => row3 ^= 0b0000_0100, KeyCode::Char('l') => row3 ^= 0b0000_0100,
KeyCode::Char('2') => row3 ^= 0b0000_0010, KeyCode::Char('2') => row3 ^= 0b0000_0010,
KeyCode::Char('4') => row3 ^= 0b0000_0001, KeyCode::Char('4') => row3 ^= 0b0000_0001,
KeyCode::Char('x') => row4 ^= 0b0100_0000, KeyCode::Char('x') => row4 ^= 0b0100_0000,
KeyCode::Char('c') => row4 ^= 0b0010_0000, KeyCode::Char('c') => row4 ^= 0b0010_0000,
KeyCode::Char('n') => row4 ^= 0b0001_0000, KeyCode::Char('n') => row4 ^= 0b0001_0000,
KeyCode::Char('m') => row4 ^= 0b0000_1000, KeyCode::Char('m') => row4 ^= 0b0000_1000,
KeyCode::Char(',') => row4 ^= 0b0000_0100, KeyCode::Char(',') => row4 ^= 0b0000_0100,
KeyCode::Char('1') => row4 ^= 0b0000_0010, KeyCode::Char('1') => row4 ^= 0b0000_0010,
KeyCode::Char('3') => row4 ^= 0b0000_0001, KeyCode::Char('3') => row4 ^= 0b0000_0001,
KeyCode::Char(' ') => row5 ^= 0b0100_0000, KeyCode::Char(' ') => row5 ^= 0b0100_0000,
_ => {} _ => {
row0 = 0;
row1 = 0;
row2 = 0;
row3 = 0;
row4 = 0;
row5 = 0;
} }
}; };
@ -86,68 +91,68 @@ impl MemoryWriter for Keyboard {
} }
} }
// impl InputCallback for Keyboard { impl InputCallback for Keyboard {
// fn add_char(&mut self, _uni_char: u32) {} fn add_char(&mut self, _uni_char: u32) {}
// fn set_key_state(&mut self, key: Key, _state: bool) { fn set_key_state(&mut self, key: Key, _state: bool) {
// let mut row0 = 0; let mut row0 = 0;
// let mut row1 = 0; let mut row1 = 0;
// let mut row2 = 0; let mut row2 = 0;
// let mut row3 = 0; let mut row3 = 0;
// let mut row4 = 0; let mut row4 = 0;
// let mut row5 = 0; let mut row5 = 0;
// match key { match key {
// Key::Escape => row0 ^= 0b1000_0000, Key::Escape => row0 ^= 0b1000_0000,
// Key::W => row0 ^= 0b0100_0000, Key::W => row0 ^= 0b0100_0000,
// Key::E => row0 ^= 0b0010_0000, Key::E => row0 ^= 0b0010_0000,
// Key::R => row0 ^= 0b0001_0000, Key::R => row0 ^= 0b0001_0000,
// Key::T => row0 ^= 0b0000_1000, Key::T => row0 ^= 0b0000_1000,
// Key::U => row0 ^= 0b0000_0100, Key::U => row0 ^= 0b0000_0100,
// Key::O => row0 ^= 0b0000_0010, Key::O => row0 ^= 0b0000_0010,
// Key::Backspace => row0 ^= 0b0000_0001, Key::Backspace => row0 ^= 0b0000_0001,
// Key::Tab => row1 ^= 0b1000_0000, Key::Tab => row1 ^= 0b1000_0000,
// Key::Q => row1 ^= 0b0100_0000, Key::Q => row1 ^= 0b0100_0000,
// Key::S => row1 ^= 0b0010_0000, Key::S => row1 ^= 0b0010_0000,
// Key::G => row1 ^= 0b0001_0000, Key::G => row1 ^= 0b0001_0000,
// Key::Y => row1 ^= 0b0000_1000, Key::Y => row1 ^= 0b0000_1000,
// Key::I => row1 ^= 0b0000_0100, Key::I => row1 ^= 0b0000_0100,
// Key::P => row1 ^= 0b0000_0010, Key::P => row1 ^= 0b0000_0010,
// Key::Enter => row1 ^= 0b0000_0001, Key::Enter => row1 ^= 0b0000_0001,
// Key::LeftShift | Key::RightShift => row2 ^= 0b1000_0000, Key::LeftShift | Key::RightShift => row2 ^= 0b1000_0000,
// Key::D => row2 ^= 0b0100_0000, Key::D => row2 ^= 0b0100_0000,
// Key::V => row2 ^= 0b0010_0000, Key::V => row2 ^= 0b0010_0000,
// Key::H => row2 ^= 0b0001_0000, Key::H => row2 ^= 0b0001_0000,
// Key::K => row2 ^= 0b0000_1000, Key::K => row2 ^= 0b0000_1000,
// Key::Apostrophe => row2 ^= 0b0000_0100, Key::Apostrophe => row2 ^= 0b0000_0100,
// Key::Slash => row2 ^= 0b0000_0010, Key::Slash => row2 ^= 0b0000_0010,
// Key::A => row2 ^= 0b0000_0001, Key::A => row2 ^= 0b0000_0001,
// Key::LeftCtrl | Key::RightCtrl => row3 ^= 0b1000_0000, Key::LeftCtrl | Key::RightCtrl => row3 ^= 0b1000_0000,
// Key::Z => row3 ^= 0b0100_0000, Key::Z => row3 ^= 0b0100_0000,
// Key::F => row3 ^= 0b0010_0000, Key::F => row3 ^= 0b0010_0000,
// Key::B => row3 ^= 0b0001_0000, Key::B => row3 ^= 0b0001_0000,
// Key::J => row3 ^= 0b0000_1000, Key::J => row3 ^= 0b0000_1000,
// Key::L => row3 ^= 0b0000_0100, Key::L => row3 ^= 0b0000_0100,
// Key::Key2 => row3 ^= 0b0000_0010, Key::Key2 => row3 ^= 0b0000_0010,
// Key::Key4 => row3 ^= 0b0000_0001, Key::Key4 => row3 ^= 0b0000_0001,
// Key::LeftAlt | Key::RightAlt => row4 ^= 0b1000_0000, Key::LeftAlt | Key::RightAlt => row4 ^= 0b1000_0000,
// Key::X => row4 ^= 0b0100_0000, Key::X => row4 ^= 0b0100_0000,
// Key::C => row4 ^= 0b0010_0000, Key::C => row4 ^= 0b0010_0000,
// Key::N => row4 ^= 0b0001_0000, Key::N => row4 ^= 0b0001_0000,
// Key::M => row4 ^= 0b0000_1000, Key::M => row4 ^= 0b0000_1000,
// Key::Comma => row4 ^= 0b0000_0100, Key::Comma => row4 ^= 0b0000_0100,
// Key::Key1 => row4 ^= 0b0000_0010, Key::Key1 => row4 ^= 0b0000_0010,
// Key::Key3 => row4 ^= 0b0000_0001, Key::Key3 => row4 ^= 0b0000_0001,
// Key::LeftSuper => row5 ^= 0b1000_0000, Key::LeftSuper => row5 ^= 0b1000_0000,
// Key::Space => row5 ^= 0b0100_0000, Key::Space => row5 ^= 0b0100_0000,
// Key::RightSuper => row5 ^= 0b0010_0000, Key::RightSuper => row5 ^= 0b0010_0000,
// _ => {} _ => {}
// }; };
// self.memory.write(0x4400, row0); self.memory.write(0x4400, row0);
// self.memory.write(0x4401, row1); self.memory.write(0x4401, row1);
// self.memory.write(0x4402, row2); self.memory.write(0x4402, row2);
// self.memory.write(0x4403, row3); self.memory.write(0x4403, row3);
// self.memory.write(0x4404, row4); self.memory.write(0x4404, row4);
// self.memory.write(0x4405, row5); self.memory.write(0x4405, row5);
// } }
// } }

View File

@ -17,7 +17,7 @@ use crossterm::execute;
use crossterm::terminal::{size, Clear, ClearType, SetSize}; use crossterm::terminal::{size, Clear, ClearType, SetSize};
// use cpu::CpuController; // use cpu::CpuController;
use memory::MemHandle; use memory::MemHandle;
// use minifb::{Scale, ScaleMode, Window, WindowOptions}; use minifb::{Scale, ScaleMode, Window, WindowOptions};
use std::io::{stdout, Result}; use std::io::{stdout, Result};
use std::thread::{self, sleep}; use std::thread::{self, sleep};
use std::time::Duration; use std::time::Duration;
@ -61,9 +61,10 @@ fn main() -> Result<()> {
let mut stdout = stdout(); let mut stdout = stdout();
let (cols, rows) = size()?; let (cols, rows) = size()?;
let mut memory = Mem::new(); let config = get_input();
get_input(&mut memory); let mut memory = Mem::new();
let _ = memory.load_rom(&config.rom);
execute!(stdout, SetSize(64, 29), cursor::Hide, EnterAlternateScreen)?; execute!(stdout, SetSize(64, 29), cursor::Hide, EnterAlternateScreen)?;
enable_raw_mode()?; enable_raw_mode()?;
@ -82,20 +83,18 @@ fn main() -> Result<()> {
cpu.cycle(); cpu.cycle();
}); });
let stdout_lock = stdout.lock(); let mut screen = Screen::new(&config, cpu_controller, screen_memory);
let renderer = TerminalRenderer::new(screen_memory, stdout_lock);
let mut screen = Screen::new(renderer, cpu_controller);
loop { loop {
sleep(Duration::from_millis(16)); sleep(Duration::from_millis(16));
screen.draw(); screen.draw();
if event::poll(std::time::Duration::from_millis(16))? { // if event::poll(std::time::Duration::from_millis(16))? {
if let event::Event::Key(key) = event::read()? { if let event::Event::Key(key) = event::read()? {
keyboard.read_keys(key); keyboard.read_keys(key);
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
break; break;
}
} }
// }
} }
} }

View File

@ -1,7 +1,7 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use std::cell::RefCell; use std::cell::RefCell;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -71,7 +71,14 @@ impl Mem {
self.0[address as usize] = data; self.0[address as usize] = data;
} }
pub fn load_rom(&mut self, rom: File) -> Result<()> { pub fn load_rom<P>(&mut self, rom: P) -> Result<()>
where
P: AsRef<Path>,
{
let rom = match File::open(rom) {
Ok(rom) => rom,
Err(_) => bail!("rom could not be opened!"),
};
let bytes = rom.bytes(); let bytes = rom.bytes();
for (address, byte) in bytes.enumerate() { for (address, byte) in bytes.enumerate() {
// println!("{address}"); // println!("{address}");

View File

@ -4,6 +4,7 @@
.org $8000 .org $8000
n = $01 ; temporary storage for data stack operations n = $01 ; temporary storage for data stack operations
key_buffer = $200
reset: reset:
sei sei
@ -27,10 +28,40 @@ cleardisplay:
cli cli
main: main:
; jmp draw ; jsr read_keys
jmp cleardisplay ; lda key_buffer
lda $4402
sta $6000
jmp main jmp main
; first, let's do the simplest case of just the letter a being pressed
; 1. check row 2 ($4402, where the a key is) for pressed keys
; 2. if any keys are pressed, check if the key is a (bit 0)
; 3. if the key is not a, store zero in the key buffer
; 4. if the key is a, store the ascii for a in the key buffer
; 5. return
; so u don't have to scroll: key_buffer = $200
; key buffer just shows the current state of the keyboard
; it is not a queue of keys to print
read_keys:
lda $4402 ; check row 2
beq check_key ; if there're any keys, check which
clear_buffer:
stz key_buffer
rts
check_key: ; if there is a key pressed, check if it's a
ror
bmi store_key
rts
store_key:
; in a sec we'll set up ascii table lookup,
; for now let's just load the ascii byte for a
lda #$61
sta key_buffer
rts
draw: draw:
push_coords #0, #0 push_coords #0, #0
push_char #$af push_char #$af
@ -73,8 +104,6 @@ fill: ; fills an area from (x1, y1) to (x2, y2) will character c, (n1: c n2: x1
jsr get_char_address jsr get_char_address
irq: irq:
keyboard:
rts rts
isr: ; interrupt service routine isr: ; interrupt service routine

View File

@ -1,175 +0,0 @@
// use std::time::Duration;
mod tabs;
mod term;
use std::{
io::Result,
sync::{mpsc::Receiver, Arc, Mutex},
time::Duration,
};
use crossterm::event::{self, poll, Event, KeyCode, KeyEvent, KeyEventKind};
use ratatui::{
layout::Layout,
prelude::*,
widgets::{Block, Cell, Paragraph, Row, Table, TableState},
};
use crate::{
cpu::{CpuController, CpuState},
memory::{MemHandle, MemoryReader, MemoryWriter},
};
pub struct App {
cpu: CpuController,
state: Receiver<CpuState>,
memory: MemHandle,
running: bool,
table_state: TableState,
}
impl MemoryReader for App {
fn read(&self, address: u16) -> u8 {
self.memory.read(address)
}
}
impl MemoryWriter for App {
fn write(&self, address: u16, data: u8) {
self.memory.write(address, data)
}
}
impl App {
pub fn new(cpu: CpuController, memory: MemHandle, state: Receiver<CpuState>) -> Self {
Self {
cpu,
memory,
running: true,
table_state: TableState::default(),
state,
}
}
pub fn update(&mut self, terminal: &mut Terminal<impl Backend>) -> Result<()> {
self.draw(terminal)?;
self.handle_events()?;
Ok(())
}
/// Draw a single frame of the app.
fn draw(&self, terminal: &mut Terminal<impl Backend>) -> Result<()> {
terminal
.draw(|frame| {
frame.render_widget(self, frame.size());
})
.unwrap();
Ok(())
}
fn handle_events(&mut self) -> Result<()> {
if poll(Duration::from_secs_f32(1.0 / 25.0))? {
match event::read()? {
Event::Key(key) if key.kind == KeyEventKind::Press => self.handle_key_press(key),
_ => {}
}
}
Ok(())
}
fn handle_key_press(&mut self, key: KeyEvent) {
// let mut cpu = self.cpu.lock().unwrap();
match key.code {
KeyCode::Enter => {
if !self.running {
// cpu.cycle()
}
}
KeyCode::Char(' ') => {
self.running = !self.running;
match self.running {
true => self.cpu.stop(),
false => self.cpu.resume(),
}
}
_ => {}
};
}
}
/// Implement Widget for &App rather than for App as we would otherwise have to clone or copy the
/// entire app state on every frame. For this example, the app state is small enough that it doesn't
/// matter, but for larger apps this can be a significant performance improvement.
impl Widget for &App {
fn render(self, area: Rect, buf: &mut Buffer) {
self.cpu.data();
let [cpu_area, memory_area] =
Layout::horizontal([Constraint::Percentage(50), Constraint::Fill(1)]).areas(area);
let [memory_table, memory_info] =
Layout::vertical([Constraint::Fill(1), Constraint::Percentage(10)]).areas(memory_area);
let cpu = self.state.recv().unwrap();
let cpu_info = format!("a: {a:#04x}, x: {x:#04x}, y: {y:#04x}, pc: {pc:#06x}, sp: {s:#04x}, sr: {p:#010b}, irq: {irq:?}, nmi: {nmi:?}", a = cpu.a, x = cpu.x, y = cpu.y, pc = cpu.pc, s = cpu.s, p = cpu.p, irq = cpu.irq, nmi = cpu.nmi);
Paragraph::new(cpu_info)
.block(Block::bordered().title("cpu info!"))
.render(cpu_area, buf);
// let table_height = memory_table.rows().count() - 2;
// TODO: impl Iterator for MemHandle so we can get references to the underlying data from other threads without cloning
// let rows: Vec<Row> = self.memory.data()[0..table_height * 16]
// .chunks(16)
// .map(|chunk| {
// chunk
// .iter()
// .map(|content| Cell::from(Text::from(format!("{content:x}"))))
// .collect::<Row>()
// })
// .collect();
let zero = self.memory.read(0);
let rows: Vec<Row> = vec![Row::new([format!("{zero}")])];
let widths = vec![Constraint::Length(2); 16];
Widget::render(
Table::new(rows, widths)
.header(
Row::new(vec![
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e",
"f",
])
.style(Style::new().bold()), // To add space between the header and the rest of the rows, specify the margin
// .bottom_margin(1),
)
.block(Block::bordered().title_top("memory")),
memory_table,
buf,
);
Paragraph::new(format!("program counter: {:#04x}", cpu.pc))
.block(Block::bordered().title_top("info"))
.render(memory_info, buf);
}
}
// impl Widget for App {
// fn render_title_bar(&self, area: Rect, buf: &mut Buffer) {
// // let layout = Layout::horizontal([Constraint::Min(0), Constraint::Length(43)]);
// // let [title] = layout.areas(area);
// Span::styled("Ratatui", Style::default()).render(area, buf);
// // let titles = Tab::iter().map(Tab::title);
// // Tabs::new(titles)
// // .style(THEME.tabs)
// // .highlight_style(THEME.tabs_selected)
// // .select(self.tab as usize)
// // .divider("")
// // .padding("", "")
// // .render(tabs, buf);
// }
// // fn render_selected_tab(&self, area: Rect, buf: &mut Buffer) {
// // match self.tab {
// // Tab::About => self.about_tab.render(area, buf),
// // Tab::Recipe => self.recipe_tab.render(area, buf),
// // Tab::Email => self.email_tab.render(area, buf),
// // Tab::Traceroute => self.traceroute_tab.render(area, buf),
// // Tab::Weather => self.weather_tab.render(area, buf),
// // };
// // }
// }

View File

@ -3,28 +3,27 @@ use crossterm::{
execute, queue, execute, queue,
style::{Color, PrintStyledContent, Stylize}, style::{Color, PrintStyledContent, Stylize},
}; };
use minifb::{Scale, ScaleMode, Window, WindowOptions};
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
cli::Config,
cpu::CpuController, cpu::CpuController,
memory::{MemHandle, MemoryReader}, memory::{MemHandle, MemoryReader},
types::{Byte, Word}, types::{Byte, Word},
}; };
use std::{ use std::{
fs::File, fs::File,
io::{Read, StdoutLock, Write}, io::{self, Read, Write},
path::Path, path::Path,
process::exit,
sync::mpsc::Sender,
time::Instant,
}; };
const FG_COLOR: u32 = 0xFFCC00; const FG_COLOR: u32 = 0xFFCC00;
const BG_COLOR: u32 = 0x110500; const BG_COLOR: u32 = 0x110500;
// // BGR for softbuffer const WIDTH: usize = 512;
// const FG_COLOR: u32 = 0x00CCFF; const HEIGHT: usize = 380;
// const BG_COLOR: u32 = 0x000511;
// pub fn get_char_bin<P>(char_rom: Option<P>) -> [u8; 0x8000]
pub fn get_char_bin<P>(char_rom: Option<P>) -> Vec<u8>
where where
P: AsRef<Path>, P: AsRef<Path>,
{ {
@ -34,9 +33,9 @@ where
let mut bin = vec![0; 0x8000]; let mut bin = vec![0; 0x8000];
file.read_exact(&mut bin).unwrap(); file.read_exact(&mut bin).unwrap();
// println!("reading char rom"); // println!("reading char rom");
bin bin.try_into().unwrap()
} }
None => include_bytes!("./roms/cozette.rom").to_vec(), None => *include_bytes!("./roms/cozette.rom"),
} }
} }
@ -44,14 +43,21 @@ trait Renderer {
fn render(&mut self) {} fn render(&mut self) {}
} }
#[derive(Serialize, Deserialize, Debug, Default)]
pub enum ScreenType {
Window,
#[default]
Terminal,
}
pub struct WindowRenderer { pub struct WindowRenderer {
char_rom: Vec<u8>, char_rom: [u8; 0x8000],
window: Sender<Vec<u32>>, window: Window,
memory: MemHandle, memory: MemHandle,
} }
impl WindowRenderer { impl WindowRenderer {
pub fn new<P>(memory: MemHandle, char_rom: Option<P>, window: Sender<Vec<u32>>) -> Self pub fn new<P>(memory: MemHandle, char_rom: Option<P>, window: Window) -> Self
where where
P: AsRef<Path>, P: AsRef<Path>,
{ {
@ -70,7 +76,7 @@ impl Renderer for WindowRenderer {
// based on the specifics of george's weird // based on the specifics of george's weird
// display and characters... don't fuck around w it // display and characters... don't fuck around w it
let mut i = 0; let mut i = 0;
let mut buffer = vec![0; 512 * 380]; let mut buffer = [0; 512 * 380];
for char_row in 0..29 { for char_row in 0..29 {
for char_col in 0..64 { for char_col in 0..64 {
let ascii = self.read(0x6000 + i); let ascii = self.read(0x6000 + i);
@ -89,7 +95,9 @@ impl Renderer for WindowRenderer {
} }
} }
let _ = self.window.send(buffer.clone()); self.window
.update_with_buffer(&buffer, WIDTH, HEIGHT)
.unwrap();
} }
} }
} }
@ -100,19 +108,23 @@ impl MemoryReader for WindowRenderer {
} }
} }
pub struct TerminalRenderer<'a> { // pub struct TerminalRenderer<'a> {
pub struct TerminalRenderer {
memory: MemHandle, memory: MemHandle,
// stdout: Stdout, // stdout: Stdout,
stdout: StdoutLock<'a>, // stdout: StdoutLock<'a>,
} }
impl<'a> TerminalRenderer<'a> { // impl<'a> TerminalRenderer<'a> {
pub fn new(memory: MemHandle, stdout: StdoutLock<'a>) -> Self { impl TerminalRenderer {
Self { memory, stdout } // pub fn new(memory: MemHandle, stdout: StdoutLock<'a>) -> Self {
pub fn new(memory: MemHandle) -> Self {
Self { memory }
} }
} }
impl MemoryReader for TerminalRenderer<'_> { // impl MemoryReader for TerminalRenderer<'_> {
impl MemoryReader for TerminalRenderer {
fn read(&self, address: Word) -> Byte { fn read(&self, address: Word) -> Byte {
self.memory.read(address) self.memory.read(address)
} }
@ -135,10 +147,12 @@ const ASCII_LOOPUP: [&str; 256] = [
"", "", "", "", "🎁", "", "", "", "", "", "", "", "", "", "", "", "", "", "🎁", "", "", "", "", "", "", "", "", "",
]; ];
impl Renderer for TerminalRenderer<'_> { // impl Renderer for TerminalRenderer<'_> {
impl Renderer for TerminalRenderer {
fn render(&mut self) { fn render(&mut self) {
// let now = Instant::now(); // let now = Instant::now();
let _ = execute!(self.stdout, SavePosition); let mut stdout = io::stdout();
let _ = execute!(stdout, SavePosition);
let mut i = 0; let mut i = 0;
for char_row in 0..29 { for char_row in 0..29 {
for char_col in 0..64 { for char_col in 0..64 {
@ -148,7 +162,7 @@ impl Renderer for TerminalRenderer<'_> {
let _ = queue!( let _ = queue!(
// FG_COLOR = 0xFFCC00 // FG_COLOR = 0xFFCC00
// BG_COLOR = 0x110500 // BG_COLOR = 0x110500
self.stdout, stdout,
MoveTo(char_col, char_row), MoveTo(char_col, char_row),
PrintStyledContent( PrintStyledContent(
char.with(Color::Rgb { char.with(Color::Rgb {
@ -165,23 +179,46 @@ impl Renderer for TerminalRenderer<'_> {
); );
} }
} }
let _ = self.stdout.flush(); let _ = stdout.flush();
let _ = execute!(self.stdout, RestorePosition); let _ = execute!(stdout, RestorePosition);
// let elapsed = now.elapsed(); // let elapsed = now.elapsed();
// println!("{elapsed:?}"); // println!("{elapsed:?}");
// exit(0); // exit(0);
} }
} }
pub struct Screen<'a> { // pub struct Screen<'a> {
// renderer: Box<dyn Renderer>, pub struct Screen {
renderer: TerminalRenderer<'a>, renderer: Box<dyn Renderer>,
// renderer: TerminalRenderer<'a>,
controller: CpuController, controller: CpuController,
} }
impl<'a> Screen<'a> { impl Screen {
// pub fn new(cpu_controller: CpuController, renderer: Box<dyn Renderer>) -> Self { pub fn new(config: &Config, controller: CpuController, memory: MemHandle) -> Self {
pub fn new(renderer: TerminalRenderer<'a>, controller: CpuController) -> Self { let renderer: Box<dyn Renderer> = match config.screen {
ScreenType::Window => {
let window = Window::new(
"ʕ·ᴥ·ʔ-☆",
512,
380,
WindowOptions {
resize: true,
borderless: true,
title: true,
transparency: false,
scale: Scale::X2,
scale_mode: ScaleMode::AspectRatioStretch,
topmost: false,
none: true,
},
)
.unwrap();
Box::new(WindowRenderer::new(memory, config.char_rom.clone(), window))
}
ScreenType::Terminal => Box::new(TerminalRenderer::new(memory)),
};
Self { Self {
renderer, renderer,
controller, controller,