forked from AbleOS/ableos
Compare commits
69 commits
Author | SHA1 | Date | |
---|---|---|---|
peony | 5028062e39 | ||
peony | f7f9fece4f | ||
b505622601 | |||
80ae717dd9 | |||
ab8b2309ae | |||
koniifer | 7b7e02976d | ||
koniifer | c1c02ffefd | ||
peony | f4ceab972c | ||
able | 8602ceb0d3 | ||
peony | 96c07e137b | ||
peony | d78878a12f | ||
Able | 6b673bc7e6 | ||
peony | 8f265ebf40 | ||
peony | 3d5a8f6f10 | ||
peony | f11122e58e | ||
peony | 2fdede7199 | ||
koniifer | 0af4d142a4 | ||
peony | 13422dfd9f | ||
peony | 90a97cd160 | ||
peony | 23b45b1887 | ||
koniifer | 36f0d357cf | ||
peony | cf37eaf086 | ||
peony | 284aa5a5e6 | ||
koniifer | ccddf36050 | ||
peony | 11976b752f | ||
peony | 98b15d4c10 | ||
peony | f5c6d7d822 | ||
koniifer | da5f1a7a19 | ||
koniifer | 2808bc9e7c | ||
koniifer | d958a103fa | ||
koniifer | ee82bc5705 | ||
Able | 3d53b641bf | ||
peony | efcd6c0631 | ||
peony | b795aced8e | ||
peony | 08099b0877 | ||
koniifer | cea7f1fa5c | ||
Able | 614bef7ec5 | ||
Able | b0f6aa53bd | ||
Able | d5f4ce18a3 | ||
koniifer | 907c0d0dd4 | ||
koniifer | 95b4a921dc | ||
koniifer | b6261d014d | ||
Able | 56ee0fe851 | ||
koniifer | b07bac1f1f | ||
peony | a1bfd8e85f | ||
koniifer | dc9273b3c1 | ||
Able | e6d8f5c822 | ||
koniifer | 8ad7542b9c | ||
Able | e40a22fccd | ||
koniifer | cf917927a5 | ||
peony | edfb588060 | ||
peony | cc4a32afaa | ||
koniifer | 97ceb12d6e | ||
koniifer | bae58ade61 | ||
koniifer | b21c05e924 | ||
Able | 2f5bc73665 | ||
Able | 0003464099 | ||
koniifer | 77a708d41e | ||
peony | be6a095c14 | ||
peony | 3409f5051a | ||
peony | aac1164d55 | ||
peony | 89d08d8a62 | ||
peony | 8f5833955f | ||
peony | 4c0adbe15d | ||
peony | 3708acc077 | ||
peony | b5b122f451 | ||
Able | 8c7b95277d | ||
peony | 39ebaa03ba | ||
peony | de8000f596 |
126
Cargo.lock
generated
126
Cargo.lock
generated
|
@ -1,6 +1,6 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aarch64-cpu"
|
||||
|
@ -13,9 +13,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.19"
|
||||
version = "0.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f"
|
||||
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
|
@ -65,15 +65,6 @@ 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"
|
||||
|
@ -82,9 +73,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.37"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
|
||||
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
@ -208,12 +199,6 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.1"
|
||||
|
@ -228,24 +213,23 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "hbbytecode"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
|
||||
|
||||
[[package]]
|
||||
name = "hblang"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.1",
|
||||
"hashbrown",
|
||||
"hbbytecode",
|
||||
"hbvm",
|
||||
"log",
|
||||
"regalloc2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbvm"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#8b98c2ed1becb92046bb7b687ca00813da441248"
|
||||
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#86ca959ea3eae1cb32298e135a444820583d24a0"
|
||||
dependencies = [
|
||||
"hbbytecode",
|
||||
]
|
||||
|
@ -396,7 +380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.1",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -406,8 +390,9 @@ dependencies = [
|
|||
"aarch64-cpu",
|
||||
"crossbeam-queue",
|
||||
"derive_more",
|
||||
"hashbrown 0.15.1",
|
||||
"hashbrown",
|
||||
"hbvm",
|
||||
"ktest_macro",
|
||||
"limine",
|
||||
"log",
|
||||
"sbi",
|
||||
|
@ -420,6 +405,14 @@ dependencies = [
|
|||
"xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ktest_macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
|
@ -428,9 +421,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.162"
|
||||
version = "0.2.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
|
||||
[[package]]
|
||||
name = "limine"
|
||||
|
@ -440,9 +433,9 @@ checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
|
|||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
|
||||
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
@ -519,9 +512,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.89"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -553,19 +546,6 @@ 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"
|
||||
|
@ -602,12 +582,6 @@ 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"
|
||||
|
@ -619,9 +593,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.16"
|
||||
version = "0.23.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
|
||||
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
|
@ -675,18 +649,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -752,9 +726,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.87"
|
||||
version = "2.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -824,9 +798,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uart_16550"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d"
|
||||
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"rustversion",
|
||||
|
@ -835,9 +809,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.13"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
|
@ -868,9 +842,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.3"
|
||||
version = "2.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
|
||||
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
|
@ -911,9 +885,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.6"
|
||||
version = "0.26.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
|
||||
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
@ -1070,9 +1044,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
|
||||
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"stable_deref_trait",
|
||||
|
@ -1082,9 +1056,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "yoke-derive"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1094,18 +1068,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
|
||||
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
|
||||
dependencies = [
|
||||
"zerofrom-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom-derive"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
96
flake.lock
Normal file
96
flake.lock
Normal file
|
@ -0,0 +1,96 @@
|
|||
{
|
||||
"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
|
||||
}
|
30
flake.nix
Normal file
30
flake.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
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
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
|
@ -3,12 +3,15 @@ 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",
|
||||
] }
|
||||
ktest_macro = { path = "ktest_macro" }
|
||||
log = "0.4"
|
||||
spin = "0.9"
|
||||
slab = { version = "0.4", default-features = false }
|
||||
|
|
11
kernel/ktest_macro/Cargo.toml
Normal file
11
kernel/ktest_macro/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[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"] }
|
29
kernel/ktest_macro/src/lib.rs
Normal file
29
kernel/ktest_macro/src/lib.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
extern crate proc_macro;
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
use {
|
||||
proc_macro::TokenStream,
|
||||
quote::quote,
|
||||
syn::{parse_macro_input, ItemFn}
|
||||
};
|
||||
|
||||
#[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 static_var_name = syn::Ident::new(
|
||||
&format!("__ktest_{}", test_name),
|
||||
test_name.span(),
|
||||
);
|
||||
let out = quote! {
|
||||
// #[cfg(feature = "ktest")]
|
||||
#input
|
||||
|
||||
// #[cfg(feature = "ktest")]
|
||||
#[unsafe(link_section = ".note.ktest")]
|
||||
#[used]
|
||||
pub static #static_var_name: fn() = #test_name;
|
||||
};
|
||||
|
||||
TokenStream::from(out)
|
||||
}
|
|
@ -38,8 +38,16 @@ 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)
|
||||
*(.bss .bss.*)
|
||||
|
|
|
@ -14,3 +14,29 @@ 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)
|
||||
});
|
||||
|
|
|
@ -11,7 +11,9 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
|||
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||
|
||||
#[repr(u8)]
|
||||
enum Interrupt {
|
||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
||||
|
||||
pub enum Interrupt {
|
||||
Timer = 32,
|
||||
ApicErr = u8::MAX - 1,
|
||||
Spurious = u8::MAX,
|
||||
|
@ -60,17 +62,49 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
fn interrupt(interrupt_type: Interrupt) {
|
||||
use crate::arch::INTERRUPT_LIST;
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// log::info!("{}", buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::asm!(
|
||||
core::arch::naked_asm!(
|
||||
// Initialise SSE
|
||||
"mov rax, cr0",
|
||||
"and ax, 0xfffb",
|
||||
|
@ -46,7 +46,6 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
// Jump to the kernel entry point
|
||||
"jmp {}",
|
||||
sym start,
|
||||
options(noreturn),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -54,7 +53,7 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
#[naked]
|
||||
#[cfg(target_feature = "avx2")]
|
||||
unsafe extern "C" fn _kernel_start() -> ! {
|
||||
core::arch::asm!(
|
||||
core::arch::naked_asm!(
|
||||
// Enable protected mode and configure control registers
|
||||
"mov rax, cr0",
|
||||
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
|
||||
|
@ -100,7 +99,6 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
|||
"jmp {0}",
|
||||
sym start,
|
||||
sym oops,
|
||||
options(noreturn),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -111,7 +109,7 @@ unsafe extern "C" fn oops() -> ! {
|
|||
unsafe extern "C" fn start() -> ! {
|
||||
logging::init();
|
||||
crate::logger::init().expect("failed to set logger");
|
||||
log::info!("Initialising AKern {}", crate::VERSION);
|
||||
log::debug!("Initialising AKern {}", crate::VERSION);
|
||||
|
||||
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
|
||||
memory::init_pt(VirtAddr::new(
|
||||
|
@ -190,7 +188,7 @@ unsafe extern "C" fn start() -> ! {
|
|||
// TODO: Add in rdseed and rdrand as sources for randomness
|
||||
let _rand = xml::XMLElement::new("Random");
|
||||
|
||||
log::trace!("Getting boot modules");
|
||||
log::debug!("Getting boot modules");
|
||||
let bm = MOD_REQ.get_response().get();
|
||||
|
||||
let mut bootmodules = alloc::vec::Vec::new();
|
||||
|
@ -228,7 +226,7 @@ unsafe extern "C" fn start() -> ! {
|
|||
break;
|
||||
}
|
||||
}
|
||||
log::info!("Boot module count: {:?}", bootmodules.len());
|
||||
log::debug!("Boot module count: {:?}", bootmodules.len());
|
||||
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
||||
}
|
||||
|
||||
|
|
|
@ -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::info!("pci device-({}) addr {} is {}", device, addr, reg2);
|
||||
log::debug!("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);
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
//! Environment call handling routines
|
||||
|
||||
use crate::holeybytes::kernel_services::{
|
||||
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 {
|
||||
|
@ -58,10 +67,10 @@ pub fn handler(vm: &mut Vm) {
|
|||
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 => {
|
||||
|
@ -143,6 +152,43 @@ pub fn handler(vm: &mut Vm) {
|
|||
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();
|
||||
|
@ -182,7 +228,7 @@ pub fn handler(vm: &mut Vm) {
|
|||
} else {
|
||||
unsafe {
|
||||
let ptr = map_ptr as *mut u8;
|
||||
ptr.copy_from(msg.as_ptr(), msg.len());
|
||||
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
|
||||
}
|
||||
|
||||
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||
|
|
|
@ -9,7 +9,20 @@ 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);
|
||||
|
||||
let log_level = msg_vec[0];
|
||||
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 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;
|
||||
|
||||
|
@ -20,18 +33,6 @@ 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))
|
||||
|
|
|
@ -25,42 +25,16 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
||||
const BLOCK_SIZE: usize = 64;
|
||||
let mut remaining = count * size;
|
||||
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
||||
let total_size = count * size;
|
||||
src.copy_to_nonoverlapping(dest, size);
|
||||
|
||||
if remaining < 16 {
|
||||
src.copy_to_nonoverlapping(dest, remaining);
|
||||
return;
|
||||
}
|
||||
let mut copied = 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);
|
||||
while copied < total_size {
|
||||
let copy_size = copied.min(total_size - copied);
|
||||
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
|
||||
copied += copy_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,8 +92,7 @@ fn sds_create_service(protocol: &'static str) -> u64 {
|
|||
// let a: protocol::Protocol = protocol.into();
|
||||
buff_id
|
||||
}
|
||||
|
||||
fn sds_search_service(protocol: &str) -> u64 {
|
||||
pub fn sds_search_service(protocol: &str) -> u64 {
|
||||
let services = SERVICES.lock();
|
||||
let compare = Protocol::from(protocol);
|
||||
for (bid, protocol_canidate) in &services.0 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mod ecah;
|
||||
mod kernel_services;
|
||||
pub mod kernel_services;
|
||||
mod mem;
|
||||
|
||||
use {
|
||||
|
|
|
@ -8,7 +8,10 @@ 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},
|
||||
|
@ -19,6 +22,14 @@ use {
|
|||
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||
debug!("Entered kmain");
|
||||
|
||||
#[cfg(feature = "ktest")] {
|
||||
use crate::ktest;
|
||||
debug!("TESTING");
|
||||
ktest::test_main();
|
||||
|
||||
loop {};
|
||||
}
|
||||
|
||||
// let kcmd = build_cmd("Kernel Command Line", cmdline);
|
||||
// trace!("Cmdline: {kcmd:?}");
|
||||
|
||||
|
@ -65,13 +76,24 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
fb1.address.as_ptr().unwrap() as *const u8
|
||||
);
|
||||
|
||||
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!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||
log::info!(
|
||||
"Starting {}",
|
||||
module
|
||||
.path
|
||||
.split('/')
|
||||
.last()
|
||||
.unwrap()
|
||||
.split('.')
|
||||
.next()
|
||||
.unwrap()
|
||||
);
|
||||
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||
|
||||
// decode AbleOS Executable format
|
||||
let header = &module.bytes[0..46];
|
||||
|
@ -92,17 +114,17 @@ 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::info!("{code_length} + {data_length} = {end}");
|
||||
log::debug!("{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(async move {
|
||||
executor.spawn(Box::pin(async move {
|
||||
if let Err(e) = thr.await {
|
||||
log::error!("{e:?}");
|
||||
}
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
debug!("Random number: {}", hardware_random_u64());
|
||||
|
@ -113,6 +135,10 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
|||
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)
|
||||
|
@ -130,10 +156,3 @@ 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]");
|
||||
}
|
||||
|
|
38
kernel/src/ktest.rs
Normal file
38
kernel/src/ktest.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
pub use ktest_macro::ktest;
|
||||
use log::debug;
|
||||
|
||||
extern "C" {
|
||||
static __ktest_start: fn();
|
||||
static __ktest_end: fn();
|
||||
}
|
||||
|
||||
// TODO: Get test_fn linker name (may require no_mangle in macro)
|
||||
// More info on tests (run the rest even if panic)
|
||||
// Implement ktest for arm and riscv (Later problems, see below)
|
||||
// Allow for arch specific tests (Leave for now)
|
||||
// Allow for ktest test name attr
|
||||
// Usefull message at the end of testing
|
||||
pub fn test_main() {
|
||||
unsafe {
|
||||
let mut current_test = &__ktest_start as *const fn();
|
||||
let mut current = 1;
|
||||
let test_end = &__ktest_end as *const fn();
|
||||
|
||||
while current_test < test_end {
|
||||
let test_fn = *current_test;
|
||||
|
||||
debug!("Running test {}", current);
|
||||
|
||||
test_fn();
|
||||
debug!("Test {} passed", current);
|
||||
|
||||
current_test = current_test.add(1);
|
||||
current += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[ktest]
|
||||
pub fn trivial_assertion() {
|
||||
assert_eq!(1, 1);
|
||||
}
|
|
@ -2,20 +2,19 @@
|
|||
//! 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,
|
||||
ptr_sub_ptr,
|
||||
custom_test_frameworks,
|
||||
naked_functions,
|
||||
pointer_is_aligned_to
|
||||
pointer_is_aligned_to,
|
||||
)]
|
||||
#![test_runner(crate::test_runner)]
|
||||
#![allow(dead_code, internal_features)]
|
||||
#![allow(dead_code, internal_features, static_mut_refs)]
|
||||
extern crate alloc;
|
||||
|
||||
mod allocator;
|
||||
|
@ -33,6 +32,10 @@ mod memory;
|
|||
mod task;
|
||||
mod utils;
|
||||
|
||||
// #[cfg(feature = "tests")]
|
||||
mod ktest;
|
||||
|
||||
use alloc::string::ToString;
|
||||
use versioning::Version;
|
||||
|
||||
/// Kernel's version
|
||||
|
@ -56,15 +59,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
|
|||
));
|
||||
}
|
||||
|
||||
let msg = info.message();
|
||||
let msg = info.message().to_string().replace("\n", "\r\n");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,24 +29,24 @@ pub fn yield_now() -> impl Future<Output = ()> {
|
|||
YieldNow(false)
|
||||
}
|
||||
|
||||
pub struct Executor<F: Future<Output = ()> + Send> {
|
||||
tasks: Slab<Task<F>>,
|
||||
pub struct Executor {
|
||||
tasks: Slab<Task>,
|
||||
task_queue: Arc<TaskQueue>,
|
||||
}
|
||||
|
||||
impl<F: Future<Output = ()> + Send> Executor<F> {
|
||||
pub fn new(size: usize) -> Self {
|
||||
impl Executor {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tasks: Slab::with_capacity(size),
|
||||
tasks: Slab::new(),
|
||||
task_queue: Arc::new(TaskQueue::new()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn spawn(&mut self, future: F) {
|
||||
self.task_queue
|
||||
.queue
|
||||
.push(self.tasks.insert(Task::new(future)));
|
||||
pub fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) -> usize {
|
||||
let id = self.tasks.insert(Task::new(future));
|
||||
self.task_queue.queue.push(id);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
|
@ -83,16 +83,16 @@ impl<F: Future<Output = ()> + Send> Executor<F> {
|
|||
}
|
||||
}
|
||||
|
||||
struct Task<F: Future<Output = ()> + Send> {
|
||||
future: Pin<Box<F>>,
|
||||
struct Task {
|
||||
future: Pin<Box<dyn Future<Output = ()> + Send>>,
|
||||
waker: Option<TaskWaker>,
|
||||
}
|
||||
|
||||
impl<F: Future<Output = ()> + Send> Task<F> {
|
||||
impl Task {
|
||||
#[inline(always)]
|
||||
pub fn new(future: F) -> Self {
|
||||
pub fn new(future: Pin<Box<dyn Future<Output = ()> + Send>>) -> Self {
|
||||
Self {
|
||||
future: Box::pin(future),
|
||||
future,
|
||||
waker: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"arch": "aarch64",
|
||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||
"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,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(unused)]
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::format,
|
||||
fs::{read_to_string, File},
|
||||
io::{BufWriter, Write},
|
||||
|
@ -13,6 +14,7 @@ pub struct Package {
|
|||
name: String,
|
||||
binaries: Vec<String>,
|
||||
build_cmd: String,
|
||||
args: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Package {
|
||||
|
@ -46,36 +48,46 @@ impl Package {
|
|||
let mut binaries = vec![];
|
||||
|
||||
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
||||
// if count != 0 {
|
||||
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);
|
||||
// build_cmd.pop();
|
||||
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>>(),
|
||||
};
|
||||
|
||||
Self {
|
||||
name,
|
||||
binaries,
|
||||
build_cmd,
|
||||
args,
|
||||
}
|
||||
}
|
||||
pub fn build(&self, out: &mut Vec<u8>) -> 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();
|
||||
|
||||
hblang::run_compiler(
|
||||
&path,
|
||||
Options {
|
||||
fmt: true,
|
||||
in_house_regalloc: true,
|
||||
..Default::default()
|
||||
},
|
||||
out,
|
||||
&mut warnings,
|
||||
)?;
|
||||
|
||||
match std::fs::create_dir("target/programs") {
|
||||
|
@ -87,9 +99,11 @@ impl Package {
|
|||
hblang::run_compiler(
|
||||
&path,
|
||||
Options {
|
||||
in_house_regalloc: true,
|
||||
..Default::default()
|
||||
},
|
||||
out,
|
||||
&mut warnings,
|
||||
)?;
|
||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
|
||||
out.clear();
|
||||
|
@ -98,9 +112,11 @@ impl Package {
|
|||
&path,
|
||||
Options {
|
||||
dump_asm: true,
|
||||
in_house_regalloc: true,
|
||||
..Default::default()
|
||||
},
|
||||
out,
|
||||
&mut warnings,
|
||||
)?;
|
||||
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
|
||||
out.clear();
|
||||
|
|
|
@ -27,6 +27,7 @@ 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;
|
||||
|
@ -38,17 +39,42 @@ 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).change_context(Error::Build)
|
||||
build(release, target, debuginfo, tests).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" {
|
||||
|
@ -63,12 +89,14 @@ 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)?;
|
||||
build(release, target, debuginfo, tests)?;
|
||||
run(release, target, do_accel)
|
||||
}
|
||||
Some("help" | "h") => {
|
||||
|
@ -82,6 +110,7 @@ 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(())
|
||||
|
@ -310,7 +339,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
|
|||
.expect("Copy failed");
|
||||
}
|
||||
|
||||
fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||
fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<(), Error> {
|
||||
let fs = get_fs().change_context(Error::Io)?;
|
||||
let mut com = Command::new("cargo");
|
||||
com.current_dir("kernel");
|
||||
|
@ -322,6 +351,10 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
|||
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
|
||||
}
|
||||
|
||||
if tests {
|
||||
com.args(["--features", "ktest"]);
|
||||
}
|
||||
|
||||
if target == Target::Riscv64Virt {
|
||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||
}
|
||||
|
@ -378,6 +411,7 @@ 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"])
|
||||
|
@ -413,6 +447,8 @@ 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 => {
|
||||
|
@ -470,6 +506,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||
let (ovmf_url, ovmf_path) = match target {
|
||||
Target::X86_64 | Target::X86_64Avx2 => (
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-07-27"
|
||||
# old toolchain
|
||||
# channel = "nightly-2024-07-27"
|
||||
channel = "nightly-2024-11-20"
|
||||
components = ["rust-src", "llvm-tools"]
|
||||
|
|
|
@ -3,7 +3,7 @@ stn := @use("../../../../libraries/stn/src/lib.hb");
|
|||
.{Vec2} := stn.math
|
||||
|
||||
render := @use("../../../../libraries/render/src/lib.hb");
|
||||
.{Surface} := render;
|
||||
.{Surface, Color} := render;
|
||||
.{Font} := render.text
|
||||
|
||||
Label := struct {
|
||||
|
@ -12,6 +12,8 @@ Label := struct {
|
|||
surface: Surface,
|
||||
text: ^u8,
|
||||
text_length: uint,
|
||||
bg: Color,
|
||||
fg: Color,
|
||||
}
|
||||
|
||||
set_label_text := fn(label: Label, text: ^u8): void {
|
||||
|
@ -24,8 +26,8 @@ set_label_text := fn(label: Label, text: ^u8): void {
|
|||
|
||||
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
|
||||
if label.is_dirty {
|
||||
render.clear(label.surface, render.black)
|
||||
render.put_text(label.surface, font, .(0, 0), render.white, label.text)
|
||||
render.clear(label.surface, label.bg)
|
||||
render.put_text(label.surface, font, .(0, 0), label.fg, label.text)
|
||||
}
|
||||
render.put_surface(surface, label.surface, pos, false)
|
||||
}
|
||||
|
@ -33,6 +35,12 @@ render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: V
|
|||
new_label := fn(text: ^u8): Label {
|
||||
text_surface := render.new_surface(1024, 20)
|
||||
text_length := string.length(text)
|
||||
label := Label.(3, true, text_surface, text, text_length)
|
||||
label := Label.(3, true, text_surface, text, text_length, render.black, render.white)
|
||||
return label
|
||||
}
|
||||
|
||||
$set_color := fn(label: Label, bg: Color, fg: Color): void {
|
||||
label.bg = bg
|
||||
label.fg = fg
|
||||
label.is_dirty = true
|
||||
}
|
|
@ -1,13 +1,9 @@
|
|||
keycodes := @use("keycodes.hb");
|
||||
.{KeyCode} := keycodes
|
||||
|
||||
KeyEvent := struct {
|
||||
// 0 if down
|
||||
// 1 if up
|
||||
up: u8,
|
||||
// 0 if not just triggered
|
||||
// 1 if just triggered
|
||||
just_triggered: u8,
|
||||
KeyEvent := packed struct {
|
||||
up: bool,
|
||||
just_triggered: bool,
|
||||
key: KeyCode,
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,17 @@ events := @use("events.hb");
|
|||
.{KeyEvent, MouseEvent} := events
|
||||
|
||||
recieve_key_event := fn(): ?KeyEvent {
|
||||
kevent := KeyEvent.(false, false, 0)
|
||||
|
||||
buf_id := buffer.search("PS/2 Keyboard\0")
|
||||
|
||||
// Read out of the Keyboard buffer here
|
||||
buffer.recv(KeyEvent, buf_id, &kevent)
|
||||
|
||||
if kevent.just_triggered {
|
||||
return kevent
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -15,7 +26,7 @@ recieve_mouse_event := fn(): ?MouseEvent {
|
|||
buf_id := buffer.search("PS/2 Mouse\0")
|
||||
|
||||
// Read out of the Mouse buffer here
|
||||
buffer.recv(MouseEvent, buf_id, @bitcast(&mevent))
|
||||
buffer.recv(MouseEvent, buf_id, &mevent)
|
||||
|
||||
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
|
||||
return mevent
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
# Images
|
||||
- General over image format
|
||||
- Support formats:
|
||||
- PNG
|
||||
- Animation
|
||||
|
||||
# API
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
|
||||
.{log, memory} := @use("../../../stn/src/lib.hb")
|
||||
.{log} := @use("../../../stn/src/lib.hb")
|
||||
|
||||
BitmapFileHeader := packed struct {
|
||||
magic: u16,
|
||||
|
@ -41,7 +41,7 @@ from := fn(bmp: ^u8): ?Surface {
|
|||
return null
|
||||
}
|
||||
|
||||
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height)
|
||||
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
|
||||
rhs := new_surface(info_header.width, info_header.height)
|
||||
put_surface(rhs, lhs, .(0, 0), true)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.{Color, Surface, new_surface} := @use("../lib.hb");
|
||||
.{log, memory} := @use("../../../stn/src/lib.hb")
|
||||
.{log} := @use("../../../stn/src/lib.hb")
|
||||
|
||||
/* source:
|
||||
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
||||
|
@ -13,7 +13,7 @@ $QOI_OP_RUN := 0xC0
|
|||
$QOI_OP_RGB := 0xFE
|
||||
$QOI_OP_RGBA := 0xFF
|
||||
$QOI_MASK_2 := 0xC0
|
||||
QOI_COLOR_HASH := fn(c: Color): u8 {
|
||||
$QOI_COLOR_HASH := fn(c: Color): u8 {
|
||||
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
|
||||
}
|
||||
$QOI_MAGIC := 0x716F6966
|
||||
|
@ -89,7 +89,7 @@ from := fn(qoi: ^u8): ?Surface {
|
|||
run = b1 & 0x3F
|
||||
}
|
||||
|
||||
index[@inline(QOI_COLOR_HASH, px)] = px
|
||||
index[QOI_COLOR_HASH(px)] = px
|
||||
};
|
||||
|
||||
*(surface.buf + px_pos) = px
|
||||
|
|
|
@ -38,14 +38,20 @@ $light_cyan := Color.(255, 255, 0, 255)
|
|||
put_pixel := mode.put_pixel
|
||||
put_rect := mode.put_rect
|
||||
put_filled_rect := mode.put_filled_rect
|
||||
put_trirect := mode.put_trirect
|
||||
put_circle := mode.put_circle
|
||||
put_filled_circle := mode.put_filled_circle
|
||||
put_textured_circle := mode.put_textured_circle
|
||||
put_line := mode.put_line
|
||||
put_vline := mode.put_vline
|
||||
put_hline := mode.put_hline
|
||||
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
|
||||
//put_trirect := mode.put_trirect
|
||||
//put_vline := mode.put_vline
|
||||
//put_hline := mode.put_hline
|
||||
|
||||
// Display
|
||||
sync := mode.sync
|
|
@ -10,19 +10,21 @@ Surface := struct {
|
|||
buf: ^Color,
|
||||
width: uint,
|
||||
height: uint,
|
||||
size: uint,
|
||||
}
|
||||
|
||||
new_surface := fn(width: uint, height: uint): Surface {
|
||||
return .(
|
||||
@inline(memory.alloc, Color, width * height),
|
||||
memory.alloc(Color, width * height),
|
||||
width,
|
||||
height,
|
||||
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))
|
||||
memory.copy(Color, surface.buf, new.buf, @intcast(surface.size))
|
||||
return new
|
||||
}
|
||||
|
||||
|
@ -33,42 +35,38 @@ init := fn(doublebuffer: bool): Surface {
|
|||
if doublebuffer {
|
||||
return new_surface(width, height)
|
||||
} else {
|
||||
return .(framebuffer, width, height)
|
||||
return .(framebuffer, width, height, width * height)
|
||||
}
|
||||
}
|
||||
|
||||
clear := fn(surface: Surface, color: Color): void {
|
||||
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
|
||||
$clear := fn(surface: Surface, color: Color): void {
|
||||
memory.set(Color, &color, surface.buf, surface.width * surface.height)
|
||||
}
|
||||
|
||||
sync := fn(surface: Surface): void {
|
||||
if surface.buf == framebuffer {
|
||||
return
|
||||
}
|
||||
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
|
||||
$sync := fn(surface: Surface): void {
|
||||
memory.copy(Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
|
||||
}
|
||||
|
||||
index := fn(surface: Surface, x: uint, y: uint): uint {
|
||||
$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)
|
||||
$indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
|
||||
return surface.buf + 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_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
|
||||
return *indexptr(surface, pos.x, pos.y) = color
|
||||
}
|
||||
|
||||
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)
|
||||
top_start_idx := indexptr(surface, pos.x, pos.y)
|
||||
bottom_start_idx := 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, tr.x)
|
||||
@inline(memory.set, Color, &color, bottom_start_idx, tr.x)
|
||||
memory.set(Color, &color, top_start_idx, tr.x)
|
||||
memory.set(Color, &color, bottom_start_idx, tr.x)
|
||||
|
||||
top_start_idx += surface.width
|
||||
bottom_start_idx -= surface.width
|
||||
|
@ -76,16 +74,16 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color:
|
|||
}
|
||||
|
||||
if rows_to_fill == 1 {
|
||||
@inline(memory.set, Color, &color, top_start_idx, tr.x)
|
||||
memory.set(Color, &color, top_start_idx, tr.x)
|
||||
}
|
||||
|
||||
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)
|
||||
start_idx := indexptr(surface, pos.x, pos.y)
|
||||
end_idx := indexptr(surface, pos.x, pos.y + tr.y)
|
||||
right_start_idx := indexptr(surface, pos.x + tr.x, pos.y)
|
||||
|
||||
loop if start_idx > end_idx break else {
|
||||
*start_idx = color;
|
||||
|
@ -94,8 +92,8 @@ put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color):
|
|||
right_start_idx += surface.width
|
||||
}
|
||||
|
||||
@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))
|
||||
memory.set(Color, &color, indexptr(surface, pos.x, pos.y), @bitcast(tr.x + 1))
|
||||
memory.set(Color, &color, indexptr(surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -112,7 +110,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
|
|||
y := p0.y
|
||||
x := p0.x
|
||||
loop if x == p1.x break else {
|
||||
*@inline(indexptr, surface, x, y) = color
|
||||
*indexptr(surface, x, y) = color
|
||||
if D > 0 {
|
||||
y += yi
|
||||
D += 2 * (dy - dx)
|
||||
|
@ -136,7 +134,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Col
|
|||
x := p0.x
|
||||
y := p0.y
|
||||
loop if y == p1.y break else {
|
||||
*@inline(indexptr, surface, x, y) = color
|
||||
*indexptr(surface, x, y) = color
|
||||
if D > 0 {
|
||||
x += xi
|
||||
D += 2 * (dx - dy)
|
||||
|
@ -169,8 +167,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
|
|||
src_top_cursor := top.buf
|
||||
src_bottom_cursor := top.buf + top.width * (top.height - 1)
|
||||
|
||||
dst_top_idx := @inline(indexptr, surface, pos.x, pos.y)
|
||||
dst_bottom_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
|
||||
dst_top_idx := indexptr(surface, pos.x, pos.y)
|
||||
dst_bottom_idx := indexptr(surface, pos.x, pos.y + top.height - 1)
|
||||
|
||||
dst_increment := surface.width
|
||||
|
||||
|
@ -184,8 +182,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
|
|||
rows_to_copy := top.height
|
||||
|
||||
loop if rows_to_copy <= 1 break else {
|
||||
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
|
||||
@inline(memory.copy, Color, src_bottom_cursor, dst_bottom_idx, top.width)
|
||||
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
|
||||
|
@ -195,7 +193,7 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
|
|||
}
|
||||
|
||||
if rows_to_copy == 1 {
|
||||
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
|
||||
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -233,7 +231,7 @@ put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): vo
|
|||
y := y0
|
||||
|
||||
loop if y == y1 break else {
|
||||
*@inline(indexptr, surface, x, y) = color
|
||||
*indexptr(surface, x, y) = color
|
||||
y += 1
|
||||
}
|
||||
|
||||
|
@ -247,10 +245,95 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
|
|||
x0 = x1
|
||||
x1 = tmp
|
||||
}
|
||||
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
|
||||
// x0 = math.min(x0, x1)
|
||||
memory.set(Color, &color, indexptr(surface, x0, y), @bitcast(x1 - x0 - 1))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
||||
x := 0
|
||||
y := radius
|
||||
error := @as(int, 3) - @intcast(2 * radius);
|
||||
*indexptr(surface, pos.x + radius, pos.y) = color;
|
||||
*indexptr(surface, pos.x - radius, pos.y) = color;
|
||||
*indexptr(surface, pos.x, pos.y + radius) = color;
|
||||
*indexptr(surface, pos.x, pos.y - radius) = color
|
||||
|
||||
loop if y < x break else {
|
||||
x += 1
|
||||
|
||||
if error > 0 {
|
||||
y -= 1
|
||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||
} else {
|
||||
error += 4 * @intcast(x) + 6
|
||||
};
|
||||
*indexptr(surface, pos.x + x, pos.y + y) = color;
|
||||
*indexptr(surface, pos.x + y, pos.y + x) = color;
|
||||
*indexptr(surface, pos.x - x, pos.y + y) = color;
|
||||
*indexptr(surface, pos.x - y, pos.y + x) = color;
|
||||
*indexptr(surface, pos.x + x, pos.y - y) = color;
|
||||
*indexptr(surface, pos.x + y, pos.y - x) = color;
|
||||
*indexptr(surface, pos.x - x, pos.y - y) = color;
|
||||
*indexptr(surface, pos.x - y, pos.y - x) = color
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
||||
x := 0
|
||||
y := radius
|
||||
error := @as(int, 3) - @intcast(2 * radius)
|
||||
put_hline(surface, pos.y - x, pos.x - radius, pos.x + radius, color);
|
||||
*indexptr(surface, pos.x, pos.y + radius) = color;
|
||||
*indexptr(surface, pos.x, pos.y - radius) = color
|
||||
|
||||
loop if y < x break else {
|
||||
x += 1
|
||||
|
||||
if error > 0 {
|
||||
put_hline(surface, pos.y + y, pos.x - x, pos.x + x, color)
|
||||
put_hline(surface, pos.y - y, pos.x - x, pos.x + x, color)
|
||||
y -= 1
|
||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||
} else {
|
||||
error += 4 * @intcast(x) + 6
|
||||
}
|
||||
put_hline(surface, pos.y + x, pos.x - y, pos.x + y, color)
|
||||
put_hline(surface, pos.y - x, pos.x - y, pos.x + y, color)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
|
||||
x := 0
|
||||
y := radius
|
||||
error := @as(int, 3) - @intcast(2 * radius)
|
||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y), indexptr(surface, pos.x - y, pos.y), 2 * y);
|
||||
*indexptr(surface, pos.x, pos.y + y) = *indexptr(source, source_pos.x, source_pos.y + y);
|
||||
*indexptr(surface, pos.x, pos.y - y) = *indexptr(source, source_pos.x, source_pos.y - y)
|
||||
|
||||
loop if y < x break else {
|
||||
x += 1
|
||||
|
||||
if error > 0 {
|
||||
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y + y), indexptr(surface, pos.x - x, pos.y + y), 2 * x)
|
||||
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y - y), indexptr(surface, pos.x - x, pos.y - y), 2 * x)
|
||||
y -= 1
|
||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||
} else {
|
||||
error += 4 * @intcast(x) + 6
|
||||
}
|
||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y + x), indexptr(surface, pos.x - y, pos.y + x), 2 * y)
|
||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y - x), indexptr(surface, pos.x - y, pos.y - x), 2 * y)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
utf8_len_table := [u8].(0, 0, 2, 3)
|
||||
|
||||
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
|
||||
|
@ -280,7 +363,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
|
|||
str += 1
|
||||
continue
|
||||
}
|
||||
glyph_data = @inline(get_glyph, font, *str)
|
||||
glyph_data = get_glyph(font, *str)
|
||||
} else {
|
||||
if *str < UNC_TABLE_SIZE {
|
||||
glyph_index := *(font.unicode + *str)
|
||||
|
@ -352,7 +435,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
|
|||
cursor.y += next_line_y
|
||||
}
|
||||
|
||||
dest := @inline(indexptr, surface, cursor.x, cursor.y)
|
||||
dest := indexptr(surface, cursor.x, cursor.y)
|
||||
rows := font.height
|
||||
|
||||
loop if rows == 0 break else {
|
||||
|
|
|
@ -74,16 +74,16 @@ font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
|
|||
return font
|
||||
}
|
||||
|
||||
get_glyph := fn(font: Font, index: u8): ^u8 {
|
||||
$get_glyph := fn(font: Font, index: u8): ^u8 {
|
||||
return font.data + @as(uint, index) * font.bytes_per_glyph
|
||||
}
|
||||
|
||||
UNC_TABLE_SIZE := 1 << 16
|
||||
$UNC_TABLE_SIZE := 1 << 16
|
||||
|
||||
init_unicode := fn(font: ^Font): void {
|
||||
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
|
||||
|
||||
@inline(memory.set, u16, &0xFFFF, font.unicode, 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)
|
||||
|
@ -121,8 +121,6 @@ init_unicode := fn(font: ^Font): void {
|
|||
next_byte := *table
|
||||
if (next_byte & 0xC0) != 0x80 {
|
||||
valid = false
|
||||
}
|
||||
if valid == false {
|
||||
break
|
||||
}
|
||||
unicode = unicode << 6 | next_byte & 0x3F
|
||||
|
|
|
@ -1,27 +1,35 @@
|
|||
string := @use("string.hb")
|
||||
|
||||
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): void {
|
||||
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
|
||||
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
|
||||
}
|
||||
|
||||
write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
|
||||
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void {
|
||||
return @eca(3, buffer_id, msg, @sizeof(Expr))
|
||||
}
|
||||
|
||||
recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
|
||||
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void {
|
||||
return @eca(4, buffer_id, memory_map_location, length)
|
||||
}
|
||||
|
||||
write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
|
||||
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void {
|
||||
return @eca(3, buffer_id, msg, length)
|
||||
}
|
||||
|
||||
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
|
||||
|
||||
create := fn(msg: ^u8): int {
|
||||
create := fn(msg: ^u8): uint {
|
||||
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
||||
}
|
||||
|
||||
search := fn(msg: ^u8): int {
|
||||
$create_nameless := fn(): uint {
|
||||
return @eca(1, 0)
|
||||
}
|
||||
|
||||
$delete_buffer := fn(buffer_id: uint): void {
|
||||
return @eca(2, buffer_id)
|
||||
}
|
||||
|
||||
search := fn(msg: ^u8): uint {
|
||||
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
||||
}
|
|
@ -7,6 +7,7 @@ math := @use("math.hb")
|
|||
random := @use("random.hb")
|
||||
file := @use("file_io.hb")
|
||||
dt := @use("dt.hb")
|
||||
process := @use("process.hb")
|
||||
|
||||
panic := fn(message: ?^u8): never {
|
||||
log.error("Error: Panic Called, Message:\0")
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
abs := fn($Expr: type, x: Expr): Expr {
|
||||
mask := x >> @bitcast(@sizeof(Expr) - 1)
|
||||
return (x ^ mask) - mask
|
||||
$abs := fn($Expr: type, x: Expr): Expr {
|
||||
return (x ^ x >> @sizeof(Expr) - 1) - (x >> @sizeof(Expr) - 1)
|
||||
}
|
||||
min := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||
c := a - b
|
||||
return b + (c & c >> @bitcast(@sizeof(Expr) - 1))
|
||||
$min := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||
return b + (a - b & a - b >> @sizeof(Expr) - 1)
|
||||
}
|
||||
max := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||
c := a - b
|
||||
return a - (c & c >> @bitcast(@sizeof(Expr) - 1))
|
||||
$max := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||
return a - (a - b & a - b >> @sizeof(Expr) - 1)
|
||||
}
|
||||
signum := fn($Expr: type, x: Expr): int {
|
||||
if x > @as(Expr, @intcast(0)) {
|
||||
return 1
|
||||
} else if x < @as(Expr, @intcast(0)) {
|
||||
return -1
|
||||
} else {
|
||||
return 0
|
||||
$sign := fn($Expr: type, x: Expr): i8 {
|
||||
return @bitcast(x > 0) - @bitcast(x < 0)
|
||||
}
|
||||
$log := fn($Expr: type, base: uint, x: Expr): uint {
|
||||
// if x <= 0 {}
|
||||
// if base <= 1 {}
|
||||
result := 0
|
||||
loop if x < base break else {
|
||||
x /= base
|
||||
result += 1
|
||||
}
|
||||
signincl := fn($Expr: type, x: Expr): int {
|
||||
if x > @as(Expr, @intcast(0)) {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
return result
|
||||
}
|
||||
|
||||
Vec2 := fn($Expr: type): type {
|
||||
|
@ -40,7 +35,7 @@ $TABLE_SIZE := @as(i32, 256)
|
|||
|
||||
sin := fn(theta: f32): f32 {
|
||||
si := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
|
||||
d := theta - @floatcast(@itf(si)) * 2.0 * PI / @itf(TABLE_SIZE)
|
||||
d := theta - @floatcast(@itf(si)) * 2.0 * PI / @floatcast(@itf(TABLE_SIZE))
|
||||
ci := si + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
||||
si &= TABLE_SIZE - 1
|
||||
return SIN_TABLE[@bitcast(si)] + (SIN_TABLE[@bitcast(ci)] - 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
|
||||
|
@ -48,10 +43,10 @@ sin := fn(theta: f32): f32 {
|
|||
|
||||
cos := fn(theta: f32): f32 {
|
||||
ci := @fti(theta * 0.5 * @itf(TABLE_SIZE) / PI)
|
||||
d := theta - @floatcast(@itf(ci)) * 2.0 * PI / @itf(TABLE_SIZE)
|
||||
d := theta - @floatcast(@itf(ci)) * 2.0 * PI / @floatcast(@itf(TABLE_SIZE))
|
||||
si := ci + TABLE_SIZE / 4 & TABLE_SIZE - 1
|
||||
ci &= TABLE_SIZE - 1
|
||||
return SIN_TABLE[@bitcast(si)] + (SIN_TABLE[@bitcast(ci)] - 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
|
||||
return SIN_TABLE[@bitcast(si)] - (SIN_TABLE[@bitcast(ci)] + 0.5 * SIN_TABLE[@bitcast(si)] * d) * d
|
||||
}
|
||||
|
||||
tan := fn(theta: f32): f32 {
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
PAGE_SIZE := 4096
|
||||
MAX_ALLOC := 0xFF
|
||||
MAX_FREE := 0xFF
|
||||
$PAGE_SIZE := 4096
|
||||
$MAX_ALLOC := 0xFF
|
||||
$MAX_FREE := 0xFF
|
||||
|
||||
dangling := fn($Expr: type): ^Expr {
|
||||
$uninit := fn($Expr: type): ?Expr {
|
||||
return null
|
||||
}
|
||||
|
||||
$dangling := fn($Expr: type): ^Expr {
|
||||
return @bitcast(@alignof(Expr))
|
||||
}
|
||||
|
||||
calc_pages := fn($Expr: type, num: uint): uint {
|
||||
$calc_pages := fn($Expr: type, num: uint): uint {
|
||||
return 1 + @sizeof(Expr) * num / PAGE_SIZE
|
||||
}
|
||||
|
||||
// ! will be replaced, don't get attached
|
||||
alloc := fn($Expr: type, num: uint): ^Expr {
|
||||
pages := @inline(calc_pages, Expr, num)
|
||||
pages := calc_pages(Expr, num)
|
||||
if pages <= MAX_ALLOC {
|
||||
return @bitcast(request_page(@intcast(pages)))
|
||||
}
|
||||
ptr := request_page(0xFF)
|
||||
ptr := request_page(MAX_ALLOC)
|
||||
remaining := pages - MAX_ALLOC
|
||||
loop if remaining < MAX_ALLOC break else {
|
||||
_ = request_page(@intcast(MAX_ALLOC))
|
||||
_ = request_page(MAX_ALLOC)
|
||||
remaining -= MAX_ALLOC
|
||||
}
|
||||
_ = request_page(@intcast(remaining))
|
||||
|
@ -26,46 +31,46 @@ alloc := fn($Expr: type, num: uint): ^Expr {
|
|||
}
|
||||
|
||||
// ! stub
|
||||
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
||||
$free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
||||
return
|
||||
}
|
||||
|
||||
RqPageMsg := packed struct {a: u8, count: u8}
|
||||
request_page := fn(count: u8): ^u8 {
|
||||
$request_page := fn(count: u8): ^u8 {
|
||||
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
|
||||
}
|
||||
|
||||
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
|
||||
release_page := fn(ptr: ^u8, count: u8): void {
|
||||
$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))
|
||||
}
|
||||
|
||||
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
|
||||
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
||||
$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))
|
||||
}
|
||||
|
||||
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
|
||||
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
||||
$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))
|
||||
}
|
12
sysdata/libraries/stn/src/process.hb
Normal file
12
sysdata/libraries/stn/src/process.hb
Normal file
|
@ -0,0 +1,12 @@
|
|||
// ! 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 */
|
|
@ -1,7 +1,15 @@
|
|||
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 @inline(any, Expr) % (max - min) + @intcast(1) + min
|
||||
$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)
|
||||
}
|
6
sysdata/libraries/stn/src/sleep.hb
Normal file
6
sysdata/libraries/stn/src/sleep.hb
Normal file
|
@ -0,0 +1,6 @@
|
|||
subscribe_to_interrupt := fn(interrupt_number: u8): bool {
|
||||
return false
|
||||
}
|
||||
// Pauses execution until the interrupt occures
|
||||
sleep_until_interrupt := fn(interrupt_number: u8): void {
|
||||
}
|
|
@ -4,118 +4,213 @@ length := fn(ptr: ^u8): uint {
|
|||
}
|
||||
|
||||
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
|
||||
is_negative := num < 0
|
||||
if is_negative num = -num
|
||||
|
||||
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 {
|
||||
*ptr = 0x30;
|
||||
*(ptr + 1) = 0
|
||||
return p
|
||||
}
|
||||
|
||||
loop if num == 0 break else {
|
||||
digit := num % @bitcast(radix)
|
||||
if digit < 10 {
|
||||
*ptr = @intcast(digit) + 48
|
||||
} else {
|
||||
*ptr = @intcast(digit) + 55
|
||||
remainder := num % @bitcast(radix)
|
||||
num /= @bitcast(radix);
|
||||
*ptr = @intcast(remainder + 0x30)
|
||||
if remainder > 9 {
|
||||
*ptr = @intcast(remainder - 10 + 0x41)
|
||||
}
|
||||
ptr += 1
|
||||
num /= @bitcast(radix)
|
||||
}
|
||||
}
|
||||
|
||||
if negative {
|
||||
*ptr = 45
|
||||
if is_negative {
|
||||
*ptr = 0x2D
|
||||
ptr += 1
|
||||
};
|
||||
|
||||
*ptr = 0
|
||||
|
||||
@inline(reverse, digits_start)
|
||||
}
|
||||
// ! it gets broked when you do this ??
|
||||
// *ptr = 0
|
||||
|
||||
@inline(reverse, p)
|
||||
return p
|
||||
}
|
||||
|
||||
reverse := fn(s: ^u8): void {
|
||||
i := 0
|
||||
j := @inline(length, s) - 1
|
||||
j := s + @inline(length, s) - 1
|
||||
temp := @as(u8, 0)
|
||||
loop if i >= j break else {
|
||||
temp = *(s + i);
|
||||
*(s + i) = *(s + j);
|
||||
*(s + j) = temp
|
||||
i += 1
|
||||
loop if s < j {
|
||||
temp = *s;
|
||||
*s = *j;
|
||||
*j = temp
|
||||
s += 1
|
||||
j -= 1
|
||||
}
|
||||
return
|
||||
} else return
|
||||
}
|
||||
|
||||
equals := fn(lhs: ^u8, rhs: ^u8): bool {
|
||||
if lhs == rhs {
|
||||
return true
|
||||
}
|
||||
i := 0
|
||||
loop if *(lhs + i) != *(rhs + i) {
|
||||
loop if *lhs != *rhs {
|
||||
return false
|
||||
} else if *lhs == 0 {
|
||||
return true
|
||||
} else {
|
||||
i += 1
|
||||
lhs += 1
|
||||
rhs += 1
|
||||
}
|
||||
}
|
||||
|
||||
contains := fn(haystack: ^u8, needle: ^u8): bool {
|
||||
haystack_len := @inline(length, haystack)
|
||||
needle_len := @inline(length, needle)
|
||||
|
||||
if needle_len == 0 {
|
||||
return true
|
||||
clear := fn(ptr: ^u8): void {
|
||||
loop if *ptr == 0 break else {
|
||||
*ptr = 0
|
||||
ptr += 1
|
||||
}
|
||||
if haystack_len < needle_len {
|
||||
return false
|
||||
}
|
||||
|
||||
max_start := haystack_len - needle_len
|
||||
|
||||
pos := 0
|
||||
loop if pos > max_start break else {
|
||||
is_match := true
|
||||
offset := 0
|
||||
|
||||
loop if offset >= needle_len break else {
|
||||
if *(haystack + pos + offset) != *(needle + offset) {
|
||||
is_match = false
|
||||
split_once := fn(haystack: ^u8, needle: u8): ?^u8 {
|
||||
loop if *haystack == needle return haystack else if *haystack == 0 return null else haystack += 1
|
||||
}
|
||||
if is_match == false {
|
||||
|
||||
split_once_str := fn(haystack: ^u8, needle: ^u8): ?^u8 {
|
||||
if *needle == 0 return null
|
||||
|
||||
loop if *haystack == 0 return null else {
|
||||
if *haystack == *needle {
|
||||
h := haystack
|
||||
n := needle
|
||||
|
||||
loop {
|
||||
n += 1
|
||||
h += 1
|
||||
if *n == 0 {
|
||||
return haystack
|
||||
} else if *h == 0 | *h != *n {
|
||||
break
|
||||
}
|
||||
offset += 1
|
||||
}
|
||||
}
|
||||
haystack += 1
|
||||
}
|
||||
}
|
||||
|
||||
if is_match {
|
||||
return true
|
||||
}
|
||||
pos += 1
|
||||
Split := struct {
|
||||
str: ^u8,
|
||||
needle: u8,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
return false
|
||||
split := fn(iter: ^u8, needle: u8): Split {
|
||||
return .(
|
||||
iter,
|
||||
needle,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
iter_split := fn(iter: ^Split): ?^u8 {
|
||||
if iter.done | *iter.str == 0 {
|
||||
return null
|
||||
}
|
||||
|
||||
next := split_once(iter.str + 1, iter.needle)
|
||||
|
||||
if next == null {
|
||||
iter.done = true
|
||||
return iter.str
|
||||
}
|
||||
s := iter.str
|
||||
iter.str = next + 1
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
SplitStr := struct {
|
||||
str: ^u8,
|
||||
needle: ^u8,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
split_str := fn(iter: ^u8, needle: ^u8): SplitStr {
|
||||
return .(
|
||||
iter,
|
||||
needle,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
iter_split_str := fn(iter: ^SplitStr): ?^u8 {
|
||||
if iter.done | *iter.str == 0 {
|
||||
return null
|
||||
}
|
||||
|
||||
next := split_once_str(iter.str, iter.needle)
|
||||
|
||||
if next == null {
|
||||
iter.done = true
|
||||
return iter.str
|
||||
}
|
||||
|
||||
s := iter.str
|
||||
|
||||
iter.str = next + length(iter.needle)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
find_once := fn(haystack: ^u8, needle: u8): ?uint {
|
||||
return @bitcast(@inline(split_once, haystack, needle) - haystack)
|
||||
}
|
||||
|
||||
find_once_str := fn(haystack: ^u8, needle: ^u8): ?uint {
|
||||
return @bitcast(@inline(split_once_str, haystack, needle) - haystack)
|
||||
}
|
||||
|
||||
count := fn(haystack: ^u8, needle: ^u8): uint {
|
||||
c := 0
|
||||
loop if *haystack == needle {
|
||||
c += 1
|
||||
haystack += 1
|
||||
} else if *haystack == 0 return c else haystack += 1
|
||||
}
|
||||
|
||||
count_str := fn(haystack: ^u8, needle: ^u8): uint {
|
||||
if *needle == 0 return 0
|
||||
c := 0
|
||||
loop if *haystack == 0 return c else {
|
||||
if *haystack == *needle {
|
||||
h := haystack
|
||||
n := needle
|
||||
|
||||
loop {
|
||||
n += 1
|
||||
h += 1
|
||||
if *n == 0 {
|
||||
c += 1
|
||||
break
|
||||
} else if *h == 0 | *h != *n {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
haystack += 1
|
||||
}
|
||||
}
|
||||
|
||||
left_trim := fn(str: ^u8, sub: ^u8): ^u8 {
|
||||
original := str
|
||||
if *str == *sub {
|
||||
loop if *sub == 0 {
|
||||
return str
|
||||
} else if *str != *sub {
|
||||
return original
|
||||
} else if *str == 0 {
|
||||
return original
|
||||
} else {
|
||||
str += 1
|
||||
sub += 1
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
63
sysdata/libraries/sunset_proto/src/client.hb
Normal file
63
sysdata/libraries/sunset_proto/src/client.hb
Normal file
|
@ -0,0 +1,63 @@
|
|||
.{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
|
||||
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
|
||||
.{new_surface, Color} := @use("../../render/src/lib.hb")
|
||||
|
||||
// ! in the future this should be safely handled
|
||||
channel := Channel.(0, 0)
|
||||
|
||||
find_server := fn(): void {
|
||||
log.info("client: locating server\0")
|
||||
channel2 := await_channel()
|
||||
channel.server = channel2.server
|
||||
channel.client = channel2.client
|
||||
log.info("client: server located\0")
|
||||
}
|
||||
|
||||
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\0")
|
||||
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\0")
|
||||
surface := new_surface(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
|
||||
}
|
97
sysdata/libraries/sunset_proto/src/lib.hb
Normal file
97
sysdata/libraries/sunset_proto/src/lib.hb
Normal file
|
@ -0,0 +1,97 @@
|
|||
.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb");
|
||||
.{Surface} := @use("../../render/src/lib.hb")
|
||||
|
||||
$BUFFER_SERVER := "sunset_server\0"
|
||||
$BUFFER_CLIENT := "sunset_client\0"
|
||||
|
||||
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 {
|
||||
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 {
|
||||
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),
|
||||
// ! replace with owned string type later
|
||||
title: ^u8,
|
||||
}
|
||||
|
||||
WindowData := struct {
|
||||
props: WindowProps,
|
||||
channel: Channel,
|
||||
permissions: uint,
|
||||
}
|
||||
|
||||
Window := struct {
|
||||
data: WindowData,
|
||||
surface: Surface,
|
||||
}
|
8
sysdata/libraries/sunset_proto/src/message.hb
Normal file
8
sysdata/libraries/sunset_proto/src/message.hb
Normal file
|
@ -0,0 +1,8 @@
|
|||
// ! all values in this file are subject to change.
|
||||
$syn := 1
|
||||
$ack := 2
|
||||
$refused := 3
|
||||
$quit := 4
|
||||
$props := 5
|
||||
$shutdown := 6
|
||||
$frame_ready := 7
|
5
sysdata/libraries/sunset_proto/src/permissions.hb
Normal file
5
sysdata/libraries/sunset_proto/src/permissions.hb
Normal file
|
@ -0,0 +1,5 @@
|
|||
$none := 0b0
|
||||
$exclusive_framebuffer := 0b1
|
||||
$shutdown := 0b100
|
||||
|
||||
$default := none
|
135
sysdata/libraries/sunset_proto/src/server.hb
Normal file
135
sysdata/libraries/sunset_proto/src/server.hb
Normal file
|
@ -0,0 +1,135 @@
|
|||
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
|
||||
.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("../../render/src/lib.hb");
|
||||
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb")
|
||||
|
||||
WindowServer := struct {
|
||||
window_count: uint,
|
||||
channel: Channel,
|
||||
// ! replace this with a collection when we get an allocator
|
||||
windows: [?Window; 10],
|
||||
font: text.Font,
|
||||
}
|
||||
|
||||
// ! in the future this should be safely handled
|
||||
server := @as(WindowServer, idk)
|
||||
|
||||
psf := @embed("../../../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\0")
|
||||
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\0")
|
||||
}
|
||||
|
||||
incoming := fn(): bool {
|
||||
msg := recv_header(server.channel.server)
|
||||
if msg == null {
|
||||
return true
|
||||
}
|
||||
if msg.kind == message.syn {
|
||||
log.info("server: recv syn\0")
|
||||
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\0")
|
||||
// ! 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
|
||||
title_length := string.length(title)
|
||||
deco_length := title_length * 10
|
||||
// draw the window tab bar
|
||||
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
|
||||
// Draw the window tab
|
||||
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
|
||||
|
||||
// Draw the outside box
|
||||
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
|
||||
|
||||
put_text(surface, 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 new_surface(
|
||||
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 {
|
||||
return
|
||||
}
|
||||
put_surface(
|
||||
window.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
|
||||
}
|
||||
put_surface(screen, window.surface, window.data.props.position, false)
|
||||
i += 1
|
||||
}
|
||||
}
|
|
@ -56,23 +56,13 @@ main := fn(): int {
|
|||
loop {
|
||||
// Clear the screen
|
||||
render.clear(screen, render.black)
|
||||
|
||||
render.put_surface(screen, wallpaper, .(0, 0), false)
|
||||
|
||||
// TODO: Read the window buffer here
|
||||
{
|
||||
// ret := buffer.recv([u8; 4096], win_buff, mem_buf)
|
||||
// for some reason this null check causes the compiler to spin forever
|
||||
// if ret == null {
|
||||
// log.info("No messages\0")
|
||||
// } else {
|
||||
// log.info("Handle Messages\0")
|
||||
// }
|
||||
}
|
||||
|
||||
// get input events from drivers via intouch
|
||||
// key_event := intouch.recieve_key_event();
|
||||
// log.info("before mouse event check\0");
|
||||
|
||||
if false {
|
||||
// Scroll bar :ThumbsUp:
|
||||
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
|
||||
|
@ -82,18 +72,35 @@ main := fn(): int {
|
|||
render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
|
||||
}
|
||||
|
||||
{
|
||||
// osu dots
|
||||
render.put_rect(screen, .(400, 100), .(100, 100), render.red)
|
||||
render.put_rect(screen, .(100, 100 + 300), .(100, 100), render.red)
|
||||
}
|
||||
|
||||
{
|
||||
pos := Vec2(uint).(1, screen.height - 21)
|
||||
render_label_to_surface(screen, text_label, font, pos)
|
||||
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), render.white)
|
||||
}
|
||||
|
||||
// Screen border
|
||||
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
|
||||
|
||||
// get input events from drivers via intouch
|
||||
if false {
|
||||
key_event := intouch.recieve_key_event()
|
||||
if key_event != null {
|
||||
log.info("Key event \0")
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
mouse_event := intouch.recieve_mouse_event()
|
||||
//
|
||||
|
||||
if mouse_event != null {
|
||||
// log.warn("Mouse event recieved\0")
|
||||
// log.warn("Mouse event received\0")
|
||||
|
||||
change_x := @as(i16, mouse_event.x_change)
|
||||
change_x = change_x << 8
|
||||
|
@ -130,15 +137,9 @@ main := fn(): int {
|
|||
}
|
||||
}
|
||||
|
||||
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
|
||||
|
||||
// render mouse
|
||||
lum := render.indexptr(screen, mouse_x, mouse_y)
|
||||
if lum.r / 3 + lum.g / 3 + lum.b / 3 < 128 {
|
||||
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
|
||||
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
|
||||
} else {
|
||||
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
|
||||
}
|
||||
|
||||
// Send events to focused window
|
||||
}
|
||||
|
||||
|
|
11
sysdata/programs/processes/meta.toml
Normal file
11
sysdata/programs/processes/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "processes"
|
||||
authors = ["koniifer"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
7
sysdata/programs/processes/src/hello_world_and_spin.hb
Normal file
7
sysdata/programs/processes/src/hello_world_and_spin.hb
Normal file
|
@ -0,0 +1,7 @@
|
|||
.{log} := @use("../../../libraries/stn/src/lib.hb")
|
||||
|
||||
main := fn(): void {
|
||||
log.info("Hello, World!\0")
|
||||
loop {
|
||||
}
|
||||
}
|
BIN
sysdata/programs/processes/src/hello_world_and_spin.hbf
Normal file
BIN
sysdata/programs/processes/src/hello_world_and_spin.hbf
Normal file
Binary file not shown.
19
sysdata/programs/processes/src/main.hb
Normal file
19
sysdata/programs/processes/src/main.hb
Normal file
|
@ -0,0 +1,19 @@
|
|||
.{process, log, string, memory} := @use("../../../libraries/stn/src/lib.hb")
|
||||
|
||||
exe := @embed("./hello_world_and_spin.hbf")
|
||||
|
||||
main := fn(): void {
|
||||
buf := "\0\0\0\0\0\0\0"
|
||||
loop {
|
||||
log.info(
|
||||
string.display_int(
|
||||
@bitcast(process.spawn(@bitcast(&exe), 356)),
|
||||
buf,
|
||||
10,
|
||||
),
|
||||
)
|
||||
// spin so we don't spawn 10 quattuordecillion processes
|
||||
i := 0
|
||||
loop if i == 1000000 break else i += 1
|
||||
}
|
||||
}
|
23
sysdata/programs/ps2_driver/README.md
Normal file
23
sysdata/programs/ps2_driver/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Unified PS/2 Driver
|
||||
|
||||
Te entire thing is held together inspite
|
||||
|
||||
## !!Assumptions!!
|
||||
Anyone who works on this should work to keep this list as small as possible/remove as many of these as possible.
|
||||
- Bit 5 of the response form 0x64 indicates which port the data is coming from. (Not true on all systems)
|
||||
- A parity or timeout error never occurs.
|
||||
- PS/2 controller exists.
|
||||
- Both PS/2 ports being broken doesn't need handling.
|
||||
- One PS/2 port being broken doesn't need special attention.
|
||||
- PS/2 controller doesn't need to perform a self-check.
|
||||
- These DeviceIDs never exist:
|
||||
- 0xFFFD
|
||||
- 0xFFFE
|
||||
- 0xFFFF
|
||||
- 0x01xx
|
||||
- 0x03xx
|
||||
- 0x04xx
|
||||
- Literally all PS/2 keyboards can be handeled the exact same way. We have the capability for detecting different keyboard types, I just don't bother with it because that would litreally take months to get working.
|
||||
- The device doesn't send any data while we're waiting for an `ACK`.
|
||||
|
||||
Supporting mice in the keyboard port and vice versa was a ***bad*** idea, but I do not regret it because it means we're "superior" to real world operating systems.
|
11
sysdata/programs/ps2_driver/meta.toml
Normal file
11
sysdata/programs/ps2_driver/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "ps2_driver"
|
||||
authors = ["Peony"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
26
sysdata/programs/ps2_driver/src/bits.hb
Normal file
26
sysdata/programs/ps2_driver/src/bits.hb
Normal file
|
@ -0,0 +1,26 @@
|
|||
//Do not question.
|
||||
|
||||
$bit0 := fn(value: u8): bool {
|
||||
return (value & 0x1) > 0
|
||||
}
|
||||
$bit1 := fn(value: u8): bool {
|
||||
return (value & 0x2) > 0
|
||||
}
|
||||
$bit2 := fn(value: u8): bool {
|
||||
return (value & 0x4) > 0
|
||||
}
|
||||
$bit3 := fn(value: u8): bool {
|
||||
return (value & 0x8) > 0
|
||||
}
|
||||
$bit4 := fn(value: u8): bool {
|
||||
return (value & 0x10) > 0
|
||||
}
|
||||
$bit5 := fn(value: u8): bool {
|
||||
return (value & 0x20) > 0
|
||||
}
|
||||
$bit6 := fn(value: u8): bool {
|
||||
return (value & 0x40) > 0
|
||||
}
|
||||
$bit7 := fn(value: u8): bool {
|
||||
return (value & 0x80) > 0
|
||||
}
|
95
sysdata/programs/ps2_driver/src/controller.hb
Normal file
95
sysdata/programs/ps2_driver/src/controller.hb
Normal file
|
@ -0,0 +1,95 @@
|
|||
.{memory, log} := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{bit0, bit1, bit5, bit6, bit7} := @use("bits.hb");
|
||||
.{Port, PORT_AT_STARTUP} := @use("port.hb")
|
||||
|
||||
port1 := @as(Port, PORT_AT_STARTUP)
|
||||
port2 := @as(Port, PORT_AT_STARTUP)
|
||||
|
||||
$disable_port1 := fn(): void memory.outb(0x64, 0xAD)
|
||||
$enable_port1 := fn(): void memory.outb(0x64, 0xAE)
|
||||
$disable_port2 := fn(): void memory.outb(0x64, 0xA7)
|
||||
$enable_port2 := fn(): void memory.outb(0x64, 0xA8)
|
||||
|
||||
test_port1 := fn(): bool {
|
||||
memory.outb(0x64, 0xAB)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
test_port2 := fn(): bool {
|
||||
memory.outb(0x64, 0xA9)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
get_config_byte := fn(): u8 {
|
||||
memory.outb(0x64, 0x20)
|
||||
loop if has_input(get_info()) break
|
||||
return get_input()
|
||||
}
|
||||
|
||||
Info := struct {d: u8}
|
||||
|
||||
$get_info := fn(): Info return .(memory.inb(0x64))
|
||||
//inline when can
|
||||
has_input := fn(info: Info): bool return bit0(info.d)
|
||||
can_send := fn(info: Info): bool return bit1(info.d) == false
|
||||
timed_out := fn(info: Info): bool return bit6(info.d)
|
||||
check_parity := fn(info: Info): bool return bit7(info.d)
|
||||
get_port := fn(info: Info): ^Port {
|
||||
if bit5(info.d) {
|
||||
return &port2
|
||||
} else {
|
||||
return &port1
|
||||
}
|
||||
}
|
||||
|
||||
send_byte := fn(port: ^Port, byte: u8): void {
|
||||
if port == &port2 {
|
||||
memory.outb(0x64, 0xD4)
|
||||
}
|
||||
loop if can_send(get_info()) break
|
||||
memory.outb(0x60, byte)
|
||||
}
|
||||
|
||||
$get_input := fn(): u8 return memory.inb(0x60)
|
||||
$write_out := fn(data: u8): void memory.outb(0x60, data)
|
||||
|
||||
flush_input := fn(): void {
|
||||
loop if has_input(get_info()) == false break else get_info()
|
||||
}
|
||||
|
||||
init := fn(): void {
|
||||
disable_port1()
|
||||
disable_port2()
|
||||
//Disables ports to make sure that they won't interfere with the setup process.
|
||||
|
||||
flush_input()
|
||||
|
||||
enable_port2()
|
||||
port2.exists = bit5(@inline(get_config_byte)) == false
|
||||
disable_port2()
|
||||
|
||||
flush_input()
|
||||
|
||||
port1.exists = test_port1()
|
||||
|
||||
if port2.exists {
|
||||
port2.exists = test_port2()
|
||||
}
|
||||
|
||||
if (port1.exists | port2.exists) == false {
|
||||
log.error("No ports detected! No input will be processed! Cannot handle this!\0")
|
||||
}
|
||||
|
||||
if port1.exists {
|
||||
log.info("Port 1 exists.\0")
|
||||
enable_port1()
|
||||
}
|
||||
if port2.exists {
|
||||
log.info("Port 2 exists.\0")
|
||||
enable_port2()
|
||||
}
|
||||
}
|
15
sysdata/programs/ps2_driver/src/devices.hb
Normal file
15
sysdata/programs/ps2_driver/src/devices.hb
Normal file
|
@ -0,0 +1,15 @@
|
|||
DeviceID := struct {value: u16}
|
||||
|
||||
$MOUSE_3_BUTTON := DeviceID.(0x0)
|
||||
$MOUSE_SCROLLWHEEL := DeviceID.(0x3)
|
||||
$MOUSE_5_BUTTON := DeviceID.(0x4)
|
||||
$KEYBOARD_SPACESAVER := DeviceID.(0x84AB)
|
||||
$KEYBOARD_122_KEY := DeviceID.(0x86AB)
|
||||
$KEYBOARD_JAPANESE_G := DeviceID.(0x90AB)
|
||||
$KEYBOARD_JAPANESE_P := DeviceID.(0x91AB)
|
||||
$KEYBOARD_JAPANESE_A := DeviceID.(0x92AB)
|
||||
$KEYBOARD_NCD_SUN := DeviceID.(0xA1AC)
|
||||
|
||||
$MOUSE_INIT_1 := DeviceID.(0xFFFD)
|
||||
$MOUSE_INIT_2 := DeviceID.(0xFFFE)
|
||||
$NO_DEVICE := DeviceID.(0xFFFF)
|
152
sysdata/programs/ps2_driver/src/main.hb
Normal file
152
sysdata/programs/ps2_driver/src/main.hb
Normal file
|
@ -0,0 +1,152 @@
|
|||
.{memory, log, buffer, string} := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{MouseEvent} := @use("../../../libraries/intouch/src/lib.hb").events;
|
||||
.{bit0, bit1, bit2, bit3, bit4} := @use("bits.hb")
|
||||
devices := @use("devices.hb")
|
||||
controller := @use("controller.hb");
|
||||
.{Info, Port} := controller
|
||||
mouse := @use("mouse.hb")
|
||||
format_page := memory.dangling(u8)
|
||||
|
||||
mouse_buffer := 0
|
||||
keyboard_buffer := 0
|
||||
info := Info.(0)
|
||||
|
||||
send_command := fn(port: ^Port, byte: u8): void {
|
||||
tries := 3
|
||||
loop if tries == 0 break else {
|
||||
controller.send_byte(port, byte)
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
if controller.has_input(info) == false {
|
||||
continue
|
||||
}
|
||||
input := controller.get_input()
|
||||
if controller.get_port(info) != port {
|
||||
if check_complete(port) == false {
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
if input == 0xFA {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
tries -= 1
|
||||
}
|
||||
}
|
||||
|
||||
enable_streaming := fn(port: ^Port): void {
|
||||
@inline(send_command, port, 0xF4)
|
||||
}
|
||||
|
||||
process := fn(port: ^controller.Port): void {
|
||||
if port.device.value < devices.MOUSE_5_BUTTON.value {
|
||||
event := MouseEvent.(0, 0, false, false, false)
|
||||
|
||||
event.left = bit0(port.packet[0])
|
||||
event.right = bit1(port.packet[0])
|
||||
event.middle = bit2(port.packet[0])
|
||||
|
||||
event.x_change = @intcast(port.packet[1])
|
||||
event.y_change = @intcast(port.packet[2])
|
||||
|
||||
buffer.write(MouseEvent, mouse_buffer, &event)
|
||||
} else if port.device == devices.MOUSE_INIT_1 {
|
||||
port.device.value = port.packet[0]
|
||||
if port.device != devices.MOUSE_SCROLLWHEEL {
|
||||
enable_streaming(port)
|
||||
return
|
||||
}
|
||||
port.device = devices.MOUSE_INIT_2
|
||||
} else if port.device == devices.MOUSE_INIT_2 {
|
||||
port.device.value = port.packet[0]
|
||||
} else if port.device == devices.NO_DEVICE {
|
||||
if port.packet_length == 1 {
|
||||
port.device.value = port.packet[0]
|
||||
enable_streaming(port)
|
||||
//TODO: Upgrade mouse.
|
||||
} else {
|
||||
port.device.value = port.packet[1] | port.packet[0] << 8
|
||||
enable_streaming(port)
|
||||
}
|
||||
log.info("Identified device!\0")
|
||||
log.info(string.display_int(port.device.value, format_page, 16))
|
||||
} else {
|
||||
log.info("KEY PRESSED\0")
|
||||
}
|
||||
}
|
||||
|
||||
check_complete := fn(port: ^controller.Port): bool {
|
||||
last_value := port.packet[port.packet_length - 1]
|
||||
if port.device == devices.NO_DEVICE {
|
||||
if last_value == 0 | last_value == 3 | last_value == 4 {
|
||||
return true
|
||||
} else if port.packet_length == 2 {
|
||||
return true
|
||||
}
|
||||
} else if port.device == devices.MOUSE_3_BUTTON {
|
||||
if port.packet_length == 3 return true
|
||||
} else if port.device == devices.MOUSE_SCROLLWHEEL | port.device == devices.MOUSE_5_BUTTON {
|
||||
if port.packet_length == 4 return true
|
||||
} else {
|
||||
if port.packet[0] == 0xE1 {
|
||||
if port.packet_length == 6 {
|
||||
return true
|
||||
}
|
||||
} else if port.packet[0] != 0xE0 {
|
||||
return true
|
||||
} else if port.packet_length == 2 & port.packet[1] != 0x2A & port.packet[1] != 0xB7 {
|
||||
return true
|
||||
} else if port.packet_length == 4 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
mouse_buffer = buffer.create("PS/2 Mouse\0")
|
||||
format_page = memory.alloc(u8, 1024)
|
||||
|
||||
controller.init()
|
||||
|
||||
if controller.port1.exists {
|
||||
//log.info("Port 1 exists.\0")
|
||||
controller.send_byte(@bitcast(0), 0xF4)
|
||||
}
|
||||
if controller.port2.exists {
|
||||
//controller.send_byte(&controller.port2, 0xF4)
|
||||
}
|
||||
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
|
||||
if controller.timed_out(info) {
|
||||
log.error("Timeout error! Cannot handle these!\0")
|
||||
}
|
||||
if controller.check_parity(info) {
|
||||
log.error("Parity error! Cannot handle these!\0")
|
||||
}
|
||||
/*
|
||||
if controller.has_input(info) {
|
||||
port := controller.get_port(info)
|
||||
if port.packet_length > 0 & check_complete(port) {
|
||||
process(port)
|
||||
}
|
||||
input := controller.get_input()
|
||||
/*if input == 0xAA & port.can_hot_plug {
|
||||
port.device = devices.NO_DEVICE
|
||||
controller.send_byte(port, 0xF4)
|
||||
}*/
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
if check_complete(port) {
|
||||
process(port)
|
||||
port.packet_length = 0
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
21
sysdata/programs/ps2_driver/src/mouse.hb
Normal file
21
sysdata/programs/ps2_driver/src/mouse.hb
Normal file
|
@ -0,0 +1,21 @@
|
|||
Button := struct {id: u8}
|
||||
$LEFT_BUTTON := Button.(1)
|
||||
$RIGHT_BUTTON := Button.(2)
|
||||
$MIDDLE_BUTTON := Button.(4)
|
||||
$BUTTON4 := Button.(8)
|
||||
$BUTTON5 := Button.(16)
|
||||
|
||||
SampleRate := struct {value: u8}
|
||||
$SR10 := SampleRate.(10)
|
||||
$SR20 := SampleRate.(20)
|
||||
$SR40 := SampleRate.(40)
|
||||
$SR60 := SampleRate.(60)
|
||||
$SR80 := SampleRate.(80)
|
||||
$SR100 := SampleRate.(100)
|
||||
$SR200 := SampleRate.(200)
|
||||
|
||||
Resolution := struct {value: u8}
|
||||
$RES_1COUNT_PER_MM := Resolution.(0)
|
||||
$RES_2COUNT_PER_MM := Resolution.(1)
|
||||
$RES_4COUNT_PER_MM := Resolution.(2)
|
||||
$RES_8COUNT_PER_MM := Resolution.(3)
|
21
sysdata/programs/ps2_driver/src/port.hb
Normal file
21
sysdata/programs/ps2_driver/src/port.hb
Normal file
|
@ -0,0 +1,21 @@
|
|||
.{DeviceID, NO_DEVICE} := @use("devices.hb")
|
||||
|
||||
State := struct {s: u8}
|
||||
$Recive := State.(0)
|
||||
$Reboot := State.(1)
|
||||
|
||||
Port := packed struct {
|
||||
exists: bool,
|
||||
device: DeviceID,
|
||||
packet: [u8; 8],
|
||||
packet_length: u8,
|
||||
can_hot_plug: bool,
|
||||
}
|
||||
|
||||
$PORT_AT_STARTUP := Port.(
|
||||
true,
|
||||
NO_DEVICE,
|
||||
.(0, 0, 0, 0, 0, 0, 0, 0),
|
||||
0,
|
||||
true,
|
||||
)
|
|
@ -1,4 +1,8 @@
|
|||
.{memory, log, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{memory, log, buffer} := stn
|
||||
|
||||
intouch := @use("../../../libraries/intouch/src/lib.hb");
|
||||
.{KeyEvent} := intouch
|
||||
|
||||
send_byte := fn(byte: u8): u8 {
|
||||
memory.outb(96, byte)
|
||||
|
@ -6,23 +10,31 @@ send_byte := fn(byte: u8): u8 {
|
|||
}
|
||||
|
||||
main := fn(): int {
|
||||
buf := buffer.create("XKeyboard\0")
|
||||
buf := buffer.create("PS/2 Keyboard\0")
|
||||
_ = send_byte(238)
|
||||
log.info("PS/2 Driver Loaded\0")
|
||||
|
||||
if send_byte(238) == 238 {
|
||||
log.info("PS/2 Keyboard Echoed\0")
|
||||
}
|
||||
|
||||
if send_byte(244) == 250 {
|
||||
log.info("Enabled scanning\0")
|
||||
}
|
||||
|
||||
prev_input := 250
|
||||
loop {
|
||||
loop if (memory.inb(0x64) & 0x20) == 0x20 break
|
||||
|
||||
input := memory.inb(96)
|
||||
|
||||
if input == prev_input {
|
||||
continue
|
||||
}
|
||||
prev_input = input
|
||||
buffer.write(u8, &input, buf)
|
||||
kevent := KeyEvent.(false, true, input)
|
||||
|
||||
buffer.write(KeyEvent, buf, &kevent)
|
||||
}
|
||||
return 0
|
||||
}
|
|
@ -145,7 +145,7 @@ main := fn(): int {
|
|||
event.x_change = x_change
|
||||
event.y_change = y_change
|
||||
|
||||
buffer.write(MouseEvent, &event, mouse_buffer)
|
||||
buffer.write(MouseEvent, mouse_buffer, &event)
|
||||
}
|
||||
|
||||
return 0
|
||||
|
|
|
@ -10,12 +10,12 @@ example := fn(): void {
|
|||
color := render.light_cyan
|
||||
n := @as(u8, 1)
|
||||
loop {
|
||||
// ! dead code elimination bug
|
||||
render.clear(screen, color)
|
||||
render.sync(screen)
|
||||
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
||||
if color.b == 255 | color.b == 0 {
|
||||
n = -n
|
||||
}
|
||||
color.b += n
|
||||
}
|
||||
return
|
||||
}
|
35
sysdata/programs/render_example/src/examples/orbit.hb
Normal file
35
sysdata/programs/render_example/src/examples/orbit.hb
Normal file
|
@ -0,0 +1,35 @@
|
|||
.{Vec2, sin, cos, PI} := @use("../../../../libraries/stn/src/lib.hb").math
|
||||
render := @use("../../../../libraries/render/src/lib.hb")
|
||||
|
||||
able_bmp := @embed("../../../../assets/able.bmp")
|
||||
mini_bmp := @embed("../../../../assets/mini.bmp")
|
||||
|
||||
/* expected result:
|
||||
two textured circles rotating
|
||||
around one yellow filled circle
|
||||
with a blue line showing their
|
||||
'orbit' */
|
||||
|
||||
example := fn(): void {
|
||||
able := render.image.from(@bitcast(&able_bmp))
|
||||
mini := render.image.from(@bitcast(&mini_bmp))
|
||||
if able == null | mini == null {
|
||||
return
|
||||
}
|
||||
|
||||
angle := 0.0
|
||||
|
||||
screen := render.init(true)
|
||||
|
||||
loop {
|
||||
render.clear(screen, render.black)
|
||||
render.put_filled_circle(screen, .(screen.width / 2, screen.height / 2), 128, render.light_yellow)
|
||||
render.put_circle(screen, .(screen.width / 2, screen.height / 2), 256, render.light_blue)
|
||||
render.put_textured_circle(screen, able, .(able.width / 2, able.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle) * 256)), screen.height / 2 + @intcast(@fti(cos(angle) * 256))), able.width / 2 - 1)
|
||||
render.put_textured_circle(screen, mini, .(mini.width / 2, mini.height / 2), .(screen.width / 2 + @intcast(@fti(sin(angle + PI) * 256)), screen.height / 2 + @intcast(@fti(cos(angle + PI) * 256))), mini.width / 2 - 1)
|
||||
render.sync(screen)
|
||||
|
||||
angle += 0.01
|
||||
}
|
||||
return
|
||||
}
|
|
@ -46,7 +46,7 @@ example := fn(): void {
|
|||
|
||||
bottom := buf + msg_len
|
||||
|
||||
@inline(memory.copy, u8, msg, buf, msg_len)
|
||||
memory.copy(u8, msg, buf, msg_len)
|
||||
cursor := bottom
|
||||
|
||||
draw_window(window, font, buf, cursor)
|
||||
|
|
11
sysdata/programs/sunset_client/meta.toml
Normal file
11
sysdata/programs/sunset_client/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "sunset_client"
|
||||
authors = ["koniifer"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
29
sysdata/programs/sunset_client/src/main.hb
Normal file
29
sysdata/programs/sunset_client/src/main.hb
Normal file
|
@ -0,0 +1,29 @@
|
|||
.{log} := @use("../../../libraries/stn/src/lib.hb")
|
||||
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
|
||||
render := @use("../../../libraries/render/src/lib.hb")
|
||||
|
||||
bmp := @embed("../../../assets/mini.bmp")
|
||||
|
||||
main := fn(): void {
|
||||
sunset.client.find_server()
|
||||
|
||||
image := render.image.bmp.from(@bitcast(&bmp))
|
||||
if image == null {
|
||||
log.error("got no image\0")
|
||||
return
|
||||
}
|
||||
|
||||
window := sunset.client.new(.(.(100, 100), .(200, 200), "Hello,\0"))
|
||||
|
||||
if window == null {
|
||||
log.error("got no window\0")
|
||||
return
|
||||
}
|
||||
x := 0
|
||||
loop {
|
||||
render.clear(window.surface, render.black)
|
||||
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
|
||||
_ = sunset.client.send_frame(window)
|
||||
x += 1
|
||||
}
|
||||
}
|
11
sysdata/programs/sunset_client_2/meta.toml
Normal file
11
sysdata/programs/sunset_client_2/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "sunset_client_2"
|
||||
authors = ["koniifer"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
29
sysdata/programs/sunset_client_2/src/main.hb
Normal file
29
sysdata/programs/sunset_client_2/src/main.hb
Normal file
|
@ -0,0 +1,29 @@
|
|||
.{log} := @use("../../../libraries/stn/src/lib.hb")
|
||||
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
|
||||
render := @use("../../../libraries/render/src/lib.hb")
|
||||
|
||||
bmp := @embed("../../../assets/able.bmp")
|
||||
|
||||
main := fn(): void {
|
||||
sunset.client.find_server()
|
||||
|
||||
image := render.image.bmp.from(@bitcast(&bmp))
|
||||
if image == null {
|
||||
log.error("got no image\0")
|
||||
return
|
||||
}
|
||||
|
||||
window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0"))
|
||||
|
||||
if window == null {
|
||||
log.error("got no window\0")
|
||||
return
|
||||
}
|
||||
x := 0
|
||||
loop {
|
||||
render.clear(window.surface, render.black)
|
||||
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 40), false)
|
||||
_ = sunset.client.send_frame(window)
|
||||
x += 1
|
||||
}
|
||||
}
|
11
sysdata/programs/sunset_server/meta.toml
Normal file
11
sysdata/programs/sunset_server/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "sunset_server"
|
||||
authors = ["koniifer"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
99
sysdata/programs/sunset_server/src/main.hb
Normal file
99
sysdata/programs/sunset_server/src/main.hb
Normal file
|
@ -0,0 +1,99 @@
|
|||
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
|
||||
render := @use("../../../libraries/render/src/lib.hb")
|
||||
intouch := @use("../../../libraries/intouch/src/lib.hb")
|
||||
|
||||
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
|
||||
.{new_label, render_label_to_surface, set_label_text, set_color} := horizon_api.widgets.label
|
||||
|
||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||
.{Vec2} := stn.math
|
||||
|
||||
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
|
||||
img := @embed("../../../assets/wallpaper.qoi")
|
||||
|
||||
main := fn(): int {
|
||||
sunset.server.start()
|
||||
|
||||
screen := render.init(true)
|
||||
render.clear(screen, render.black)
|
||||
|
||||
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
|
||||
|
||||
wallpaper := render.image.from(@bitcast(&img))
|
||||
if wallpaper == null {
|
||||
// stn.panic("Wallpaper not loaded\0")
|
||||
return 1
|
||||
}
|
||||
|
||||
mouse_x := 100
|
||||
mouse_y := 100
|
||||
|
||||
text_label := new_label("Hi\0")
|
||||
set_color(text_label, sunset.server.DECO_COLOUR, render.black)
|
||||
|
||||
loop {
|
||||
mouse_event := intouch.recieve_mouse_event()
|
||||
if mouse_event != null {
|
||||
change_x := @as(i16, mouse_event.x_change)
|
||||
change_x = change_x << 8
|
||||
change_x = change_x >> 8
|
||||
|
||||
mouse_x += change_x
|
||||
if mouse_x <= 0 {
|
||||
mouse_x = 0
|
||||
}
|
||||
if mouse_x >= screen.width - 20 {
|
||||
mouse_x = @intcast(screen.width - 21)
|
||||
}
|
||||
|
||||
change_y := @as(i16, mouse_event.y_change)
|
||||
change_y = change_y << 8
|
||||
change_y = change_y >> 8
|
||||
|
||||
mouse_y -= change_y
|
||||
if mouse_y < 0 {
|
||||
mouse_y = 1
|
||||
}
|
||||
if mouse_y >= screen.height - 20 {
|
||||
mouse_y = @intcast(screen.height - 21)
|
||||
}
|
||||
|
||||
if mouse_event.left {
|
||||
set_label_text(text_label, "LEFT CLICK\0")
|
||||
}
|
||||
if mouse_event.middle {
|
||||
set_label_text(text_label, "MIDDLE CLICK\0")
|
||||
}
|
||||
if mouse_event.right {
|
||||
set_label_text(text_label, "RIGHT CLICK\0")
|
||||
}
|
||||
}
|
||||
{
|
||||
render.clear(screen, render.black)
|
||||
render.put_surface(screen, wallpaper, .(0, 0), false)
|
||||
|
||||
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), sunset.server.DECO_COLOUR)
|
||||
}
|
||||
|
||||
if sunset.server.incoming() {
|
||||
sunset.server.collect_frames()
|
||||
sunset.server.render_clients(screen)
|
||||
}
|
||||
|
||||
{
|
||||
pos := Vec2(uint).(1, screen.height - 21)
|
||||
render_label_to_surface(screen, text_label, font, pos)
|
||||
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), sunset.server.DECO_COLOUR)
|
||||
}
|
||||
|
||||
// Mouse cursor
|
||||
{
|
||||
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR_DARKER)
|
||||
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR)
|
||||
}
|
||||
|
||||
render.sync(screen)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
|
@ -25,11 +25,20 @@ resolution = "1024x768x24"
|
|||
# [boot.limine.ableos.modules.render_example]
|
||||
# path = "boot:///render_example.hbf"
|
||||
|
||||
[boot.limine.ableos.modules.horizon]
|
||||
path = "boot:///horizon.hbf"
|
||||
# [boot.limine.ableos.modules.horizon]
|
||||
# path = "boot:///horizon.hbf"
|
||||
|
||||
[boot.limine.ableos.modules.ps2_mouse_driver]
|
||||
path = "boot:///ps2_mouse_driver.hbf"
|
||||
# [boot.limine.ableos.modules.ps2_mouse_driver]
|
||||
# path = "boot:///ps2_mouse_driver.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
||||
# path = "boot:///ps2_keyboard_driver.hbf"
|
||||
|
||||
[boot.limine.ableos.modules.ps2_driver]
|
||||
path = "boot:///ps2_driver.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.sunset_client]
|
||||
# path = "boot:///sunset_client.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.sunset_server]
|
||||
# path = "boot:///sunset_server.hbf"
|
||||
|
|
40
todo.md
Normal file
40
todo.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
@konii
|
||||
Windowing System
|
||||
Rendering
|
||||
|
||||
@able
|
||||
Windowing System
|
||||
Interrupt Forwarding
|
||||
|
||||
|
||||
@peony
|
||||
PS/2
|
||||
XYZ
|
||||
|
||||
|
||||
@kodin
|
||||
AIDL AbleOS Interface Description Language
|
||||
UI-SEXPR lispy ui decl language
|
||||
|
||||
@morshy
|
||||
Simple Userland Allocator
|
||||
|
||||
@funky
|
||||
Kernel Testing Framework (A rust framework for testing the kernel)
|
||||
|
||||
@unassigned
|
||||
FileIO (Fat32)
|
||||
DiskIO (Undecided Disk type)
|
||||
Proper Memory Protection
|
||||
Channels (Two buffers bundled together to form two way communication)
|
||||
Userland Testing Framework (An hblang framework for testing the userspace)
|
||||
PCI/E (Honestly I have no fucking clue whats going on with PCI or why userland cant properly read it)
|
||||
Kernel Reimpl (Do not you dare think about this yet its only here as an option to show goals)
|
||||
|
||||
AbleOS Compiler Collection
|
||||
acc-asm
|
||||
hblang^2 (hblang compiler in hblang)
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in a new issue