Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

187 changed files with 1714 additions and 5951 deletions

View file

@ -1,3 +1,3 @@
[alias]
repbuild = "run --manifest-path ./repbuild/Cargo.toml -- "
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
dev = "run --manifest-path ./dev/Cargo.toml -r --"

View file

@ -1,6 +1,4 @@
{
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"rust-analyzer.checkOnSave.allTargets": false,
"rust-analyzer.showUnlinkedFileNotification": false,
"C_Cpp.errorSquiggles": "disabled"

591
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
version = 3
[[package]]
name = "aarch64-cpu"
@ -13,15 +13,30 @@ dependencies = [
[[package]]
name = "allocator-api2"
version = "0.2.21"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.95"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
[[package]]
name = "autocfg"
@ -65,6 +80,15 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
dependencies = [
"allocator-api2",
]
[[package]]
name = "byteorder"
version = "1.5.0"
@ -73,9 +97,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.6"
version = "1.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
dependencies = [
"shlex",
]
@ -87,19 +111,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "derive_more"
@ -129,17 +173,6 @@ dependencies = [
"logos",
]
[[package]]
name = "displaydoc"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -164,6 +197,7 @@ checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0"
dependencies = [
"bitflags 1.3.2",
"byteorder",
"chrono",
"log",
]
@ -175,9 +209,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.4"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]]
name = "form_urlencoded"
@ -201,9 +235,15 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.2"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
dependencies = [
"allocator-api2",
"equivalent",
@ -213,174 +253,78 @@ dependencies = [
[[package]]
name = "hbbytecode"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
[[package]]
name = "hblang"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
dependencies = [
"hashbrown",
"hashbrown 0.15.0",
"hbbytecode",
"hbvm",
"log",
"regalloc2",
]
[[package]]
name = "hbvm"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#faa8dd2e6fabe2e0e4a375e677171856da491c61"
dependencies = [
"hbbytecode",
]
[[package]]
name = "icu_collections"
version = "1.5.0"
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "icu_locid"
version = "1.5.0"
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"displaydoc",
"litemap",
"tinystr",
"writeable",
"zerovec",
]
[[package]]
name = "icu_locid_transform"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
dependencies = [
"displaydoc",
"icu_locid",
"icu_locid_transform_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_locid_transform_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
[[package]]
name = "icu_properties"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
[[package]]
name = "icu_provider"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
dependencies = [
"displaydoc",
"icu_locid",
"icu_provider_macros",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_provider_macros"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"cc",
]
[[package]]
name = "idna"
version = "1.0.3"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"idna_adapter",
"smallvec",
"utf8_iter",
]
[[package]]
name = "idna_adapter"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
dependencies = [
"icu_normalizer",
"icu_properties",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "2.7.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.15.0",
]
[[package]]
name = "js-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
[[package]]
@ -390,9 +334,8 @@ dependencies = [
"aarch64-cpu",
"crossbeam-queue",
"derive_more",
"hashbrown",
"hashbrown 0.15.0",
"hbvm",
"ktest_macro",
"limine",
"log",
"sbi",
@ -401,18 +344,10 @@ dependencies = [
"uart_16550",
"versioning",
"x2apic",
"x86_64 0.15.2",
"x86_64 0.15.1",
"xml",
]
[[package]]
name = "ktest_macro"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -421,9 +356,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.169"
version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "limine"
@ -431,12 +366,6 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
[[package]]
name = "litemap"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "lock_api"
version = "0.4.12"
@ -455,18 +384,18 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "logos"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458"
checksum = "1c6b6e02facda28ca5fb8dbe4b152496ba3b1bd5a4b40bb2b1b2d8ad74e0f39b"
dependencies = [
"logos-derive",
]
[[package]]
name = "logos-codegen"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f"
checksum = "b32eb6b5f26efacd015b000bfc562186472cd9b34bdba3f6b264e2a052676d10"
dependencies = [
"beef",
"fnv",
@ -479,9 +408,9 @@ dependencies = [
[[package]]
name = "logos-derive"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d"
checksum = "3e5d0c5463c911ef55624739fc353238b4e310f0144be1f875dc42fec6bfd5ec"
dependencies = [
"logos-codegen",
]
@ -492,6 +421,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.20.2"
@ -512,18 +450,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.38"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
@ -546,6 +484,19 @@ dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "regalloc2"
version = "0.10.2"
source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#21c43e3ee182824e92e2b25f1d3c03ed47f9c02b"
dependencies = [
"allocator-api2",
"bumpalo",
"hashbrown 0.14.5",
"log",
"rustc-hash",
"smallvec",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
@ -582,6 +533,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "rustc-hash"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustc_version"
version = "0.4.1"
@ -593,9 +550,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.20"
version = "0.23.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993"
dependencies = [
"log",
"once_cell",
@ -608,9 +565,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.10.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]]
name = "rustls-webpki"
@ -625,9 +582,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.19"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "sbi"
@ -643,24 +600,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.24"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.217"
version = "1.0.213"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.217"
version = "1.0.213"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5"
dependencies = [
"proc-macro2",
"quote",
@ -706,12 +663,6 @@ dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "str-reader"
version = "0.1.2"
@ -726,9 +677,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.93"
version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"proc-macro2",
"quote",
@ -736,25 +687,19 @@ dependencies = [
]
[[package]]
name = "synstructure"
version = "0.13.1"
name = "tinyvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
dependencies = [
"proc-macro2",
"quote",
"syn",
"tinyvec_macros",
]
[[package]]
name = "tinystr"
version = "0.7.6"
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
dependencies = [
"displaydoc",
"zerovec",
]
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tock-registers"
@ -798,9 +743,9 @@ dependencies = [
[[package]]
name = "uart_16550"
version = "0.3.2"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d"
dependencies = [
"bitflags 2.6.0",
"rustversion",
@ -808,10 +753,25 @@ dependencies = [
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
name = "unicode-bidi"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-normalization"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-xid"
@ -827,9 +787,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.12.1"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a"
dependencies = [
"base64",
"log",
@ -842,27 +802,15 @@ dependencies = [
[[package]]
name = "url"
version = "2.5.4"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "versioning"
version = "0.1.3"
@ -884,14 +832,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "webpki-roots"
version = "0.26.7"
name = "wasm-bindgen"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "webpki-roots"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
@ -967,25 +979,13 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.6.21"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
dependencies = [
"memchr",
]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "x2apic"
version = "0.4.3"
@ -996,7 +996,7 @@ dependencies = [
"bitflags 1.3.2",
"paste",
"raw-cpuid 10.7.0",
"x86_64 0.14.13",
"x86_64 0.14.12",
]
[[package]]
@ -1012,9 +1012,9 @@ dependencies = [
[[package]]
name = "x86_64"
version = "0.14.13"
version = "0.14.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491"
checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062"
dependencies = [
"bit_field",
"bitflags 2.6.0",
@ -1024,9 +1024,9 @@ dependencies = [
[[package]]
name = "x86_64"
version = "0.15.2"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [
"bit_field",
"bitflags 2.6.0",
@ -1042,75 +1042,8 @@ dependencies = [
"serde",
]
[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
]
[[package]]
name = "yoke-derive"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zerofrom"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
dependencies = [
"yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -1,77 +0,0 @@
# Style Guide
This style guide has two modes that a guideline may be.
`strict` means that prs will be rejected if they do not follow the guideline.
`loose` means that a pr would be accepted but should later be fixed.
## Empty Functions | loose
Empty functions are typically a sign of an unfinished program or driver.
In cases where there is a clear reason to have an empty function it will be allowed.
For example FakeAlloc is only empty functions because it is a example of an the allocator api.
### Allowed
```rust
/// in example.hb
a := fn(): void {}
```
### Not Allowed
```rust
/// in fat32.hb
a := fn(): void {}
```
## Magic Functions | loose
'Magic functions' are what I am calling small helper functions that do one or two things.
### Example
```rust
a := null
magic_a := fn(){
a = 10
}
```
The exact policy I want to have here is a bit fuzzy. I think that functions like this are nice in certain situations and not in others.
Regardless of if you use them or not, put a comment above the function explaining rational.
## Magic Numbers | loose
The policy on magic numbers is make them const and have a comment above them. Typically linking to a source of information about the magic number.
This helps cut down on magic numbers while making acceptable names and atleast half assed documentation.
Constants are inlined anyways, so its the same thing in the binary.
```rust
// The standard vga port is mapped at 0xB8000
$VGA_PTR := 0xB8000
```
## Tabs Vs Spaces | strict
I prefer for hblang code to use hard tabs.
The rational behind this is that a tab is `1 Indent` which some developers might want to be various different sizes when displayed
Soft tabs do not allow this user/editor specific as soft tabs always become spaces.
Bottom line is this is an accessibility feature.
There are some samples below.
```
\t means hard tab
\n means new line
\0x20 means space
```
### Allowed
```rust
if x == y {\n
\tlog(z)\n
}\n
```
### Not Allowed
```rust
if x == y {\n
\0x20\0x20\0x20\0x20log(z)\n
}\n
```

View file

@ -1,96 +0,0 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1732014248,
"narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "23e89b7da85c3640bbc2173fe04f4bd114342367",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1732328983,
"narHash": "sha256-RHt12f/slrzDpSL7SSkydh8wUE4Nr4r23HlpWywed9E=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "ed8aa5b64f7d36d9338eb1d0a3bb60cf52069a72",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -1,30 +0,0 @@
{
description = "A devShell example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
in
with pkgs;
{
devShells.default = mkShell {
buildInputs = [
rustToolchain
qemu_full
];
};
}
);
}

View file

@ -3,15 +3,12 @@ edition = "2021"
name = "kernel"
version = "0.2.0"
[features]
ktest = []
[dependencies]
# embedded-graphics = "0.8"
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"nightly", "alloc", "disasm"
"nightly",
] }
ktest_macro = { path = "ktest_macro" }
log = "0.4"
spin = "0.9"
slab = { version = "0.4", default-features = false }
@ -27,6 +24,10 @@ version = "0.3"
default-features = false
features = ["alloc", "nightly"]
# [dependencies.clparse]
# git = "https://git.ablecorp.us/ableos/ableos_userland"
# default-features = false
[dependencies.derive_more]
version = "1"
default-features = false

View file

@ -1,11 +0,0 @@
[package]
edition = "2021"
name = "ktest_macro"
version = "0.1.0"
[lib]
proc-macro = true
[dependencies]
quote = "1.0.37"
syn = { version = "2.0.89", features = ["full"] }

View file

@ -1,86 +0,0 @@
extern crate proc_macro;
extern crate quote;
extern crate syn;
use {
proc_macro::TokenStream,
quote::quote,
syn::{parse::Parse, parse_macro_input, Expr, ItemFn, Token}
};
struct KtestInput {
lhs: Expr,
_comma: Token![,],
rhs: Expr,
}
impl Parse for KtestInput {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
Ok(Self {
lhs: input.parse()?,
_comma: input.parse()?,
rhs: input.parse()?,
})
}
}
#[proc_macro]
pub fn ktest_eq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs != #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro]
pub fn ktest_neq(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as KtestInput);
let lhs = input.lhs;
let rhs = input.rhs;
let out = quote! {
if #lhs == #rhs {
return Err(name);
}
};
TokenStream::from(out)
}
#[proc_macro_attribute]
pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
let test_name = &input.sig.ident;
let test_string = test_name.to_string();
let static_var_name = syn::Ident::new(
&format!("__ktest_{}", test_name).to_uppercase(),
test_name.span(),
);
let block = &input.block;
let out = quote! {
#[cfg(feature = "ktest")]
fn #test_name() -> Result<String, String> {
use crate::alloc::string::ToString;
let name = #test_string.to_string();
#block
return Ok(name);
}
#[cfg(feature = "ktest")]
#[unsafe(link_section = ".note.ktest")]
#[used]
pub static #static_var_name: fn() -> Result<String, String> = #test_name;
};
TokenStream::from(out)
}

View file

@ -6,11 +6,6 @@ SECTIONS
.text.boot : { *(.text.boot) }
.text : { *(.text) }
.data : { *(.data) }
.note.ktest : {
__ktest_start = .;
*(.note.ktest)
__ktest_end = .;
}
.rodata : { *(.rodata) }
.bss : {
*(COMMON)

View file

@ -38,15 +38,7 @@ SECTIONS
.data : {
*(.data .data.*)
*(.got .got.*)
} :data
/* Add the .ktest section for test functions */
.note.ktest : {
__ktest_start = .; /* Mark the beginning of the section */
*(.note.ktest) /* Include all items in the .ktest section */
__ktest_end = .; /* Mark the end of the section */
}
.bss : {
*(COMMON)

View file

@ -14,29 +14,3 @@ arch_cond!(
riscv64: "riscv64",
x86_64: "x86_64",
);
#[cfg(target_arch = "x86_64")]
use {crate::arch::interrupts::Interrupt, alloc::string::String};
#[cfg(target_arch = "x86_64")]
pub struct InterruptList {
list: HashMap<Interrupt, String>,
}
#[cfg(target_arch = "x86_64")]
use hashbrown::HashMap;
#[cfg(target_arch = "x86_64")]
impl InterruptList {
pub fn new() -> Self {
Self {
list: HashMap::new(),
}
}
}
#[cfg(target_arch = "x86_64")]
use spin::{Lazy, Mutex};
#[cfg(target_arch = "x86_64")]
pub static INTERRUPT_LIST: Lazy<Mutex<InterruptList>> = Lazy::new(|| {
let mut il = InterruptList::new();
use crate::alloc::string::ToString;
il.list.insert(Interrupt::Timer, "PS/2 Mouse".to_string());
Mutex::new(il)
});

View file

@ -11,9 +11,7 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
#[repr(u8)]
#[derive(Debug, Eq, Hash, PartialEq)]
pub enum Interrupt {
enum Interrupt {
Timer = 32,
ApicErr = u8::MAX - 1,
Spurious = u8::MAX,
@ -62,52 +60,17 @@ extern "x86-interrupt" fn page_fault(
}
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
interrupt(Interrupt::Timer);
unsafe {
LAPIC.end_of_interrupt();
}
}
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
interrupt(Interrupt::ApicErr);
panic!("Internal APIC error");
}
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
interrupt(Interrupt::Spurious);
unsafe {
LAPIC.end_of_interrupt();
}
}
#[allow(unused_imports)]
fn interrupt(interrupt_type: Interrupt) {
use crate::{arch::INTERRUPT_LIST, kmain::EXECUTOR};
// let il = INTERRUPT_LIST.lock();
// let val = il.list.get(&interrupt_type).unwrap();
// use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
// let buffer = sds_search_service(val);
// if buffer != 0 {
// use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
// let mut buffs = IPC_BUFFERS.lock();
// match buffs.get_mut(&buffer) {
// Some(buff) => {
// let mut msg_vec = Vec::new();
// msg_vec.push(0xFF);
// buff.push(msg_vec.to_vec());
// log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
// }
// None => {
// log::error!("Access of non-existent buffer {}", buffer)
// }
// }
// }
unsafe {
EXECUTOR.send_interrupt(interrupt_type as u8);
}
}

View file

@ -33,7 +33,7 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
#[cfg(not(target_feature = "avx2"))]
unsafe extern "C" fn _kernel_start() -> ! {
// Initialise SSE, then jump to kernel entrypoint
core::arch::naked_asm!(
core::arch::asm!(
// Initialise SSE
"mov rax, cr0",
"and ax, 0xfffb",
@ -46,6 +46,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
// Jump to the kernel entry point
"jmp {}",
sym start,
options(noreturn),
)
}
@ -53,7 +54,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
#[naked]
#[cfg(target_feature = "avx2")]
unsafe extern "C" fn _kernel_start() -> ! {
core::arch::naked_asm!(
core::arch::asm!(
// Enable protected mode and configure control registers
"mov rax, cr0",
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
@ -99,6 +100,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
"jmp {0}",
sym start,
sym oops,
options(noreturn),
)
}
@ -109,7 +111,7 @@ unsafe extern "C" fn oops() -> ! {
unsafe extern "C" fn start() -> ! {
logging::init();
crate::logger::init().expect("failed to set logger");
log::debug!("Initialising AKern {}", crate::VERSION);
log::info!("Initialising AKern {}", crate::VERSION);
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
memory::init_pt(VirtAddr::new(
@ -188,7 +190,7 @@ unsafe extern "C" fn start() -> ! {
// TODO: Add in rdseed and rdrand as sources for randomness
let _rand = xml::XMLElement::new("Random");
log::debug!("Getting boot modules");
log::trace!("Getting boot modules");
let bm = MOD_REQ.get_response().get();
let mut bootmodules = alloc::vec::Vec::new();
@ -226,7 +228,7 @@ unsafe extern "C" fn start() -> ! {
break;
}
}
log::debug!("Boot module count: {:?}", bootmodules.len());
log::info!("Boot module count: {:?}", bootmodules.len());
assert_eq!(bm.module_count, bootmodules.len() as u64);
}

View file

@ -69,7 +69,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
}
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
log::debug!("pci device-({}) addr {} is {}", device, addr, reg2);
log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
let pci_class = PciFullClass::from_u16(class);
let header_type = get_header_type(bus, device, 0);

View file

@ -1,17 +1,8 @@
//! Environment call handling routines
use {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address};
use crate::{
holeybytes::{
kernel_services::{
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
service_definition_service::sds_msg_handler,
},
ExecThread,
},
kmain::EXECUTOR,
task::Executor,
use crate::holeybytes::kernel_services::{
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
service_definition_service::sds_msg_handler,
};
use {
@ -33,7 +24,7 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
}
#[inline(always)]
pub fn handler(vm: &mut Vm, pid: &usize) {
pub fn handler(vm: &mut Vm) {
let ecall_number = vm.registers[2].cast::<u64>();
match ecall_number {
@ -67,10 +58,10 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
true => IpcBuffer::new(true, length),
},
);
info!("Buffer ID: {}", buff_id);
vm.registers[1] = hbvm::value::Value(buff_id);
}
2 => {
log::error!("Oops, deleting buffers is not implemented.")
// Delete buffer
}
3 => {
@ -80,10 +71,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let length = vm.registers[5].cast::<u64>() as usize;
trace!("IPC address: {:?}", mem_addr);
unsafe { LazyCell::<Executor>::get_mut(&mut EXECUTOR) }
.unwrap()
.send_buffer(buffer_id as usize);
match buffer_id {
0 => match sds_msg_handler(vm, mem_addr, length) {
Ok(()) => {}
@ -156,43 +143,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
Ok(()) => {}
Err(_) => log::error!("Improper dt query"),
},
6 => unsafe {
let program = block_read(mem_addr, length);
// decode AbleOS Executable format
let header = &program[0..46];
let magic_slice = &header[0..3];
if magic_slice != [0x15, 0x91, 0xD2] {
log::error!("Invalid magic number at the start of executable.");
return;
}
let executable_format_version =
u32::from_le_bytes(header[3..7].try_into().unwrap());
let offset = if executable_format_version == 0 {
47
} else {
error!("Invalid executable format.");
return;
};
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::debug!("{code_length} + {data_length} = {end}");
let thr = ExecThread::new(&program[offset..end], Address::new(0));
vm.registers[1] = Value(
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.spawn(Box::pin(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
})) as u64,
);
log::debug!("spawned a process");
},
buffer_id => {
let mut buffs = IPC_BUFFERS.lock();
@ -213,6 +163,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let buffer_id = vm.registers[3].cast::<u64>();
let map_ptr = vm.registers[4].cast::<u64>();
let max_length = vm.registers[5].cast::<u64>();
let mut buffs = IPC_BUFFERS.lock();
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
Some(buff) => buff,
@ -231,7 +182,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
} else {
unsafe {
let ptr = map_ptr as *mut u8;
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
ptr.copy_from(msg.as_ptr(), msg.len());
}
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
@ -246,28 +197,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
vm.registers[3] = x
}
}
6 => {
// Wait till interrupt
use crate::kmain::EXECUTOR;
let interrupt_type = vm.registers[3].cast::<u8>();
debug!("Interrupt subscribed: {}", interrupt_type);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.interrupt_subscribe(*pid, interrupt_type);
}
}
7 => {
// Wait till buffer
use crate::kmain::EXECUTOR;
let buffer_id = vm.registers[3].cast::<u64>() as usize;
debug!("Buffer subscribed: {}", buffer_id);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.buffer_subscribe(*pid, buffer_id);
}
}
_ => {
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
}

View file

@ -9,20 +9,7 @@ use log::Record;
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
let msg_vec = block_read(mem_addr, length);
use log::Level::*;
let log_level = match msg_vec[0] {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
if log_level > log::max_level() {
return Ok(());
}
let log_level = msg_vec[0];
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
@ -33,6 +20,18 @@ pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(),
match core::str::from_utf8(&str) {
Ok(strr) => {
use log::Level::*;
let log_level = match log_level {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
log::logger().log(
&Record::builder()
.args(format_args!("{}", strr))

View file

@ -25,16 +25,42 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
}
#[inline(always)]
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
let total_size = count * size;
src.copy_to_nonoverlapping(dest, size);
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
const BLOCK_SIZE: usize = 64;
let mut remaining = count * size;
let mut copied = size;
if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
while copied < total_size {
let copy_size = copied.min(total_size - copied);
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
copied += copy_size;
let mut buffer = [0u8; BLOCK_SIZE];
let mut buffer_size = size;
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
buffer
.as_mut_ptr()
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
buffer_size *= 2;
}
let buffer_ptr = buffer.as_ptr() as *const u64;
while (dest as usize) & 7 != 0 && remaining >= 8 {
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
dest = dest.add(1);
remaining -= 1;
}
while core::intrinsics::likely(remaining >= 8) {
*(dest as *mut u64) = *buffer_ptr;
dest = dest.add(8);
remaining -= 8;
}
if remaining > 0 {
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
}
}
@ -48,24 +74,29 @@ pub fn memory_msg_handler(
let msg_type = msg_vec[0];
match msg_type {
0 => unsafe {
let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize;
let page_count = msg_vec[1];
let ptr = alloc(Layout::from_size_align_unchecked(page_count * 4096, 1));
let ptr = alloc(Layout::from_size_align_unchecked(
page_count as usize * 4096,
8,
));
log::debug!("Allocating {} pages @ {:?}", page_count, ptr);
log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
vm.registers[1] = hbvm::value::Value(ptr as u64);
log::debug!("Kernel ptr: {:x}", ptr as u64);
},
1 => unsafe {
let page_count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap()) as usize;
let page_count = msg_vec[1];
let mptr = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as *mut u8;
log::debug!("Deallocating {} pages @ {:?}", page_count, mptr);
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
let mptr: u64 = u64::from_le_bytes(mptr_raw);
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
dealloc(
mptr,
Layout::from_size_align_unchecked(page_count * 4096, 1),
mptr as *mut u8,
Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
)
},
2 => {
@ -91,21 +122,18 @@ pub fn memory_msg_handler(
log::debug!(" {} pages", page_count);
}
4 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[5..13].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[13..21].try_into().unwrap_unchecked()) as *mut u8;
src.copy_to_nonoverlapping(dest, count);
},
5 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
let size = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as usize;
let src =
u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[25..33].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let size = u32::from_le_bytes(msg_vec[5..9].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
memset(dest, src, count, size);
},
_ => {

View file

@ -92,7 +92,8 @@ fn sds_create_service(protocol: &'static str) -> u64 {
// let a: protocol::Protocol = protocol.into();
buff_id
}
pub fn sds_search_service(protocol: &str) -> u64 {
fn sds_search_service(protocol: &str) -> u64 {
let services = SERVICES.lock();
let compare = Protocol::from(protocol);
for (bid, protocol_canidate) in &services.0 {

View file

@ -15,10 +15,8 @@ fn calc_start_of_page(ptr: u64) -> u64 {
panic!("unaligned");
}
#[derive(Default)]
pub struct Memory {
// TODO: map page aligned segments of memory into a table or some sort here
logger: hbvm::mem::InstrLogger,
}
impl Memory {
@ -58,11 +56,4 @@ impl hbvm::mem::Memory for Memory {
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
(addr.get() as *const T).read()
}
#[inline(always)]
fn log_instr(&mut self, _at: Address, _regs: &[hbvm::value::Value]) {
// log::debug!("exec: [{:02x}] {}", at.get(), unsafe {
// self.logger.display_instr(at, regs)
// });
}
}

View file

@ -1,5 +1,5 @@
mod ecah;
pub mod kernel_services;
mod kernel_services;
mod mem;
use {
@ -36,7 +36,7 @@ impl ExecThread {
pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self {
let mut vm = Vm::new(
mem::Memory::default(),
mem::Memory {},
Address::new(program.as_ptr() as u64 + entrypoint.get()),
);
@ -65,12 +65,7 @@ impl<'p> Future for ExecThread {
return Poll::Ready(Err(err));
}
Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
Ok(VmRunOk::Ecall) => ecah::handler(
&mut self.vm,
cx.ext()
.downcast_ref()
.expect("PID did not exist in Context"),
),
Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm),
Ok(VmRunOk::Timer) => (),
Ok(VmRunOk::Breakpoint) => {
log::error!(

View file

@ -8,10 +8,7 @@ use {
device_tree::DeviceTree,
holeybytes::ExecThread,
ipc::buffer::IpcBuffer,
task::Executor,
},
alloc::boxed::Box,
core::cell::LazyCell,
hashbrown::HashMap,
hbvm::mem::Address,
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
@ -22,18 +19,6 @@ use {
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
debug!("Entered kmain");
#[cfg(feature = "ktest")]
{
use {
crate::ktest,
log::info,
};
info!("Running tests");
ktest::test_main();
loop {}
}
// let kcmd = build_cmd("Kernel Command Line", cmdline);
// trace!("Cmdline: {kcmd:?}");
@ -79,26 +64,14 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
"Graphics front ptr {:?}",
fb1.address.as_ptr().unwrap() as *const u8
);
log::info!("Started AbleOS");
let mut executor = crate::task::Executor::new(256);
unsafe {
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
for module in boot_modules.iter() {
let cmd = module.cmd.trim_matches('"');
let cmd_len = cmd.len() as u64;
log::info!(
"Starting {}",
module
.path
.split('/')
.last()
.unwrap()
.split('.')
.next()
.unwrap()
);
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
// decode AbleOS Executable format
let header = &module.bytes[0..46];
@ -119,30 +92,27 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::debug!("{code_length} + {data_length} = {end}");
log::info!("{code_length} + {data_length} = {end}");
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
if cmd_len > 0 {
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
}
executor.spawn(Box::pin(async {
executor.spawn(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
}));
})
}
debug!("Random number: {}", hardware_random_u64());
executor.run();
};
crate::arch::spin_loop()
}
// ! SAFETY: this is not threadsafe at all, like even a little bit.
// ! SERIOUSLY
pub static mut EXECUTOR: LazyCell<Executor> = LazyCell::new(|| Executor::new());
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
let dt = DeviceTree::new();
Mutex::new(dt)
@ -160,3 +130,10 @@ pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
Mutex::new(bufs)
});
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

View file

@ -1,51 +0,0 @@
pub use ktest_macro::*;
use {
alloc::string::String,
log::{error, info},
};
extern "C" {
static __ktest_start: fn() -> Result<String, String>;
static __ktest_end: fn() -> Result<String, String>;
}
// TODO: Implement ktest for arm and riscv (Later problems, see below)
// Allow for arch specific tests (Leave for now)
// Should panic tests
// Test specific panic handler
pub fn test_main() {
unsafe {
let mut current_test = &__ktest_start as *const fn() -> Result<String, String>;
let test_end = &__ktest_end as *const fn() -> Result<String, String>;
let mut pass = 0;
let mut fail = 0;
while current_test < test_end {
let test_fn = *current_test;
let test_name = test_fn();
match test_name {
Ok(name) => {
info!("Test: {} passed", name);
pass += 1;
},
Err(name) => {
error!("Test: {} failed", name);
fail += 1;
}
}
current_test = current_test.add(1);
}
info!("{}/{} tests passed", pass, pass + fail);
}
}
#[ktest]
pub fn trivial_assertion() {
ktest_eq!(1, 1);
ktest_neq!(0, 1);
}

View file

@ -2,21 +2,20 @@
//! Named akern.
//! Akern is woefully undersupported at the moment but we are looking to add support improve hardware discovery and make our lives as kernel and operating system developers easier and better
#![no_std]
#![no_main]
#![feature(
slice_split_once,
exclusive_wrapper,
new_uninit,
core_intrinsics,
abi_x86_interrupt,
lazy_get,
alloc_error_handler,
local_waker,
context_ext,
ptr_sub_ptr,
custom_test_frameworks,
naked_functions,
pointer_is_aligned_to
)]
#![allow(dead_code, internal_features, static_mut_refs)]
#![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features)]
extern crate alloc;
mod allocator;
@ -34,9 +33,6 @@ mod memory;
mod task;
mod utils;
#[allow(improper_ctypes, non_upper_case_globals)]
mod ktest;
use versioning::Version;
/// Kernel's version
@ -49,7 +45,6 @@ pub const VERSION: Version = Version {
#[panic_handler]
#[cfg(target_os = "none")]
fn panic(info: &core::panic::PanicInfo) -> ! {
use alloc::string::ToString;
arch::register_dump();
if let Some(loc) = info.location() {
@ -61,7 +56,15 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
));
}
let msg = info.message().to_string().replace("\n", "\r\n");
let msg = info.message();
let _ = crate::arch::log(format_args!("{msg}\r\n"));
loop {}
}
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

@ -36,26 +36,13 @@ impl log::Log for Logger {
Level::Debug => "25",
Level::Trace => "103",
};
let module = record
.module_path()
.unwrap_or_default()
.rsplit_once(':')
.unwrap_or_default()
.1;
if module == "" {
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
record.args(),
))
.expect("write to serial console");
} else {
let line = record.line().unwrap_or_default();
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
record.args(),
))
.expect("write to serial console");
}
let module = record.module_path().unwrap_or_default();
let line = record.line().unwrap_or_default();
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
record.args(),
))
.expect("write to serial console");
}
fn flush(&self) {}

View file

@ -1,14 +1,9 @@
use {
alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
sync::Arc,
},
alloc::{boxed::Box, sync::Arc},
core::{
future::Future,
pin::Pin,
sync::atomic::{AtomicBool, Ordering},
task::{Context, ContextBuilder, Poll, RawWaker, RawWakerVTable, Waker},
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
},
crossbeam_queue::SegQueue,
slab::Slab,
@ -19,6 +14,7 @@ pub fn yield_now() -> impl Future<Output = ()> {
impl Future for YieldNow {
type Output = ();
#[inline(always)]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 {
Poll::Ready(())
@ -33,184 +29,150 @@ pub fn yield_now() -> impl Future<Output = ()> {
YieldNow(false)
}
pub trait Process: Future<Output = ()> + Send {}
impl<T: Future<Output = ()> + Send> Process for T {}
pub struct Executor {
tasks: Slab<Task>,
task_queue: Arc<SegQueue<usize>>,
interrupt_lookup: [Option<usize>; u8::MAX as usize],
buffer_lookup: BTreeMap<usize, BTreeSet<usize>>,
pub struct Executor<F: Future<Output = ()> + Send> {
tasks: Slab<Task<F>>,
task_queue: Arc<TaskQueue>,
}
impl Executor {
pub fn new() -> Self {
impl<F: Future<Output = ()> + Send> Executor<F> {
pub fn new(size: usize) -> Self {
Self {
tasks: Slab::new(),
task_queue: Arc::new(SegQueue::new()),
interrupt_lookup: [None; u8::MAX as usize],
buffer_lookup: BTreeMap::new(),
tasks: Slab::with_capacity(size),
task_queue: Arc::new(TaskQueue::new()),
}
}
pub fn spawn(&mut self, future: Pin<Box<dyn Process>>) -> usize {
let id = self.tasks.insert(Task::new(future));
self.task_queue.push(id);
id
}
pub fn pause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(true);
}
}
pub fn unpause(&self, id: usize) {
if let Some(task) = self.tasks.get(id) {
task.set_paused(false);
self.task_queue.push(id);
}
}
pub fn interrupt_subscribe(&mut self, pid: usize, interrupt_type: u8) {
self.pause(pid);
self.interrupt_lookup[interrupt_type as usize] = Some(pid);
}
pub fn buffer_subscribe(&mut self, pid: usize, buffer_id: usize) {
self.pause(pid);
if let Some(buf) = self.buffer_lookup.get_mut(&buffer_id) {
buf.insert(pid);
} else {
self.buffer_lookup.insert(buffer_id, BTreeSet::from([pid]));
}
#[inline]
pub fn spawn(&mut self, future: F) {
self.task_queue
.queue
.push(self.tasks.insert(Task::new(future)));
}
pub fn run(&mut self) {
let mut task_batch = [0; 32];
loop {
let mut batch_len = 0;
let mut batch_len = 0;
while let Some(id) = self.task_queue.pop() {
task_batch[batch_len] = id;
batch_len += 1;
if batch_len == task_batch.len() {
loop {
self.task_queue.batch_pop(&mut task_batch, &mut batch_len);
if batch_len == 0 {
if self.task_queue.is_empty() {
break;
} else {
continue;
}
}
if batch_len == 0 {
// break;
continue;
}
for &(mut id) in &task_batch[..batch_len] {
for &id in &task_batch[..batch_len] {
if let Some(task) = self.tasks.get_mut(id) {
if task.is_paused() {
continue;
}
let waker = task
.waker
.get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue)));
let waker = create_waker(id, Arc::clone(&self.task_queue));
let mut cx = ContextBuilder::from_waker(&waker).ext(&mut id).build();
let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) };
let mut cx = Context::from_waker(&waker);
if let Poll::Ready(()) = task.poll(&mut cx) {
self.tasks.remove(id);
self.interrupt_lookup.map(|pid| {
if let Some(pid) = pid {
if pid == id {
return None;
}
}
return pid;
});
self.buffer_lookup.iter_mut().for_each(|(_, pid_set)| {
pid_set.remove(&id);
});
self.task_queue.free_tasks.push(id);
}
}
}
}
}
pub fn send_interrupt(&self, interrupt: u8) {
let id = self.interrupt_lookup[interrupt as usize];
if let Some(id) = id {
self.unpause(id);
}
}
pub fn send_buffer(&self, id: usize) {
if let Some(buf) = self.buffer_lookup.get(&id) {
buf.iter().for_each(|pid| self.unpause(*pid));
}
}
}
struct Task {
future: Pin<Box<dyn Process>>,
paused: AtomicBool,
struct Task<F: Future<Output = ()> + Send> {
future: Pin<Box<F>>,
waker: Option<TaskWaker>,
}
impl Task {
fn new(future: Pin<Box<dyn Process>>) -> Self {
impl<F: Future<Output = ()> + Send> Task<F> {
#[inline(always)]
pub fn new(future: F) -> Self {
Self {
future,
paused: AtomicBool::new(false),
future: Box::pin(future),
waker: None,
}
}
#[inline(always)]
fn poll(&mut self, cx: &mut Context) -> Poll<()> {
self.future.as_mut().poll(cx)
}
fn is_paused(&self) -> bool {
self.paused.load(Ordering::Acquire)
}
fn set_paused(&self, paused: bool) {
self.paused.store(paused, Ordering::Release)
}
}
fn create_waker(task_id: usize, task_queue: Arc<SegQueue<usize>>) -> Waker {
let data = Box::new(TaskWaker {
task_id,
task_queue,
});
let raw_waker = RawWaker::new(Box::into_raw(data) as *const (), &VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
#[derive(Clone)]
struct TaskWaker {
task_id: usize,
task_queue: Arc<SegQueue<usize>>,
id: usize,
task_queue: Arc<TaskQueue>,
}
impl TaskWaker {
#[inline(always)]
fn new(id: usize, task_queue: Arc<TaskQueue>) -> Self {
Self { id, task_queue }
}
#[inline(always)]
fn wake(&self) {
self.task_queue.push(self.task_id);
self.task_queue.queue.push(self.id);
}
fn into_raw_waker(waker: &TaskWaker) -> RawWaker {
let ptr = waker as *const TaskWaker;
RawWaker::new(ptr.cast(), &VTABLE)
}
}
const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw);
unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
let task_waker = Box::from_raw(ptr as *mut TaskWaker);
let raw_waker = RawWaker::new(Box::into_raw(task_waker.clone()) as *const (), &VTABLE);
raw_waker
let waker = &*(ptr as *const TaskWaker);
TaskWaker::into_raw_waker(waker)
}
unsafe fn wake_raw(ptr: *const ()) {
let task_waker = Box::from_raw(ptr as *mut TaskWaker);
task_waker.wake();
let waker = &*(ptr as *const TaskWaker);
waker.wake();
}
unsafe fn wake_by_ref_raw(ptr: *const ()) {
let task_waker = &*(ptr as *const TaskWaker);
task_waker.wake();
let waker = &*(ptr as *const TaskWaker);
waker.wake();
}
unsafe fn drop_raw(ptr: *const ()) {
drop(Box::from_raw(ptr as *mut TaskWaker));
unsafe fn drop_raw(_: *const ()) {}
struct TaskQueue {
queue: SegQueue<usize>,
next_task: usize,
free_tasks: SegQueue<usize>,
}
impl TaskQueue {
fn new() -> Self {
Self {
queue: SegQueue::new(),
next_task: 0,
free_tasks: SegQueue::new(),
}
}
#[inline(always)]
fn batch_pop(&self, output: &mut [usize], len: &mut usize) {
*len = 0;
while let Some(id) = self.queue.pop() {
output[*len] = id;
*len += 1;
if *len == output.len() {
break;
}
}
}
#[inline(always)]
fn is_empty(&self) -> bool {
self.queue.is_empty()
}
}

View file

@ -1,25 +1,25 @@
{
"arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
"disable-redzone": true,
"env": "",
"executables": true,
"features": "+strict-align,+neon,+fp-armv8",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"linker-is-gnu": true,
"pre-link-args": {
"ld.lld": [
"-Tkernel/lds/aarch64-qemu.ld"
]
},
"llvm-target": "aarch64-unknown-none",
"max-atomic-width": 128,
"os": "none",
"panic-strategy": "abort",
"relocation-model": "static",
"target-c-int-width": "32",
"target-endian": "little",
"target-pointer-width": "64",
"vendor": "ablecorp"
"arch": "aarch64",
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
"disable-redzone": true,
"env": "",
"executables": true,
"features": "+strict-align,+neon,+fp-armv8",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"linker-is-gnu": true,
"pre-link-args": {
"ld.lld": [
"-Tkernel/lds/aarch64-qemu.ld"
]
},
"llvm-target": "aarch64-unknown-none",
"max-atomic-width": 128,
"os": "none",
"panic-strategy": "abort",
"relocation-model": "static",
"target-c-int-width": "32",
"target-endian": "little",
"target-pointer-width": "64",
"vendor": ""
}

View file

@ -6,16 +6,29 @@ edition = "2021"
[dependencies]
str-reader = "0.1"
derive_more = { version = "1", default-features = false, features = [
"add",
"add_assign",
"constructor",
"display",
"from",
"into",
"mul",
"mul_assign",
"not",
"sum",
] }
error-stack = "0.5"
fatfs = { version = "0.3", default-features = false, features = [
"std",
"alloc",
] }
fatfs = "0.3"
toml = "0.8"
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
# hblang.path = "../../holey-bytes/lang/"
hblang = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"std",
"opts",
], default-features = false }
log = "0.4"
raw-cpuid = "11"
ureq = { version = "2", default-features = false, features = ["tls"] }
# [dependencies.reqwest]
# version = "0.12"
# default-features = false
# features = ["rustls-tls", "blocking"]

View file

@ -1,6 +1,5 @@
#![allow(unused)]
use std::{
collections::HashMap,
fmt::format,
fs::{read_to_string, File},
io::{BufWriter, Write},
@ -14,7 +13,6 @@ pub struct Package {
name: String,
binaries: Vec<String>,
build_cmd: String,
args: HashMap<String, String>,
}
impl Package {
@ -48,47 +46,48 @@ impl Package {
let mut binaries = vec![];
for (count, (name, table)) in bin_table.into_iter().enumerate() {
// if count != 0 {
println!("{}", name);
binaries.push(name.clone());
// }
}
let build_table = data.get("build").unwrap();
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
build_cmd.remove(0);
let mut args: HashMap<String, String> = match build_table.get("args") {
None => HashMap::new(),
Some(v) => v
.as_table()
.unwrap()
.into_iter()
.map(|(k, v)| (k.clone(), v.to_string()))
.collect::<HashMap<String, String>>(),
};
// build_cmd.pop();
Self {
name,
binaries,
build_cmd,
args,
}
}
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
pub fn build(&self) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
let path = format!("sysdata/programs/{}/{}", self.name, file);
// compile here
let mut warnings = String::new();
let path = format!("sysdata/programs/{}/{}", self.name, file);
let mut bytes = Vec::new();
// compile here
hblang::run_compiler(
&path,
Options {
fmt: true,
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
optimize: true,
..Default::default()
},
out,
&mut warnings,
&mut bytes,
)?;
hblang::run_compiler(
&path,
Options {
optimize: true,
..Default::default()
},
&mut bytes,
)?;
match std::fs::create_dir("target/programs") {
@ -96,33 +95,18 @@ impl Package {
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
Err(e) => panic!("{}", e),
}
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
bytes.clear();
hblang::run_compiler(
&path,
Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
..Default::default()
},
out,
&mut warnings,
)?;
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
out.clear();
let err = hblang::run_compiler(
&path,
Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
dump_asm: true,
optimize: true,
..Default::default()
},
out,
&mut warnings,
);
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
out.clear();
return err;
&mut bytes,
)?;
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
}
Ok(())
}

View file

@ -1,7 +1,6 @@
mod dev;
use {
core::fmt::Write as _,
derive_more::Display,
dev::Package,
error_stack::{bail, report, Context, Report, Result, ResultExt},
@ -27,7 +26,6 @@ fn main() -> Result<(), Error> {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
for arg in args {
if arg == "-r" || arg == "--release" {
release = true;
@ -39,42 +37,17 @@ fn main() -> Result<(), Error> {
target = Target::Aarch64;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo, tests).change_context(Error::Build)
build(release, target, debuginfo).change_context(Error::Build)
}
// Some("test" | "t") => {
// let mut release = false;
// let mut debuginfo = false;
// let mut target = Target::X86_64;
// for arg in args {
// if arg == "-r" || arg == "--release" {
// release = true;
// } else if arg == "-d" || arg == "--debuginfo" {
// debuginfo = true;
// } else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
// target = Target::Riscv64Virt;
// } else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
// target = Target::Aarch64;
// } else if arg == "avx2" {
// target = Target::X86_64Avx2;
// } else {
// return Err(report!(Error::InvalidSubCom));
// }
// }
// test(release, target, debuginfo).change_context(Error::Build)
// }
Some("run" | "r") => {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
let mut do_accel = true;
for arg in args {
if arg == "-r" || arg == "--release" {
@ -89,14 +62,12 @@ fn main() -> Result<(), Error> {
do_accel = false;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo, tests)?;
build(release, target, debuginfo)?;
run(release, target, do_accel)
}
Some("help" | "h") => {
@ -110,7 +81,6 @@ fn main() -> Result<(), Error> {
" -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\n",
" --noaccel: run without acceleration (e.g, no kvm)\n",
" --ktest: Enables tests via ktest\n",
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
),);
Ok(())
@ -234,9 +204,6 @@ TERM_BACKDROP={}
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
// let mut real_modules = modules.clone();
let mut errors = String::new();
let mut out = Vec::new();
modules
.into_iter()
.map(|(_, value)| -> Result<(), io::Error> {
@ -251,26 +218,11 @@ TERM_BACKDROP={}
let p = Package::load_from_file(
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
);
match p.build(&mut out) {
Ok(()) => {}
Err(e) => {
writeln!(errors, "========= while compiling {} {} =========", path, e)
.unwrap();
errors.push_str(&String::from_utf8_lossy(&out));
out.clear();
}
}
p.build()?;
}
Ok(())
})
.for_each(drop);
if !errors.is_empty() {
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
std::eprint!("{errors}");
continue;
}
modules.into_iter().for_each(|(_key, value)| {
if value.is_table() {
let path = value.get("path").expect("You must have `path` as a value");
@ -339,7 +291,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
.expect("Copy failed");
}
fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<(), Error> {
fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
let fs = get_fs().change_context(Error::Io)?;
let mut com = Command::new("cargo");
com.current_dir("kernel");
@ -351,10 +303,6 @@ fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
}
if tests {
com.args(["--features", "ktest"]);
}
if target == Target::Riscv64Virt {
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
}
@ -411,7 +359,6 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
};
let (mut com, mut com2) = (Command::new(target_str), Command::new(target_str));
let ovmf_path = fetch_ovmf(target);
#[cfg(target_arch = "x86_64")]
let accel = if do_accel {
let supported = String::from_utf8(
com2.args(["--accel", "help"])
@ -447,24 +394,16 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
} else {
"accel=tcg"
};
#[cfg(not(target_arch = "x86_64"))]
let accel = "accel=tcg";
match target {
Target::X86_64 | Target::X86_64Avx2 => {
#[rustfmt::skip]
com.args([
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
//"-hda", "target/disk.img",
"-drive", "file=target/disk.img,index=0,if=ide,format=raw",
"-drive", "file=target/disk.img,format=raw",
"-device", "vmware-svga",
// "-serial", "stdio",
"-m", "2G",
"-smp", "1",
"-audiodev",
"pa,id=speaker",
"-machine",
"pcspk-audiodev=speaker",
"-parallel", "none",
"-monitor", "none",
"-machine", accel,
@ -490,7 +429,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip]
com.args([
"-M", "virt",
"-cpu", "max",
"-cpu", "neoverse-n2",
"-device", "ramfb",
"-device", "qemu-xhci",
"-device", "usb-kbd",

View file

@ -1,7 +1,3 @@
[toolchain]
# old toolchain
# channel = "nightly-2024-07-27"
# last stable
# channel = "nightly-2024-11-20"
channel = "nightly"
channel = "nightly-2024-07-27"
components = ["rust-src", "llvm-tools"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +0,0 @@
(horizontal
spacing : 10
(label "hi")
(label "goodbye"))

View file

@ -1 +0,0 @@
(label "hello")

View file

@ -1,3 +0,0 @@
(vertical
(label "hello")
(label "hello" color:red))

View file

@ -5,37 +5,42 @@ render := @use("../../../libraries/render/src/lib.hb")
input := @use("../../intouch/src/lib.hb")
widgets := @use("widgets/widgets.hb")
ui := @use("ui.hb")
widgets := @use("widgets.hb")
WindowID := struct {
host_id: uint,
window_id: uint,
host_id: int,
window_id: int,
}
VoidWindowID := WindowID.(0, 0)
create_window := fn(channel: uint): ^render.Surface {
create_window := fn(channel: int): ^render.Surface {
// get the horizon buffer
// request a new window and provide the callback buffer
// wait to recieve a message
windowing_system_buffer := buffer.search("XHorizon")
windowing_system_buffer := buffer.search("XHorizon\0")
mem_buf := memory.request_page(1)
if windowing_system_buffer == 0 {
return @as(^render.Surface, idk)
} else {
// ! bad able, stop using string messages :ragey:
// msg := "\{01}\0"
// msg_length := 2
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
x := 0
loop if x > 1000 break else x += 1
ret := buffer.recv([4096]u8, windowing_system_buffer, mem_buf)
if ret == null {
log.info("No messages")
ret := buffer.recv([u8; 4096], windowing_system_buffer, mem_buf)
if ret == 0 {
log.info("No messages\0")
}
if *mem_buf == 0 {
log.info("No messages")
log.info("No messages\0")
}
return @as(^render.Surface, idk)

View file

@ -1,44 +0,0 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
UI := struct {raw: []u8, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
// children: ^^u8,
}
render_ui := fn(surface: Surface, ui: UI): void {
if ui.is_dirty {
render.clear(ui.surface, render.black)
ui.is_dirty = false
}
pos := Vec2(uint).(0, 0)
render.put_surface(surface, ui.surface, pos, false)
}
sexpr_parser := fn(sexpr: []u8): UI {
i := 0
paren_balance := 0
loop {
if i == sexpr.len {
if paren_balance != 0 {
log.error("Unbalanced Parens")
}
break
} else if sexpr[i] == '(' {
log.info("Open paren")
paren_balance += 1
} else if sexpr[i] == ')' {
log.info("Closed paren")
paren_balance -= 1
}
i += 1
}
ui_surface := render.new_surface(100, 100)
return UI.(sexpr, true, ui_surface)
}

View file

@ -0,0 +1,20 @@
// Widget types
// End types
LayoutChildHorizontalFirst := 0
LayoutChildVerticalFirst := 1
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Widget := struct {
size: Size,
clickable: bool,
layout: u8,
a: bool,
}

View file

@ -1,13 +0,0 @@
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render
Image := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
}
image_from_surface := fn(surface: Surface): Image {
img := Image.(4, true, surface)
return img
}

View file

@ -1,41 +0,0 @@
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface, Color} := render;
.{Font} := render.text
Label := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
text: []u8,
bg: Color,
fg: Color,
new_label := fn(text: []u8, width: uint): Self {
text_surface := render.Surface.new(width, 20)
label := Self.(3, true, text_surface, text, render.BLACK, render.WHITE)
return label
}
$set_label_text := fn(self: ^Self, text: []u8): void {
self.is_dirty = true
self.text = text
}
$set_color := fn(self: ^Self, bg: Color, fg: Color): void {
self.bg = bg
self.fg = fg
self.is_dirty = true
}
}
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
if label.is_dirty {
label.surface.clear(label.bg)
label.surface.put_text(font, .(0, 0), label.fg, label.text)
}
surface.put_surface(label.surface, pos, false)
}

View file

@ -1,7 +0,0 @@
NoWidget := 0
VerticalWidgetType := 1
HorizontalWidgetType := 2
LabelWidgetType := 3
ImageWidgetType := 4

View file

@ -1,36 +0,0 @@
// Widget types
// End types
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
widget_types := @use("widget_types.hb")
label := @use("label.hb")
image := @use("image.hb")
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Vertical := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}
Horizontal := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}

View file

@ -1,18 +0,0 @@
keycodes := @use("keycodes.hb");
.{KeyCode} := keycodes
KeyEvent := packed struct {
up: bool,
just_triggered: bool,
key: KeyCode,
}
MouseEvent := packed struct {
x_change: i8,
y_change: i8,
left: bool,
middle: bool,
right: bool,
}
GamepadEvent := struct {}

View file

@ -1,121 +1,67 @@
/*
Originally I was modelling this after the following(1). I have since changed my mind.
I am now modelling it as I see fit. This is likely not the final version.
1) https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
*/
KeyCode := u32
// Typically this is not a keycode you will ever recieve.
None := KeyCode.(0)
// https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
Backspace := KeyCode.(8)
Tab := KeyCode.(9)
Clear := KeyCode.(12)
Return := KeyCode.(13)
Pause := KeyCode.(19)
Escape := KeyCode.(27)
Space := KeyCode.(32)
Escape := KeyCode.(1)
/* Alphabet keycodes */
A := KeyCode.(97)
/*
ETC
*/
Z := KeyCode.(122)
A := KeyCode.(2)
B := KeyCode.(3)
C := KeyCode.(4)
D := KeyCode.(5)
E := KeyCode.(6)
F := KeyCode.(7)
G := KeyCode.(8)
H := KeyCode.(9)
I := KeyCode.(10)
J := KeyCode.(11)
K := KeyCode.(12)
L := KeyCode.(13)
M := KeyCode.(14)
N := KeyCode.(15)
O := KeyCode.(16)
P := KeyCode.(17)
Q := KeyCode.(18)
R := KeyCode.(19)
S := KeyCode.(20)
T := KeyCode.(21)
U := KeyCode.(22)
V := KeyCode.(23)
W := KeyCode.(24)
X := KeyCode.(25)
Y := KeyCode.(26)
Z := KeyCode.(27)
/* Numeric keycodes*/
Number0 := KeyCode.(28)
Number1 := KeyCode.(29)
Number2 := KeyCode.(30)
Number3 := KeyCode.(31)
Number4 := KeyCode.(32)
Number5 := KeyCode.(33)
Number6 := KeyCode.(34)
Number7 := KeyCode.(35)
Number8 := KeyCode.(36)
Number9 := KeyCode.(37)
KeypadNumber0 := KeyCode.(38)
KeypadNumber1 := KeyCode.(39)
KeypadNumber2 := KeyCode.(40)
KeypadNumber3 := KeyCode.(41)
KeypadNumber4 := KeyCode.(42)
KeypadNumber5 := KeyCode.(43)
KeypadNumber6 := KeyCode.(44)
KeypadNumber7 := KeyCode.(45)
KeypadNumber8 := KeyCode.(46)
KeypadNumber9 := KeyCode.(47)
KeypadPeriod := KeyCode.(48)
KeypadDivide := KeyCode.(49)
KeypadMultiply := KeyCode.(50)
KeypadMinus := KeyCode.(51)
KeypadPlus := KeyCode.(52)
KeypadEnter := KeyCode.(53)
KeypadEquals := KeyCode.(54)
Delete := KeyCode.(55)
/* Locking Keys */
NumLock := KeyCode.(56)
CapsLock := KeyCode.(57)
ScrollLock := KeyCode.(58)
/* "Alt Gr" key */
Mode := KeyCode.(59)
/* Multi-key compose key */
Compose := KeyCode.(60)
LeftAlt := KeyCode.(61)
LeftControl := KeyCode.(62)
LeftMeta := KeyCode.(63)
LeftShift := KeyCode.(64)
/* Left "Windows" key */
LeftSuper := KeyCode.(65)
RightAlt := KeyCode.(66)
RightControl := KeyCode.(67)
RightMeta := KeyCode.(68)
RightShift := KeyCode.(69)
/* Right "Windows" key */
RightSuper := KeyCode.(70)
Delete := KeyCode.(127)
/*
This block of any triggers on any press of any of the keys.
Typically this is the event to care about.
ETC
*/
AnyNumber0 := KeyCode.(71)
AnyNumber1 := KeyCode.(72)
AnyNumber2 := KeyCode.(73)
AnyNumber3 := KeyCode.(74)
AnyNumber4 := KeyCode.(75)
AnyNumber5 := KeyCode.(76)
AnyNumber6 := KeyCode.(77)
AnyNumber7 := KeyCode.(78)
AnyNumber8 := KeyCode.(79)
AnyNumber9 := KeyCode.(80)
AnyAlt := KeyCode.(81)
AnyControl := KeyCode.(82)
AnyMeta := KeyCode.(83)
AnyShift := KeyCode.(84)
/* Any "Windows" key */
AnySuper := KeyCode.(85)
KeypadNumber0 := KeyCode.(256)
KeypadNumber1 := KeyCode.(257)
KeypadNumber2 := KeyCode.(258)
KeypadNumber3 := KeyCode.(259)
KeypadNumber4 := KeyCode.(260)
KeypadNumber5 := KeyCode.(261)
KeypadNumber6 := KeyCode.(262)
KeypadNumber7 := KeyCode.(263)
KeypadNumber8 := KeyCode.(264)
KeypadNumber9 := KeyCode.(265)
KeypadPeriod := KeyCode.(266)
KeypadDivide := KeyCode.(267)
KeypadMultiply := KeyCode.(268)
KeypadMinus := KeyCode.(269)
KeypadPlus := KeyCode.(270)
KeypadEnter := KeyCode.(271)
KeypadEquals := KeyCode.(272)
NumLock := KeyCode.(300)
CapsLock := KeyCode.(301)
ScrollLock := KeyCode.(302)
RightShift := KeyCode.(303)
LeftShift := KeyCode.(304)
RightControl := KeyCode.(305)
LeftControl := KeyCode.(306)
RightAlt := KeyCode.(307)
LeftAlt := KeyCode.(308)
RightMeta := KeyCode.(309)
LeftMeta := KeyCode.(310)
/* Left "Windows" key */
LeftSuper := KeyCode.(311)
/* Right "Windows" key */
RightSuper := KeyCode.(312)
/* "Alt Gr" key */
Mode := KeyCode.(313)
/* Multi-key compose key */
Compose := KeyCode.(314)

View file

@ -1,36 +1,22 @@
stn := @use("stn");
.{log, buffer, memory} := stn
keycodes := @use("keycodes.hb")
keycodes := @use("keycodes.hb");
.{KeyCode} := keycodes
events := @use("events.hb");
.{KeyEvent, MouseEvent} := events
recieve_key_event := fn(): ?KeyEvent {
kevent := KeyEvent.(false, false, 0)
buf_id := buffer.search("PS/2 Keyboard")
// Read out of the Keyboard buffer here
buffer.recv(KeyEvent, buf_id, &kevent)
if kevent.just_triggered {
return kevent
}
return null
MouseEvent := struct {
x_change: u8,
y_change: u8,
left: u8,
middle: u8,
right: u8,
}
recieve_mouse_event := fn(): ?MouseEvent {
mevent := MouseEvent.(0, 0, false, false, false)
KeyEvent := struct {
// 0 if down
// 1 if up
up: u8,
// 0 if not just triggered
// 1 if just triggered
just_triggered: u8,
key: KeyCode,
}
buf_id := buffer.search("PS/2 Mouse")
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, &mevent)
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
return mevent
}
return null
}
GamepadEvent := struct {}

View file

@ -1,4 +1,4 @@
.{string, memory, buffer, log} := @use("stn")
.{string, memory, buffer, log} := @use("../../stn/src/lib.hb")
PCIAddress := struct {
bus: u8,
@ -51,9 +51,9 @@ check_device := fn(bus: u8, device: u8): PciDeviceInfo {
pci_id := get_ids(bus, device, 0)
if pci_id.vendor == 0xFFFF {
log.warn(":|")
log.warn(":|\0")
} else {
log.info(":)")
log.info(":)\0")
}
address := calculate_address(bus, device, 0, 0x8)
reg2 := config_read32(bus, device, 0, 0x8)

View file

@ -3,4 +3,7 @@ Rendering interface for SVGA and Software renderers
# TODO:
- SVGA Driver
- needs pci driver
- needs pci driver
- needs init (requiring program)
- Double Buffer mode for Software renderer
- needs init (requiring program)

View file

@ -1,4 +1,7 @@
# Images
- General over image format
- Support formats:
- PNG
- Animation
# API

View file

@ -0,0 +1,102 @@
.{Color, Surface, new_surface} := @use("./lib.hb");
.{log, memory} := @use("../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
img_type: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
surface_from_bmp := fn(bmp: ^u8): Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return idk
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
px := info_header.width * info_header.height
ptr := @as(^Color, @bitcast(bmp))
tmp := @as(Color, idk)
row := @as(i32, 0)
loop if row == info_header.height / 2 break else {
col := @as(i32, 0)
loop if col == info_header.width break else {
top_index := row * info_header.width + col
bottom_index := (info_header.height - 1 - row) * info_header.width + col
tmp = *(ptr + top_index);
*(ptr + top_index) = *(ptr + bottom_index);
*(ptr + bottom_index) = tmp
col += 1
}
row += 1
}
return .(@bitcast(bmp), info_header.width, info_header.height)
}
new_surface_from_bmp := fn(bmp: ^u8): Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return idk
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
width := @as(uint, @intcast(info_header.width))
height := @as(uint, @intcast(info_header.height))
surface := new_surface(width, height)
top_start_idx := surface.buf
bottom_start_idx := surface.buf + width * (height - 1)
rows_to_copy := height
top_cursor := @as(^Color, @bitcast(bmp))
bottom_cursor := top_cursor + width * (height - 1)
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(width))
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += width
bottom_cursor -= width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(width))
}
return surface
}

View file

@ -1,49 +0,0 @@
.{Color, Surface, new_surface, put_surface} := @use("lib:render");
.{log} := @use("stn")
BitmapFileHeader := packed struct {
magic: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
from := fn(bmp: ^u8): ?Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
log.error("Invalid BMP image.")
return null
}
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
rhs := Surface.new(info_header.width, info_header.height)
rhs.put_surface(lhs, .(0, 0), true)
return rhs
}

View file

@ -1,31 +0,0 @@
.{log} := @use("stn");
.{Surface} := @use("lib:render")
bmp := @use("bmp.hb")
qoi := @use("qoi.hb")
$BMP := 0x4D42
$QOI := 0x66696F71
get_format := fn(file: ^u8): ?uint {
if *@as(^u16, @bitcast(file)) == BMP {
return BMP
} else if *@as(^u32, @bitcast(file)) == QOI {
return QOI
} else {
return null
}
}
from := fn(file: ^u8): ?Surface {
format := get_format(file)
if format == null {
log.error("Could not detect image format.")
return null
} else if format == BMP {
return bmp.from(file)
} else if format == QOI {
return qoi.from(file)
}
return null
}

View file

@ -1,101 +0,0 @@
.{Color, Surface, new_surface} := @use("lib:render");
.{log} := @use("stn")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
$QOI_SRGB := 0
$QOI_LINEAR := 1
$QOI_OP_INDEX := 0x0
$QOI_OP_DIFF := 0x40
$QOI_OP_LUMA := 0x80
$QOI_OP_RUN := 0xC0
$QOI_OP_RGB := 0xFE
$QOI_OP_RGBA := 0xFF
$QOI_MASK_2 := 0xC0
$QOI_COLOR_HASH := fn(c: Color): u8 {
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
}
$QOI_MAGIC := 0x716F6966
$QOI_PIXELS_MAX := 400000000
QuiteOkayHeader := packed struct {
magic: u32,
width: u32,
height: u32,
channels: u8,
colorspace: u8,
}
be_to_le := fn(big: u32): u32 {
return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24
}
from := fn(qoi: ^u8): ?Surface {
header := @as(^QuiteOkayHeader, @bitcast(qoi))
qoi += @sizeof(QuiteOkayHeader)
width := be_to_le(header.width)
height := be_to_le(header.height)
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
log.error("Invalid QOI image.")
return null
}
surface := Surface.new(width, height)
index := @as([64]Color, idk)
run := 0
px := Color.(0, 0, 0, 255)
px_pos := 0
total_pixels := width * height
loop if px_pos >= total_pixels break else {
if run > 0 {
run -= 1
} else {
b1 := *qoi
qoi += 1
if b1 == QOI_OP_RGB {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
qoi += 3
} else if b1 == QOI_OP_RGBA {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
px.a = *(qoi + 3)
qoi += 4
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
px = index[b1 & 0x3F]
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
b2 := *qoi
vg := (b1 & 0x3F) - 32
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
px.g = px.g + vg & 0xFF
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
qoi += 1
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
run = b1 & 0x3F
}
index[QOI_COLOR_HASH(px)] = px
};
*(surface.buf + px_pos) = px
px_pos += 1
}
return surface
}

View file

@ -1,28 +1,51 @@
software := @use("software.hb")
image := @use("image/lib.hb")
image := @use("image.hb")
text := @use("text.hb")
// default mode
mode := software
init := mode.init
doublebuffer := mode.doublebuffer
Surface := mode.Surface
new_surface := mode.new_surface
surface_from_ptr := mode.surface_from_ptr
clone_surface := mode.clone_surface
free_surface := mode.free_surface
index := mode.index
indexptr := mode.indexptr
// Colours
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
$WHITE := Color.(255, 255, 255, 255)
$BLACK := Color.(0, 0, 0, 255)
$GRAY := Color.(127, 127, 127, 255)
$RED := Color.(0, 0, 205, 255)
$GREEN := Color.(0, 205, 0, 255)
$YELLOW := Color.(0, 205, 205, 255)
$BLUE := Color.(205, 0, 0, 255)
$MAGENTA := Color.(205, 0, 205, 255)
$CYAN := Color.(205, 205, 0, 255)
$LIGHT_GRAY := Color.(229, 229, 229, 255)
$LIGHT_RED := Color.(0, 0, 255, 255)
$LIGHT_GREEN := Color.(0, 255, 0, 255)
$LIGHT_YELLOW := Color.(0, 255, 255, 255)
$LIGHT_BLUE := Color.(255, 0, 0, 255)
$LIGHT_MAGENTA := Color.(255, 0, 255, 255)
$LIGHT_CYAN := Color.(255, 255, 0, 255)
white := Color.(255, 255, 255, 255)
black := Color.(0, 0, 0, 255)
gray := Color.(127, 127, 127, 255)
red := Color.(0, 0, 205, 255)
green := Color.(0, 205, 0, 255)
yellow := Color.(0, 205, 205, 255)
blue := Color.(205, 0, 0, 255)
magenta := Color.(205, 0, 205, 255)
cyan := Color.(205, 205, 0, 255)
light_gray := Color.(229, 229, 229, 255)
light_red := Color.(0, 0, 255, 255)
light_green := Color.(0, 255, 0, 255)
light_yellow := Color.(0, 255, 255, 255)
light_blue := Color.(255, 0, 0, 255)
light_magenta := Color.(255, 0, 255, 255)
light_cyan := Color.(255, 255, 0, 255)
// Drawing
put_pixel := mode.put_pixel
put_rect := mode.put_rect
put_filled_rect := mode.put_filled_rect
put_line := mode.put_line
clear := mode.clear
put_surface := mode.put_surface
put_text := mode.put_text
// thanks peony for these three!
put_trirect := mode.put_trirect
put_vline := mode.put_vline
put_hline := mode.put_hline
// Display
sync := mode.sync

View file

@ -1,443 +1,320 @@
.{math, memory, dt} := @use("stn");
.{Color, text} := @use("lib:render");
.{get_glyph, get_glyph_unicode, Font, UNC_TABLE_SIZE} := text;
.{math, memory, dt} := @use("../../stn/src/lib.hb");
.{Color, text} := @use("lib.hb");
.{get_glyph, Font} := text;
.{Vec2} := math
// safety: don't use before init() or you will get a memory access violation
framebuffer := memory.dangling(Color)
utf8_len_table := u8.[0, 0, 2, 3]
init := fn(doublebuffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr")
width := dt.get(uint, "framebuffer/fb0/width")
height := dt.get(uint, "framebuffer/fb0/height")
if doublebuffer {
return Surface.new(width, height)
} else {
return .(framebuffer, width, height, width * height)
}
}
Surface := struct {
buf: ^Color,
width: uint,
height: uint,
size: uint,
}
new := fn(width: uint, height: uint): Self {
size := width * height
return .(
memory.alloc(Color, size),
width,
height,
size,
)
new_surface := fn(width: uint, height: uint): Surface {
return .(
@inline(memory.alloc, Color, width * height),
width,
height,
)
}
surface_from_ptr := fn(ptr: ^Color, width: uint, height: uint): Surface {
return .(
ptr,
width,
height,
)
}
clone_surface := fn(surface: ^Surface): Surface {
new := new_surface(surface.width, surface.height)
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
return new
}
// ! is broken, check memory.free function
free_surface := fn(surface: Surface): void {
return @inline(memory.free, Color, surface.buf, @intcast(surface.width * surface.height), false)
}
framebuffer := @as(^Color, idk)
init := fn(doublebuffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
width := dt.get(uint, "framebuffer/fb0/width\0")
height := dt.get(uint, "framebuffer/fb0/height\0")
if doublebuffer {
return new_surface(width, height)
} else {
return .(framebuffer, width, height)
}
}
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
}
sync := fn(surface: Surface): void {
// vague safety
if surface.buf == framebuffer {
return
}
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
}
index := fn(surface: Surface, x: uint, y: uint): uint {
return x + surface.width * y
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + @inline(index, surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
*@inline(indexptr, surface, pos.x, pos.y) = color
return
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
rows_to_fill -= 2
}
clone := fn(self: ^Self): Self {
new_self := Self.new(self.width, self.height)
memory.copy(Color, self.buf, new_self.buf, self.size)
return new_self
}
$clear := fn(self: Self, color: Color): void {
memory.set(Color, &color, self.buf, self.size)
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
}
$sync := fn(self: Self): void {
memory.copy(Color, self.buf, framebuffer, self.size)
return
}
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
*right_start_idx = color
start_idx += surface.width
right_start_idx += surface.width
}
$index := fn(self: Self, x: uint, y: uint): uint {
return x + self.width * y
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return
}
put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
yi := 1
if dy < 0 {
yi = -1
dy = -dy
}
$indexptr := fn(self: Self, x: uint, y: uint): ^Color {
return self.buf + self.index(x, y)
}
$put_pixel := fn(self: Self, pos: Vec2(uint), color: Color): void {
*self.indexptr(pos.x, pos.y) = color
}
put_filled_rect := fn(self: Self, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := self.indexptr(pos.x, pos.y)
bottom_start_idx := self.indexptr(pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
memory.set(Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, bottom_start_idx, tr.x)
top_start_idx += self.width
bottom_start_idx -= self.width
rows_to_fill -= 2
}
if rows_to_fill == 1 {
memory.set(Color, &color, top_start_idx, tr.x)
}
}
put_rect := fn(self: Self, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := self.indexptr(pos.x, pos.y)
end_idx := self.indexptr(pos.x, pos.y + tr.y)
right_start_idx := self.indexptr(pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
*right_start_idx = color
start_idx += self.width
right_start_idx += self.width
}
memory.set(Color, &color, self.indexptr(pos.x, pos.y), @bitcast(tr.x + 1))
memory.set(Color, &color, self.indexptr(pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
}
put_line_low := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
yi := 1
if dy < 0 {
yi = -1
dy = -dy
}
D := @as(int, 2) * dy - dx
y := p0.y
x := p0.x
loop if x == p1.x break else {
*self.indexptr(x, y) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
} else {
D += 2 * dy
}
x += 1
}
}
put_line_high := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
xi := 1
if dy < 0 {
xi = -1
dx = -dx
}
D := @as(int, 2) * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
*self.indexptr(x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
} else {
D += 2 * dx
}
y += 1
}
}
put_line := fn(self: Self, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
if math.abs(int, @bitcast(p1.y - p0.y)) < math.abs(int, @bitcast(p1.x - p0.x)) {
if p0.x > p1.x {
@inline(put_line_low, self, p1, p0, color)
} else {
@inline(put_line_low, self, p0, p1, color)
}
D := @as(int, 2) * dy - dx
y := p0.y
x := p0.x
loop if x == p1.x break else {
*@inline(indexptr, surface, x, y) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
} else {
if p0.y > p1.y {
@inline(put_line_high, self, p1, p0, color)
} else {
@inline(put_line_high, self, p0, p1, color)
}
D += 2 * dy
}
x += 1
}
return
}
put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
xi := 1
if dy < 0 {
xi = -1
dx = -dx
}
D := @as(int, 2) * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
*@inline(indexptr, surface, x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
} else {
D += 2 * dx
}
y += 1
}
return
}
put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
if math.abs(uint, p1.y - p0.y) < math.abs(uint, p1.x - p0.x) {
if p0.x > p1.x {
@inline(put_line_low, surface, p1, p0, color)
} else {
@inline(put_line_low, surface, p0, p1, color)
}
} else {
if p0.y > p1.y {
@inline(put_line_high, surface, p1, p0, color)
} else {
@inline(put_line_high, surface, p0, p1, color)
}
}
return
}
put_surface := fn(self: Self, top: Self, pos: Vec2(uint), flip_v: bool): void {
src_top_cursor := top.buf
src_bottom_cursor := top.buf + top.width * (top.height - 1)
dst_top_idx := self.indexptr(pos.x, pos.y)
dst_bottom_idx := self.indexptr(pos.x, pos.y + top.height - 1)
dst_increment := self.width
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
rows_to_copy := top.height
top_cursor := top.buf
bottom_cursor := top.buf + top.width * (top.height - 1)
loop if rows_to_copy <= 1 break else {
if flip_v {
dst_increment = -dst_increment
tmp := dst_top_idx
dst_top_idx = dst_bottom_idx
dst_bottom_idx = tmp
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width))
} else {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width))
}
rows_to_copy := top.height
loop if rows_to_copy <= 1 break else {
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
memory.copy(Color, src_bottom_cursor, dst_bottom_idx, top.width)
dst_top_idx += dst_increment
dst_bottom_idx -= dst_increment
src_top_cursor += top.width
src_bottom_cursor -= top.width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
}
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += top.width
bottom_cursor -= top.width
rows_to_copy -= 2
}
// peony-made
put_trirect := fn(self: Self, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void {
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y /= @bitcast(size.x)
}
start_y := pos.y
target := pos + @bitcast(size)
loop if pos.x == target.x break else {
@inline(put_vline, self, pos.x, pos.y, target.y, color0)
@inline(put_vline, self, pos.x, pos.y, start_y, color1)
pos += @bitcast(step)
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
}
// peony-made
put_vline := fn(self: Self, x: uint, y0: uint, y1: uint, color: Color): void {
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
return
}
loop if y == y1 break else {
*self.indexptr(x, y) = color
y += 1
}
// peony-made
put_trirect := fn(surface: Surface, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void {
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y /= @bitcast(size.x)
}
// peony-made
put_hline := fn(self: Self, y: uint, x0: uint, x1: uint, color: Color): void {
if x1 < x0 {
tmp := x0
x0 = x1
x1 = tmp
}
memory.set(Color, &color, self.indexptr(x0, y), @bitcast(x1 - x0))
start_y := pos.y
target := pos + @bitcast(size)
loop if pos.x == target.x break else {
@inline(put_vline, surface, pos.x, pos.y, target.y, color0)
@inline(put_vline, surface, pos.x, pos.y, start_y, color1)
pos += @bitcast(step)
}
put_circle := fn(self: Self, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - 2 * @intcast(radius)
loop if x > y break else {
self.put_pixel(pos + .(x, y), color)
self.put_pixel(pos + .(-x, y), color)
self.put_pixel(pos + .(x, -y), color)
self.put_pixel(pos + .(-x, -y), color)
self.put_pixel(pos + .(y, x), color)
self.put_pixel(pos + .(-y, x), color)
self.put_pixel(pos + .(y, -x), color)
self.put_pixel(pos + .(-y, -x), color)
if error < 0 {
error += 4 * @intcast(x) + 6
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
}
return
}
// peony-made
put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): void {
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
loop if y == y1 break else {
*@inline(indexptr, surface, x, y) = color
y += 1
}
put_filled_circle := fn(self: Self, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - 2 * @intcast(radius)
return
}
loop if x > y break else {
self.put_hline(pos.y + y, pos.x - x, pos.x + x, color)
self.put_hline(pos.y - y, pos.x - x, pos.x + x, color)
if x != y {
self.put_hline(pos.y + x, pos.x - y, pos.x + y, color)
self.put_hline(pos.y - x, pos.x - y, pos.x + y, color)
}
if error < 0 {
error += 4 * @intcast(x) + 6
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
}
// peony-made
put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): void {
if x1 < x0 {
tmp := x0
x0 = x1
x1 = tmp
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
put_textured_circle := fn(self: Self, source: Self, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
x := 0
y := radius
error := @as(int, 3) - 2 * @intcast(radius)
return
}
loop if x > y break else {
memory.copy(Color, source.indexptr(source_pos.x - x, source_pos.y + y), self.indexptr(pos.x - x, pos.y + y), 2 * x)
memory.copy(Color, source.indexptr(source_pos.x - x, source_pos.y - y), self.indexptr(pos.x - x, pos.y - y), 2 * x)
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
cursor := Vec2(uint).(pos.x, pos.y)
current_char := str
if x != y {
memory.copy(Color, source.indexptr(source_pos.x - y, source_pos.y + x), self.indexptr(pos.x - y, pos.y + x), 2 * y)
memory.copy(Color, source.indexptr(source_pos.x - y, source_pos.y - x), self.indexptr(pos.x - y, pos.y - x), 2 * y)
}
if error < 0 {
error += 4 * @intcast(x) + 6
} else {
error += 4 * (@intcast(x) - @intcast(y)) + 10
y -= 1
}
x += 1
loop if *current_char == 0 break else {
if *current_char == 10 {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
current_char += 1
continue
}
}
put_text := fn(self: Self, font: Font, pos: Vec2(uint), color: Color, str: []u8): void {
cursor := Vec2(uint).(pos.x, pos.y)
glyph_data := @inline(get_glyph, font, @intcast(*current_char))
if glyph_data == idk {
current_char += 1
continue
}
max_y := self.height - font.height
next_line_y := font.height + font.line_gap
char_advance := font.width + font.char_gap
self_width := self.width
if cursor.x % surface.width + font.width >= surface.width {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
}
if cursor.y + font.height > surface.height break
i := 0
dest := @inline(indexptr, surface, cursor.x, cursor.y)
src := glyph_data
rows_remaining := font.height
loop if i >= str.len break else {
if cursor.y > max_y break
loop if rows_remaining == 0 break else {
byte := *glyph_data
pixel_dest := dest
mask := @as(u8, 0x80)
bits_remaining := font.width
glyph_data := @as(^u8, idk)
code_point := @as(uint, 0)
if (str[i] & 0x80) == 0 {
if str[i] == '\n' {
cursor.x = pos.x
cursor.y += next_line_y
i += 1
continue
loop if bits_remaining == 0 break else {
if (byte & mask) != 0 {
*pixel_dest = color
}
if font.unicode == null {
if str[i] > font.num_glyphs {
i += 1
continue
}
glyph_data = get_glyph(font, str[i])
} else {
if str[i] < UNC_TABLE_SIZE {
glyph_index := *(font.unicode + str[i])
if glyph_index == 0xFFFF {
i += 1
continue
}
glyph_data = font.data + glyph_index * font.bytes_per_glyph
} else {
i += 1
continue
}
}
i += 1
} else if font.unicode != null {
first_byte := str[i]
num_bytes := @as(uint, 0)
num_bytes = utf8_len_table[first_byte >> 5 & 0x3]
if num_bytes == 0 {
i += 1
continue
}
code_point = first_byte & (0x7F >> num_bytes | 0x1F)
valid_sequence := true
bytes_processed := 1
loop if bytes_processed >= num_bytes break else {
i += 1
if i == str.len | (str[i] & 0xC0) != 0x80 {
valid_sequence = false
}
if valid_sequence == false {
break
}
code_point = code_point << 6 | str[i] & 0x3F
bytes_processed += 1
}
if valid_sequence == false {
i += 1
continue
}
i += 1
if code_point == '\n' {
cursor.x = pos.x
cursor.y += next_line_y
continue
}
if code_point >= UNC_TABLE_SIZE {
continue
}
glyph_index := *(font.unicode + code_point)
if glyph_index == 0xFFFF {
continue
}
glyph_data = font.data + glyph_index * font.bytes_per_glyph
}
if cursor.x + font.width >= self_width {
cursor.x = pos.x
cursor.y += next_line_y
}
dest := self.indexptr(cursor.x, cursor.y)
rows := font.height
loop if rows == 0 break else {
byte := *glyph_data
pixel_dest := dest
mask := @as(u8, 0x80)
bits := font.width
loop if bits == 0 break else {
if (byte & mask) != 0 {
*pixel_dest = color
}
pixel_dest += 1
mask >>= 1
if mask == 0 & bits > 0 {
glyph_data += 1
byte = *glyph_data
mask = 0x80
}
bits -= 1
}
if mask != 0x80 {
pixel_dest += 1
mask >>= 1
if mask == 0 {
glyph_data += 1
byte = *glyph_data
mask = 0x80
}
dest += self_width
rows -= 1
bits_remaining -= 1
}
cursor.x += char_advance
glyph_data += 1
dest += surface.width
rows_remaining -= 1
}
cursor.x += font.width + font.char_gap
current_char += 1
}
return
}

View file

@ -1,4 +1,4 @@
.{log, memory} := @use("stn")
.{log} := @use("../../stn/src/lib.hb")
PSF1Header := packed struct {
magic: u16,
@ -23,16 +23,16 @@ Font := struct {
height: uint,
num_glyphs: uint,
bytes_per_glyph: uint,
has_unicode_table: bool,
line_gap: uint,
char_gap: uint,
unicode: ?^u16,
}
font_from_psf1 := fn(psf: ^u8): ?Font {
font_from_psf1 := fn(psf: ^u8): Font {
header := @as(^PSF1Header, @bitcast(psf))
if header.magic != 0x436 {
log.error("failed to load psf font: not a psf1 font, idiot")
return null
log.error("failed to load psf font: not a psf1 font, idiot\0")
return idk
}
psf += @sizeof(PSF1Header)
@ -40,121 +40,36 @@ font_from_psf1 := fn(psf: ^u8): ?Font {
return .(
psf,
8,
header.character_size,
@intcast(header.character_size),
256,
header.character_size,
@intcast(header.character_size),
false,
0,
0,
null,
)
}
font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
font_from_psf2 := fn(psf: ^u8): Font {
header := @as(^PSF2Header, @bitcast(psf))
if header.magic != 0x864AB572 {
log.error("failed to load psf font: not a psf2 font, idiot")
return null
log.error("failed to load psf font: not a psf2 font, idiot\0")
return idk
}
psf += header.header_size
font := Font.(
return .(
psf,
header.width,
header.height,
header.num_glyph,
header.bytes_per_glyph,
@intcast(header.width),
@intcast(header.height),
@intcast(header.num_glyph),
@intcast(header.bytes_per_glyph),
(header.flags & 1) != 0,
0,
0,
null,
)
if (header.flags & 1) != 0 & unicode {
init_unicode(&font)
}
return font
}
$get_glyph := fn(font: Font, index: u8): ^u8 {
return font.data + @as(uint, index) * font.bytes_per_glyph
}
$UNC_TABLE_SIZE := 1 << 16
init_unicode := fn(font: ^Font): void {
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
memory.set(u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
table := font.data + font.num_glyphs * font.bytes_per_glyph
curr_glyph := @as(u16, 0)
loop if curr_glyph >= font.num_glyphs break else {
loop {
byte := *table
table += 1
if byte == 0xFF break
if byte == 0xFE {
continue
}
unicode := @as(uint, 0)
bytes_to_read := @as(uint, 1)
if (byte & 0x80) == 0 {
unicode = byte
} else if (byte & 0xE0) == 0xC0 {
unicode = byte & 0x1F
bytes_to_read = 2
} else if (byte & 0xF0) == 0xE0 {
unicode = byte & 0xF
bytes_to_read = 3
} else if (byte & 0xF8) == 0xF0 {
unicode = byte & 0x7
bytes_to_read = 4
} else {
continue
}
valid := true
loop if bytes_to_read <= 1 break else {
next_byte := *table
if (next_byte & 0xC0) != 0x80 {
valid = false
break
}
unicode = unicode << 6 | next_byte & 0x3F
table += 1
bytes_to_read -= 1
}
if valid == false continue
if bytes_to_read == 4 {
if unicode < 0x10000 | unicode > 0x10FFFF continue
if unicode <= 0xFFFF {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
} else {
unicode -= 0x10000
high_surrogate := 0xD800 | unicode >> 10 & 0x3FF
low_surrogate := 0xDC00 | unicode & 0x3FF
if high_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + high_surrogate) = curr_glyph
}
if low_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + low_surrogate) = curr_glyph
}
}
} else {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
}
}
curr_glyph += 1
}
get_glyph := fn(font: Font, index: uint): ^u8 {
return font.data + index * font.bytes_per_glyph
}

View file

@ -1,4 +0,0 @@
AllocReturn := struct {
byte_count: uint,
ptr: ?^u8,
}

View file

@ -1,90 +0,0 @@
.{log, panic, memory} := @use("stn")
alloc_return := @use("alloc_return.hb")
/* the block size is 64 bytes, 64 blocks of 64 bytes.
this will very quickly lead to exhaustion of free blocks.
*/
BlockAlloc := struct {
// hi
state: uint,
ptr: ?^u8,
$init := fn(): Self {
alloc_page_ptr := memory.request_page(1)
state := 0xFFFFFFFFFFFFFFFF
return .(state, alloc_page_ptr)
}
alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
offset := 0
state_2 := 0
loop {
xyz := self.state & 1
abc := if xyz == 1 {
true
} else {
false
}
// check if the `offset` bit is 1, if it is move to the next offset
if abc {
offset += 1
return .(0, null)
} else {
log.info("Already Allocated")
}
// else {
// // self it to 1 and return the ptr to the allocation
// self.state |= a
// // return ptr + offset * 64
// if self.ptr != null {
// return .(64, self.ptr + offset * 64)
// } else {
// // panic.panic("Allocator is not inited.")
// // return .(0, null)
// }
// }
// there are only 64 blocks
if offset >= 64 {
return .(0, null)
}
}
}
dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
// size := size_of(alloc_type)*count
size := 64
// get the size alligned to the nearest block
// rounded_size := nearest_block_size_rounded_up(size)
rounded_size := 64
state_bit_start := {
// Do math here to figure out what starting ptr corresponds to what bit
3
}
offset := 0
loop {
if rounded_size > 0 {
// set state_bit_start+offset to 0
// at the end move to the next one
offset += 1
} else {
break
}
rounded_size -= 64
}
return void
}
$deinit := fn(self: Self): void {
self.state = 0
self.ptr = null
}
}
// request a kernel page
// ptr := memory.alloc(1)

View file

@ -1,19 +0,0 @@
alloc_return := @use("alloc_return.hb")
FakeAlloc := struct {
$init := fn(): Self {
return .()
}
$alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn {
return .(0, null)
}
$dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void {
return void
}
// Nothing to clean up here
$deinit := fn(self: Self): void {
return void
}
}

View file

@ -1,2 +0,0 @@
.{BlockAlloc} := @use("block_alloc.hb");
.{FakeAlloc} := @use("fake_alloc.hb")

View file

@ -1,25 +0,0 @@
allocators := @use("alloc/alloc.hb")
AStruct := struct {
a_field: u8,
}
main := fn():void{
alloc := allocators.FakeAlloc.init()
astruct := alloc.alloc(AStruct, 2)
if astruct.ptr != null{
panic("FakeAlloc actually allocated.")
}
alloc.dealloc(astruct_ptr, AStruct, 2)
alloc.deinit()
balloc := allocators.BlockAlloc.init()
bstruct_ptr := balloc.alloc(AStruct, 2)
if bstruct_ptr == null {
panic("BlockAlloc actually didn't allocate.")
}
balloc.dealloc(bstruct_ptr, AStruct, 2)
balloc.deinit()
}

Binary file not shown.

View file

@ -1,37 +1,27 @@
$await := fn(buffer_id: uint): void {
return @eca(7, buffer_id)
}
string := @use("string.hb")
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): ^Expr {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
}
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void {
write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
return @eca(3, buffer_id, msg, @sizeof(Expr))
}
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void {
recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
return @eca(4, buffer_id, memory_map_location, length)
}
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void {
write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
return @eca(3, buffer_id, msg, length)
}
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
$create := fn(msg: []u8): uint {
return @eca(3, 0, BufferMsg.(0, msg.ptr, msg.len), @sizeof(BufferMsg))
create := fn(msg: ^u8): int {
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}
$create_nameless := fn(): uint {
return @eca(1, 0)
}
$delete := fn(buffer_id: uint): void {
return @eca(2, buffer_id)
}
$search := fn(msg: []u8): uint {
return @eca(3, 0, BufferMsg.(3, msg.ptr, msg.len), @sizeof(BufferMsg))
search := fn(msg: ^u8): int {
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}

View file

@ -1,3 +1,5 @@
$get := fn($Expr: type, query: []u8): Expr {
return @eca(3, 5, query, query.len)
.{string} := @use("../../stn/src/lib.hb")
get := fn($Expr: type, query: ^u8): Expr {
return @eca(3, 5, query, @inline(string.length, query))
}

View file

@ -2,7 +2,7 @@ acs := @use("acs.hb");
.{DiskID, FileID} := acs
// Paths without a node-disk component are to be treated as local files.
// file_path := "DID:/test"
// file_path := "DID:/test\0";
Path := struct {
// DiskID holds the host id
disk_id: DiskID,

View file

@ -1,285 +0,0 @@
.{Kind, usize, string, signed_int, panic, float, integer, memory, log: .{LogLevel}} := @use("stn")
fmt_int := fn(v: @Any(), str: []u8, radix: @TypeOf(v)): uint {
is_negative := signed_int(@TypeOf(v)) & v < 0
prefix_len := 0
if is_negative {
v = -v
str[0] = '-'
prefix_len += 1
}
if radix == 16 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0x".ptr)
prefix_len += 2
} else if radix == 2 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0b".ptr)
prefix_len += 2
} else if radix == 8 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0o".ptr)
prefix_len += 2
}
if v == 0 {
str[prefix_len] = '0'
return prefix_len + 1
}
i := prefix_len
loop if v <= 0 break else {
remainder := v % radix
v /= radix
if remainder > 9 {
str[i] = @intcast(remainder - 10 + 'A')
} else {
str[i] = @intcast(remainder + '0')
}
i += 1
}
string.reverse(str[prefix_len..i])
return i
}
fmt_bool := fn(v: bool, str: []u8): uint {
if v {
*@as(^[4]u8, @bitcast(str.ptr)) = *@bitcast("true".ptr)
return 4
} else {
*@as(^[5]u8, @bitcast(str.ptr)) = *@bitcast("false".ptr)
return 5
}
}
$FP_TOLERANCE := 0.00000001
fmt_float := fn(v: @Any(), str: []u8, precision: uint, radix: int): uint {
is_negative := v < 0
prefix_len := 0
if is_negative {
v = -v
str[0] = '-'
prefix_len += 1
}
if radix == 16 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0x".ptr)
prefix_len += 2
} else if radix == 2 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0b".ptr)
prefix_len += 2
} else if radix == 8 {
*@as(^[2]u8, @bitcast(str.ptr + prefix_len)) = *@bitcast("0o".ptr)
prefix_len += 2
}
integer_part := @fti(v)
fractional_part := v - @itf(integer_part)
i := prefix_len
loop if integer_part == 0 & i > prefix_len break else {
remainder := integer_part % radix
integer_part /= radix
if remainder > 9 {
str[i] = @intcast(remainder - 10 + 'A')
} else {
str[i] = @intcast(remainder + '0')
}
i += 1
}
string.reverse(str[prefix_len..i])
str[i] = '.'
i += 1
p := precision
loop if p <= 0 | fractional_part < FP_TOLERANCE break else {
fractional_part *= @itf(radix)
digit := @fti(fractional_part)
if digit > 9 {
str[i] = @intcast(digit - 10 + 'A')
} else {
str[i] = @intcast(digit + '0')
}
i += 1
fractional_part -= @itf(digit)
p -= 1
}
return i
}
fmt_container := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T2 := @TypeOf(v)
kind := Kind.of(T2)
i := 0
len := 0
if kind == .Struct {
*@as(^[@intcast(@nameof(T2).len)]u8, @bitcast(str.ptr + len)) = *@bitcast(@nameof(T2).ptr)
len += @nameof(T2).len;
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
} else if kind == .Slice {
*@as(^[@intcast(@nameof(@ChildOf(T2)).len)]u8, @bitcast(str.ptr + len)) = *@bitcast(@nameof(@ChildOf(T2)).ptr)
len += @nameof(@ChildOf(T2)).len;
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".[".ptr)
len += 2
} else if kind == .Tuple {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
}
if kind == .Slice {
loop {
len += @inline(format, v[i], str[len..], opts)
i += 1
if i == v.len break else {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(", ".ptr)
len += 2
}
}
} else {
$loop {
len += @inline(format, v[i], str[len..], opts)
i += 1
if i == @lenof(T2) break else {
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(", ".ptr)
len += 2
}
}
}
if kind == .Struct | kind == .Tuple {
*@as(^[1]u8, @bitcast(str.ptr + len)) = *@bitcast(")".ptr)
len += 1
} else if kind == .Slice {
*@as(^[1]u8, @bitcast(str.ptr + len)) = *@bitcast("]".ptr)
len += 1
}
return len
}
fmt_nullable := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
if v == null {
*@as(^[4]u8, @bitcast(str.ptr)) = *@bitcast("null".ptr)
return 4
} else {
return @inline(format, @as(@ChildOf(@TypeOf(v)), v), str, opts)
}
}
fmt_enum := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
len := @nameof(T).len;
*@as(^[@intcast(@nameof(T).len)]u8, @bitcast(str.ptr)) = *@bitcast(@nameof(T).ptr);
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(".(".ptr)
len += 2
len += fmt_int(@as(usize(T), @bitcast(v)), str[len..], 10);
*@as(^[2]u8, @bitcast(str.ptr + len)) = *@bitcast(")".ptr)
return len + 1
}
/* TODO:
* Custom formatters using struct methods (T._fmt(self, str): uint),
* Format struct fields "Name.{a: x, b: y, c: z}"
* Optionally tabulate
* Add more FormatOption fields
* Support scientific notation for floating point
* Support format string
*/
FormatOptions := struct {
precision: uint = 2,
radix: uint = 10,
// temporarily here, will change later maybe
log: LogLevel = .Info,
}
/* SAFETY:
* Assumes the buffer is wide enough for the formatted text and a null char
* Does not clear the buffer for you
*/
format := fn(v: @Any(), str: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
match Kind.of(T) {
.Pointer => return @inline(fmt_int, @as(uint, @bitcast(v)), str, 16),
.Builtin => {
if integer(T) {
return @inline(fmt_int, v, str, @intcast(opts.radix))
} else if T == bool {
return @inline(fmt_bool, v, str)
} else if float(T) {
return @inline(fmt_float, v, str, opts.precision, @intcast(opts.radix))
}
},
.Opt => return @inline(fmt_nullable, v, str, opts),
.Enum => return @inline(fmt_enum, v, str, opts),
.Struct => return @inline(fmt_container, v, str, opts),
.Tuple => return @inline(fmt_container, v, str, opts),
.Slice => if T != []u8 return @inline(fmt_container, v, str, opts) else {
i := 0
loop if i == v.len break else {
str[i] = v[i]
i += 1
}
return v.len
},
_ => @error("Type: \"", T, "\" is not supported."),
}
}
format_with_str := fn(v: @Any(), read: []u8, write: []u8, opts: FormatOptions): uint {
T := @TypeOf(v)
n := string.count(read, '{')
if n != string.count(read, '}') panic("Missing closing '}' in format string.")
if Kind.of(T) == .Tuple {
if @lenof(T) != n panic("Format string has different number of '{}' than args given.")
m := 0
i := 0
j := 0
$loop if m > @lenof(T) break else {
if m == @lenof(T) {
loop if i == read.len break else {
write[j] = read[i]
i += 1
j += 1
}
m += 1
} else {
v2 := v[m]
loop if i == read.len break else {
if read[i] == '{' & read[i + 1] == '}' {
j += format(v2, write[j..], opts)
i += 2
break
} else {
write[j] = read[i]
i += 1
j += 1
}
}
m += 1
}
}
return j
} else if n > 1 {
panic("Format string has multiple '{}' but value provided is not a tuple.")
} else {
i := 0
j := 0
loop if i == read.len break else {
if read[i] == '{' & read[i + 1] == '}' {
j += format(v, write[j..], opts)
i += 2
} else {
write[j] = read[i]
i += 1
j += 1
}
}
return j
}
}

View file

@ -1,181 +0,0 @@
/*
* This code is an implementation of the FoldHash algorithm from https://github.com/orlp/foldhash,
* originally written by Orson Peters under the zlib license.
*
* Changes to the original code were made to meet the simplicity requirements of this implementation.
* Behaviour aims to be equivalent but not identical to the original code.
*
* Copyright (c) 2024 Orson Peters
*
* This software is provided 'as-is', without any express or implied warranty. In
* no event will the authors be held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software for any purpose, including
* commercial applications, and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
* that you wrote the original software. If you use this software in a product,
* an acknowledgment in the product documentation would be appreciated but is
* not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/;
.{math, random} := @use("stn")
$ARBITRARY0 := 0x243F6A8885A308D3
$ARBITRARY1 := 0x13198A2E03707344
$ARBITRARY2 := 0xA4093822299F31D0
$ARBITRARY3 := 0x82EFA98EC4E6C89
$ARBITRARY4 := 0x452821E638D01377
$ARBITRARY5 := 0xBE5466CF34E90C6C
$ARBITRARY6 := 0xC0AC29B7C97C50DD
$ARBITRARY7 := 0x3F84D5B5B5470917
$ARBITRARY8 := 0x9216D5D98979FB1B
$ARBITRARY9 := 0xD1310BA698DFB5AC
$FIXED_GLOBAL_SEED := uint.[ARBITRARY4, ARBITRARY5, ARBITRARY6, ARBITRARY7]
global_seed := 0
u128 := packed struct {a: uint, b: uint}
$folded_multiply := fn(x: uint, y: uint): uint {
lx := @as(u32, @intcast(x))
ly := @as(u32, @intcast(y))
hx := x >> 32
hy := y >> 32
afull := lx * hy
bfull := hx * ly
return afull ^ (bfull << 32 | bfull >> 32)
}
hash_bytes_medium := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, fold_seed: uint): uint {
lo := bytes
end := bytes + len
hi := end - 16
loop if lo >= hi break else {
a := *@as(^uint, @bitcast(lo))
b := *@as(^uint, @bitcast(lo + 8))
c := *@as(^uint, @bitcast(hi))
d := *@as(^uint, @bitcast(hi + 8))
s0 = folded_multiply(a ^ s0, c ^ fold_seed)
s1 = folded_multiply(b ^ s1, d ^ fold_seed)
hi -= 16
lo += 16
}
return s0 ^ s1
}
hash_bytes_long := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, s2: uint, s3: uint, fold_seed: uint): uint {
$chunk_size := 64
chunks := len / chunk_size
remainder := len % chunk_size
ptr := bytes
i := 0
loop if i >= chunks break else {
a := *@as(^uint, @bitcast(ptr))
b := *@as(^uint, @bitcast(ptr + 8))
c := *@as(^uint, @bitcast(ptr + 16))
d := *@as(^uint, @bitcast(ptr + 24))
e := *@as(^uint, @bitcast(ptr + 32))
f := *@as(^uint, @bitcast(ptr + 40))
g := *@as(^uint, @bitcast(ptr + 48))
h := *@as(^uint, @bitcast(ptr + 56))
s0 = folded_multiply(a ^ s0, e ^ fold_seed)
s1 = folded_multiply(b ^ s1, f ^ fold_seed)
s2 = folded_multiply(c ^ s2, g ^ fold_seed)
s3 = folded_multiply(d ^ s3, h ^ fold_seed)
ptr += chunk_size
i += 1
}
s0 ^= s2
s1 ^= s3
if remainder > 0 {
remainder_start := bytes + len - math.max(uint, remainder, 16)
return @inline(hash_bytes_medium, remainder_start, math.max(uint, remainder, 16), s0, s1, fold_seed)
}
return s0 ^ s1
}
FoldHasher := struct {
accumulator: uint,
original_seed: uint,
sponge: u128,
sponge_len: u8,
fold_seed: uint,
expand_seed: uint,
expand_seed2: uint,
expand_seed3: uint,
$new := fn(seed: uint): Self {
return .(
seed,
seed,
.(0, 0),
0,
FIXED_GLOBAL_SEED[0],
FIXED_GLOBAL_SEED[1],
FIXED_GLOBAL_SEED[2],
FIXED_GLOBAL_SEED[3],
)
}
default := fn(): Self {
if global_seed == 0 {
// ! consider this "secure enough" for now
global_seed = random.any(uint)
}
return Self.new(global_seed)
}
write := fn(self: ^Self, bytes: ^u8, len: uint): void {
s0 := self.accumulator
s1 := self.expand_seed
if len <= 16 {
if len >= 8 {
s0 ^= *@bitcast(bytes)
s1 ^= *@bitcast(bytes + len - 8)
} else if len >= 4 {
s0 ^= *@as(^u32, @bitcast(bytes))
s1 ^= *@as(^u32, @bitcast(bytes + len - 4))
} else if len > 0 {
lo := *bytes
mid := *(bytes + len / 2)
hi := *(bytes + len - 1)
s0 ^= lo
s1 ^= @as(uint, hi) << 8 | mid
}
self.accumulator = folded_multiply(s0, s1)
} else if len < 256 {
self.accumulator = @inline(hash_bytes_medium, bytes, len, s0, s1, self.fold_seed)
} else {
self.accumulator = @inline(hash_bytes_long, bytes, len, s0, s1, self.expand_seed2, self.expand_seed3, self.fold_seed)
}
}
finish := fn(self: ^Self): uint {
if self.sponge_len > 0 {
return folded_multiply(self.sponge.b ^ self.accumulator, self.sponge.a ^ self.fold_seed)
} else {
return self.accumulator
}
}
reset := fn(self: ^Self): void {
self.accumulator = self.original_seed
self.sponge = .(0, 0)
self.sponge_len = 0
}
}

View file

@ -1,2 +0,0 @@
//! NON CRYPTOGRAPHIC HASHER
foldhash := @use("foldhash.hb")

View file

@ -1,7 +1,4 @@
acs := @use("acs.hb")
allocators := @use("alloc/lib.hb")
fmt := @use("fmt.hb")
hashers := @use("hash/lib.hb")
string := @use("string.hb")
log := @use("log.hb")
memory := @use("memory.hb")
@ -9,58 +6,4 @@ buffer := @use("buffer.hb")
math := @use("math.hb")
random := @use("random.hb")
file := @use("file_io.hb")
dt := @use("dt.hb")
process := @use("process.hb")
sleep := @use("sleep.hb")
panic := fn(message: ?[]u8): never {
log.printf("HBLang Panic: {}", message, .{log: .Error})
die
}
Kind := enum {
Builtin,
Struct,
Tuple,
Enum,
Union,
Pointer,
Slice,
Opt,
Function,
Template,
Global,
Const,
Module,
$of := fn($T: type): Self {
return @bitcast(@kindof(T))
}
}
$unsigned_int := fn($T: type): bool {
return T == uint | T == u8 | T == u16 | T == u32
}
$signed_int := fn($T: type): bool {
return T == int | T == i8 | T == i16 | T == i32
}
$integer := fn($T: type): bool {
return unsigned_int(T) | signed_int(T)
}
$float := fn($T: type): bool {
return T == f32 | T == f64
}
$usize := fn($T: type): type {
if @sizeof(T) == 1 return u8 else if @sizeof(T) == 2 return u16 else if @sizeof(T) == 4 return u32 else return uint
}
$bits := fn($T: type): usize(T) {
return @sizeof(T) << 3
}
$bitmask := fn($T: type): usize(T) {
return -1
}
dt := @use("dt.hb")

View file

@ -1,41 +1,13 @@
.{string, fmt, memory} := @use("stn")
string := @use("string.hb")
LogMsg := packed struct {level: LogLevel, string: ^u8, strlen: uint}
LogMsg := packed struct {level: u8, string: ^u8, strlen: uint}
LogLevel := enum {
Error,
Warn,
Info,
Debug,
Trace,
log := fn(level: u8, message: ^u8): void {
return @eca(3, 1, LogMsg.(level, message, @inline(string.length, message)), @sizeof(LogMsg))
}
$log := fn(level: LogLevel, message: []u8): void {
return @eca(3, 1, LogMsg.(level, message.ptr, message.len), @sizeof(LogMsg))
}
$error := fn(message: []u8): void return log(LogLevel.Error, message)
$warn := fn(message: []u8): void return log(LogLevel.Warn, message)
$info := fn(message: []u8): void return log(LogLevel.Info, message)
$debug := fn(message: []u8): void return log(LogLevel.Debug, message)
$trace := fn(message: []u8): void return log(LogLevel.Trace, message)
print_buffer := memory.dangling(u8)
print := fn(v: @Any(), opts: fmt.FormatOptions): void {
if print_buffer == memory.dangling(u8) {
print_buffer = memory.request_page(1)
}
len := @inline(fmt.format, v, print_buffer[0..memory.PAGE_SIZE], opts)
@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
memory.set(u8, &0, print_buffer, len)
}
printf := fn(str: []u8, v: @Any(), opts: fmt.FormatOptions): void {
if print_buffer == memory.dangling(u8) {
print_buffer = memory.request_page(1)
}
len := @inline(fmt.format_with_str, v, str, print_buffer[0..memory.PAGE_SIZE], opts)
@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
memory.set(u8, &0, print_buffer, len)
}
error := fn(message: ^u8): void return @inline(log, 0, message)
warn := fn(message: ^u8): void return @inline(log, 1, message)
info := fn(message: ^u8): void return @inline(log, 2, message)
debug := fn(message: ^u8): void return @inline(log, 3, message)
trace := fn(message: ^u8): void return @inline(log, 4, message)

File diff suppressed because one or more lines are too long

View file

@ -1,79 +1,67 @@
$PAGE_SIZE := 4096
$MAX_ALLOC := 0xFF
$MAX_FREE := 0xFF
PAGE_SIZE := 4096
MAX_ALLOC := 0xFF
MAX_FREE := 0xFF
$uninit := fn($Expr: type): Expr {
return idk
calc_pages := fn($Expr: type, num: uint): uint {
return 1 + @sizeof(Expr) * num / PAGE_SIZE
}
$nulled := fn($Expr: type): ?Expr {
return null
}
$dangling := fn($Expr: type): ^Expr {
return @bitcast(@alignof(Expr))
}
$calc_pages := fn($Expr: type, num: uint): uint {
return (num + PAGE_SIZE - 1) / PAGE_SIZE
}
// ! will be replaced, don't get attached
alloc := fn($Expr: type, num: uint): ^Expr {
return @bitcast(request_page(@intcast(calc_pages(Expr, num))))
pages := @inline(calc_pages, Expr, num)
if pages <= MAX_ALLOC {
return @bitcast(request_page(@intcast(pages)))
}
ptr := request_page(0xFF)
remaining := pages - MAX_ALLOC
loop if remaining < MAX_ALLOC break else {
_ := request_page(@intcast(MAX_ALLOC))
remaining -= MAX_ALLOC
}
_ := request_page(@intcast(remaining))
return @bitcast(ptr)
}
// ! stub
$free := fn($Expr: type, ptr: ^Expr, num: uint): void {
release_page(@bitcast(ptr), @intcast(calc_pages(Expr, num)))
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
return
}
RqPageMsg := packed struct {a: u8, count: uint}
$request_page := fn(count: uint): ^u8 {
RqPageMsg := packed struct {a: u8, count: u8}
request_page := fn(count: u8): ^u8 {
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
}
RlPageMsg := packed struct {a: u8, count: uint, ptr: ^u8}
$release_page := fn(ptr: ^u8, count: uint): void {
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
release_page := fn(ptr: ^u8, count: u8): void {
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
}
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
$outb := fn(addr: u16, value: u8): void {
outb := fn(addr: u16, value: u8): void {
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
}
InbMsg := packed struct {a: u8, b: u8, addr: u16}
$inb := fn(addr: u16): u8 {
inb := fn(addr: u16): u8 {
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
}
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
$outl := fn(addr: u16, value: u32): void {
outl := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
}
InlMsg := packed struct {a: u8, b: u8, addr: u16}
$inl := fn(addr: u16): u32 {
inl := fn(addr: u16): u32 {
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
}
OutsMsg := packed struct {a: u8, b: u8, addr: u16, value: u16}
$outs := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutsMsg.(1, 1, addr, value), @sizeof(OutsMsg))
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
InsMsg := packed struct {a: u8, b: u8, addr: u16}
$ins := fn(addr: u16): u16 {
return @eca(3, 3, &InsMsg.(0, 1, addr), @sizeof(InsMsg))
}
CopyMsg := packed struct {a: u8, count: uint, src: ^u8, dest: ^u8}
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8}
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}

View file

@ -1,12 +0,0 @@
// ! will be rewritten to take a file object when filesystem is exist
// returns PID
$spawn := fn(proc_exe: ^u8, length: uint): uint {
return @eca(3, 6, proc_exe, length)
}
/* TODO:
- Spawn an empty process
- Call a function to load bytes into that process from a function
Or
- Manually fill the bytes in
- Execute the process via a run type command */

View file

@ -1,15 +1,7 @@
$any := fn($Expr: type): Expr {
any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
}
$range := fn($Expr: type, min: Expr, max: Expr): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) % (max - min) + *@bitcast(&1) + min
}
$fill := fn($Expr: type, ptr: ^Expr): void {
return @eca(3, 4, ptr, @sizeof(Expr))
}
$fill_buffer := fn(buf: ^u8, len: uint): void {
return @eca(3, 4, buf, len)
range := fn($Expr: type, min: Expr, max: Expr): Expr {
return @inline(any, Expr) % (max - min) + @intcast(1) + min
}

View file

@ -1,7 +0,0 @@
$subscribe_to_interrupt := fn(interrupt_number: u8): bool {
return false
}
// Pauses execution until the interrupt occures
$sleep_until_interrupt := fn(interrupt_number: u8): void {
@eca(6, interrupt_number)
}

View file

@ -1,172 +1,72 @@
// todo: splice function
length := fn(ptr: ^u8): uint {
len := @as(uint, 0)
// loop if *(ptr + len) == 0 return len else len += 1
loop if *(ptr + len) == 0 break else len += 1
return len
}
reverse := fn(str: []u8): void {
if str.len == 0 return;
j := str.len - 1
i := 0
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
ptr := p
negative := num < 0
if negative {
num = -num
}
if radix == 2 {
*ptr = 48
ptr += 1;
*ptr = 98
ptr += 1
} else if radix == 16 {
*ptr = 48
ptr += 1;
*ptr = 120
ptr += 1
} else if radix == 8 {
*ptr = 48
ptr += 1;
*ptr = 111
ptr += 1
}
digits_start := ptr
if num == 0 {
*ptr = 48
ptr += 1
} else {
loop if num == 0 break else {
digit := num % @bitcast(radix)
if digit < 10 {
*ptr = @intcast(digit) + 48
} else {
*ptr = @intcast(digit) + 55
}
ptr += 1
num /= @bitcast(radix)
}
}
if negative {
*ptr = 45
ptr += 1
};
*ptr = 0
@inline(reverse, digits_start)
return p
}
reverse := fn(s: ^u8): void {
i := @as(uint, 0)
j := @inline(length, s) - 1
temp := @as(u8, 0)
loop if i < j {
temp = str[i]
str[i] = str[j]
str[j] = temp
loop if i >= j break else {
temp = *(s + i);
*(s + i) = *(s + j);
*(s + j) = temp
i += 1
j -= 1
} else return
}
equals := fn(lhs: []u8, rhs: []u8): bool {
if lhs.len != rhs.len return false
if lhs.ptr == rhs.ptr return true
i := 0
loop if i == lhs.len break else {
if lhs[i] != rhs[i] return false
i += 1
}
return true
}
clear := fn(str: []u8): void {
i := 0
loop if i == str.len break else {
str[i] = 0
i += 1
}
}
split_once := fn(haystack: []u8, needle: @Any()): ?struct {left: []u8, right: []u8} {
T := @TypeOf(needle)
i := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return null
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches return .(haystack[0..i], haystack[i + needle.len..])
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle {
return .(haystack[0..i], haystack[i + 1..])
} else if i == haystack.len return null
i += 1
}
} else {
@error("Type of needle must be []u8 or u8.")
}
}
split := fn(iter: []u8, needle: @Any()): struct {
str: []u8,
needle: @TypeOf(needle),
done: bool,
next := fn(self: ^Self): ?[]u8 {
if self.done return null;
splits := split_once(self.str, self.needle)
if splits != null {
self.str = splits.right
return splits.left
} else {
self.done = true
return self.str
}
}
} {
T := @TypeOf(needle)
if T != []u8 & T != u8 {
@error("Type of needle must be []u8 or u8.")
}
return .(iter, needle, false)
}
chars := fn(iter: []u8): struct {
str: []u8,
next := fn(self: ^Self): ?u8 {
if self.str.len == 0 return null
self.str = self.str[1..]
return self.str[0]
}
} {
return .(iter)
}
count := fn(haystack: []u8, needle: @Any()): uint {
T := @TypeOf(needle)
i := 0
c := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return c
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches c += 1
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle c += 1 else if i == haystack.len return c
i += 1
}
} else {
@error("Type of needle must be []u8 or u8.")
}
}
left_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[0] == sub[0] {
loop if i == sub.len {
return str[i..str.len]
} else if str[i] != sub[i] | i == str.len {
break
} else {
i += 1
}
}
return str
}
right_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[str.len - 1] == sub[sub.len - 1] {
loop if i == sub.len {
return str[0..str.len - i]
} else if str[str.len - i - 1] != sub[sub.len - i - 1] | i == str.len {
break
} else {
i += 1
}
}
return str
}
trim := fn(str: []u8, sub: []u8): []u8 {
return right_trim(left_trim(str, sub), sub)
return
}

View file

@ -1,63 +0,0 @@
.{math: .{Vec2}, buffer, log, memory, string} := @use("stn");
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("lib:sunset_proto");
.{Surface, Color} := @use("lib:render")
// ! in the future this should be safely handled
channel := Channel.(0, 0)
find_server := fn(): void {
log.info("client: locating server")
channel2 := await_channel()
channel.server = channel2.server
channel.client = channel2.client
log.info("client: server located")
}
new := fn(props: WindowProps): ?Window {
send_header(message.syn, channel.server)
response := await_message(Channel, channel.client)
if response.header.kind != message.ack {
return null
}
log.info("client: recv ack")
send_message(WindowProps, message.props, props, response.body.server)
windowdata := await_message(WindowData, response.body.client)
if windowdata.header.kind != message.ack {
return null
}
log.info("client: recv windowdata")
surface := Surface.new(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
return .(windowdata.body, surface)
}
quit := fn(client: Window): void {
send_header(message.quit, client.data.channel.server)
}
connected := fn(client: Window): bool {
return true
}
shutdown_server := fn(client: Window): bool {
return false
}
update_props := fn(client: Window): bool {
return false
}
update_permissions := fn(client: Window): bool {
return false
}
send_frame := fn(client: Window): bool {
send_header(message.frame_ready, client.data.channel.server)
response := await_message(uint, client.data.channel.client)
if response.header.kind != message.ack {
return false
}
// ! FOR NOW, server will ALWAYS be local,
// ! so we can send pointer to surface.
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
return true
}

View file

@ -1,100 +0,0 @@
.{math: .{Vec2}, buffer, memory} := @use("stn");
.{Surface} := @use("lib:render")
$BUFFER_SERVER := "sunset_server"
$BUFFER_CLIENT := "sunset_client"
Channel := packed struct {
client: uint,
server: uint,
}
client := @use("./client.hb")
server := @use("./server.hb")
message := @use("./message.hb")
permissions := @use("./permissions.hb")
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
}
$send_header := fn(kind: MessageKind, buffer_id: uint): void {
buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
}
$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
buffer.recv(?Message(Expr), buffer_id, &response)
return response
}
$recv_header := fn(buffer_id: uint): ?MessageHeader {
response := @as(?MessageHeader, null)
buffer.recv(?MessageHeader, buffer_id, &response)
return response
}
await_channel := fn(): Channel {
channel := Channel.(0, 0)
loop if channel.server != 0 break else {
channel.server = buffer.search(BUFFER_SERVER)
}
loop if channel.client != 0 break else {
channel.client = buffer.search(BUFFER_CLIENT)
}
return channel
}
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?Message(Expr), buffer_id, &response)
if response != null {
return @as(Message(Expr), response)
}
}
}
await_header := fn(buffer_id: uint): MessageHeader {
response := @as(?MessageHeader, null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?MessageHeader, buffer_id, &response)
if response != null {
return @as(MessageHeader, response)
}
}
}
MessageKind := u8
MessageHeader := packed struct {
kind: MessageKind,
}
Message := fn($Expr: type): type {
return packed struct {
header: MessageHeader,
body: Expr,
}
}
WindowProps := struct {
position: Vec2(uint),
dimensions: Vec2(uint),
title: []u8,
}
WindowData := struct {
props: WindowProps,
channel: Channel,
permissions: uint,
}
Window := struct {
data: WindowData,
surface: Surface,
}

View file

@ -1,8 +0,0 @@
// ! all values in this file are subject to change.
$syn := 1
$ack := 2
$refused := 3
$quit := 4
$props := 5
$shutdown := 6
$frame_ready := 7

View file

@ -1,5 +0,0 @@
$none := 0b0
$exclusive_framebuffer := 0b1
$shutdown := 0b100
$default := none

View file

@ -1,131 +0,0 @@
.{math, log, string, random, buffer, memory} := @use("stn");
.{Color, Surface, text} := @use("lib:render");
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("lib:sunset_proto")
WindowServer := struct {
window_count: uint,
channel: Channel,
// ! replace this with a collection when we get an allocator
windows: [10]?Window,
font: text.Font,
}
// ! in the future this should be safely handled
server := @as(WindowServer, idk)
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
start := fn(): void {
font := text.font_from_psf2(@bitcast(&psf), false)
if font == null {
log.error("server: failed to load asset")
return
}
server = .(
0,
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
.[null, null, null, null, null, null, null, null, null, null],
@as(text.Font, font),
)
log.info("server: started server")
}
incoming := fn(): bool {
msg := recv_header(server.channel.server)
if msg == null {
return true
}
if msg.kind == message.syn {
log.info("server: recv syn")
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
send_message(Channel, message.ack, channel, server.channel.client)
props := await_message(WindowProps, channel.server)
if props.header.kind != message.props {
return true
}
log.info("server: recv props")
// ! do inspection of requested props here
data := WindowData.(props.body, channel, permissions.default)
send_message(WindowData, message.ack, data, channel.client)
surface := new_window_decorations(data.props.dimensions)
// decorations
{
title := data.props.title
deco_length := title.len * 10
// draw the window tab bar
surface.put_filled_rect(.(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
// Draw the window tab
surface.put_filled_rect(.(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
// Draw the outside box
surface.put_rect(.(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
surface.put_text(server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
}
server.windows[server.window_count] = .(data, surface)
server.window_count += 1
}
return true
}
$DECO_WIDTH := 2
$DECO_HEIGHT_TOP := 20
$DECO_HEIGHT_BOTTOM := 1
$DECO_COLOUR := Color.(100, 200, 255, 255)
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
return @inline(Surface.new, dimensions.x + DECO_WIDTH, dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM)
}
// ! compositor code. this currently disallows tearing.
collect_frames := fn(): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
header := recv_header(window.data.channel.server)
if header == null {
i += 1
continue
}
if header.kind != message.frame_ready {
i += 1
continue
}
send_header(message.ack, window.data.channel.client)
ptr := await_message(^Color, window.data.channel.server)
if ptr.header.kind != message.ack {
i += 1
continue
}
window.surface.put_surface(
Surface.(
ptr.body,
window.data.props.dimensions.x,
window.data.props.dimensions.y,
window.data.props.dimensions.x * window.data.props.dimensions.y,
),
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
false,
)
i += 1
}
}
render_clients := fn(screen: Surface): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
screen.put_surface(window.surface, window.data.props.position, false)
i += 1
}
}

View file

@ -1 +0,0 @@
# ablefetch

View file

@ -1,43 +0,0 @@
stn := @use("stn")
sunset := @use("lib:sunset_proto")
render := @use("lib:render")
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
horizon_api := @use("lib:horizon_api");
.{Vec2} := stn.math;
.{log} := stn;
.{set_color, render_label_to_surface, Label} := horizon_api.widgets.label
main := fn(): void {
sunset.client.find_server()
window := sunset.client.new(.(.(10, 10), .(400, 300), "ableFetch!"))
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
// pos := Vec2(uint).(1, 100)
if window == null {
log.error("got no window")
return
}
text_label := Label.new_label("kernel : akern 0.2.0", 300)
text_label_2 := Label.new_label("os : ableos", 300)
text_label_3 := Label.new_label("wm : sunset", 300)
text_label.set_color(render.BLACK, render.WHITE)
text_label_2.set_color(render.BLACK, render.WHITE)
text_label_3.set_color(render.BLACK, render.WHITE)
pos1 := Vec2(uint).(1, 1)
pos2 := Vec2(uint).(1, 20)
pos3 := Vec2(uint).(1, 40)
render_label_to_surface(window.surface, text_label, font, pos1)
render_label_to_surface(window.surface, text_label_2, font, pos2)
render_label_to_surface(window.surface, text_label_3, font, pos3)
loop {
// stn.log.info("AAAA")
_ = sunset.client.send_frame(window)
// stn.sleep.sleep_until_interrupt(100)
}
}

Some files were not shown because too many files have changed in this diff Show more