commit 01cc63c7f1e204e02ea82cd6d778428a99f762b5 Author: Sarah Jamie Lewis Date: Mon Nov 8 18:19:34 2021 -0800 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..72a7bff --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/side.iml b/.idea/side.iml new file mode 100644 index 0000000..758ceaa --- /dev/null +++ b/.idea/side.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..a6f18ed --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ceec750 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,903 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bindgen" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bumpalo" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" + +[[package]] +name = "cc" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" + +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom 5.1.2", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "cmake" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b858541263efe664aead4a5209a4ae5c5d2811167d4ed4ee0944503f8d2089" +dependencies = [ + "cc", +] + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "encoding_rs" +version = "0.8.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "env_logger" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "filetime" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if 1.0.0", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "font8x8" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875488b8711a968268c7cf5d139578713097ca4635a76044e8fe8eedf831d07e" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" + +[[package]] +name = "libloading" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memoffset" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minifb" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b6e41119d1667465608d36488fa5dcd228057a26c156e25f17f492f38435124" +dependencies = [ + "cc", + "orbclient", + "raw-window-handle", + "tempfile", + "wayland-client", + "wayland-cursor", + "wayland-protocols", + "winapi", + "x11-dl", + "xkb", + "xkbcommon-sys", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "nix" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +dependencies = [ + "memchr", + "minimal-lexical", + "version_check", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "orbclient" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c976c5018e7f1db4359616d8b31ef8ae7d9649b11803c0b38fff67fd2999fc8" +dependencies = [ + "libc", + "raw-window-handle", + "redox_syscall", + "sdl2", + "sdl2-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pkg-config" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" + +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "raw-window-handle" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" +dependencies = [ + "libc", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "sdl2" +version = "0.34.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deecbc3fa9460acff5a1e563e05cb5f31bba0aa0c214bb49a43db8159176d54b" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "raw-window-handle", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.34.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a29aa21f175b5a41a6e26da572d5e5d1ee5660d35f9f9d0913e8a802098f74" +dependencies = [ + "cfg-if 0.1.10", + "cmake", + "flate2", + "libc", + "tar", + "unidiff", + "version-compare", +] + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "side" +version = "0.1.0" +dependencies = [ + "font8x8", + "minifb", +] + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tar" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "unidiff" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a62719acf1933bfdbeb73a657ecd9ecece70b405125267dd549e2e2edc232c" +dependencies = [ + "encoding_rs", + "lazy_static", + "regex", +] + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version-compare" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" + +[[package]] +name = "wayland-client" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" +dependencies = [ + "nix", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" +dependencies = [ + "nix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +dependencies = [ + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "x11-dl" +version = "2.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" +dependencies = [ + "lazy_static", + "libc", + "pkg-config", +] + +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] + +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom 7.1.0", +] + +[[package]] +name = "xkb" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aec02bc5de902aa579f3d2f2c522edaf40fa42963cbaffe645b058ddcc68fdb2" +dependencies = [ + "bitflags", + "libc", + "xkbcommon-sys", +] + +[[package]] +name = "xkbcommon-sys" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a001b79d45b0b4541c228a501177f2b35db976bf7ee3f7fce8fa2381554ab5" +dependencies = [ + "bindgen", + "libc", + "pkg-config", +] + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..df7a8db --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "side" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +minifb = "0.19.3" +font8x8 = "0.3.1" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..99a0268 --- /dev/null +++ b/README.md @@ -0,0 +1,178 @@ +# Philosophy of Boo OS + +> Operating System: An operating system is a collection of things that don't fit into a language. There shouldn't be one. - [Design Principles Behind Smalltalk](https://www.cs.virginia.edu/~evans/cs655/readings/smalltalk.html) + +Boo OS is a meditation on recursive complexity and the curse of simplicity. In an age where computers are so powerful, it is sometimes healing to start again. + +I have often been stuck between my desire to build either an operating system, a shell, a language or an ide. None +of those categories ever quite fit the hole I was intending them to fill. + +After much introspection and research I finally decided that what I really needed was something different. + +Inspired by smalltalk, Boo OS is "image" based, the entire system can be dumped and reloaded to the same state. + +Eventually my plan is that Boo OS contain all the essentials necessary for **self modification**. It should be possible to (safely) modify the operating system from within the operating system and have the changes take effect. + +How that will look is undecided. For now, Boo OS is coded entirely in Boo Bytecode Assembly Language and assembled +using a Rust based assembler. One of my first targets for a real application is an Assembler written in Boo Bytecode, +run on BooOS and outputting a Boo Bytecode image. + +## BooVM + +Boo OS is written in Boo Bytecode which is run by the Boo Virtual Machine (BooVM). BooVM and Boo Bytecode is inspired +by various retro computing architectures with minimal instructions, but a focus on integrating with the core +systems. + +As such. the BooVM offers minimal integration with the outside world. Interaction is limited to: + +- Reading and Writing BooVM images to/from the Host OS +- Exposing The State of the Keyboard and Mouse +- Offering a Framebuffer for Display Output +- (Provisional) Reading and Writing "Files" from the Host OS OR Loading and Interacting with a generalized +File System that can be loaded by both operating systems (i.e. some kind of virtual disk image) + +### Why Write a Custom VM? + +Why Not? This is a meditation on recursive complexity. I was already set on writing a new language and building one from the ground up on a custom instruction set seemed like a great idea. + +The longer version is that I looked into many options for the base of this project. They fell into +two main categories: + +The first featured existing ISA emulations (e.g. QEMU) and existing production ready language virtual machines (e.g. JVM, Lua) - I decided that using an existing architecture wasn't in the spirit of the project. Further, both of these options +would require extra work to integrate a framebuffer display and input up to the extent where I would be writing an OS +for an existing architecture. I wanted to keep the wrapping interface to the host OS as simple as possible. + +The second category featured older reto architectures, emulators and the like. I rejected this approach because +there are some details I don't want to care about, like scanlines and cartridge layouts. This approach would also +make interaction with the Host OS a project in itself likely requiring forking and significant rework resulting in +a custom emulator any way. + +After research, designing and implementing an assembler for some custom bytecode and building a small VM to run +it seemed to be the simplest option and provides me with a lot of freedom moving forward, and lends itself to +infinite experimentation. + +## TODO List + +The below represents some ideas for projects to tackle within Boo OS. + +- [x] Print Strings to the FrameBuffer + - [x] Set Framebuffer Position Helper Function + - [x] `put_char` Helper Function +- [ ] Memory Management + - [ ] Heap Design + - [ ] Implement Helper Functions `alloc` and `free` + - [ ] Memory Safety +- [ ] Keyboard Input + - [ ] Designing Input Interaction (poll v.s. interrupts) +- [ ] Create a Console Shell to Interact with the System + - [ ] At first this shell will be limited to pre-programmed commands + - [ ] But, it should quickly all the construction of new commands from old ones + - [ ] Finally, the shell should facilitate saving and loading of images +- [ ] Write a Bootstrapped Assembler Application in Boo Bytecode Assembly + + + +# Formal Reqs + + +Run time: +- Memory needs R/W/E flags - 3 bits +- Mapping Memory before handing off to lesser privileged processes +- Needs some understanding off operating mode + + +- Never attempt to pop an empty stack + + + +Memory + +We treat each 64 chunks of memory as a single page: + + 0x0000 4800 Pages of Write only Display Memory + 0x4B000 1 Page of Registers [rip, mode, display, rax, r2, r3, r4, r5, r6, r7, r8] + 0x4B040 1 Page of Call Stack + 0x4B080 1 Page of Input Flags (Keys Down etc) + 0x4B0C0 Dynamic Memory Begins + + +## Instructions + +All instructions are fixed length. + + +## Meta Instructions + +0x00 - Nop +0x01 - Update Display +0x0F - HLT + +## Dynamic Instructions + +Prefix 0x1#,0x2#,0x3# are given to dynamin register based commands + +- 0x1n STORE(n) $Addr (R(n)) -> Addr) +- 0x2n LOAD(n) $Addr (Addr -> R(n)) +- 0x3n LOADI(n) IMM (Immediate -> R(n)) +- 0x4n INC(n) +- 0x5n DEC(n) +- 0x6n ISTORE(n) +- 0x7n x LDSTORE Load the Address Stored in n into reg(x) +- 0x8n x Transfer R(n) to R(x) + + +- 0x9n Shift + +## Arithmetic + +Prefix 0xa# is given to arithmetic functions + +- 0xa1 ADD (R2 + R3 -> RAX) +- 0xa2 SUB (R2 - R3 -> RAX) +- 0xa3 MUL (R2 * R3 -> RAX) +- 0xa4 DIV (R2 / R3 -> RAX) +- 0xa5 SHIFT (R2 >> R3 -> RAX) +- 0xa6 AND (R2 & R3 -> RAX) + + +# Stack + +Prefix 0xc# allows call stack manipulation. The machine denotes 64 memory addresses at memoo + +- 0xc0 RET +- 0xc1 PUSH Call Stack + +# Jumps and Branches (0x5#) + +- 0xE0 JMP $Addr - Unconditional jump to $Addr +- 0xE1 JMPEQ $Addr (if R1 == R2 jmp $Addr else ) +- 0xE2 JMPNEQ $Addr (if R1 != R2 jmp $Addr else ) +- 0xE3 JMPGT $Addr (if R1 > R2 jmp $Addr else ) +- 0xE4 JMPLT $Addr (if R1 < R2 jmp $Addr else ) +- 0xE5 JMPGEQ $Addr (if R1 >= R2 jmp $Addr else ) +- 0xE6 JMPLEQ $Addr (if R1 <= R2 jmp $Addr else ) + +## Admin Mode Instructions + +Instructions prefixed with 0xF are admin instructions + +- 0xF0 UNSET_R $Addr (Sets the 64 addresses after $Addr as Not Readable) +- 0xF1 SET_R $Addr (Sets the 64 addresses after $Addr as Readable) + +- 0xF2 UNSET_W $Addr (Sets the 64 addresses after $Addr as Not Writable) +- 0xF3 SET_W $Addr (Sets the 64 addresses after $Addr as Writable) + +- 0xF4 UNSET_X $Addr (Sets the 64 addresses after $Addr as Not Executable) +- 0xF5 SET_X $Addr (Sets the 64 addresses after $Addr as Executable) + +- 0xFF DROP_MODE $Addr - Drops from Admin Mode into User Mode (No access to Admin mode instructions) + + + +0: LOAD_IMM 10 +1: NOP +2: DEC(1) +3: JNEQ + + +## \ No newline at end of file diff --git a/charset.asm b/charset.asm new file mode 100644 index 0000000..a2a3984 --- /dev/null +++ b/charset.asm @@ -0,0 +1,290 @@ +label char_space: + $00000000 + $00000000 +label char_!: + $183c3c18 + $18001800 +label char_": + $36360000 + $00000000 +label char_#: + $36367f36 + $7f363600 +label char_$: + $0c3e031e + $301f0c00 +label char_%: + $00633318 + $0c666300 +label char_&: + $1c361c6e + $3b336e00 +label char_': + $06060300 + $00000000 +label char_(: + $180c0606 + $060c1800 +label char_): + $060c1818 + $180c0600 +label char_*: + $00663cff + $3c660000 +label char_+: + $000c0c3f + $0c0c0000 +label char_,: + $00000000 + $000c0c06 +label char_-: + $0000003f + $00000000 +label char_.: + $00000000 + $000c0c00 +label char_/: + $6030180c + $06030100 +label char_0: + $3e63737b + $6f673e00 +label char_1: + $0c0e0c0c + $0c0c3f00 +label char_2: + $1e33301c + $06333f00 +label char_3: + $1e33301c + $30331e00 +label char_4: + $383c3633 + $7f307800 +label char_5: + $3f031f30 + $30331e00 +label char_6: + $1c06031f + $33331e00 +label char_7: + $3f333018 + $0c0c0c00 +label char_8: + $1e33331e + $33331e00 +label char_9: + $1e33333e + $30180e00 +label char_:: + $000c0c00 + $000c0c00 +label char_;: + $000c0c00 + $000c0c06 +label char_<: + $180c0603 + $060c1800 +label char_=: + $00003f00 + $003f0000 +label char_>: + $060c1830 + $180c0600 +label char_?: + $1e333018 + $0c000c00 +label char_@: + $3e637b7b + $7b031e00 +label char_A: + $0c1e3333 + $3f333300 +label char_B: + $3f66663e + $66663f00 +label char_C: + $3c660303 + $03663c00 +label char_D: + $1f366666 + $66361f00 +label char_E: + $7f46161e + $16467f00 +label char_F: + $7f46161e + $16060f00 +label char_G: + $3c660303 + $73667c00 +label char_H: + $3333333f + $33333300 +label char_I: + $1e0c0c0c + $0c0c1e00 +label char_J: + $78303030 + $33331e00 +label char_K: + $6766361e + $36666700 +label char_L: + $0f060606 + $46667f00 +label char_M: + $63777f7f + $6b636300 +label char_N: + $63676f7b + $73636300 +label char_O: + $1c366363 + $63361c00 +label char_P: + $3f66663e + $06060f00 +label char_Q: + $1e333333 + $3b1e3800 +label char_R: + $3f66663e + $36666700 +label char_S: + $1e33070e + $38331e00 +label char_T: + $3f2d0c0c + $0c0c1e00 +label char_U: + $33333333 + $33333f00 +label char_V: + $33333333 + $331e0c00 +label char_W: + $6363636b + $7f776300 +label char_X: + $6363361c + $1c366300 +label char_Y: + $3333331e + $0c0c1e00 +label char_Z: + $7f633118 + $4c667f00 +label char_[: + $1e060606 + $06061e00 +label char_\: + $03060c18 + $30604000 +label char_]: + $1e181818 + $18181e00 +label char_^: + $081c3663 + $00000000 +label char__: + $00000000 + $000000ff +label char_`: + $0c0c1800 + $00000000 +label char_a: + $00001e30 + $3e336e00 +label char_b: + $0706063e + $66663b00 +label char_c: + $00001e33 + $03331e00 +label char_d: + $3830303e + $33336e00 +label char_e: + $00001e33 + $3f031e00 +label char_f: + $1c36060f + $06060f00 +label char_g: + $00006e33 + $333e301f +label char_h: + $0706366e + $66666700 +label char_i: + $0c000e0c + $0c0c1e00 +label char_j: + $30003030 + $3033331e +label char_k: + $07066636 + $1e366700 +label char_l: + $0e0c0c0c + $0c0c1e00 +label char_m: + $0000337f + $7f6b6300 +label char_n: + $00001f33 + $33333300 +label char_o: + $00001e33 + $33331e00 +label char_p: + $00003b66 + $663e060f +label char_q: + $00006e33 + $333e3078 +label char_r: + $00003b6e + $66060f00 +label char_s: + $00003e03 + $1e301f00 +label char_t: + $080c3e0c + $0c2c1800 +label char_u: + $00003333 + $33336e00 +label char_v: + $00003333 + $331e0c00 +label char_w: + $0000636b + $7f7f3600 +label char_x: + $00006336 + $1c366300 +label char_y: + $00003333 + $333e301f +label char_z: + $00003f19 + $0c263f00 +label char_{: + $380c0c07 + $0c0c3800 +label char_|: + $18181800 + $18181800 +label char_}: + $070c0c38 + $0c0c0700 +label char_~: + $6e3b0000 + $00000000 +label char_delete: + $00000000 + $00000000 + +data ascii HEX_TABLE 0123456789ABCDEF \ No newline at end of file diff --git a/display.asm b/display.asm new file mode 100644 index 0000000..4cf132b --- /dev/null +++ b/display.asm @@ -0,0 +1,5 @@ +label set_pos: + loadi 2 $280 + mul $2 $A $2 ; Mul Y * 640 + add $2 $9 $B ; + X = VBUF POS + ret \ No newline at end of file diff --git a/example.asm b/example.asm new file mode 100644 index 0000000..c12831b --- /dev/null +++ b/example.asm @@ -0,0 +1,71 @@ +@ $00000: + label vbuf: + +@ $4B000: + $5B000 ; Set Instruction Pointer to $5B000 + label RAX: + $0000000 ; RAX + $0000000 ; R2 - Temp Scratch + $0000000 ; R3 - Temp Scratch + $0000000 ; R4 - ARG 1 + $0000000 ; R5 - ARG 2 + $0000000 ; R6 - ARG 3 + $0000000 ; R7 - ARG 4 + $0000000 ; R8 - ARG 5 + $0000000 ; RX + $0000000 ; RY + $0000000 ; RVBUF (RY * 640) + RX + +@ $4B0C0: + +import display.asm +import charset.asm +import strings.asm +import util.asm + +; Common Strings +data ascii HelloWorld Welcome to Boo OS Running on Boo Byte Code! +data ascii Welcome !@#$%^&*()_+=-0987654321 +data ascii Introspection We Can Now Do Introspection: +data ascii label_rax RAX: +data ascii label_rip RIP: +data ascii label_cycles Instruction Count: + + +; Kernel Begins +@ $5B000: + loadi $9 1; + loadi $A 1; + call set_pos + + loadi $4 HelloWorld + call draw_string; + + loadi $9 1; + loadi $A 10; + call set_pos + + loadi $4 Welcome + call draw_string; + + ; OK! Time for some self referencing!! + loadi $9 1; + loadi $A 20; + call set_pos + + loadi $4 Introspection + call draw_string; + + loadi $9 1; + loadi $A 30; + call set_pos + + loadi $4 label_cycles + call draw_string; + + loadi $4 $4B000 + loadi $2 $40 + add $2 $4 $4 + call print_addr + updsp + jmp $5B000; \ No newline at end of file diff --git a/src/assembler.rs b/src/assembler.rs new file mode 100644 index 0000000..7776188 --- /dev/null +++ b/src/assembler.rs @@ -0,0 +1,280 @@ +use crate::{Machine, MEMORY}; +use std::collections::HashMap; +use std::fs::read_to_string; + +pub struct ImageAssembler { + memory: [u32; MEMORY], + ptr: usize, + labels: HashMap, +} + +impl ImageAssembler { + pub fn new() -> ImageAssembler { + ImageAssembler { + memory: [0; MEMORY], + ptr: 0, + labels: HashMap::new(), + } + } + + pub fn extract(self) -> Machine { + let mut machine = Machine::new(); + machine.memory = self.memory; + return machine; + } + + pub fn assemble(&mut self, filename: &str) { + let asm = read_to_string(filename).unwrap_or_default(); + let lines = asm.split('\n'); + for line in lines { + let parts = line.split_once(';'); + + let command = match parts { + Some((command, _comment)) => command.trim(), + _ => line.trim(), + }; + + let command_parts = command.split_whitespace().collect::>(); + + if command_parts.is_empty() { + continue; + } + + if command_parts.len() == 1 { + match command_parts[0] { + "nop" => { + self.memory[self.ptr] = 0x00000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + "ret" => { + self.memory[self.ptr] = 0xC0000000; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "hlt" => { + self.memory[self.ptr] = 0x0F000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + "inc1" => { + self.memory[self.ptr] = 0x41000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + "inc2" => { + self.memory[self.ptr] = 0x42000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + "inc3" => { + self.memory[self.ptr] = 0x43000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + "updsp" => { + self.memory[self.ptr] = 0x01000000; + self.ptr += 1; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + } + _ => { + let data = self.parse_addr(command_parts[0]); + self.memory[self.ptr] = data; + self.ptr += 1; + } + } + } else if command_parts.len() == 2 && command_parts[0] != "data" { + match command_parts[0] { + "label" => { + self.labels + .insert(command_parts[1].replace(":", ""), self.ptr); + } + "@" => { + self.ptr = self.parse_addr(command_parts[1]) as usize; + println!("Setting addr to ${:X}", self.ptr); + } + "inc" => { + let num = self.parse_addr(command_parts[1]); + let inst = 0x40 + num; + self.memory[self.ptr] = inst << 24; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "dec" => { + let num = self.parse_addr(command_parts[1]); + let inst = 0x50 + num; + self.memory[self.ptr] = inst << 24; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "jmp" => { + let addr = self.parse_addr(command_parts[1]); + self.memory[self.ptr] = 0xE0000000 + addr; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "jneq" => { + let addr = self.parse_addr(command_parts[1]); + self.memory[self.ptr] = 0xE2000000 + addr; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "call" => { + let addr = self.parse_addr(command_parts[1]); + self.memory[self.ptr] = 0xC1000000 + addr; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "import" => { + self.assemble(command_parts[1]); + } + _ => { + panic!("Unknown Instruction: {:?}", command_parts) + } + } + } else if command_parts.len() == 3 && command_parts[0] != "data" { + match command_parts[0] { + "ldstore" => { + // Load Immediate + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x70 + target_reg) << 24; + let imm = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + imm; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "loadi" => { + // Load Immediate + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x30 + target_reg) << 24; + let imm = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + imm; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "load" => { + // Load Immediate + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x20 + target_reg) << 24; + let reg = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "store" => { + // Load Immediate + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x10 + target_reg) << 24; + let reg = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "rstore" => { + // Load Immediate + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x60 + target_reg) << 24; + let reg = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "tx" => { + let target_reg = self.parse_addr(command_parts[1]); + let inst = (0x80 + target_reg) << 24; + let reg = self.parse_addr(command_parts[2]); + self.memory[self.ptr] = inst + reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + _ => { + panic!("unknown opcpde {}", command_parts[0]) + } + } + } else if command_parts.len() == 4 && command_parts[0] != "data" { + // Every Instruction with 3 is [INST] [Source Reg] [Target Addr / Reg] + let a_reg = self.parse_addr(command_parts[1]); + let b_reg = self.parse_addr(command_parts[2]); + let result_reg = self.parse_addr(command_parts[3]); + match command_parts[0] { + "add" => { + self.memory[self.ptr] = + (0xa1 << 24) + (a_reg << 16) + (b_reg << 8) + result_reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "sub" => { + self.memory[self.ptr] = + (0xa2 << 24) + (a_reg << 16) + (b_reg << 8) + result_reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "mul" => { + self.memory[self.ptr] = + (0xa3 << 24) + (a_reg << 16) + (b_reg << 8) + result_reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "shift" => { + self.memory[self.ptr] = + (0xa5 << 24) + (a_reg << 16) + (b_reg << 8) + result_reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + "and" => { + self.memory[self.ptr] = + (0xa6 << 24) + (a_reg << 16) + (b_reg << 8) + result_reg; + println!("{:X}: {:X}", self.ptr, self.memory[self.ptr]); + self.ptr += 1; + } + _ => { + panic!("Unknown Instruction: {:?}", command_parts) + } + } + } else { + match command_parts[0] { + "data" => match command_parts[1] { + "ascii" => { + self.labels + .insert(command_parts[2].replace(":", ""), self.ptr); + let data = command_parts + .iter() + .skip(3) + .map(|x| String::from(*x)) + .collect::>() + .join(" "); + for char in data.chars() { + self.memory[self.ptr] = char as u32; + self.ptr += 1; + } + self.memory[self.ptr] = 0x00; + self.ptr += 1; + } + _ => { + panic!("unknown type {}", command_parts[1]) + } + }, + _ => { + panic!("unknown command {}", command_parts[0]) + } + } + } + } + } + + fn parse_addr(&self, input: &str) -> u32 { + match u32::from_str_radix(input.replace("$", "").replace(":", "").as_str(), 16) { + Ok(addr) => { + return addr; + } + _ => match self.labels.get(input) { + Some(addr) => { + return addr.clone() as u32; + } + _ => { + panic!("Not a Hex Encoded Address {:?}", input) + } + }, + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..87ce3ad --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,230 @@ +pub mod assembler; + +pub const VRAM: usize = 640 * 480; +pub const REGISTER_PAGE: usize = VRAM; +pub const INPUT_PAGE: usize = VRAM + 64; +pub const OFFSET: usize = INPUT_PAGE; +pub const MEM_SIZE: usize = 65535; +pub const MEMORY: usize = OFFSET + MEM_SIZE; + +pub struct Machine { + pub memory: [u32; MEMORY], +} + +impl Machine { + pub fn new() -> Machine { + let mut memory = [0; MEMORY]; + + memory[REGISTER_PAGE] = 0x00; + + Machine { memory } + } + + pub fn load(&mut self, memory: [u32; MEMORY]) { + self.memory = memory; + self.memory[INPUT_PAGE] = 0x00; + } + + pub fn dump(&self) -> [u32; MEMORY] { + return self.memory; + } + + pub fn cycle(&mut self) { + let ip = self.memory[REGISTER_PAGE] as usize; + let instruction = self.memory[ip]; + self.memory[INPUT_PAGE] += 1; + + match instruction >> 28 { + 0x0 => { + match instruction >> 24 { + 0x00 => { + // NOP + } + 0x01 => { + self.memory[REGISTER_PAGE + 63] = 0x01; + } + 0x0F => { + println!("---"); + println!( + "REG 1:{:X} 2:{:X} 3:{:X} 4:{:X}", + self.memory[REGISTER_PAGE + 1], + self.memory[REGISTER_PAGE + 2], + self.memory[REGISTER_PAGE + 3], + self.memory[REGISTER_PAGE + 4] + ); + println!( + "REG 5:{:X} 6:{:X} 7:{:X} 8:{:X}", + self.memory[REGISTER_PAGE + 5], + self.memory[REGISTER_PAGE + 6], + self.memory[REGISTER_PAGE + 7], + self.memory[REGISTER_PAGE + 8], + ); + println!( + "REG 9:{:X} A:{:X} B:{:X} C:{:X}", + self.memory[REGISTER_PAGE + 9], + self.memory[REGISTER_PAGE + 10], + self.memory[REGISTER_PAGE + 11], + self.memory[REGISTER_PAGE + 12], + ); + + panic!("HLT"); + } + op => { + unimplemented!("0x0 Meta Instruction {}", op) + } + } + } + 0x1 => { + // STORE R(X) => ADDR + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let mem = instruction & 0x00FFFFFF; + self.memory[mem as usize] = self.memory[REGISTER_PAGE + input_reg]; + } + 0x2 => { + // LOAD ADDR => R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let mem = instruction & 0x00FFFFFF; + self.memory[REGISTER_PAGE + input_reg] = self.memory[mem as usize]; + } + 0x3 => { + // LOAD IMMEDIATE => R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let imm = instruction & 0x00FFFFFF; + self.memory[REGISTER_PAGE + input_reg] = imm; + } + 0x04 => { + // INC R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + self.memory[REGISTER_PAGE + input_reg] += 1; + } + 0x05 => { + // DEC R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + self.memory[REGISTER_PAGE + input_reg] -= 1; + } + 0x06 => { + // STORE Mem[R(In)] = R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let reg = (instruction & 0x000000FF) as usize; + let addr = self.memory[REGISTER_PAGE + reg] as usize; + self.memory[addr] = self.memory[REGISTER_PAGE + input_reg]; + } + 0x07 => { + // LOAD R(X) = MEM(R(In)) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let reg = (instruction & 0x000000FF) as usize; + self.memory[REGISTER_PAGE + reg] = + self.memory[self.memory[REGISTER_PAGE + input_reg] as usize]; + } + 0x08 => { + // TX R(In) => R(X) + let input_reg = ((instruction) >> 24 & 0x0F) as usize; + let reg = (instruction & 0x000000FF) as usize; + self.memory[REGISTER_PAGE + input_reg] = self.memory[REGISTER_PAGE + reg]; + } + 0x0A => { + match instruction >> 24 { + // ADD A B => C + 0xA1 => { + let a_reg = ((instruction & 0x00FF0000) >> 16) as usize; + let b_reg = ((instruction & 0x0000FF00) >> 8) as usize; + let dest_reg = (instruction & 0xFF) as usize; + let a = self.memory[REGISTER_PAGE + a_reg]; + let b = self.memory[REGISTER_PAGE + b_reg]; + let result = a + b; + self.memory[REGISTER_PAGE + dest_reg] = result; + } + // SUB A B => C + 0xA2 => { + let a_reg = ((instruction & 0x00FF0000) >> 16) as usize; + let b_reg = ((instruction & 0x0000FF00) >> 8) as usize; + let dest_reg = (instruction & 0xFF) as usize; + let a = self.memory[REGISTER_PAGE + a_reg]; + let b = self.memory[REGISTER_PAGE + b_reg]; + + let result = a - b; + self.memory[REGISTER_PAGE + dest_reg] = result; + } + // MUL A B => C + 0xA3 => { + let a_reg = ((instruction & 0x00FF0000) >> 16) as usize; + let b_reg = ((instruction & 0x0000FF00) >> 8) as usize; + let dest_reg = (instruction & 0xFF) as usize; + let a = self.memory[REGISTER_PAGE + a_reg]; + let b = self.memory[REGISTER_PAGE + b_reg]; + let result = a * b; + self.memory[REGISTER_PAGE + dest_reg] = result; + } + // RSHIFT A >> B => C + 0xA5 => { + let source_reg = ((instruction & 0x00FF0000) >> 16) as usize; + let bit_reg = ((instruction & 0x0000FF00) >> 8) as usize; + let dest_reg = (instruction & 0xFF) as usize; + let source = self.memory[REGISTER_PAGE + source_reg]; + let bits = self.memory[REGISTER_PAGE + bit_reg]; + let result = source >> bits; + self.memory[REGISTER_PAGE + dest_reg] = result; + } + // AND A & B => C + 0xA6 => { + let source_reg = ((instruction & 0x00FF0000) >> 16) as usize; + let mask_reg = ((instruction & 0x0000FF00) >> 8) as usize; + let dest_reg = (instruction & 0xFF) as usize; + let source = self.memory[REGISTER_PAGE + source_reg]; + let bits = self.memory[REGISTER_PAGE + mask_reg]; + let result = source & bits; + self.memory[REGISTER_PAGE + dest_reg] = result; + } + op => { + unimplemented!("0x0 Addition Instruction {}", op) + } + } + } + 0x0C => { + match instruction >> 24 { + // RET (Pops call stack and JMPs) + 0xC0 => { + let sp = self.memory[REGISTER_PAGE + 62] as usize; + self.memory[REGISTER_PAGE] = self.memory[REGISTER_PAGE + 62 - sp]; + self.memory[REGISTER_PAGE + 62] -= 1; + } + // CALL Addr (Pushed Addr and JMPS) + 0xC1 => { + self.memory[REGISTER_PAGE + 62] += 1; + let sp = self.memory[REGISTER_PAGE + 62] as usize; + self.memory[REGISTER_PAGE + 62 - sp] = self.memory[REGISTER_PAGE]; + let mem = instruction & 0x00FFFFFF; + self.memory[REGISTER_PAGE] = mem - 1; + } + op => { + unimplemented!("0x0 Call Strack Instruction {}", op) + } + } + } + 0x0E => { + match instruction >> 24 { + 0xE0 => { + // Unconditional JMP + let mem = instruction & 0x00FFFFFF; + self.memory[REGISTER_PAGE] = mem - 1; + } + 0xE2 => { + // JEQ ADDR if R(1) != R(2) + if self.memory[REGISTER_PAGE + 1] != self.memory[REGISTER_PAGE + 2] { + let mem = instruction & 0x00FFFFFF; + self.memory[REGISTER_PAGE] = mem - 1; + } + } + op => { + unimplemented!("0x0 JMP Instruction {}", op) + } + } + } + x => { + panic!("unknown bytecode opcode {:X} {:X} {:X}", x, ip, instruction) + } + } + self.memory[REGISTER_PAGE] += 1; + // + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ebb8c14 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,54 @@ +extern crate minifb; + +use minifb::{Key, Scale, Window, WindowOptions}; +use side::assembler::ImageAssembler; +use side::{Machine, REGISTER_PAGE}; +use std::env; + +//use font8x8::{BASIC_FONTS, UnicodeFonts}; + +const WIDTH: usize = 640; +const HEIGHT: usize = 360; + +fn main() { + // for font in BASIC_FONTS.iter().skip(0x20) { + // println!("label char_{}:", font.0); + // println!("\t${:02x}{:02x}{:02x}{:02x}", font.1[0],font.1[1],font.1[2],font.1[3]); + // println!("\t${:02x}{:02x}{:02x}{:02x}", font.1[4],font.1[5],font.1[6],font.1[7]); + // } + // return; + + let args: Vec = env::args().collect(); + + let mut machine = Machine::new(); + if args.len() == 3 { + match args[1].as_str() { + "assemble" => { + let mut ia = ImageAssembler::new(); + ia.assemble(&args[2]); + machine = ia.extract(); + } + _ => { + panic!("unknown command {}", args[1]) + } + } + } + + let mut opts = WindowOptions::default(); + opts.scale = Scale::X1; + let mut window = Window::new("Test - ESC to exit", WIDTH, HEIGHT, opts).unwrap_or_else(|e| { + panic!("{}", e); + }); + + while window.is_open() && !window.is_key_down(Key::Escape) { + machine.cycle(); + + if machine.memory[REGISTER_PAGE + 63] == 0x01 { + // We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different way + window + .update_with_buffer(&machine.memory, WIDTH, HEIGHT) + .unwrap(); + machine.memory[REGISTER_PAGE + 63] = 0x00; + } + } +} diff --git a/strings.asm b/strings.asm new file mode 100644 index 0000000..320167b --- /dev/null +++ b/strings.asm @@ -0,0 +1,144 @@ + label draw_char_pixels: + + shift 5 2 1; Shift 5 by count in R(2) + + loadi 6 1; + and 1 6 1; Mask with 0x01 + + loadi 6 $FFFFFF + mul 1 6 1; + + rstore 1 $B; Transfer RAX to the Address Stored in R11 + + inc $B; Increment VBuf Pointer + + inc 2; INC Scratch Pixel + loadi 1 8; For Every Pixel in this Row of 8 + jneq draw_char_pixels + ret + + label draw_char: + ldstore 4 3; Load Arg 1 in 3 + + loadi 6 $18; + shift 3 6 5; Shift To First Byte + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $10; + shift 3 6 5; Shift To Second Byte + loadi 6 $0000FF; + and 6 5 5; Mask Off + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $8; + shift 3 6 5; Shift To Third Byte + loadi 6 $0000FF; + and 6 5 5; + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $0; + shift 3 6 5; Shift To 4th Byte + loadi 6 $0000FF; + and 6 5 5; MASK off last Byte + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + inc 4; Move to Second Part + ldstore 4 3; Load Arg 1 in 3 + + loadi 6 $18; + shift 3 6 5; Shift To First Byte + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $10; + shift 3 6 5; Shift To Second Byte + loadi 6 $0000FF; + and 6 5 5; Mask Off + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $8; + shift 3 6 5; Shift To Third Byte + loadi 6 $0000FF; + and 6 5 5; + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + + loadi 6 $278 + add $6 $B $B ; Move VBUF + + loadi 6 $0; + shift 3 6 5; Shift To 4th Byte + loadi 6 $0000FF; + and 6 5 5; MASK off last Byte + loadi 2 0; Set Pixel to 8 + call draw_char_pixels + ret + + label _scratch_draw_string: + nop + + label draw_string: + label draw_next_char: + ldstore 4 3; Load Arg 1 in 3 + store 4 _scratch_draw_string + + loadi $2 $20 ; Load Addr of [SPACE] in $2 + sub $3 $2 $1 ; Sub the Character From Space + + loadi $2 2 + mul $1 $2 $1 ; Mull By 2 + + loadi $2 char_space + add $2 $1 $1 ; Add to Char Space + + tx $4 $1 + + call draw_char; Call draw_char + + loadi $2 8 + add $2 $9 $9; // X = X + 9 + call set_pos + + load $4 _scratch_draw_string + inc $4; + ldstore 4 3; Load Arg 1 in 3 + tx $2 $3 + loadi $1 0 + jneq draw_next_char + ret + +label num_to_char: + loadi $2 HEX_TABLE + add $2 $4 $4 + ldstore 4 3; Load Arg 1 in 3 + loadi $2 $20 ; Load Addr of [SPACE] in $2 + sub $3 $2 $1 ; Sub the Character From Space + loadi $2 2 + mul $1 $2 $1 ; Mull By 2 + loadi $2 char_space + add $2 $1 $1 ; Add to Char Space + tx $4 $1 + ret \ No newline at end of file diff --git a/util.asm b/util.asm new file mode 100644 index 0000000..1239f5c --- /dev/null +++ b/util.asm @@ -0,0 +1,39 @@ +label _scratch_print_var: + nop + +label print_addr: + ldstore 4 3; Load Arg 1 in 3 + store $3 _scratch_print_var ; preserve rax + loadi $7 $1C + + label print_rax_digit: + loadi $2 8 + add $2 $9 $9; // X = X + 9 + call set_pos + + load $3 _scratch_print_var + shift $3 $7 $4 + loadi $2 $00000F + and $2 $4 $4 + + call num_to_char; + call draw_char; + + loadi $2 4 + sub $7 $2 $7 + tx $2 $7 + loadi $1 0 + jneq print_rax_digit + + loadi $2 8 + add $2 $9 $9; // X = X + 9 + call set_pos + + load $3 _scratch_print_var + shift $3 $7 $4 + loadi $2 $00000F + and $2 $4 $4 + + call num_to_char; + call draw_char; + ret \ No newline at end of file