Compare commits

..

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

148 changed files with 1478 additions and 3961 deletions

View file

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

139
Cargo.lock generated
View file

@ -13,15 +13,15 @@ dependencies = [
[[package]]
name = "allocator-api2"
version = "0.2.21"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
[[package]]
name = "anyhow"
version = "1.0.95"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]]
name = "autocfg"
@ -73,9 +73,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.5"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
dependencies = [
"shlex",
]
@ -88,18 +88,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-queue"
version = "0.3.12"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "derive_more"
@ -175,9 +175,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.4"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]]
name = "form_urlencoded"
@ -201,9 +201,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.15.2"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
dependencies = [
"allocator-api2",
"equivalent",
@ -213,12 +213,12 @@ dependencies = [
[[package]]
name = "hbbytecode"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#08fc9d6ab6a8dd539255bf45d892f4b7f08776c5"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
[[package]]
name = "hblang"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#08fc9d6ab6a8dd539255bf45d892f4b7f08776c5"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
dependencies = [
"hashbrown",
"hbbytecode",
@ -229,7 +229,7 @@ dependencies = [
[[package]]
name = "hbvm"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#08fc9d6ab6a8dd539255bf45d892f4b7f08776c5"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#37dd13cab295aa9e74d704b3345685b4428d149a"
dependencies = [
"hbbytecode",
]
@ -375,9 +375,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.7.0"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
@ -392,7 +392,6 @@ dependencies = [
"derive_more",
"hashbrown",
"hbvm",
"ktest_macro",
"limine",
"log",
"sbi",
@ -401,18 +400,10 @@ dependencies = [
"uart_16550",
"versioning",
"x2apic",
"x86_64 0.15.2",
"x86_64 0.15.1",
"xml",
]
[[package]]
name = "ktest_macro"
version = "0.1.0"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -421,9 +412,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.169"
version = "0.2.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
[[package]]
name = "limine"
@ -433,9 +424,9 @@ checksum = "02034f8f6b3e7bf050f310fbaf6db0018b8e54b75598d0a4c97172054752fede"
[[package]]
name = "litemap"
version = "0.7.4"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]]
name = "lock_api"
@ -455,18 +446,18 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "logos"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7251356ef8cb7aec833ddf598c6cb24d17b689d20b993f9d11a3d764e34e6458"
checksum = "1c6b6e02facda28ca5fb8dbe4b152496ba3b1bd5a4b40bb2b1b2d8ad74e0f39b"
dependencies = [
"logos-derive",
]
[[package]]
name = "logos-codegen"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f80069600c0d66734f5ff52cc42f2dabd6b29d205f333d61fd7832e9e9963f"
checksum = "b32eb6b5f26efacd015b000bfc562186472cd9b34bdba3f6b264e2a052676d10"
dependencies = [
"beef",
"fnv",
@ -479,9 +470,9 @@ dependencies = [
[[package]]
name = "logos-derive"
version = "0.14.4"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24fb722b06a9dc12adb0963ed585f19fc61dc5413e6a9be9422ef92c091e731d"
checksum = "3e5d0c5463c911ef55624739fc353238b4e310f0144be1f875dc42fec6bfd5ec"
dependencies = [
"logos-codegen",
]
@ -512,9 +503,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "proc-macro2"
version = "1.0.92"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@ -593,9 +584,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.20"
version = "0.23.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e"
dependencies = [
"log",
"once_cell",
@ -608,9 +599,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
version = "1.10.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]]
name = "rustls-webpki"
@ -643,24 +634,24 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.24"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.216"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.216"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
@ -726,9 +717,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.91"
version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
@ -809,9 +800,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "unicode-xid"
@ -827,9 +818,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.12.1"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a"
dependencies = [
"base64",
"log",
@ -842,9 +833,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.5.4"
version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada"
dependencies = [
"form_urlencoded",
"idna",
@ -885,9 +876,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "webpki-roots"
version = "0.26.7"
version = "0.26.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958"
dependencies = [
"rustls-pki-types",
]
@ -996,7 +987,7 @@ dependencies = [
"bitflags 1.3.2",
"paste",
"raw-cpuid 10.7.0",
"x86_64 0.14.13",
"x86_64 0.14.12",
]
[[package]]
@ -1012,9 +1003,9 @@ dependencies = [
[[package]]
name = "x86_64"
version = "0.14.13"
version = "0.14.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491"
checksum = "96cb6fd45bfeab6a5055c5bffdb08768bd0c069f1d946debe585bbb380a7c062"
dependencies = [
"bit_field",
"bitflags 2.6.0",
@ -1024,9 +1015,9 @@ dependencies = [
[[package]]
name = "x86_64"
version = "0.15.2"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [
"bit_field",
"bitflags 2.6.0",
@ -1044,9 +1035,9 @@ dependencies = [
[[package]]
name = "yoke"
version = "0.7.5"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
dependencies = [
"serde",
"stable_deref_trait",
@ -1056,9 +1047,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
version = "0.7.5"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
dependencies = [
"proc-macro2",
"quote",
@ -1068,18 +1059,18 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.5"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.5"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
dependencies = [
"proc-macro2",
"quote",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -62,7 +62,7 @@ extern "x86-interrupt" fn page_fault(
}
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
interrupt(Interrupt::Timer);
// interrupt(Interrupt::Timer);
unsafe {
LAPIC.end_of_interrupt();
@ -83,31 +83,28 @@ extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
}
}
#[allow(unused_imports)]
fn interrupt(interrupt_type: Interrupt) {
use crate::{arch::INTERRUPT_LIST, kmain::EXECUTOR};
// let il = INTERRUPT_LIST.lock();
// let val = il.list.get(&interrupt_type).unwrap();
use crate::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)
// }
// }
// }
use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
let buffer = sds_search_service(val);
if buffer != 0 {
use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
let mut buffs = IPC_BUFFERS.lock();
match buffs.get_mut(&buffer) {
Some(buff) => {
let mut msg_vec = Vec::new();
msg_vec.push(0xFF);
buff.push(msg_vec.to_vec());
log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
}
None => {
log::error!("Access of non-existent buffer {}", buffer)
}
}
unsafe {
EXECUTOR.send_interrupt(interrupt_type as u8);
// log::info!("{}", buffer);
}
}

View file

@ -33,7 +33,7 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
}
#[inline(always)]
pub fn handler(vm: &mut Vm, pid: &usize) {
pub fn handler(vm: &mut Vm) {
let ecall_number = vm.registers[2].cast::<u64>();
match ecall_number {
@ -80,10 +80,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let length = vm.registers[5].cast::<u64>() as usize;
trace!("IPC address: {:?}", mem_addr);
unsafe { LazyCell::<Executor>::get_mut(&mut EXECUTOR) }
.unwrap()
.send_buffer(buffer_id as usize);
match buffer_id {
0 => match sds_msg_handler(vm, mem_addr, length) {
Ok(()) => {}
@ -213,6 +209,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
let buffer_id = vm.registers[3].cast::<u64>();
let map_ptr = vm.registers[4].cast::<u64>();
let max_length = vm.registers[5].cast::<u64>();
let mut buffs = IPC_BUFFERS.lock();
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
Some(buff) => buff,
@ -246,28 +243,6 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
vm.registers[3] = x
}
}
6 => {
// Wait till interrupt
use crate::kmain::EXECUTOR;
let interrupt_type = vm.registers[3].cast::<u8>();
debug!("Interrupt subscribed: {}", interrupt_type);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.interrupt_subscribe(*pid, interrupt_type);
}
}
7 => {
// Wait till buffer
use crate::kmain::EXECUTOR;
let buffer_id = vm.registers[3].cast::<u64>() as usize;
debug!("Buffer subscribed: {}", buffer_id);
unsafe {
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
.unwrap()
.buffer_subscribe(*pid, buffer_id);
}
}
_ => {
log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
}

View file

@ -96,21 +96,18 @@ pub fn memory_msg_handler(
log::debug!(" {} pages", page_count);
}
4 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[5..13].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[13..21].try_into().unwrap_unchecked()) as *mut u8;
src.copy_to_nonoverlapping(dest, count);
},
5 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
let size = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as usize;
let src =
u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[25..33].try_into().unwrap_unchecked()) as *mut u8;
debug_assert!(src.addr() & 0xFFFF000000000000 != 0);
debug_assert!(dest.addr() & 0xFFFF000000000000 != 0);
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
let size = u32::from_le_bytes(msg_vec[5..9].try_into().unwrap_unchecked()) as usize;
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
memset(dest, src, count, size);
},
_ => {

View file

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

View file

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

View file

@ -22,18 +22,6 @@ use {
pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
debug!("Entered kmain");
#[cfg(feature = "ktest")]
{
use {
crate::ktest,
log::info,
};
info!("Running tests");
ktest::test_main();
loop {}
}
// let kcmd = build_cmd("Kernel Command Line", cmdline);
// trace!("Cmdline: {kcmd:?}");
@ -79,7 +67,6 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
"Graphics front ptr {:?}",
fb1.address.as_ptr().unwrap() as *const u8
);
log::info!("Started AbleOS");
unsafe {
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
@ -125,7 +112,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
if cmd_len > 0 {
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
}
executor.spawn(Box::pin(async {
executor.spawn(Box::pin(async move {
if let Err(e) = thr.await {
log::error!("{e:?}");
}
@ -136,6 +123,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
executor.run();
};
crate::arch::spin_loop()
}
@ -160,3 +148,10 @@ pub static IPC_BUFFERS: Lazy<Mutex<IpcBuffers>> = Lazy::new(|| {
Mutex::new(bufs)
});
#[test_case]
fn trivial_assertion() {
trace!("trivial assertion... ");
assert_eq!(1, 1);
info!("[ok]");
}

View file

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

View file

@ -2,7 +2,6 @@
//! 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,
@ -10,12 +9,12 @@
abi_x86_interrupt,
lazy_get,
alloc_error_handler,
local_waker,
context_ext,
ptr_sub_ptr,
custom_test_frameworks,
naked_functions,
pointer_is_aligned_to
)]
#![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features, static_mut_refs)]
extern crate alloc;
@ -34,9 +33,6 @@ mod memory;
mod task;
mod utils;
#[allow(improper_ctypes, non_upper_case_globals)]
mod ktest;
use versioning::Version;
/// Kernel's version
@ -49,7 +45,6 @@ pub const VERSION: Version = Version {
#[panic_handler]
#[cfg(target_os = "none")]
fn panic(info: &core::panic::PanicInfo) -> ! {
use alloc::string::ToString;
arch::register_dump();
if let Some(loc) = info.location() {
@ -61,7 +56,15 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
));
}
let msg = info.message().to_string().replace("\n", "\r\n");
let msg = info.message();
let _ = crate::arch::log(format_args!("{msg}\r\n"));
loop {}
}
#[cfg(test)]
fn test_runner(tests: &[&dyn Fn()]) {
println!("Running {} tests", tests.len());
for test in tests {
test();
}
}

View file

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

View file

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

View file

@ -15,7 +15,6 @@ fatfs = { version = "0.3", default-features = false, features = [
] }
toml = "0.8"
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
# hblang.path = "../../holey-bytes/lang/"
log = "0.4"
raw-cpuid = "11"
ureq = { version = "2", default-features = false, features = ["tls"] }

View file

@ -83,8 +83,7 @@ impl Package {
&path,
Options {
fmt: true,
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
in_house_regalloc: true,
..Default::default()
},
out,
@ -100,7 +99,7 @@ impl Package {
hblang::run_compiler(
&path,
Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
in_house_regalloc: true,
..Default::default()
},
out,
@ -109,20 +108,18 @@ impl Package {
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
out.clear();
let err = hblang::run_compiler(
hblang::run_compiler(
&path,
Options {
resolver: Some(hblang::ABLEOS_PATH_RESOLVER),
dump_asm: true,
in_house_regalloc: true,
..Default::default()
},
out,
&mut warnings,
);
)?;
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
out.clear();
return err;
}
Ok(())
}

View file

@ -27,7 +27,6 @@ fn main() -> Result<(), Error> {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
for arg in args {
if arg == "-r" || arg == "--release" {
release = true;
@ -39,42 +38,17 @@ fn main() -> Result<(), Error> {
target = Target::Aarch64;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo, tests).change_context(Error::Build)
build(release, target, debuginfo).change_context(Error::Build)
}
// Some("test" | "t") => {
// let mut release = false;
// let mut debuginfo = false;
// let mut target = Target::X86_64;
// for arg in args {
// if arg == "-r" || arg == "--release" {
// release = true;
// } else if arg == "-d" || arg == "--debuginfo" {
// debuginfo = true;
// } else if arg == "rv64" || arg == "riscv64" || arg == "riscv64-virt" {
// target = Target::Riscv64Virt;
// } else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
// target = Target::Aarch64;
// } else if arg == "avx2" {
// target = Target::X86_64Avx2;
// } else {
// return Err(report!(Error::InvalidSubCom));
// }
// }
// test(release, target, debuginfo).change_context(Error::Build)
// }
Some("run" | "r") => {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut tests = false;
let mut do_accel = true;
for arg in args {
if arg == "-r" || arg == "--release" {
@ -89,14 +63,12 @@ fn main() -> Result<(), Error> {
do_accel = false;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else if arg == "--ktest" {
tests = true;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo, tests)?;
build(release, target, debuginfo)?;
run(release, target, do_accel)
}
Some("help" | "h") => {
@ -110,7 +82,6 @@ fn main() -> Result<(), Error> {
" -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\n",
" --noaccel: run without acceleration (e.g, no kvm)\n",
" --ktest: Enables tests via ktest\n",
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
),);
Ok(())
@ -253,10 +224,10 @@ TERM_BACKDROP={}
);
match p.build(&mut out) {
Ok(()) => {}
Err(e) => {
writeln!(errors, "========= while compiling {} {} =========", path, e)
Err(_) => {
writeln!(errors, "========= while compiling {} =========", path)
.unwrap();
errors.push_str(&String::from_utf8_lossy(&out));
errors.push_str(core::str::from_utf8(&out).expect("no"));
out.clear();
}
}
@ -339,7 +310,7 @@ fn copy_file_to_img(fpath: &str, fs: &FileSystem<File>) {
.expect("Copy failed");
}
fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<(), Error> {
fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
let fs = get_fs().change_context(Error::Io)?;
let mut com = Command::new("cargo");
com.current_dir("kernel");
@ -351,10 +322,6 @@ fn build(release: bool, target: Target, debuginfo: bool, tests: bool) -> Result<
com.env("RUSTFLAGS", "-Cdebug-assertions=true");
}
if tests {
com.args(["--features", "ktest"]);
}
if target == Target::Riscv64Virt {
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
}
@ -455,16 +422,11 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip]
com.args([
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
//"-hda", "target/disk.img",
"-drive", "file=target/disk.img,index=0,if=ide,format=raw",
"-drive", "file=target/disk.img,format=raw",
"-device", "vmware-svga",
// "-serial", "stdio",
"-m", "2G",
"-smp", "1",
"-audiodev",
"pa,id=speaker",
"-machine",
"pcspk-audiodev=speaker",
"-parallel", "none",
"-monitor", "none",
"-machine", accel,
@ -490,7 +452,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip]
com.args([
"-M", "virt",
"-cpu", "max",
"-cpu", "neoverse-n2",
"-device", "ramfb",
"-device", "qemu-xhci",
"-device", "usb-kbd",

View file

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

View file

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

View file

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

View file

@ -10,32 +10,37 @@ Label := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
text: []u8,
text: ^u8,
text_length: uint,
bg: Color,
fg: Color,
}
new_label := fn(text: []u8, width: uint): Self {
text_surface := render.Surface.new(width, 20)
label := Self.(3, true, text_surface, text, render.BLACK, render.WHITE)
return label
}
set_label_text := fn(label: Label, text: ^u8): void {
text_length := string.length(text)
$set_label_text := fn(self: ^Self, text: []u8): void {
self.is_dirty = true
self.text = text
}
$set_color := fn(self: ^Self, bg: Color, fg: Color): void {
self.bg = bg
self.fg = fg
self.is_dirty = true
}
label.is_dirty = true
label.text = text
label.text_length = text_length
}
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
if label.is_dirty {
label.surface.clear(label.bg)
label.surface.put_text(font, .(0, 0), label.fg, label.text)
render.clear(label.surface, label.bg)
render.put_text(label.surface, font, .(0, 0), label.fg, label.text)
}
surface.put_surface(label.surface, pos, false)
render.put_surface(surface, label.surface, pos, false)
}
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, 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
}

View file

@ -1,4 +1,4 @@
stn := @use("stn");
stn := @use("../../stn/src/lib.hb");
.{log, buffer, memory} := stn
keycodes := @use("keycodes.hb")
@ -8,7 +8,7 @@ events := @use("events.hb");
recieve_key_event := fn(): ?KeyEvent {
kevent := KeyEvent.(false, false, 0)
buf_id := buffer.search("PS/2 Keyboard")
buf_id := buffer.search("PS/2 Keyboard\0")
// Read out of the Keyboard buffer here
buffer.recv(KeyEvent, buf_id, &kevent)
@ -23,7 +23,7 @@ recieve_key_event := fn(): ?KeyEvent {
recieve_mouse_event := fn(): ?MouseEvent {
mevent := MouseEvent.(0, 0, false, false, false)
buf_id := buffer.search("PS/2 Mouse")
buf_id := buffer.search("PS/2 Mouse\0")
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, &mevent)

View file

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

View file

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

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface, put_surface} := @use("lib:render");
.{log} := @use("stn")
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
.{log} := @use("../../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
magic: u16,
@ -37,13 +37,13 @@ from := fn(bmp: ^u8): ?Surface {
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
log.error("Invalid BMP image.")
log.error("Invalid BMP image.\0")
return null
}
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
rhs := Surface.new(info_header.width, info_header.height)
rhs.put_surface(lhs, .(0, 0), true)
rhs := new_surface(info_header.width, info_header.height)
put_surface(rhs, lhs, .(0, 0), true)
return rhs
}

View file

@ -1,5 +1,5 @@
.{log} := @use("stn");
.{Surface} := @use("lib:render")
.{log} := @use("../../../stn/src/lib.hb");
.{Surface} := @use("../lib.hb")
bmp := @use("bmp.hb")
qoi := @use("qoi.hb")
$BMP := 0x4D42
@ -19,7 +19,7 @@ from := fn(file: ^u8): ?Surface {
format := get_format(file)
if format == null {
log.error("Could not detect image format.")
log.error("Could not detect image format.\0")
return null
} else if format == BMP {
return bmp.from(file)

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface} := @use("lib:render");
.{log} := @use("stn")
.{Color, Surface, new_surface} := @use("../lib.hb");
.{log} := @use("../../../stn/src/lib.hb")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
@ -40,12 +40,12 @@ from := fn(qoi: ^u8): ?Surface {
height := be_to_le(header.height)
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
log.error("Invalid QOI image.")
log.error("Invalid QOI image.\0")
return null
}
surface := Surface.new(width, height)
index := @as([64]Color, idk)
surface := new_surface(width, height)
index := @as([Color; 64], idk)
run := 0
px := Color.(0, 0, 0, 255)

View file

@ -6,23 +6,52 @@ text := @use("text.hb")
mode := software
init := mode.init
doublebuffer := mode.doublebuffer
Surface := mode.Surface
new_surface := mode.new_surface
surface_from_ptr := mode.surface_from_ptr
clone_surface := mode.clone_surface
free_surface := mode.free_surface
index := mode.index
indexptr := mode.indexptr
// Colours
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
$WHITE := Color.(255, 255, 255, 255)
$BLACK := Color.(0, 0, 0, 255)
$GRAY := Color.(127, 127, 127, 255)
$RED := Color.(0, 0, 205, 255)
$GREEN := Color.(0, 205, 0, 255)
$YELLOW := Color.(0, 205, 205, 255)
$BLUE := Color.(205, 0, 0, 255)
$MAGENTA := Color.(205, 0, 205, 255)
$CYAN := Color.(205, 205, 0, 255)
$LIGHT_GRAY := Color.(229, 229, 229, 255)
$LIGHT_RED := Color.(0, 0, 255, 255)
$LIGHT_GREEN := Color.(0, 255, 0, 255)
$LIGHT_YELLOW := Color.(0, 255, 255, 255)
$LIGHT_BLUE := Color.(255, 0, 0, 255)
$LIGHT_MAGENTA := Color.(255, 0, 255, 255)
$LIGHT_CYAN := Color.(255, 255, 0, 255)
$white := Color.(255, 255, 255, 255)
$black := Color.(0, 0, 0, 255)
$gray := Color.(127, 127, 127, 255)
$red := Color.(0, 0, 205, 255)
$green := Color.(0, 205, 0, 255)
$yellow := Color.(0, 205, 205, 255)
$blue := Color.(205, 0, 0, 255)
$magenta := Color.(205, 0, 205, 255)
$cyan := Color.(205, 205, 0, 255)
$light_gray := Color.(229, 229, 229, 255)
$light_red := Color.(0, 0, 255, 255)
$light_green := Color.(0, 255, 0, 255)
$light_yellow := Color.(0, 255, 255, 255)
$light_blue := Color.(255, 0, 0, 255)
$light_magenta := Color.(255, 0, 255, 255)
$light_cyan := Color.(255, 255, 0, 255)
// Drawing
put_pixel := mode.put_pixel
put_rect := mode.put_rect
put_filled_rect := mode.put_filled_rect
put_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
// Display
sync := mode.sync

View file

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

View file

@ -1,4 +1,4 @@
.{log, memory} := @use("stn")
.{log, memory} := @use("../../stn/src/lib.hb")
PSF1Header := packed struct {
magic: u16,
@ -31,7 +31,7 @@ Font := struct {
font_from_psf1 := fn(psf: ^u8): ?Font {
header := @as(^PSF1Header, @bitcast(psf))
if header.magic != 0x436 {
log.error("failed to load psf font: not a psf1 font, idiot")
log.error("failed to load psf font: not a psf1 font, idiot\0")
return null
}
@ -52,7 +52,7 @@ font_from_psf1 := fn(psf: ^u8): ?Font {
font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
header := @as(^PSF2Header, @bitcast(psf))
if header.magic != 0x864AB572 {
log.error("failed to load psf font: not a psf2 font, idiot")
log.error("failed to load psf font: not a psf2 font, idiot\0")
return null
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because one or more lines are too long

View file

@ -2,11 +2,7 @@ $PAGE_SIZE := 4096
$MAX_ALLOC := 0xFF
$MAX_FREE := 0xFF
$uninit := fn($Expr: type): Expr {
return idk
}
$nulled := fn($Expr: type): ?Expr {
$uninit := fn($Expr: type): ?Expr {
return null
}
@ -69,22 +65,12 @@ $inl := fn(addr: u16): u32 {
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
}
OutsMsg := packed struct {a: u8, b: u8, addr: u16, value: u16}
$outs := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutsMsg.(1, 1, addr, value), @sizeof(OutsMsg))
}
InsMsg := packed struct {a: u8, b: u8, addr: u16}
$ins := fn(addr: u16): u16 {
return @eca(3, 3, &InsMsg.(0, 1, addr), @sizeof(InsMsg))
}
CopyMsg := packed struct {a: u8, count: uint, src: ^u8, dest: ^u8}
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8}
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}

View file

@ -1,15 +1,7 @@
$any := fn($Expr: type): Expr {
any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
}
$range := fn($Expr: type, min: Expr, max: Expr): Expr {
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)
}

View file

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

View file

@ -1,172 +1,63 @@
// todo: splice function
length := fn(ptr: ^u8): uint {
len := 0
loop if *(ptr + len) == 0 return len else len += 1
}
reverse := fn(str: []u8): void {
if str.len == 0 return;
j := str.len - 1
i := 0
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
is_negative := num < 0
if is_negative num = -num
ptr := p
if num == 0 {
*ptr = 0x30;
*(ptr + 1) = 0
return p
}
loop if num == 0 break else {
remainder := num % @bitcast(radix)
num /= @bitcast(radix);
*ptr = @intcast(remainder + 0x30)
if remainder > 9 {
*ptr = @intcast(remainder - 10 + 0x41)
}
ptr += 1
}
if is_negative {
*ptr = 0x2D
ptr += 1
}
// ! it gets broked when you do this ??
// *ptr = 0
@inline(reverse, p)
return p
}
reverse := fn(s: ^u8): void {
j := s + @inline(length, s) - 1
temp := @as(u8, 0)
loop if i < j {
temp = str[i]
str[i] = str[j]
str[j] = temp
i += 1
loop if s < j {
temp = *s;
*s = *j;
*j = temp
s += 1
j -= 1
} else return
}
equals := fn(lhs: []u8, rhs: []u8): bool {
if lhs.len != rhs.len return false
if lhs.ptr == rhs.ptr return true
i := 0
loop if i == lhs.len break else {
if lhs[i] != rhs[i] return false
i += 1
equals := fn(lhs: ^u8, rhs: ^u8): bool {
if lhs == rhs {
return true
}
return true
}
clear := fn(str: []u8): void {
i := 0
loop if i == str.len break else {
str[i] = 0
i += 1
}
}
split_once := fn(haystack: []u8, needle: @Any()): ?struct {left: []u8, right: []u8} {
T := @TypeOf(needle)
i := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return null
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches return .(haystack[0..i], haystack[i + needle.len..])
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle {
return .(haystack[0..i], haystack[i + 1..])
} else if i == haystack.len return null
i += 1
}
loop if *lhs != *rhs {
return false
} else if *lhs == 0 {
return true
} else {
@error("Type of needle must be []u8 or u8.")
lhs += 1
rhs += 1
}
}
split := fn(iter: []u8, needle: @Any()): struct {
str: []u8,
needle: @TypeOf(needle),
done: bool,
next := fn(self: ^Self): ?[]u8 {
if self.done return null;
splits := split_once(self.str, self.needle)
if splits != null {
self.str = splits.right
return splits.left
} else {
self.done = true
return self.str
}
}
} {
T := @TypeOf(needle)
if T != []u8 & T != u8 {
@error("Type of needle must be []u8 or u8.")
}
return .(iter, needle, false)
}
chars := fn(iter: []u8): struct {
str: []u8,
next := fn(self: ^Self): ?u8 {
if self.str.len == 0 return null
self.str = self.str[1..]
return self.str[0]
}
} {
return .(iter)
}
count := fn(haystack: []u8, needle: @Any()): uint {
T := @TypeOf(needle)
i := 0
c := 0
if T == []u8 {
if needle.len == 0 return null
loop {
if i + needle.len > haystack.len return c
if haystack[i] == needle[0] {
matches := true
n := 1
loop {
if n == needle.len break
if haystack[i + n] != needle[n] {
matches = false
break
}
n += 1
}
if matches c += 1
}
i += 1
}
} else if T == u8 {
loop {
if haystack[i] == needle c += 1 else if i == haystack.len return c
i += 1
}
} else {
@error("Type of needle must be []u8 or u8.")
}
}
left_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[0] == sub[0] {
loop if i == sub.len {
return str[i..str.len]
} else if str[i] != sub[i] | i == str.len {
break
} else {
i += 1
}
}
return str
}
right_trim := fn(str: []u8, sub: []u8): []u8 {
i := 0
if str[str.len - 1] == sub[sub.len - 1] {
loop if i == sub.len {
return str[0..str.len - i]
} else if str[str.len - i - 1] != sub[sub.len - i - 1] | i == str.len {
break
} else {
i += 1
}
}
return str
}
trim := fn(str: []u8, sub: []u8): []u8 {
return right_trim(left_trim(str, sub), sub)
}

View file

@ -1,16 +1,16 @@
.{math: .{Vec2}, buffer, log, memory, string} := @use("stn");
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("lib:sunset_proto");
.{Surface, Color} := @use("lib:render")
.{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")
log.info("client: locating server\0")
channel2 := await_channel()
channel.server = channel2.server
channel.client = channel2.client
log.info("client: server located")
log.info("client: server located\0")
}
new := fn(props: WindowProps): ?Window {
@ -19,14 +19,14 @@ new := fn(props: WindowProps): ?Window {
if response.header.kind != message.ack {
return null
}
log.info("client: recv ack")
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")
surface := Surface.new(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
log.info("client: recv windowdata\0")
surface := new_surface(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
return .(windowdata.body, surface)
}

View file

@ -1,8 +1,8 @@
.{math: .{Vec2}, buffer, memory} := @use("stn");
.{Surface} := @use("lib:render")
.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb");
.{Surface} := @use("../../render/src/lib.hb")
$BUFFER_SERVER := "sunset_server"
$BUFFER_CLIENT := "sunset_client"
$BUFFER_SERVER := "sunset_server\0"
$BUFFER_CLIENT := "sunset_client\0"
Channel := packed struct {
client: uint,
@ -48,8 +48,6 @@ await_channel := fn(): Channel {
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?Message(Expr), buffer_id, &response)
if response != null {
return @as(Message(Expr), response)
@ -60,11 +58,9 @@ await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
await_header := fn(buffer_id: uint): MessageHeader {
response := @as(?MessageHeader, null)
loop {
// awaiting here causes flickering... idk why
buffer.await(buffer_id)
buffer.recv(?MessageHeader, buffer_id, &response)
if response != null {
return @as(MessageHeader, response)
return @as(?MessageHeader, response)
}
}
}
@ -85,7 +81,8 @@ Message := fn($Expr: type): type {
WindowProps := struct {
position: Vec2(uint),
dimensions: Vec2(uint),
title: []u8,
// ! replace with owned string type later
title: ^u8,
}
WindowData := struct {

View file

@ -1,33 +1,33 @@
.{math, log, string, random, buffer, memory} := @use("stn");
.{Color, Surface, text} := @use("lib:render");
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("lib:sunset_proto")
.{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: [10]?Window,
windows: [?Window; 10],
font: text.Font,
}
// ! in the future this should be safely handled
server := @as(WindowServer, idk)
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
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")
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],
.(null, null, null, null, null, null, null, null, null, null),
@as(text.Font, font),
)
log.info("server: started server")
log.info("server: started server\0")
}
incoming := fn(): bool {
@ -36,14 +36,14 @@ incoming := fn(): bool {
return true
}
if msg.kind == message.syn {
log.info("server: recv 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")
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)
@ -51,16 +51,17 @@ incoming := fn(): bool {
// decorations
{
title := data.props.title
deco_length := title.len * 10
title_length := string.length(title)
deco_length := title_length * 10
// draw the window tab bar
surface.put_filled_rect(.(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
// Draw the window tab
surface.put_filled_rect(.(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
// Draw the outside box
surface.put_rect(.(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
surface.put_text(server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
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
@ -75,7 +76,10 @@ $DECO_COLOUR := Color.(100, 200, 255, 255)
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
return @inline(Surface.new, dimensions.x + DECO_WIDTH, dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM)
return new_surface(
dimensions.x + DECO_WIDTH,
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
)
}
// ! compositor code. this currently disallows tearing.
@ -100,10 +104,10 @@ collect_frames := fn(): void {
send_header(message.ack, window.data.channel.client)
ptr := await_message(^Color, window.data.channel.server)
if ptr.header.kind != message.ack {
i += 1
continue
return
}
window.surface.put_surface(
put_surface(
window.surface,
Surface.(
ptr.body,
window.data.props.dimensions.x,
@ -125,7 +129,7 @@ render_clients := fn(screen: Surface): void {
i += 1
continue
}
screen.put_surface(window.surface, window.data.props.position, false)
put_surface(screen, window.surface, window.data.props.position, false)
i += 1
}
}

View file

@ -1 +0,0 @@
# ablefetch

View file

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

View file

@ -1,5 +0,0 @@
# angels_halo
A Minix 3 style reincarnation service.
Running in the background restarting your drivers.

View file

@ -1,7 +0,0 @@
(pkg angels-halo
(authors ("able"))
(version 0 1 0))
(dependencies
(libraries ())
(programs (hblang)))

View file

@ -1,18 +0,0 @@
stn := @use("stn");
.{log} := stn;
.{ProcessID} := stn.acs
Strategy := enum {
None,
Restart,
}
MonitoredProcess := struct {
pid: ProcessID,
}
main := fn(): int {
log.info("Angels Halo reincarnation server started.")
return 0
}

View file

@ -1,111 +1,13 @@
.{memory: .{inb, outb, ins, alloc}, log} := @use("stn")
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
$ATA_PRIMARY_DATA := 0x1F0
$ATA_PRIMARY_ERR := 0x1F1
$ATA_PRIMARY_SECCOUNT := 0x1F2
$ATA_PRIMARY_LBA_LO := 0x1F3
$ATA_PRIMARY_LBA_MID := 0x1F4
$ATA_PRIMARY_LBA_HI := 0x1F5
$ATA_PRIMARY_DRIVE_HEAD := 0x1F6
$ATA_PRIMARY_COMM_REGSTAT := 0x1F7
$ATA_PRIMARY_ALTSTAT_DCR := 0x3F6
main := fn(): int {
// shuts down ableOS
// memory.outb(0xF400, 0)
$STAT_ERR := 1 << 0
$STAT_DRQ := 1 << 3
$STAT_SRV := 1 << 4
$STAT_DF := 1 << 5
$STAT_RDY := 1 << 6
$STAT_BSY := 1 << 7
a := memory.inb(0x4600)
b := memory.inb(0x4700)
Drive := enum {Master, Slave}
select_drive := fn(drive: Drive): void {
match drive {
.Master => outb(ATA_PRIMARY_DRIVE_HEAD, 0xA0),
.Slave => outb(ATA_PRIMARY_DRIVE_HEAD, 0xB0),
}
}
identify := fn(drive: Drive): u8 {
if inb(ATA_PRIMARY_COMM_REGSTAT) == 0xFF {
log.error("(ata: drive not present) status=0xFF")
return 0
}
select_drive(drive)
inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_SECCOUNT, 0)
inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_LO, 0)
inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_MID, 0)
inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_HI, 0)
inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_COMM_REGSTAT, 0xEC)
outb(ATA_PRIMARY_COMM_REGSTAT, 0xE7)
status := inb(ATA_PRIMARY_COMM_REGSTAT)
loop if (status & STAT_BSY) == 0 break else {
// if DEBUG_PRINT log.printf("(ata: waiting for status) status={}", .(status), .{radix: 16, log: .Warn})
status = inb(ATA_PRIMARY_COMM_REGSTAT)
}
if status == 0 {
log.error("(ata: drive not present) status=0")
return 0
}
loop if (status & STAT_BSY) == 0 break else {
if DEBUG_PRINT log.printf("(ata: waiting for busy to end) status={}", .(status), .{radix: 16, log: .Warn})
status = inb(ATA_PRIMARY_COMM_REGSTAT)
}
mid := inb(ATA_PRIMARY_LBA_MID)
hi := inb(ATA_PRIMARY_LBA_HI)
if (mid | hi) != 0 {
log.error("the drive is not ata...?")
return 0
}
loop if (status & (STAT_ERR | STAT_DRQ)) != 0 break else {
if DEBUG_PRINT log.printf("(ata: waiting for ERR or DRQ) status={}", .(status), .{radix: 16, log: .Warn})
status = inb(ATA_PRIMARY_COMM_REGSTAT)
}
if (status & STAT_ERR) != 0 {
if DEBUG_PRINT log.printf("(ata: drive error) status={}", .(status), .{radix: 16, log: .Error})
return 0
}
if DEBUG_PRINT log.printf("status={}", .(status), .{radix: 16})
buffer := alloc(u16, 255)[0..255]
read(buffer)
if DEBUG_PRINT {
if (buffer[83] & 1 << 10) != 0 {
log.info("LBA48 mode supported")
log.printf("{} 48 bit addressable sectors", *@as(^uint, @bitcast(buffer[100..].ptr)), .{})
}
log.print(buffer, .{})
}
c := buffer.search("XNumber\0")
return 0
}
read := fn(buffer: []u16): void {
i := 0
loop if i == buffer.len break else {
buffer[i] = ins(ATA_PRIMARY_DATA)
i += 1
}
}
// inflates asm a lot
$DEBUG_PRINT := true
main := fn(): void {
identify(.Master)
}

View file

@ -1,35 +0,0 @@
// $ATA_PRIMARY_DATA := @intcast(0x1F0)
// $ATA_PRIMARY_ERR := @intcast(0x1F1)
// $ATA_PRIMARY_SECCOUNT := @intcast(0x1F2)
// $ATA_PRIMARY_LBA_LO := @intcast(0x1F3)
// $ATA_PRIMARY_LBA_MID := @intcast(0x1F4)
// $ATA_PRIMARY_LBA_HI := @intcast(0x1F5)
// $ATA_PRIMARY_DRIVE_HEAD := @intcast(0x1F6)
// $ATA_PRIMARY_COMM_REGSTAT := @intcast(0x1F7)
// $ATA_PRIMARY_ALTSTAT_DCR := @intcast(0x3F6)
$ATA_PRIMARY_IO := @intcast(0x1F0)
$ATA_PRIMARY_DEVCTL := @intcast(0x3F6)
$ATA_SECONDARY_DEVCTL := @intcast(0x3F6)
$ATA_REG_STAT := @intcast(0x7)
// // Indicates an error occurred. Send a new command to clear it
// STAT_ERR := 1 << 0
// // Set when the drive has PIO data to transfer, or is ready to accept PIO data.
// STAT_DRQ := 1 << 3
// // Overlapped Mode Service Request.
// STAT_SRV := 1 << 4
// // Drive Fault Error (does not set ERR).
// STAT_DF := 1 << 5
// // Bit is clear when drive is spun down, or after an error. Set otherwise.
// STAT_RDY := 1 << 6
// // Indicates the drive is preparing to send/receive data (wait for it to clear).
// // In case of 'hang' (it never clears), do a software reset.
// STAT_BSY := 1 << 7
$ATA_SR_BSY := 0x80
$ATA_SR_DF := 0x20
$ATA_SR_DRQ := 0x8
$ATA_SR_ERR := 0x1

View file

@ -0,0 +1 @@
# dt_buffer_test

View file

@ -1,5 +1,5 @@
[package]
name = "angels_halo"
name = "dt_buffer_test"
authors = ["able"]
[dependants.libraries]

View file

@ -0,0 +1,13 @@
.{dt} := @use("../../../libraries/stn/src/lib.hb")
main := fn(): void {
dt.get(void, "framebuffer/fb0/width\0")
dt.get(void, "cpu/cpu0/architecture\0")
// Checking if the first detected serial port is memory mapped or port mapped
// 0 -> memory mapped
// 1 -> port mapped
dt.get(void, "serial_ports/sp0/mapping\0")
return
}

View file

@ -1,7 +1,7 @@
$READ_ONLY := 0x1
$HIDDEN := 0x2
$SYSTEM := 0x4
$VOLUME_ID := 0x8
$DIRECTORY: 0x10
$ARCHIVE := 0x20
READ_ONLY := @as(u32, 0x1)
HIDDEN := @as(u32, 0x2)
SYSTEM := @as(u32, 0x4)
VOLUME_ID := @as(u32, 0x8)
DIRECTORY := @as(u32, 0x10)
ARCHIVE := @as(u32, 0x20)
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID

View file

@ -1,19 +1,19 @@
stn := @use("stn");
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, log} := stn
VALID_JUMP_BYTES := u8.[0xEB, 0x3C, 0x90]
VALID_JUMP_BYTES := [u8].(0xEB, 0x3C, 0x90)
OemIdent := struct {
dos_version: [8]u8,
dos_version_name: [8]u8,
dos_version: [u8; 8],
dos_version_name: [u8; 8],
}
new := fn(major: int, minor: int): OemIdent {
return .(.[0, 0, 0, 0, 0, 0, 0, 0], .[0, 0, 0, 0, 0, 0, 0, 0])
}
new_oem_ident := fn(major: int, minor: int): OemIdent {
return .(.(0, 0, 0, 0, 0, 0, 0, 0), .(0, 0, 0, 0, 0, 0, 0, 0))
}
BiosParameterBlock := struct {
jump_bytes: [3]u8,
jump_bytes: [u8; 3],
oem_ident: OemIdent,
bytes_per_sector: u16,
sectors_per_cluster: u8,
@ -30,21 +30,21 @@ BiosParameterBlock := struct {
head_count: u16,
hidden_sectors: u32,
large_sector_count: u32,
}
sanity_check := fn(bpb: BiosParameterBlock): int {
return 0
}
bpb_sanity_check := fn(bpb: BiosParameterBlock): int {
return 0
}
new := fn(): BiosParameterBlock {
return .(VALID_JUMP_BYTES, OemIdent.new(0, 0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
new_bpb := fn(): BiosParameterBlock {
return .(VALID_JUMP_BYTES, new_oem_ident(0, 0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
}
sector_count := fn(bpb: BiosParameterBlock): u32 {
if bpb.total_sectors == 0 {
return bpb.large_sector_count
} else {
return bpb.total_sectors
}
sector_count := fn(bpb: BiosParameterBlock): u32 {
if bpb.total_sectors == 0 {
return bpb.large_sector_count
} else {
return bpb.total_sectors
}
}
@ -53,16 +53,16 @@ FatVersionNumber := struct {
minor_version: u8,
}
FormatReservation := [12]u8
FormatReservation := [u8; 12]
// Padded with spaces.
VolumeName := [11]u8
VolumeName := [u8; 11]
SystemIdentifierString := [8]u8
VALID_SYSTEM_IDENTIFIER_STRING := u8.[46, 41, 54, 33, 32, 20, 20, 20]
SystemIdentifierString := [u8; 8]
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
BOOTABLE_PARTITION_SIGNATURE := @as(u32, 0xAA55)
BootCode := [420]u8
BootCode := [u8; 420]
ExtendedBootRecord := struct {
sectors_per_fat: u32,
@ -85,48 +85,48 @@ ExtendedBootRecord := struct {
system_identifier_string: SystemIdentifierString,
boot_code: BootCode,
partition_signature: u16,
}
sanity_check := fn(ebr: ExtendedBootRecord): int {
ret := 0
if ebr.drive_number != 0x0 | ebr.drive_number != 0x80 {
log.warn("EBR-Drive-Number sanity check failed")
}
if ebr.signature != 0x28 | ebr.signature != 0x29 {
log.warn("EBR-Signature sanity check failed")
}
// ! comparison between [u8] is not supported in hblang
// if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
// log.warn("EBR-Signature-Identifier-String sanity check failed")
// }
return 0
ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
ret := 0
if ebr.drive_number != 0x0 | ebr.drive_number != 0x80 {
log.warn("EBR-Drive-Number sanity check failed\0")
}
new := fn(): ExtendedBootRecord {
version := FatVersionNumber.(0, 0)
fmt_res := u8.[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
vol_name := @as([11]u8, idk)
boot_code := @as([420]u8, idk)
return ExtendedBootRecord.(
0,
0,
version,
0,
0,
0,
fmt_res,
0,
0,
0,
0,
vol_name,
VALID_SYSTEM_IDENTIFIER_STRING,
boot_code,
0,
)
if ebr.signature != 0x28 | ebr.signature != 0x29 {
log.warn("EBR-Signature sanity check failed\0")
}
// ! comparison between [u8] is not supported in hblang
// if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
// log.warn("EBR-Signature-Identifier-String sanity check failed\0")
// }
return 0
}
new_ebr := fn(): ExtendedBootRecord {
version := FatVersionNumber.(0, 0)
fmt_res := FormatReservation.(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
vol_name := @as([u8; 11], idk)
boot_code := @as([u8; 420], idk)
return ExtendedBootRecord.(
0,
0,
version,
0,
0,
0,
fmt_res,
0,
0,
0,
0,
vol_name,
VALID_SYSTEM_IDENTIFIER_STRING,
boot_code,
0,
)
}
VALID_LEAD_FS_INFO := @as(u32, 0x41615252)
@ -135,45 +135,45 @@ VALID_TRAIL_FS_INFO := @as(u32, 0xAA550000)
FSInfo := struct {
// Must be 0x41615252 to indicate a valid FSInfo structure
lead_signature: u32,
lead_reserved: [480]u8,
lead_reserved: [u8; 480],
// If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. However, this value might be incorrect and should at least be range checked (<= volume cluster count)
last_known_free_cluster_count: u32,
last_known_avalible_cluster: u32,
trail_reserved: [12]u8,
trail_reserved: [u8; 12],
trail_signature: u32,
}
sanity_check := fn(fs_info: FSInfo): uint {
ret := 0
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
ret &= 1
log.warn("Invalid leading signature in FSInfo.")
}
if fs_info.last_known_free_cluster_count == 0xFFFFFFFF {
ret &= 2
log.warn("Last known free cluster count unknown.")
}
if fs_info.last_known_avalible_cluster == 0xFFFFFFFF {
ret &= 4
log.warn("Last known avalible cluster count unknown.")
}
if fs_info.trail_signature != VALID_TRAIL_FS_INFO {
ret &= 8
log.warn("Invalid trailing signature in FSInfo.")
}
return ret
fs_info_sanity_check := fn(fs_info: FSInfo): uint {
ret := 0
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
ret &= 1
log.warn("Invalid leading signature in FSInfo.\0")
}
if fs_info.last_known_free_cluster_count == 0xFFFFFFFF {
ret &= 2
log.warn("Last known free cluster count unknown.\0")
}
if fs_info.last_known_avalible_cluster == 0xFFFFFFFF {
ret &= 4
log.warn("Last known avalible cluster count unknown.\0")
}
if fs_info.trail_signature != VALID_TRAIL_FS_INFO {
ret &= 8
log.warn("Invalid trailing signature in FSInfo.\0")
}
new := fn(): FSInfo {
lead_reserved := @as([480]u8, idk)
trail_reserved := @as([12]u8, idk)
return FSInfo.(
VALID_LEAD_FS_INFO,
lead_reserved,
0,
0,
trail_reserved,
VALID_TRAIL_FS_INFO,
)
}
return ret
}
new_fs_info := fn(): FSInfo {
lead_reserved := @as([u8; 480], idk)
trail_reserved := @as([u8; 12], idk)
return FSInfo.(
VALID_LEAD_FS_INFO,
lead_reserved,
0,
0,
trail_reserved,
VALID_TRAIL_FS_INFO,
)
}

View file

@ -2,25 +2,24 @@ Date := struct {
year: u16,
month: u16,
day: u16,
compress_date := fn(year: u16, month: u16, day: u16): u16 {
return 0
}
decompress_date := fn(date: u16): Date {
return Date.(0, 0, 0)
}
}
Time := struct {
hour: u16,
minutes: u16,
seconds: u16,
}
compress_time := fn(hour: u16, minutes: u16, seconds: u16): u16 {
return 0
}
compress_date := fn(year: u16, month: u16, day: u16): u16 {
return 0
}
decompress_date := fn(date: u16): Date {
return Date.(0, 0, 0)
}
decompress_time := fn(time: u16): Time {
return Time.(0, 0, 0)
}
compress_time := fn(hour: u16, minutes: u16, seconds: u16): u16 {
return 0
}
decompress_time := fn(time: u16): Time {
return Time.(0, 0, 0)
}

View file

@ -1,7 +1,7 @@
attributes := @use("attributes.hb")
datetime := @use("datetime.hb")
FileName := [11]u8
FileName := [u8; 11]
// This is the File Allocation Table entry that tells us where on disk the File is.
FileEntry := struct {
@ -18,4 +18,4 @@ FileEntry := struct {
last_modification_date: datetime.date,
low_cluster_number: u16,
file_size: u32,
}
}

View file

@ -1,4 +1,4 @@
stn := @use("stn");
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, log} := stn
attributes := @use("attributes.hb")
@ -6,19 +6,19 @@ datetime := @use("datetime.hb")
directory := @use("file.hb")
bios_parameter_block := @use("bios_parameter_block.hb");
.{bpb_sanity_check, ebr_sanity_check, fs_info_sanity_check} := bios_parameter_block;
.{BiosParameterBlock, ExtendedBootRecord, FSInfo} := bios_parameter_block
.{new_bpb, new_ebr, new_fs_info} := bios_parameter_block
$FAT12_THRESHOLD := 4085
$FAT16_THRESHOLD := 65525
FAT12_THRESHOLD := 4085
FAT16_THRESHOLD := 65525
$EXFAT := 0
$FAT12 := 1
$FAT16 := 2
$FAT32 := 3
ExFAT := 0
FAT12 := 1
FAT16 := 2
FAT32 := 3
calculate_fat_type := fn(sector_size: uint, total_clusters: uint): uint {
if sector_size == 0 {
return EXFAT
return ExFAT
} else if total_clusters < 4085 {
return FAT12
} else if total_clusters < 65525 {
@ -29,19 +29,19 @@ calculate_fat_type := fn(sector_size: uint, total_clusters: uint): uint {
}
main := fn(): int {
bpb := BiosParameterBlock.new()
ebr := ExtendedBootRecord.new()
fsi := FSInfo.new()
bpb := new_bpb()
ebr := new_ebr()
fsi := new_fs_info()
fat_type := calculate_fat_type(1, 100)
if fat_type != FAT32 {
log.warn("filesystem_fat32 driver only supports Fat32.")
log.warn("filesystem_fat32 driver only supports Fat32.\0")
}
bsc := bpb.sanity_check()
esc := ebr.sanity_check()
fssc := fsi.sanity_check()
bsc := bpb_sanity_check(bpb)
esc := ebr_sanity_check(ebr)
fssc := fs_info_sanity_check(fsi)
msg_type := 0
@ -49,7 +49,7 @@ main := fn(): int {
// Open file
if msg_type == 0 {
// Paths without a node-disk component are to be treated as local files.
file_path := "node-disk:/test"
file_path := "node-disk:/test\0"
} else {
// error
}

View file

@ -1,5 +0,0 @@
# hblang²
The hblang² or hblang2 compiler is intended to compile hblang to hbvm bytecode while also being written in hblang.
This is the first step in bootstrapping ableOS.

View file

@ -1,5 +0,0 @@
stn := @use("stn")
main := fn(): int {
return 0
}

View file

@ -1,16 +1,16 @@
stn := @use("stn");
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, random, log} := stn;
.{Vec2} := stn.math
horizon_api := @use("lib:horizon_api");
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{new_label, render_label_to_surface, set_label_text} := horizon_api.widgets.label;
.{sexpr_parser, render_ui} := horizon_api.ui
render := @use("lib:render");
render := @use("../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
intouch := @use("lib:intouch")
intouch := @use("../../../libraries/intouch/src/lib.hb")
Window := struct {
// TODO: Replace this with widgets
@ -21,23 +21,23 @@ Window := struct {
y: int,
}
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
img := @embed("sysdata:assets/wallpaper.qoi")
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
img := @embed("../../../assets/wallpaper.qoi")
main := fn(): int {
win_buff := buffer.create("XHorizon")
win_buff := buffer.create("XHorizon\0")
screen := render.init(true)
// Clear the screen to black.
screen.clear(render.BLACK)
render.clear(screen, render.black)
wallpaper := render.image.from(@bitcast(&img))
if wallpaper == null {
return 1
}
window := render.Surface.new(screen.width / 3, screen.height / 3)
window := render.new_surface(screen.width / 3, screen.height / 3)
mem_buf := memory.request_page(1)
color := random.any(render.Color)
@ -48,16 +48,16 @@ main := fn(): int {
mouse_x := @as(i16, 0)
mouse_y := @as(i16, 0)
text_label := new_label("Hi")
text_label := new_label("Hi\0")
// widgets := "()"
// widgets := "()\0"
// ui := sexpr_parser(widgets)
loop {
// Clear the screen
screen.clear(render.BLACK)
render.clear(screen, render.black)
screen.put_surface(wallpaper, .(0, 0), false)
render.put_surface(screen, wallpaper, .(0, 0), false)
// TODO: Read the window buffer here
{
@ -65,33 +65,33 @@ main := fn(): int {
if false {
// Scroll bar :ThumbsUp:
screen.put_rect(.(100, 100), .(100, 10), render.WHITE)
screen.put_filled_rect(.(110, 100), .(20, 10), render.WHITE)
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
render.put_filled_rect(screen, .(110, 100), .(20, 10), render.white)
screen.put_rect(.(90, 110), .(10, 100), render.WHITE)
screen.put_filled_rect(.(90, 120), .(10, 20), render.WHITE)
render.put_rect(screen, .(90, 110), .(10, 100), render.white)
render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
}
{
// osu dots
screen.put_rect(.(400, 100), .(100, 100), render.RED)
screen.put_rect(.(100, 100 + 300), .(100, 100), render.RED)
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)
screen.put_rect(.(0, screen.height - 21), .(screen.width - 1, 20), render.WHITE)
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), render.white)
}
// Screen border
screen.put_rect(.(0, 0), .(screen.width - 1, screen.height - 1), render.WHITE)
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 ")
log.info("Key event \0")
}
}
@ -100,7 +100,7 @@ main := fn(): int {
//
if mouse_event != null {
// log.warn("Mouse event received")
// log.warn("Mouse event received\0")
change_x := @as(i16, mouse_event.x_change)
change_x = change_x << 8
@ -127,18 +127,18 @@ main := fn(): int {
mouse_y -= change_y
if mouse_event.left {
set_label_text(text_label, "LEFT CLICK")
set_label_text(text_label, "LEFT CLICK\0")
}
if mouse_event.middle {
set_label_text(text_label, "MIDDLE CLICK")
set_label_text(text_label, "MIDDLE CLICK\0")
}
if mouse_event.right {
set_label_text(text_label, "RIGHT CLICK")
set_label_text(text_label, "RIGHT CLICK\0")
}
}
screen.put_filled_rect(.(mouse_x, mouse_y), .(20, 20), render.BLACK)
screen.put_rect(.(mouse_x, mouse_y), .(20, 20), render.WHITE)
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)
// Send events to focused window
}
@ -146,7 +146,7 @@ main := fn(): int {
// TODO: Get windows out of a collection and iter through
// Sync the screen
screen.sync()
render.sync(screen)
}
return 0

View file

@ -1,25 +1,25 @@
stn := @use("stn");
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, log} := stn
horizon_api := @use("lib:horizon_api");
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{create_window} := horizon_api
ignim := @use("lib:ignim");
ignim := @use("../../../libraries/ignim/src/lib.hb");
.{errors} := ignim
psf := @embed("sysdata:assets/consolefonts/tamsyn/10x20r.psf")
psf := @embed("../../../consolefonts/tamsyn/10x20r.psf")
main := fn(): int {
x := 0
// loop if x > 10000 break else x += 1
windowing_system_buffer := buffer.search("XHorizon")
windowing_system_buffer := buffer.search("XHorizon\0")
// TODO: get WindowID
wid := create_window(windowing_system_buffer)
if false {
program_name := "Horizon Testing Program"
program_name := "Horizon Testing Program\0"
program_version := ignim.version.make_version(0, 1, 0)
engine_name := "None"
engine_name := "None\0"
engine_version := ignim.version.make_version(0, 0, 0)
api_version := ignim.version.make_api_version(0, 1, 0, 0)
@ -32,7 +32,7 @@ main := fn(): int {
// // TODO: recursively follow this https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
ret := ignim.instance.create_instance(&create_info, 0, &instance)
if ret == errors.IncompatibleDriver {
log.error("Driver Incompatible with Vulkan")
log.error("Driver Incompatible with Vulkan\0")
}
}

View file

@ -1 +0,0 @@
# pcspkr

View file

@ -1,45 +0,0 @@
stn := @use("stn");
.{memory, buffer, log, string, math} := stn;
.{inb, outb} := memory
$PIT_CLOCK := 1193180
play_sound := fn(frequency: u32): void {
div := 0
div = PIT_CLOCK / frequency
memory.outb(0x43, 0xB6)
memory.outb(0x42, @intcast(div))
memory.outb(0x42, @intcast(div >> 8))
tmp := inb(0x61)
if tmp != (tmp | 3) {
outb(0x61, tmp | 3)
}
}
no_sound := fn(): void {
tmp := memory.inb(0x61) & 0xFC
memory.outb(0x61, tmp)
}
beep := fn(): void {
play_sound(1000)
idx := 0
loop {
if idx >= 1000000 {
idx += 1
} else {
break
}
}
no_sound()
}
main := fn(): int {
no_sound()
beep()
return 0
}

View file

@ -1,6 +1,6 @@
[package]
name = "ablefetch"
authors = [""]
name = "processes"
authors = ["koniifer"]
[dependants.libraries]

View file

@ -0,0 +1,7 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
main := fn(): void {
log.info("Hello, World!\0")
loop {
}
}

View 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
}
}

View file

@ -1,23 +0,0 @@
# 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.

View file

@ -1,11 +0,0 @@
[package]
name = "ps2_driver"
authors = ["Peony"]
[dependants.libraries]
[dependants.binaries]
hblang.version = "1.0.0"
[build]
command = "hblang src/main.hb"

View file

@ -1,26 +0,0 @@
//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
}

View file

@ -1,101 +0,0 @@
.{memory, log} := @use("stn");
.{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)
//wiki.osdev.org/"8042"_PS/2_Controller#PS/2_Controller_IO_Ports
$CONTROLLER_PORT := 0x64
$DATA_PORT := 0x60
$disable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAD)
$enable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAE)
$disable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA7)
$enable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA8)
test_port1 := fn(): bool {
memory.outb(CONTROLLER_PORT, 0xAB)
loop if has_input(get_info()) break
input := get_input()
return input == 0x0
}
test_port2 := fn(): bool {
memory.outb(CONTROLLER_PORT, 0xA9)
loop if has_input(get_info()) break
input := get_input()
return input == 0x0
}
get_config_byte := fn(): u8 {
memory.outb(CONTROLLER_PORT, 0x20)
loop if has_input(get_info()) break
return get_input()
}
Info := struct {d: u8}
$get_info := fn(): Info return .(memory.inb(CONTROLLER_PORT))
//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
}
}
//T
port2_ptr := &port2
send_byte := fn(port: ^Port, byte: u8): void {
if port == port2_ptr {
memory.outb(CONTROLLER_PORT, 0xD4)
}
loop if can_send(get_info()) break
memory.outb(DATA_PORT, byte)
}
$get_input := fn(): u8 return memory.inb(DATA_PORT)
$write_out := fn(data: u8): void memory.outb(DATA_PORT, 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!")
}
if port1.exists {
log.info("Port 1 exists.")
enable_port1()
}
if port2.exists {
log.info("Port 2 exists.")
enable_port2()
}
}

View file

@ -1,15 +0,0 @@
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)

View file

@ -1,150 +0,0 @@
.{memory, log, buffer, string} := @use("stn");
.{MouseEvent} := @use("lib:intouch").events;
.{bit0, bit1, bit2, bit3, bit4} := @use("bits.hb")
devices := @use("devices.hb")
controller := @use("controller.hb");
.{Info, Port} := controller
mouse := @use("mouse.hb")
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!")
log.print(port.device.value, .{radix: 16})
} else {
log.info("KEY PRESSED")
}
}
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")
controller.init()
if controller.port1.exists {
//log.info("Port 1 exists.")
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!")
}
if controller.check_parity(info) {
log.error("Parity error! Cannot handle these!")
}
/*
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
}
}*/
}
}

View file

@ -1,21 +0,0 @@
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)

View file

@ -1,21 +0,0 @@
.{DeviceID, NO_DEVICE} := @use("devices.hb")
State := struct {s: u8}
$Recive := State.(0)
$Reboot := State.(1)
Port := packed struct {
exists: bool,
device: DeviceID,
packet: [8]u8,
packet_length: u8,
can_hot_plug: bool,
}
$PORT_AT_STARTUP := Port.(
true,
NO_DEVICE,
.[0, 0, 0, 0, 0, 0, 0, 0],
0,
true,
)

View file

@ -0,0 +1,3 @@
# PS/2 Driver
This program is a simple driver to read keypresses from a PS/2 Keyboard Also will contain an abstraction for the PS/2 controller in general so the Mouse code will probably also live here...maybe

View file

@ -0,0 +1,11 @@
[package]
name = "ps2_keyboard_driver"
authors = ["Talha Qamar"]
[dependants.libraries]
[dependants.binaries]
hblang.version = "1.0.0"
[build]
command = "hblang src/main.hb"

View file

@ -0,0 +1,40 @@
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)
return memory.inb(96)
}
main := fn(): int {
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
kevent := KeyEvent.(false, true, input)
buffer.write(KeyEvent, buf, &kevent)
}
return 0
}

View file

@ -1,7 +1,7 @@
.{memory, buffer, log, string, math} := @use("stn")
.{memory, buffer, log, string, math} := @use("../../../libraries/stn/src/lib.hb")
Vec2 := math.Vec2
intouch := @use("lib:intouch");
intouch := @use("../../../libraries/intouch/src/lib.hb");
.{MouseEvent} := intouch.events
i9 := packed struct {sign: bool, value: u8}
@ -21,7 +21,7 @@ reset_mouse := fn(): void {
@inline(send_byte, 0x64, 0xD4)
@inline(send_byte, 0x60, 0xFF)
loop if memory.inb(0x60) == 0xAA {
log.info("Self check passed.")
log.info("Self check passed.\0")
return
}
}
@ -82,11 +82,11 @@ set_up_mouse := fn(): void {
button_states := @as(u8, 0)
main := fn(): int {
mouse_buffer := buffer.create("PS/2 Mouse")
mouse_buffer := buffer.create("PS/2 Mouse\0")
format_page := memory.alloc(u8, 1024)
send_byte(0x64, 0xA8)
log.info("Aux mouse device enabled.")
log.info("Aux mouse device enabled.\0")
set_up_mouse()
@ -102,7 +102,7 @@ main := fn(): int {
if status == 0xAA {
loop if memory.inb(0x60) == 0 break
log.info("Mouse plugged in!")
log.info("Mouse plugged in!\0")
set_up_mouse()
continue
}

View file

@ -1,4 +1,4 @@
stn := @use("stn")
stn := @use("../../../libraries/stn/src/lib.hb")
main := fn(): int {
stn.log.info("\r
@ -9,7 +9,7 @@ main := fn(): int {
| : '=.:.=' : |\r
| : :'.___.': : |\r
'-:__:__:__:__:-'\r
")
\0")
return 0
}

View file

@ -1,4 +1,4 @@
render := @use("lib:render")
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
the impostor travels left and loops around the screen */
@ -7,13 +7,13 @@ example := fn(): void {
screen := render.init(true)
x := 0
loop {
screen.clear(render.BLACK)
screen.put_rect(.(200 - x, 80), .(430, 380), render.RED)
screen.put_rect(.(630 - x, 120), .(120, 300), render.RED)
screen.put_rect(.(200 - x, 460), .(160, 270), render.RED)
screen.put_rect(.(470 - x, 460), .(160, 270), render.RED)
screen.put_rect(.(140 - x, 140), .(340, 250), render.CYAN)
screen.sync()
render.put_rect(screen, .(200 - x, 80), .(430, 380), render.red)
render.put_rect(screen, .(630 - x, 120), .(120, 300), render.red)
render.put_rect(screen, .(200 - x, 460), .(160, 270), render.red)
render.put_rect(screen, .(470 - x, 460), .(160, 270), render.red)
render.put_rect(screen, .(140 - x, 140), .(340, 250), render.cyan)
render.sync(screen)
render.clear(screen, render.black)
x += 1
}
return

View file

@ -1,4 +1,4 @@
render := @use("lib:render")
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
the screen fades from cyan to green
@ -7,11 +7,12 @@ render := @use("lib:render")
example := fn(): void {
screen := render.init(true)
color := render.LIGHT_CYAN
color := render.light_cyan
n := @as(u8, 1)
loop {
screen.clear(color)
screen.sync()
// ! dead code elimination bug
render.clear(screen, color)
render.sync(screen)
if color.b == 255 | color.b == 0 {
n = -n
}

View file

@ -1,25 +1,25 @@
.{log, math, string} := @use("stn")
render := @use("lib:render")
.{log, math, string} := @use("../../../../libraries/stn/src/lib.hb")
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
a cute qoi image and a cute bmp image */
example := fn(): void {
screen := render.init(true)
image_qoi := render.image.from(@bitcast(&@embed("sysdata:assets/mini.qoi")))
image_bmp := render.image.from(@bitcast(&@embed("sysdata:assets/mini.bmp")))
image_qoi := render.image.from(@bitcast(&@embed("../../../../assets/mini.qoi")))
image_bmp := render.image.from(@bitcast(&@embed("../../../../assets/mini.bmp")))
if image_qoi == null | image_bmp == null {
log.error("failed to load images for whatever reason")
log.error("failed to load images for whatever reason\0")
return
}
t := 0.0
loop {
screen.clear(render.BLACK)
screen.put_surface(image_bmp, .(@bitcast(@fti(math.cos(t) * 100.0)) + (screen.width - image_bmp.width * 3) / 2, (screen.height - image_bmp.height) / 2), false)
screen.put_surface(image_qoi, .((screen.width + image_qoi.width) / 2, @bitcast(@fti(math.sin(t) * 100.0)) + (screen.height - image_qoi.height) / 2), false)
screen.sync()
render.clear(screen, render.black)
render.put_surface(screen, image_bmp, .(@bitcast(@fti(math.cos(t) * 100.0)) + (screen.width - image_bmp.width * 3) / 2, (screen.height - image_bmp.height) / 2), false)
render.put_surface(screen, image_qoi, .((screen.width + image_qoi.width) / 2, @bitcast(@fti(math.sin(t) * 100.0)) + (screen.height - image_qoi.height) / 2), false)
render.sync(screen)
t += 0.02
}
return

View file

@ -1,5 +1,5 @@
.{Vec2} := @use("stn:math")
render := @use("lib:render")
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
a 3d-looking set of blue lines
@ -7,15 +7,15 @@ render := @use("lib:render")
example := fn(): void {
screen := render.init(true)
screen.clear(.(100, 50, 0, 255))
render.clear(screen, .(100, 50, 0, 255))
p0 := Vec2(uint).(0, 0)
p1 := Vec2(uint).(0, screen.height)
loop if p0.y >= screen.height break else {
screen.put_line(p0, p1, .(255, 180, 100, 255))
screen.put_line(.(screen.width, screen.height) - p0, .(screen.width, screen.height) - p1, .(255, 180, 100, 255))
render.put_line(screen, p0, p1, .(255, 180, 100, 255))
render.put_line(screen, .(screen.width, screen.height) - p0, .(screen.width, screen.height) - p1, .(255, 180, 100, 255))
p0.y += screen.height >> 6
p1.x += screen.width >> 6
}
screen.sync()
render.sync(screen)
return
}

View file

@ -1,98 +0,0 @@
render := @use("lib:render")
sunset := @use("lib:sunset_proto");
.{math, log} := @use("stn")
// full mandelbrot
$X_MIN := -2.0
$X_MAX := 0.47
$Y_MIN := -1.12
$Y_MAX := 1.12
// a minibrot
// $X_MIN := -0.94
// $X_MAX := -0.93
// $Y_MIN := 0.31
// $Y_MAX := 0.306
// zoom into that weird curve part of the main cardioid
// $X_MIN := 0.25
// $X_MAX := 0.34
// $Y_MIN := -0.075
// $Y_MAX := 0.075
$MAX_ITERATION := 300
$USE_SUNSET := true
palette := render.Color.[.(50, 0, 60, 0), .(93, 0, 157, 0), .(140, 98, 229, 0), .(191, 190, 255, 0), .(226, 234, 255, 0), .(242, 250, 255, 0), .(226, 234, 255, 0), .(191, 190, 255, 0), .(140, 98, 229, 0), .(93, 0, 157, 0), .(50, 0, 60, 0)]
$LEN_PALETTE := @sizeof(@TypeOf(palette)) / @sizeof(render.Color)
example := fn(): void {
screen := @as(render.Surface, idk)
window := @as(?sunset.Window, null)
if USE_SUNSET {
sunset.client.find_server()
window = sunset.client.new(.(.(450, 140), .(400, 400), "Mandelbrot Set"))
if window == null {
log.error("got no window")
return
}
screen = window.surface
} else {
screen = render.init(false)
}
x_scale := @as(f64, X_MAX - X_MIN) / @itf(@bitcast(screen.width))
y_scale := @as(f64, Y_MAX - Y_MIN) / @itf(@bitcast(screen.height))
py := 0
loop if py == screen.height break else {
px := 0
loop if px >= screen.width break else {
x0 := @as(f64, X_MIN) + @itf(@bitcast(px)) * x_scale
y0 := @as(f64, Y_MIN) + @itf(@bitcast(py)) * y_scale
q := (x0 - 0.25) * (x0 - 0.25) + y0 * y0
if q * (q + x0 - 0.25) <= 0.25 * y0 * y0 | (x0 + 1.0) * (x0 + 1.0) + y0 * y0 <= 0.0625 {
px += 1
continue
}
x := @as(f64, 0.0)
y := @as(f64, 0.0)
iteration := 0
// arbitrary, i cant tell the difference between 32 and 1 << 16
loop if x * x + y * y > 32.0 | iteration == MAX_ITERATION break else {
x_temp := x * x - y * y + x0
y = 2 * x * y + y0
x = x_temp
iteration += 1
}
if iteration < MAX_ITERATION {
log_zn := math.ln(f64, x * x + y * y) / 2
nu := math.ln(f64, log_zn / math.LN_2) / math.LN_2
smoothed := @as(f64, @itf(@bitcast(iteration + 1))) - nu
smoothed_int := @fti(smoothed)
normalised := smoothed - @itf(smoothed_int)
colour0 := palette[@bitcast(smoothed_int) % LEN_PALETTE]
colour1 := palette[@bitcast(smoothed_int + 1) % LEN_PALETTE]
colour := render.Color.{
r: @intcast(@fti(math.lerp(f64, @itf(colour0.r), @itf(colour1.r), normalised))),
g: @intcast(@fti(math.lerp(f64, @itf(colour0.g), @itf(colour1.g), normalised))),
b: @intcast(@fti(math.lerp(f64, @itf(colour0.b), @itf(colour1.b), normalised))),
a: 0,
}
screen.put_pixel(.(px, py), colour)
}
px += 1
}
py += 1
if USE_SUNSET {
_ = sunset.client.send_frame(window)
}
}
if USE_SUNSET loop {
_ = sunset.client.send_frame(window)
}
}

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