forked from AbleOS/ableos
Compare commits
2 commits
master
...
devcontain
Author | SHA1 | Date | |
---|---|---|---|
d979150be3 | |||
6efff7a274 |
|
@ -1,3 +1,3 @@
|
||||||
[alias]
|
[alias]
|
||||||
repbuild = "run --manifest-path ./repbuild/Cargo.toml -- "
|
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
|
||||||
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
||||||
|
|
31
.devcontainer/devcontainer.json
Normal file
31
.devcontainer/devcontainer.json
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/rust
|
||||||
|
{
|
||||||
|
"name": "Rust",
|
||||||
|
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||||
|
"image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye"
|
||||||
|
|
||||||
|
// Use 'mounts' to make the cargo cache persistent in a Docker Volume.
|
||||||
|
// "mounts": [
|
||||||
|
// {
|
||||||
|
// "source": "devcontainer-cargo-cache-${devcontainerId}",
|
||||||
|
// "target": "/usr/local/cargo",
|
||||||
|
// "type": "volume"
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
|
||||||
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
|
// "features": {},
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
// "forwardPorts": [],
|
||||||
|
|
||||||
|
// Use 'postCreateCommand' to run commands after the container is created.
|
||||||
|
// "postCreateCommand": "rustc --version",
|
||||||
|
|
||||||
|
// Configure tool-specific properties.
|
||||||
|
// "customizations": {},
|
||||||
|
|
||||||
|
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
|
// "remoteUser": "root"
|
||||||
|
}
|
1204
Cargo.lock
generated
1204
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
69
HELP.md
69
HELP.md
|
@ -1,69 +0,0 @@
|
||||||
### What are the requirements?
|
|
||||||
- A machine with [Rustc Tier 1 platform support](https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-1-with-host-tools)
|
|
||||||
- Rustup
|
|
||||||
- QEMU (for executing)
|
|
||||||
- GIT CLI
|
|
||||||
|
|
||||||
### How do I run ableos?
|
|
||||||
- It is recommended to run ableos under QEMU. Here is how:
|
|
||||||
- Install QEMU
|
|
||||||
- Clone ableos
|
|
||||||
- Go to ableos directory
|
|
||||||
- Pull the limine submodule with `git submodule update --init`
|
|
||||||
- Run `cargo repbuild help`
|
|
||||||
|
|
||||||
### How can I contribute?
|
|
||||||
- [Contribute code](#how-do-i-contribute-code)
|
|
||||||
- [Run ableos on your machine](#how-do-i-run-ableos)
|
|
||||||
- Find bugs
|
|
||||||
- Create media showing ableos
|
|
||||||
|
|
||||||
### How do I contribute code?
|
|
||||||
- Start by forking ableos
|
|
||||||
- Write something that runs in the userspace, for example:
|
|
||||||
- System drivers
|
|
||||||
- Programs
|
|
||||||
- Libraries
|
|
||||||
- Patch bugs and improve code in the kernel
|
|
||||||
- Ensure that the code is OK to be maintained by asking in the [discord](https://discord.gg/t5Wt3K4YNA)
|
|
||||||
- When you have finished your changes, you can submit a pull request for review [here](https://git.ablecorp.us/ableos/ableos)
|
|
||||||
|
|
||||||
### repbuild and kernel compile, but QEMU isn't starting
|
|
||||||
- Ensure you have the `qemu-desktop-{arch}` for your OS and target architecture installed
|
|
||||||
- Try running again with `--noaccel` if you have QEMU already
|
|
||||||
|
|
||||||
### I have run using repbuild but it's slow
|
|
||||||
- Ensure release mode is enabled with the `-r` flag
|
|
||||||
- Remove the `--noaccel` flag if you can
|
|
||||||
- If both of these are already done, there may be a problem with thee VM, kernel, your program, or the hblang compiler
|
|
||||||
|
|
||||||
### Compiler is complaining about "reg id leaked"
|
|
||||||
- [Submit](#how-do-i-report-a-compiler-bug) an issue, reg id leaked is a bug
|
|
||||||
|
|
||||||
### My program isn't running
|
|
||||||
- Refer to [here](#i-have-run-using-repbuild-but-its-slow), it may be that your program is simply starting slowly
|
|
||||||
- Ensure that your program has a properly written meta.toml file
|
|
||||||
- Ensure that your program is enabled in [system_config.toml](sysdata/system_config.toml)
|
|
||||||
- Try running again with `--noaccel`, there is a known bug with some systems that prevents programs from starting.
|
|
||||||
|
|
||||||
### Kernel panic??? Huh???
|
|
||||||
- Kernel panics can be caused by improperly using memory (e.g, writing out of bounds)
|
|
||||||
- Kernel panics are most likely to be caused when accessing memory or using `@eca` for kernel ecalls
|
|
||||||
- [Report](#how-do-i-report-an-ableos-bug) a kernel panic
|
|
||||||
|
|
||||||
### I am running in release mode but I have no debug info
|
|
||||||
- Add the `-d` flag for debug info
|
|
||||||
|
|
||||||
### What is `@eca`? How do I use it?
|
|
||||||
- Eca is an ecall. They are similar to syscalls
|
|
||||||
- The `@eca` directive takes the following arguments:
|
|
||||||
- `@eca(ecall_number, reg_1, ..., reg_n)`
|
|
||||||
- The various ecalls have different arguments that are given by register values
|
|
||||||
- Most ecalls are wrapped by `stn`, for example, `random`, `buffer`, and `memory` all make use of ecalls
|
|
||||||
- All ecalls can be found [ecah.rs](kernel/src/holeybytes/ecah.rs)
|
|
||||||
|
|
||||||
### How do I report an ableos bug?
|
|
||||||
- Submit an issue [here](https://git.ablecorp.us/ableos/ableos/issues) or report it in the [discord](https://discord.gg/t5Wt3K4YNA)
|
|
||||||
|
|
||||||
### How do I report a compiler bug?
|
|
||||||
- Submit an issue [here](https://git.ablecorp.us/ableos/holey-bytes/issues) or report it in the [discord](https://discord.gg/t5Wt3K4YNA)
|
|
12
README.md
12
README.md
|
@ -10,7 +10,15 @@ Donations can be made [here on Liberapay](https://liberapay.com/AbleTheAbove) or
|
||||||
<img src="https://img.shields.io/liberapay/patrons/AbleTheAbove.svg?logo=liberapay">
|
<img src="https://img.shields.io/liberapay/patrons/AbleTheAbove.svg?logo=liberapay">
|
||||||
|
|
||||||
# Compiling
|
# Compiling
|
||||||
See [HELP.md](HELP.md)
|
AbleOS should be able to be built on any platform which is supported by
|
||||||
|
[Rustc Tier 1 platform support](https://doc.rust-lang.org/nightly/rustc/platform-support.html#tier-1-with-host-tools).
|
||||||
|
|
||||||
|
For running AbleOS, `repbuild` uses QEMU.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
1. Ensure you have qemu installed
|
||||||
|
2. `git submodule update --init`
|
||||||
|
3. `cargo repbuild run`
|
||||||
|
|
||||||
# Developing
|
# Developing
|
||||||
There is a new work in progress developer tool for hblang. (see: dev folder)
|
There is a new work in progress developer tool for hblang.
|
|
@ -138,8 +138,8 @@ fn build(name: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_program(_name: String) {}
|
pub fn build_program(name: String) {}
|
||||||
pub fn build_library(_name: String) {}
|
pub fn build_library(name: String) {}
|
||||||
|
|
||||||
fn help() {
|
fn help() {
|
||||||
println!(
|
println!(
|
||||||
|
|
1
installers-deb.sh
Normal file
1
installers-deb.sh
Normal file
|
@ -0,0 +1 @@
|
||||||
|
sudo apt-get update && sudo apt install -y qemu-utils qemu-system-x86 qemu-system-gui clang
|
|
@ -4,3 +4,6 @@ build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "./targets/x86_64-ableos.json"
|
target = "./targets/x86_64-ableos.json"
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "x86_64")']
|
||||||
|
rustflags = ["-C", "target-feature=+rdrand"]
|
||||||
|
|
|
@ -5,10 +5,8 @@ version = "0.2.0"
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# embedded-graphics = "0.8"
|
embedded-graphics = "0.8"
|
||||||
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
|
hbvm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
"nightly",
|
|
||||||
] }
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
spin = "0.9"
|
spin = "0.9"
|
||||||
slab = { version = "0.4", default-features = false }
|
slab = { version = "0.4", default-features = false }
|
||||||
|
@ -16,14 +14,21 @@ uart_16550 = { version = "0.3", features = ["nightly"] }
|
||||||
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
hashbrown = { version = "0.15", features = ["nightly"] }
|
hashbrown = { version = "0.14", features = ["nightly"] }
|
||||||
limine = "0.1"
|
|
||||||
|
[dependencies.limine]
|
||||||
|
version = "0.1"
|
||||||
|
#git = "https://github.com/limine-bootloader/limine-rs"
|
||||||
|
|
||||||
[dependencies.crossbeam-queue]
|
[dependencies.crossbeam-queue]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc", "nightly"]
|
features = ["alloc", "nightly"]
|
||||||
|
|
||||||
|
# [dependencies.clparse]
|
||||||
|
# git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
|
# default-features = false
|
||||||
|
|
||||||
[dependencies.derive_more]
|
[dependencies.derive_more]
|
||||||
version = "1"
|
version = "1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
@ -44,7 +49,7 @@ features = [
|
||||||
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
x86_64 = "0.15"
|
x86_64 = "0.15"
|
||||||
x2apic = "0.4"
|
x2apic = "0.4"
|
||||||
# virtio-drivers = "0.7"
|
virtio-drivers = "0.7"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
[target.'cfg(target_arch = "riscv64")'.dependencies]
|
||||||
sbi = "0.2.0"
|
sbi = "0.2.0"
|
||||||
|
|
|
@ -38,7 +38,6 @@ SECTIONS
|
||||||
|
|
||||||
.data : {
|
.data : {
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.got .got.*)
|
|
||||||
} :data
|
} :data
|
||||||
|
|
||||||
.bss : {
|
.bss : {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{device_tree::DeviceTree, kmain::DEVICE_TREE},
|
crate::{alloc::string::ToString, device_tree::DeviceTree, kmain::DEVICE_TREE},
|
||||||
|
alloc::string::String,
|
||||||
core::arch::asm,
|
core::arch::asm,
|
||||||
xml::XMLElement,
|
xml::XMLElement,
|
||||||
};
|
};
|
||||||
|
@ -27,7 +28,7 @@ fn collect_cpu_info(device_tree: &mut DeviceTree) {
|
||||||
cpus.push(cpu);
|
cpus.push(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cpu_id<'a>() -> (&'a str, u64) {
|
fn cpu_id() -> (String, u64) {
|
||||||
let mut cpu_id: u64;
|
let mut cpu_id: u64;
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mrs {cpu_id}, MIDR_EL1",
|
asm!("mrs {cpu_id}, MIDR_EL1",
|
||||||
|
@ -38,11 +39,11 @@ fn cpu_id<'a>() -> (&'a str, u64) {
|
||||||
let cpu_name = match cpu_id {
|
let cpu_name = match cpu_id {
|
||||||
// the source of these two was a stackoverflow question
|
// the source of these two was a stackoverflow question
|
||||||
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
|
||||||
0x410FD034 => "Cortex-A53",
|
0x410FD034 => "Cortex-A53".to_string(),
|
||||||
0x410FD083 => "Cortex-A72",
|
0x410FD083 => "Cortex-A72".to_string(),
|
||||||
// the source of this one was checking the cpu id :thinking:
|
// the source of this one was checking the cpu id :thinking:
|
||||||
0x410FD493 => "Neoverse N2",
|
0x410FD493 => "Neoverse N2".to_string(),
|
||||||
_ => "Unknown",
|
_ => "Unknown".to_string(),
|
||||||
};
|
};
|
||||||
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ pub static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
||||||
uart: 0x09000000 as *mut u8,
|
uart: 0x09000000 as *mut u8,
|
||||||
});
|
});
|
||||||
|
|
||||||
pub struct SerialConsole {
|
struct SerialConsole {
|
||||||
uart: *mut u8,
|
uart: *mut u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,29 +14,3 @@ arch_cond!(
|
||||||
riscv64: "riscv64",
|
riscv64: "riscv64",
|
||||||
x86_64: "x86_64",
|
x86_64: "x86_64",
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use {crate::arch::interrupts::Interrupt, alloc::string::String};
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pub struct InterruptList {
|
|
||||||
list: HashMap<Interrupt, String>,
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use hashbrown::HashMap;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
impl InterruptList {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
list: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use spin::{Lazy, Mutex};
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
pub static INTERRUPT_LIST: Lazy<Mutex<InterruptList>> = Lazy::new(|| {
|
|
||||||
let mut il = InterruptList::new();
|
|
||||||
use crate::alloc::string::ToString;
|
|
||||||
il.list.insert(Interrupt::Timer, "PS/2 Mouse".to_string());
|
|
||||||
Mutex::new(il)
|
|
||||||
});
|
|
||||||
|
|
|
@ -11,9 +11,7 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||||
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Eq, Hash, PartialEq)]
|
enum Interrupt {
|
||||||
|
|
||||||
pub enum Interrupt {
|
|
||||||
Timer = 32,
|
Timer = 32,
|
||||||
ApicErr = u8::MAX - 1,
|
ApicErr = u8::MAX - 1,
|
||||||
Spurious = u8::MAX,
|
Spurious = u8::MAX,
|
||||||
|
@ -62,49 +60,17 @@ extern "x86-interrupt" fn page_fault(
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
||||||
// interrupt(Interrupt::Timer);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LAPIC.end_of_interrupt();
|
LAPIC.end_of_interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
||||||
interrupt(Interrupt::ApicErr);
|
|
||||||
|
|
||||||
panic!("Internal APIC error");
|
panic!("Internal APIC error");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
||||||
interrupt(Interrupt::Spurious);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LAPIC.end_of_interrupt();
|
LAPIC.end_of_interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn interrupt(interrupt_type: Interrupt) {
|
|
||||||
use crate::arch::INTERRUPT_LIST;
|
|
||||||
let il = INTERRUPT_LIST.lock();
|
|
||||||
let val = il.list.get(&interrupt_type).unwrap();
|
|
||||||
|
|
||||||
use crate::holeybytes::kernel_services::service_definition_service::sds_search_service;
|
|
||||||
let buffer = sds_search_service(val);
|
|
||||||
if buffer != 0 {
|
|
||||||
use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec};
|
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
|
||||||
match buffs.get_mut(&buffer) {
|
|
||||||
Some(buff) => {
|
|
||||||
let mut msg_vec = Vec::new();
|
|
||||||
msg_vec.push(0xFF);
|
|
||||||
buff.push(msg_vec.to_vec());
|
|
||||||
log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
log::error!("Access of non-existent buffer {}", buffer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log::info!("{}", buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub mod graphics;
|
||||||
pub(crate) mod interrupts;
|
pub(crate) mod interrupts;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
pub mod pci;
|
pub mod pci;
|
||||||
// pub mod virtio;
|
pub mod virtio;
|
||||||
|
|
||||||
pub use {logging::log, memory::PAGE_SIZE};
|
pub use {logging::log, memory::PAGE_SIZE};
|
||||||
|
|
||||||
|
@ -30,11 +30,9 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[naked]
|
#[naked]
|
||||||
#[cfg(not(target_feature = "avx2"))]
|
|
||||||
unsafe extern "C" fn _kernel_start() -> ! {
|
unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
// Initialise SSE, then jump to kernel entrypoint
|
// Initialise SSE and jump to kernel entrypoint
|
||||||
core::arch::naked_asm!(
|
core::arch::asm!(
|
||||||
// Initialise SSE
|
|
||||||
"mov rax, cr0",
|
"mov rax, cr0",
|
||||||
"and ax, 0xfffb",
|
"and ax, 0xfffb",
|
||||||
"or ax, 0x2",
|
"or ax, 0x2",
|
||||||
|
@ -42,74 +40,16 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
"mov rax, cr4",
|
"mov rax, cr4",
|
||||||
"or ax, 3 << 9",
|
"or ax, 3 << 9",
|
||||||
"mov cr4, rax",
|
"mov cr4, rax",
|
||||||
|
|
||||||
// Jump to the kernel entry point
|
|
||||||
"jmp {}",
|
"jmp {}",
|
||||||
sym start,
|
sym start,
|
||||||
|
options(noreturn),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
#[naked]
|
|
||||||
#[cfg(target_feature = "avx2")]
|
|
||||||
unsafe extern "C" fn _kernel_start() -> ! {
|
|
||||||
core::arch::naked_asm!(
|
|
||||||
// Enable protected mode and configure control registers
|
|
||||||
"mov rax, cr0",
|
|
||||||
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
|
|
||||||
"or ax, 0x2", // Set CR0.MP (bit 1) for coprocessor monitoring
|
|
||||||
"mov cr0, rax",
|
|
||||||
|
|
||||||
"mov rax, cr4",
|
|
||||||
"or ax, (1 << 9) | (1 << 10)", // Set CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10)
|
|
||||||
"mov cr4, rax",
|
|
||||||
|
|
||||||
// Enable OSXSAVE (required for AVX, AVX2, and XSAVE)
|
|
||||||
"mov rax, cr4",
|
|
||||||
"or eax, 1 << 18", // Set CR4.OSXSAVE (bit 18)
|
|
||||||
"mov cr4, rax",
|
|
||||||
|
|
||||||
// Enable AVX and AVX2 state saving
|
|
||||||
"xor rcx, rcx",
|
|
||||||
"xgetbv",
|
|
||||||
"or eax, 7", // Enable SSE, AVX, and AVX2 state saving
|
|
||||||
"xsetbv",
|
|
||||||
|
|
||||||
// Check for AVX and XSAVE support
|
|
||||||
"mov eax, 1",
|
|
||||||
"cpuid",
|
|
||||||
"and ecx, 0x18000000",
|
|
||||||
"cmp ecx, 0x18000000",
|
|
||||||
"jne {1}", // Jump if AVX/OSXSAVE is not supported
|
|
||||||
|
|
||||||
// Check for BMI2 and AVX2 support
|
|
||||||
"mov eax, 7",
|
|
||||||
"xor ecx, ecx",
|
|
||||||
"cpuid",
|
|
||||||
"and ebx, (1 << 8) | (1 << 5)", // Check BMI2 (bit 8) and AVX2 (bit 5)
|
|
||||||
"cmp ebx, (1 << 8) | (1 << 5)", // Compare to ensure both are supported
|
|
||||||
|
|
||||||
// Check for LZCNT and POPCNT support
|
|
||||||
"mov eax, 1",
|
|
||||||
"cpuid",
|
|
||||||
"and ecx, (1 << 5) | (1 << 23)", // Check LZCNT (bit 5) and POPCNT (bit 23)
|
|
||||||
"cmp ecx, (1 << 5) | (1 << 23)", // Compare to ensure both are supported
|
|
||||||
|
|
||||||
// Jump to the kernel entry point
|
|
||||||
"jmp {0}",
|
|
||||||
sym start,
|
|
||||||
sym oops,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "C" fn oops() -> ! {
|
|
||||||
panic!("your cpu is ancient >:(")
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe extern "C" fn start() -> ! {
|
unsafe extern "C" fn start() -> ! {
|
||||||
logging::init();
|
logging::init();
|
||||||
crate::logger::init().expect("failed to set logger");
|
crate::logger::init().expect("failed to set logger");
|
||||||
log::debug!("Initialising AKern {}", crate::VERSION);
|
log::info!("Initialising AKern {}", crate::VERSION);
|
||||||
|
|
||||||
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
|
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
|
||||||
memory::init_pt(VirtAddr::new(
|
memory::init_pt(VirtAddr::new(
|
||||||
|
@ -188,7 +128,7 @@ unsafe extern "C" fn start() -> ! {
|
||||||
// TODO: Add in rdseed and rdrand as sources for randomness
|
// TODO: Add in rdseed and rdrand as sources for randomness
|
||||||
let _rand = xml::XMLElement::new("Random");
|
let _rand = xml::XMLElement::new("Random");
|
||||||
|
|
||||||
log::debug!("Getting boot modules");
|
log::trace!("Getting boot modules");
|
||||||
let bm = MOD_REQ.get_response().get();
|
let bm = MOD_REQ.get_response().get();
|
||||||
|
|
||||||
let mut bootmodules = alloc::vec::Vec::new();
|
let mut bootmodules = alloc::vec::Vec::new();
|
||||||
|
@ -226,7 +166,7 @@ unsafe extern "C" fn start() -> ! {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::debug!("Boot module count: {:?}", bootmodules.len());
|
log::info!("Boot module count: {:?}", bootmodules.len());
|
||||||
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +189,6 @@ unsafe extern "C" fn start() -> ! {
|
||||||
/// Spin loop
|
/// Spin loop
|
||||||
pub fn spin_loop() -> ! {
|
pub fn spin_loop() -> ! {
|
||||||
loop {
|
loop {
|
||||||
core::hint::spin_loop();
|
|
||||||
x86_64::instructions::hlt()
|
x86_64::instructions::hlt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,13 @@ pub struct PciDeviceInfo {
|
||||||
pub full_class: PciFullClass,
|
pub full_class: PciFullClass,
|
||||||
pub rev_id: u8,
|
pub rev_id: u8,
|
||||||
}
|
}
|
||||||
|
use crate::alloc::string::ToString;
|
||||||
|
|
||||||
/// Enumerate PCI devices and run initialisation routines on ones we support
|
/// Enumerate PCI devices and run initialisation routines on ones we support
|
||||||
pub fn init(device_tree: &mut DeviceTree) {
|
pub fn init(device_tree: &mut DeviceTree) {
|
||||||
device_tree
|
device_tree
|
||||||
.devices
|
.devices
|
||||||
.insert("Unidentified PCI", alloc::vec![]);
|
.insert("Unidentified PCI".to_string(), alloc::vec![]);
|
||||||
let mut devices = alloc::vec![];
|
let mut devices = alloc::vec![];
|
||||||
|
|
||||||
for bus in 0..=255 {
|
for bus in 0..=255 {
|
||||||
|
@ -47,7 +48,7 @@ pub fn init(device_tree: &mut DeviceTree) {
|
||||||
pci_info.set_attribute("device", device_info.device);
|
pci_info.set_attribute("device", device_info.device);
|
||||||
pci_info.set_attribute("vendor", vendor);
|
pci_info.set_attribute("vendor", vendor);
|
||||||
pci_info.set_attribute("bus", bus);
|
pci_info.set_attribute("bus", bus);
|
||||||
pci_info.set_attribute("class", device_info.full_class);
|
pci_info.set_attribute("class", device_info.full_class.to_string());
|
||||||
dev.set_child(pci_info);
|
dev.set_child(pci_info);
|
||||||
devices.push((dev_type, dev));
|
devices.push((dev_type, dev));
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
|
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
|
||||||
log::debug!("pci device-({}) addr {} is {}", device, addr, reg2);
|
log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
|
||||||
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
|
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
|
||||||
let pci_class = PciFullClass::from_u16(class);
|
let pci_class = PciFullClass::from_u16(class);
|
||||||
let header_type = get_header_type(bus, device, 0);
|
let header_type = get_header_type(bus, device, 0);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
core::ptr::NonNull,
|
core::{ptr::NonNull},
|
||||||
virtio_drivers::{BufferDirection, Hal, PhysAddr},
|
virtio_drivers::{BufferDirection, Hal, PhysAddr},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
//! A tree of hardware devices
|
//! A tree of hardware devices
|
||||||
|
|
||||||
use {alloc::vec::Vec, core::fmt, hashbrown::HashMap};
|
use {
|
||||||
|
crate::alloc::string::ToString,
|
||||||
|
alloc::{string::String, vec::Vec},
|
||||||
|
core::fmt,
|
||||||
|
hashbrown::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
/// A device object.
|
/// A device object.
|
||||||
/// TODO define device
|
/// TODO define device
|
||||||
|
@ -9,11 +14,11 @@ pub type Device = xml::XMLElement;
|
||||||
/// A tree of devices
|
/// A tree of devices
|
||||||
// TODO: alphabetize this list
|
// TODO: alphabetize this list
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DeviceTree<'a> {
|
pub struct DeviceTree {
|
||||||
/// The device tree
|
/// The device tree
|
||||||
pub devices: HashMap<&'a str, Vec<Device>>,
|
pub devices: HashMap<String, Vec<Device>>,
|
||||||
}
|
}
|
||||||
impl<'a> DeviceTree<'a> {
|
impl DeviceTree {
|
||||||
/// Build the device tree. Does not populate the device tree
|
/// Build the device tree. Does not populate the device tree
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut dt = Self {
|
let mut dt = Self {
|
||||||
|
@ -42,7 +47,7 @@ impl<'a> DeviceTree<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
use crate::{device_tree, tab, utils::TAB};
|
use crate::{device_tree, tab, utils::TAB};
|
||||||
impl<'a> fmt::Display for DeviceTree<'a> {
|
impl fmt::Display for DeviceTree {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
for (device_type, devices) in &self.devices {
|
for (device_type, devices) in &self.devices {
|
||||||
|
|
|
@ -1,40 +1,21 @@
|
||||||
//! Environment call handling routines
|
//! Environment call handling routines
|
||||||
|
|
||||||
use {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address};
|
use crate::holeybytes::kernel_services::{
|
||||||
|
|
||||||
use crate::{
|
|
||||||
holeybytes::{
|
|
||||||
kernel_services::{
|
|
||||||
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
|
block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
|
||||||
service_definition_service::sds_msg_handler,
|
service_definition_service::sds_msg_handler,
|
||||||
},
|
|
||||||
ExecThread,
|
|
||||||
},
|
|
||||||
kmain::EXECUTOR,
|
|
||||||
task::Executor,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
super::Vm,
|
super::Vm,
|
||||||
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
|
||||||
hbvm::value::Value,
|
|
||||||
log::{debug, error, info, trace},
|
log::{debug, error, info, trace},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn x86_out<T: x86_64::instructions::port::PortWrite>(address: u16, value: T) {
|
|
||||||
x86_64::instructions::port::Port::new(address).write(value);
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
|
||||||
x86_64::instructions::port::Port::new(address).read()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn handler(vm: &mut Vm) {
|
pub fn handler(vm: &mut Vm) {
|
||||||
let ecall_number = vm.registers[2].cast::<u64>();
|
let ecall_number = vm.registers[2].cast::<u64>();
|
||||||
|
// log::info!("eca called :pensive:");
|
||||||
|
// debug!("Ecall number {:?}", ecall_number);
|
||||||
|
//info!("Register dump: {:?}", vm.registers);
|
||||||
|
|
||||||
match ecall_number {
|
match ecall_number {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -47,9 +28,9 @@ pub fn handler(vm: &mut Vm) {
|
||||||
1 => {
|
1 => {
|
||||||
// Make buffer
|
// Make buffer
|
||||||
|
|
||||||
let bounded = match vm.registers[3] {
|
let bounded = match vm.registers[3].cast::<u64>() {
|
||||||
Value(0) => false,
|
0 => false,
|
||||||
Value(1) => true,
|
1 => true,
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Bad");
|
panic!("Bad");
|
||||||
}
|
}
|
||||||
|
@ -58,19 +39,22 @@ pub fn handler(vm: &mut Vm) {
|
||||||
let length = vm.registers[4].cast::<u64>();
|
let length = vm.registers[4].cast::<u64>();
|
||||||
|
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
let mut buffs = IPC_BUFFERS.lock();
|
||||||
|
let abc;
|
||||||
|
|
||||||
let buff_id = arch::hardware_random_u64();
|
|
||||||
buffs.insert(
|
|
||||||
buff_id,
|
|
||||||
match bounded {
|
match bounded {
|
||||||
false => IpcBuffer::new(false, 0),
|
false => {
|
||||||
true => IpcBuffer::new(true, length),
|
abc = IpcBuffer::new(false, 0);
|
||||||
},
|
}
|
||||||
);
|
true => {
|
||||||
|
abc = IpcBuffer::new(true, length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let buff_id = arch::hardware_random_u64();
|
||||||
|
buffs.insert(buff_id, abc);
|
||||||
|
info!("Buffer ID: {}", buff_id);
|
||||||
vm.registers[1] = hbvm::value::Value(buff_id);
|
vm.registers[1] = hbvm::value::Value(buff_id);
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
log::error!("Oops, deleting buffers is not implemented.")
|
|
||||||
// Delete buffer
|
// Delete buffer
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
|
@ -79,6 +63,7 @@ pub fn handler(vm: &mut Vm) {
|
||||||
let mem_addr = vm.registers[4].cast::<u64>();
|
let mem_addr = vm.registers[4].cast::<u64>();
|
||||||
let length = vm.registers[5].cast::<u64>() as usize;
|
let length = vm.registers[5].cast::<u64>() as usize;
|
||||||
trace!("IPC address: {:?}", mem_addr);
|
trace!("IPC address: {:?}", mem_addr);
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
match buffer_id {
|
match buffer_id {
|
||||||
0 => match sds_msg_handler(vm, mem_addr, length) {
|
0 => match sds_msg_handler(vm, mem_addr, length) {
|
||||||
|
@ -96,15 +81,25 @@ pub fn handler(vm: &mut Vm) {
|
||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(target_arch = "x86_64"))]
|
||||||
|
3 => info!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
3 => {
|
3 => {
|
||||||
|
unsafe fn x86_out<T: x86_64::instructions::port::PortWrite>(
|
||||||
|
address: u16,
|
||||||
|
value: T,
|
||||||
|
) {
|
||||||
|
x86_64::instructions::port::Port::new(address).write(value);
|
||||||
|
}
|
||||||
|
unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
||||||
|
x86_64::instructions::port::Port::new(address).read()
|
||||||
|
}
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let msg_type = msg_vec[0];
|
let msg_type = msg_vec[0];
|
||||||
match msg_type {
|
match msg_type {
|
||||||
0 => unsafe {
|
0 => unsafe {
|
||||||
let size = msg_vec[1];
|
let size = msg_vec[1];
|
||||||
let addr =
|
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
||||||
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
|
||||||
let value = match size {
|
let value = match size {
|
||||||
0 => x86_in::<u8>(addr) as u64,
|
0 => x86_in::<u8>(addr) as u64,
|
||||||
1 => x86_in::<u16>(addr) as u64,
|
1 => x86_in::<u16>(addr) as u64,
|
||||||
|
@ -116,8 +111,7 @@ pub fn handler(vm: &mut Vm) {
|
||||||
},
|
},
|
||||||
1 => unsafe {
|
1 => unsafe {
|
||||||
let size = msg_vec[1];
|
let size = msg_vec[1];
|
||||||
let addr =
|
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
||||||
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
|
||||||
// info!("Setting address {}", addr);
|
// info!("Setting address {}", addr);
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
|
@ -140,95 +134,68 @@ pub fn handler(vm: &mut Vm) {
|
||||||
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||||
// source of rng
|
// source of rng
|
||||||
4 => {
|
4 => {
|
||||||
let block = block_read(mem_addr, length);
|
// limit to last 32 bits
|
||||||
block.chunks_mut(8.min(length)).for_each(|chunk| {
|
vm.registers[1] =
|
||||||
chunk.clone_from_slice(
|
hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF);
|
||||||
&crate::arch::hardware_random_u64().to_le_bytes()[..chunk.len()],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
vm.registers[1] = hbvm::value::Value(mem_addr);
|
|
||||||
}
|
}
|
||||||
5 => match dt_msg_handler(vm, mem_addr, length) {
|
5 => match dt_msg_handler(vm, mem_addr, length) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(_) => log::error!("Improper dt query"),
|
Err(_) => log::error!("Improper dt query"),
|
||||||
},
|
},
|
||||||
6 => unsafe {
|
|
||||||
let program = block_read(mem_addr, length);
|
|
||||||
|
|
||||||
// decode AbleOS Executable format
|
|
||||||
let header = &program[0..46];
|
|
||||||
let magic_slice = &header[0..3];
|
|
||||||
if magic_slice != [0x15, 0x91, 0xD2] {
|
|
||||||
log::error!("Invalid magic number at the start of executable.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let executable_format_version =
|
|
||||||
u32::from_le_bytes(header[3..7].try_into().unwrap());
|
|
||||||
let offset = if executable_format_version == 0 {
|
|
||||||
47
|
|
||||||
} else {
|
|
||||||
error!("Invalid executable format.");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
|
|
||||||
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
|
|
||||||
let end = (code_length + data_length) as usize;
|
|
||||||
log::debug!("{code_length} + {data_length} = {end}");
|
|
||||||
|
|
||||||
let thr = ExecThread::new(&program[offset..end], Address::new(0));
|
|
||||||
vm.registers[1] = Value(
|
|
||||||
LazyCell::<Executor>::get_mut(&mut EXECUTOR)
|
|
||||||
.unwrap()
|
|
||||||
.spawn(Box::pin(async move {
|
|
||||||
if let Err(e) = thr.await {
|
|
||||||
log::error!("{e:?}");
|
|
||||||
}
|
|
||||||
})) as u64,
|
|
||||||
);
|
|
||||||
log::debug!("spawned a process");
|
|
||||||
},
|
|
||||||
|
|
||||||
buffer_id => {
|
buffer_id => {
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
let mut buffs = IPC_BUFFERS.lock();
|
||||||
match buffs.get_mut(&buffer_id) {
|
match buffs.get_mut(&buffer_id) {
|
||||||
Some(buff) => {
|
Some(buff) => {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let mut msg_vec = Vec::with_capacity(length);
|
||||||
buff.push(msg_vec.to_vec());
|
|
||||||
debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer_id);
|
for x in 0..(length as isize) {
|
||||||
|
let xyz = mem_addr as *const u8;
|
||||||
|
let value = unsafe { xyz.offset(x).read() };
|
||||||
|
msg_vec.push(value);
|
||||||
|
}
|
||||||
|
debug!(
|
||||||
|
"Message {:?} has been sent to Buffer({})",
|
||||||
|
msg_vec, buffer_id
|
||||||
|
);
|
||||||
|
buff.push(msg_vec);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
log::error!("Access of non-existent buffer {}", buffer_id)
|
log::error!("Access of non-existent buffer {}", buffer_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
drop(buffs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
let buffer_id = vm.registers[3].cast::<u64>();
|
let buffer_id = vm.registers[3].cast::<u64>();
|
||||||
let map_ptr = vm.registers[4].cast::<u64>();
|
let mut map_ptr = vm.registers[4].cast::<u64>();
|
||||||
let max_length = vm.registers[5].cast::<u64>();
|
let max_length = vm.registers[5].cast::<u64>();
|
||||||
|
|
||||||
let mut buffs = IPC_BUFFERS.lock();
|
let mut buffs = IPC_BUFFERS.lock();
|
||||||
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
|
let buff: &mut IpcBuffer;
|
||||||
Some(buff) => buff,
|
|
||||||
None => panic!(
|
|
||||||
"Failed to get buffer: id={buffer_id}, ptr={map_ptr}, length={max_length}"
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let msg = match buff.pop() {
|
if buffs.get_mut(&buffer_id).is_some() {
|
||||||
Ok(msg) => msg,
|
buff = buffs.get_mut(&buffer_id).unwrap();
|
||||||
Err(_) => return,
|
} else {
|
||||||
};
|
// info!("AHHH");
|
||||||
if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } {
|
vm.registers[1] = hbvm::value::Value(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let pop = buff.pop();
|
||||||
|
if pop.is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let msg = pop.unwrap();
|
||||||
|
if msg.len() > max_length.try_into().unwrap() {
|
||||||
info!("{}", max_length);
|
info!("{}", max_length);
|
||||||
error!("Message is too long to map in.");
|
error!("Message is too long to map in.");
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = map_ptr as *mut u8;
|
let ptr: *mut u64 = &mut map_ptr;
|
||||||
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
|
for (index, byte) in msg.iter().enumerate() {
|
||||||
|
ptr.offset(index.try_into().unwrap()).write_bytes(*byte, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||||
|
@ -238,7 +205,13 @@ pub fn handler(vm: &mut Vm) {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
{
|
{
|
||||||
let r2 = vm.registers[2].cast::<u64>();
|
let r2 = vm.registers[2].cast::<u64>();
|
||||||
let x = hbvm::value::Value(unsafe { x86_in::<u8>(r2 as u16) } as u64);
|
unsafe fn x86_in(address: u16) -> u32 {
|
||||||
|
x86_64::instructions::port::Port::new(address).read()
|
||||||
|
}
|
||||||
|
unsafe fn x86_out(address: u16, value: u32) {
|
||||||
|
x86_64::instructions::port::Port::new(address).write(value);
|
||||||
|
}
|
||||||
|
let x = hbvm::value::Value(unsafe { x86_in(r2 as u16) } as u64);
|
||||||
// info!("Read {:?} from Port {:?}", x, r2);
|
// info!("Read {:?} from Port {:?}", x, r2);
|
||||||
vm.registers[3] = x
|
vm.registers[3] = x
|
||||||
}
|
}
|
||||||
|
@ -254,3 +227,15 @@ pub enum LogError {
|
||||||
NoMessages,
|
NoMessages,
|
||||||
InvalidLogFormat,
|
InvalidLogFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use {alloc::vec, log::Record};
|
||||||
|
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
|
// let mut val = alloc::vec::Vec::new();
|
||||||
|
// for _ in 0..4096 {
|
||||||
|
// val.push(0);
|
||||||
|
// }
|
||||||
|
// info!("Block address: {:?}", val.as_ptr());
|
||||||
|
// vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
||||||
|
// vm.registers[2] = hbvm::value::Value(4096);
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use {
|
use {
|
||||||
crate::holeybytes::{kernel_services::block_read, Vm},
|
crate::holeybytes::{kernel_services::block_read, Vm},
|
||||||
alloc::vec::Vec,
|
alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
vec::Vec,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
pub enum DtError {
|
pub enum DtError {
|
||||||
QueryFailure,
|
QueryFailure,
|
||||||
|
@ -8,13 +11,14 @@ pub enum DtError {
|
||||||
|
|
||||||
pub fn dt_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), DtError> {
|
pub fn dt_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), DtError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let query_string = core::str::from_utf8(
|
let mut bytes: Vec<u8> = Vec::new();
|
||||||
msg_vec
|
for byte in msg_vec {
|
||||||
.split_once(|&byte| byte == 0)
|
if *byte == 0 {
|
||||||
.unwrap_or((msg_vec, &[]))
|
break;
|
||||||
.0,
|
}
|
||||||
)
|
bytes.push(*byte)
|
||||||
.unwrap();
|
}
|
||||||
|
let query_string = String::from_utf8(bytes).unwrap();
|
||||||
log::trace!("Query {}", query_string);
|
log::trace!("Query {}", query_string);
|
||||||
|
|
||||||
let ret = query_parse(query_string);
|
let ret = query_parse(query_string);
|
||||||
|
@ -25,13 +29,17 @@ pub fn dt_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), D
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_parse(query_string: &str) -> u64 {
|
fn query_parse(query_string: String) -> u64 {
|
||||||
let query = query_string.split('/').collect::<Vec<&str>>();
|
let qt_parse_step_one = query_string.split("/");
|
||||||
|
let mut qt_parse_step_two: Vec<String> = Vec::new();
|
||||||
|
for a in qt_parse_step_one {
|
||||||
|
qt_parse_step_two.push(a.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
let first_fragment: &str = &query[0];
|
let first_fragment: &str = &qt_parse_step_two[0];
|
||||||
let ret = match first_fragment {
|
let ret = match first_fragment {
|
||||||
"framebuffer" => framebuffer_parse(query),
|
"framebuffer" => framebuffer_parse(qt_parse_step_two),
|
||||||
"cpu" => cpu_parse(query),
|
"cpu" => cpu_parse(qt_parse_step_two),
|
||||||
|
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
@ -39,8 +47,8 @@ fn query_parse(query_string: &str) -> u64 {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cpu_parse(qt_parse_step_two: Vec<&str>) -> u64 {
|
fn cpu_parse(qt_parse_step_two: Vec<String>) -> u64 {
|
||||||
let second_fragment: &str = qt_parse_step_two[1];
|
let second_fragment: &str = &qt_parse_step_two[1];
|
||||||
match second_fragment {
|
match second_fragment {
|
||||||
// "architecture" => {
|
// "architecture" => {
|
||||||
// return 0;
|
// return 0;
|
||||||
|
@ -51,14 +59,15 @@ fn cpu_parse(qt_parse_step_two: Vec<&str>) -> u64 {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn framebuffer_parse(qt_parse_step_two: Vec<&str>) -> u64 {
|
fn framebuffer_parse(qt_parse_step_two: Vec<String>) -> u64 {
|
||||||
use crate::kmain::FB_REQ;
|
use crate::kmain::FB_REQ;
|
||||||
let fbs = &mut FB_REQ.get_response().get().unwrap().framebuffers();
|
let fbs = &FB_REQ.get_response().get().unwrap().framebuffers();
|
||||||
let second_fragment: &str = qt_parse_step_two[1];
|
|
||||||
|
let second_fragment: &str = &qt_parse_step_two[1];
|
||||||
match second_fragment {
|
match second_fragment {
|
||||||
"fb0" => {
|
"fb0" => {
|
||||||
let fb_front = &fbs[0];
|
let fb_front = &fbs[0];
|
||||||
let third_fragment: &str = qt_parse_step_two[2];
|
let third_fragment: &str = &qt_parse_step_two[2];
|
||||||
let ret = match third_fragment {
|
let ret = match third_fragment {
|
||||||
"ptr" => {
|
"ptr" => {
|
||||||
let ptr = fb_front.address.as_ptr().unwrap();
|
let ptr = fb_front.address.as_ptr().unwrap();
|
||||||
|
|
|
@ -9,8 +9,15 @@ use log::Record;
|
||||||
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
|
|
||||||
|
let log_level = msg_vec.last().unwrap();
|
||||||
|
|
||||||
|
let file_name = "None";
|
||||||
|
let line_number = 0;
|
||||||
|
|
||||||
|
match core::str::from_utf8(&msg_vec[..msg_vec.len()]) {
|
||||||
|
Ok(strr) => {
|
||||||
use log::Level::*;
|
use log::Level::*;
|
||||||
let log_level = match msg_vec[0] {
|
let log_level = match log_level {
|
||||||
0 | 48 => Error,
|
0 | 48 => Error,
|
||||||
1 | 49 => Warn,
|
1 | 49 => Warn,
|
||||||
2 | 50 => Info,
|
2 | 50 => Info,
|
||||||
|
@ -20,19 +27,7 @@ pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(),
|
||||||
return Err(LogError::InvalidLogFormat);
|
return Err(LogError::InvalidLogFormat);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if log_level > log::max_level() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
|
|
||||||
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
|
|
||||||
|
|
||||||
let str = block_read(strptr, strlen);
|
|
||||||
|
|
||||||
let file_name = "None";
|
|
||||||
let line_number = 0;
|
|
||||||
|
|
||||||
match core::str::from_utf8(&str) {
|
|
||||||
Ok(strr) => {
|
|
||||||
log::logger().log(
|
log::logger().log(
|
||||||
&Record::builder()
|
&Record::builder()
|
||||||
.args(format_args!("{}", strr))
|
.args(format_args!("{}", strr))
|
||||||
|
|
|
@ -17,28 +17,13 @@ pub enum MemoryQuotaType {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
||||||
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 8)) };
|
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 4096)) };
|
||||||
info!("Block address: {:?}", ptr);
|
info!("Block address: {:?}", ptr);
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||||
vm.registers[2] = hbvm::value::Value(4096);
|
vm.registers[2] = hbvm::value::Value(4096);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
|
||||||
let total_size = count * size;
|
|
||||||
src.copy_to_nonoverlapping(dest, size);
|
|
||||||
|
|
||||||
let mut copied = size;
|
|
||||||
|
|
||||||
while copied < total_size {
|
|
||||||
let copy_size = copied.min(total_size - copied);
|
|
||||||
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
|
|
||||||
copied += copy_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn memory_msg_handler(
|
pub fn memory_msg_handler(
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
mem_addr: u64,
|
mem_addr: u64,
|
||||||
|
@ -47,35 +32,40 @@ pub fn memory_msg_handler(
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let msg_type = msg_vec[0];
|
let msg_type = msg_vec[0];
|
||||||
match msg_type {
|
match msg_type {
|
||||||
0 => unsafe {
|
0 => {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[1];
|
||||||
|
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||||
|
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||||
|
|
||||||
let ptr = alloc(Layout::from_size_align_unchecked(
|
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
|
||||||
|
|
||||||
|
let ptr = unsafe {
|
||||||
|
alloc(Layout::from_size_align_unchecked(
|
||||||
page_count as usize * 4096,
|
page_count as usize * 4096,
|
||||||
8,
|
4096,
|
||||||
));
|
))
|
||||||
|
};
|
||||||
log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
|
|
||||||
|
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||||
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
||||||
},
|
}
|
||||||
|
|
||||||
1 => unsafe {
|
1 => {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[1];
|
||||||
|
|
||||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||||
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
||||||
|
unsafe {
|
||||||
dealloc(
|
dealloc(
|
||||||
mptr as *mut u8,
|
mptr as *mut u8,
|
||||||
Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
|
Layout::from_size_align_unchecked(page_count as usize * 4096, 4096),
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
}
|
||||||
2 => {
|
2 => {
|
||||||
use MemoryQuotaType::*;
|
use MemoryQuotaType::*;
|
||||||
let quota_type = match msg_vec[1] {
|
let quota_type = match msg_vec[0] {
|
||||||
0 => NoQuota,
|
0 => NoQuota,
|
||||||
1 => SoftQuota,
|
1 => SoftQuota,
|
||||||
2 => HardQuota,
|
2 => HardQuota,
|
||||||
|
@ -92,24 +82,10 @@ pub fn memory_msg_handler(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[0];
|
||||||
log::debug!(" {} pages", page_count);
|
log::debug!(" {} pages", page_count);
|
||||||
}
|
}
|
||||||
4 => unsafe {
|
|
||||||
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 = 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);
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
log::debug!("Unknown memory service message type: {}", msg_type);
|
log::debug!("Unknown memory service message type: {}", msg_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,19 +22,21 @@ pub enum ServiceError {
|
||||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
||||||
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
|
|
||||||
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
|
// info!("Length {}", msg_vec.len());
|
||||||
let string_vec = block_read(strptr, strlen);
|
|
||||||
let string = core::str::from_utf8(string_vec).expect("Our bytes should be valid utf8");
|
|
||||||
|
|
||||||
use ServiceEventType::*;
|
use ServiceEventType::*;
|
||||||
match sds_event_type {
|
match sds_event_type {
|
||||||
CreateService => {
|
CreateService => {
|
||||||
|
let string =
|
||||||
|
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||||
let ret = sds_create_service(string);
|
let ret = sds_create_service(string);
|
||||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||||
}
|
}
|
||||||
DeleteService => todo!(),
|
DeleteService => todo!(),
|
||||||
SearchServices => {
|
SearchServices => {
|
||||||
|
let string =
|
||||||
|
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
||||||
let ret = sds_search_service(string);
|
let ret = sds_search_service(string);
|
||||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +94,8 @@ fn sds_create_service(protocol: &'static str) -> u64 {
|
||||||
// let a: protocol::Protocol = protocol.into();
|
// let a: protocol::Protocol = protocol.into();
|
||||||
buff_id
|
buff_id
|
||||||
}
|
}
|
||||||
pub fn sds_search_service(protocol: &str) -> u64 {
|
|
||||||
|
fn sds_search_service(protocol: &str) -> u64 {
|
||||||
let services = SERVICES.lock();
|
let services = SERVICES.lock();
|
||||||
let compare = Protocol::from(protocol);
|
let compare = Protocol::from(protocol);
|
||||||
for (bid, protocol_canidate) in &services.0 {
|
for (bid, protocol_canidate) in &services.0 {
|
||||||
|
|
|
@ -30,29 +30,30 @@ impl Memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl hbvm::mem::Memory for Memory {
|
impl hbvm::mem::Memory for Memory {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
unsafe fn load(
|
unsafe fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: Address,
|
addr: Address,
|
||||||
target: *mut u8,
|
target: *mut u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
) -> Result<(), hbvm::mem::LoadError> {
|
||||||
core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count);
|
if addr.get() % 4096 == 0 {}
|
||||||
|
core::ptr::copy(addr.get() as *const u8, target, count);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
unsafe fn store(
|
unsafe fn store(
|
||||||
&mut self,
|
&mut self,
|
||||||
addr: Address,
|
addr: Address,
|
||||||
source: *const u8,
|
source: *const u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::StoreError> {
|
) -> Result<(), hbvm::mem::StoreError> {
|
||||||
core::ptr::copy_nonoverlapping(source, addr.get() as *mut u8, count);
|
core::ptr::copy(source, addr.get() as *mut u8, count);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
||||||
(addr.get() as *const T).read()
|
(addr.get() as *const T).read()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod ecah;
|
mod ecah;
|
||||||
pub mod kernel_services;
|
mod kernel_services;
|
||||||
mod mem;
|
mod mem;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
@ -97,7 +97,7 @@ impl HandlePageFault for PageFaultHandler {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
const fn stack_layout() -> Layout {
|
const fn stack_layout() -> Layout {
|
||||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 8) }
|
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -49,7 +49,9 @@ impl<'a> IpcBuffer<'a> {
|
||||||
pub fn push(&mut self, msg: Message) {
|
pub fn push(&mut self, msg: Message) {
|
||||||
match &self.buffer {
|
match &self.buffer {
|
||||||
BufferTypes::Unbound(buff) => buff.push(msg),
|
BufferTypes::Unbound(buff) => buff.push(msg),
|
||||||
BufferTypes::Bound(buff) => buff.push(msg).unwrap(),
|
BufferTypes::Bound(buff) => {
|
||||||
|
let _ = buff.push(msg);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn pop(&mut self) -> Result<Message, IpcError> {
|
pub fn pop(&mut self) -> Result<Message, IpcError> {
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use {alloc::vec::Vec, hashbrown::HashMap};
|
use {
|
||||||
|
alloc::{string::String, vec::Vec},
|
||||||
|
hashbrown::HashMap,
|
||||||
|
};
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Type {}
|
pub struct Type {}
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Funct<'a> {
|
pub struct Funct {
|
||||||
takes: Vec<&'a str>,
|
takes: Vec<String>,
|
||||||
gives: Vec<&'a str>,
|
gives: Vec<String>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Protocol<'a> {
|
pub struct Protocol<'a> {
|
||||||
types: HashMap<&'a str, Type>,
|
types: HashMap<&'a str, Type>,
|
||||||
fns: HashMap<&'a str, Funct<'a>>,
|
fns: HashMap<&'a str, Funct>,
|
||||||
}
|
}
|
||||||
impl<'a> Protocol<'a> {
|
impl<'a> Protocol<'a> {
|
||||||
pub fn void() -> Self {
|
pub fn void() -> Self {
|
||||||
|
|
|
@ -8,10 +8,7 @@ use {
|
||||||
device_tree::DeviceTree,
|
device_tree::DeviceTree,
|
||||||
holeybytes::ExecThread,
|
holeybytes::ExecThread,
|
||||||
ipc::buffer::IpcBuffer,
|
ipc::buffer::IpcBuffer,
|
||||||
task::Executor,
|
|
||||||
},
|
},
|
||||||
alloc::boxed::Box,
|
|
||||||
core::cell::LazyCell,
|
|
||||||
hashbrown::HashMap,
|
hashbrown::HashMap,
|
||||||
hbvm::mem::Address,
|
hbvm::mem::Address,
|
||||||
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
limine::{Framebuffer, FramebufferRequest, NonNullPtr},
|
||||||
|
@ -53,6 +50,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
let fb1: &NonNullPtr<Framebuffer> = &FB_REQ.get_response().get().unwrap().framebuffers()[0];
|
||||||
|
|
||||||
{
|
{
|
||||||
|
use crate::alloc::string::ToString;
|
||||||
let mut dt = DEVICE_TREE.lock();
|
let mut dt = DEVICE_TREE.lock();
|
||||||
let mut disp = xml::XMLElement::new("display_0");
|
let mut disp = xml::XMLElement::new("display_0");
|
||||||
|
|
||||||
|
@ -60,7 +58,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
disp.set_attribute("height", fb1.height);
|
disp.set_attribute("height", fb1.height);
|
||||||
disp.set_attribute("bpp", fb1.bpp);
|
disp.set_attribute("bpp", fb1.bpp);
|
||||||
disp.set_attribute("pitch", fb1.pitch);
|
disp.set_attribute("pitch", fb1.pitch);
|
||||||
dt.devices.insert("Displays", alloc::vec![disp]);
|
dt.devices.insert("Displays".to_string(), alloc::vec![disp]);
|
||||||
}
|
}
|
||||||
debug!("Graphics initialised");
|
debug!("Graphics initialised");
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -68,24 +66,13 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
fb1.address.as_ptr().unwrap() as *const u8
|
fb1.address.as_ptr().unwrap() as *const u8
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut executor = crate::task::Executor::new(256);
|
||||||
unsafe {
|
unsafe {
|
||||||
let executor = LazyCell::<Executor>::force_mut(&mut EXECUTOR);
|
|
||||||
for module in boot_modules.iter() {
|
for module in boot_modules.iter() {
|
||||||
let cmd = module.cmd.trim_matches('"');
|
let cmd = module.cmd.trim_matches('"');
|
||||||
let cmd_len = cmd.len() as u64;
|
let cmd_len = cmd.len() as u64;
|
||||||
|
|
||||||
log::info!(
|
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
||||||
"Starting {}",
|
|
||||||
module
|
|
||||||
.path
|
|
||||||
.split('/')
|
|
||||||
.last()
|
|
||||||
.unwrap()
|
|
||||||
.split('.')
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
);
|
|
||||||
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
|
|
||||||
|
|
||||||
// decode AbleOS Executable format
|
// decode AbleOS Executable format
|
||||||
let header = &module.bytes[0..46];
|
let header = &module.bytes[0..46];
|
||||||
|
@ -106,17 +93,17 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
|
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
|
||||||
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
|
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
|
||||||
let end = (code_length + data_length) as usize;
|
let end = (code_length + data_length) as usize;
|
||||||
log::debug!("{code_length} + {data_length} = {end}");
|
log::info!("{code_length} + {data_length} = {end}");
|
||||||
|
|
||||||
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
|
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
|
||||||
if cmd_len > 0 {
|
if cmd_len > 0 {
|
||||||
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
|
thr.set_arguments(cmd.as_ptr() as u64, cmd_len);
|
||||||
}
|
}
|
||||||
executor.spawn(Box::pin(async move {
|
executor.spawn(async move {
|
||||||
if let Err(e) = thr.await {
|
if let Err(e) = thr.await {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
}
|
}
|
||||||
}));
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Random number: {}", hardware_random_u64());
|
debug!("Random number: {}", hardware_random_u64());
|
||||||
|
@ -127,10 +114,6 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
crate::arch::spin_loop()
|
crate::arch::spin_loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! SAFETY: this is not threadsafe at all, like even a little bit.
|
|
||||||
// ! SERIOUSLY
|
|
||||||
pub static mut EXECUTOR: LazyCell<Executor> = LazyCell::new(|| Executor::new());
|
|
||||||
|
|
||||||
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
pub static DEVICE_TREE: Lazy<Mutex<DeviceTree>> = Lazy::new(|| {
|
||||||
let dt = DeviceTree::new();
|
let dt = DeviceTree::new();
|
||||||
Mutex::new(dt)
|
Mutex::new(dt)
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
//! 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
|
//! 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_std]
|
||||||
#![feature(
|
#![feature(
|
||||||
slice_split_once,
|
|
||||||
exclusive_wrapper,
|
exclusive_wrapper,
|
||||||
core_intrinsics,
|
new_uninit,
|
||||||
abi_x86_interrupt,
|
abi_x86_interrupt,
|
||||||
lazy_get,
|
|
||||||
alloc_error_handler,
|
alloc_error_handler,
|
||||||
ptr_sub_ptr,
|
ptr_sub_ptr,
|
||||||
custom_test_frameworks,
|
custom_test_frameworks,
|
||||||
|
@ -15,7 +13,8 @@
|
||||||
pointer_is_aligned_to
|
pointer_is_aligned_to
|
||||||
)]
|
)]
|
||||||
#![test_runner(crate::test_runner)]
|
#![test_runner(crate::test_runner)]
|
||||||
#![allow(dead_code, internal_features, static_mut_refs)]
|
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
|
||||||
|
#![allow(dead_code)]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
|
|
|
@ -36,19 +36,7 @@ impl log::Log for Logger {
|
||||||
Level::Debug => "25",
|
Level::Debug => "25",
|
||||||
Level::Trace => "103",
|
Level::Trace => "103",
|
||||||
};
|
};
|
||||||
let module = record
|
let module = record.module_path().unwrap_or_default();
|
||||||
.module_path()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.rsplit_once(':')
|
|
||||||
.unwrap_or_default()
|
|
||||||
.1;
|
|
||||||
if module == "" {
|
|
||||||
crate::arch::log(format_args!(
|
|
||||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
|
|
||||||
record.args(),
|
|
||||||
))
|
|
||||||
.expect("write to serial console");
|
|
||||||
} else {
|
|
||||||
let line = record.line().unwrap_or_default();
|
let line = record.line().unwrap_or_default();
|
||||||
crate::arch::log(format_args!(
|
crate::arch::log(format_args!(
|
||||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
||||||
|
@ -56,7 +44,6 @@ impl log::Log for Logger {
|
||||||
))
|
))
|
||||||
.expect("write to serial console");
|
.expect("write to serial console");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,24 +29,24 @@ pub fn yield_now() -> impl Future<Output = ()> {
|
||||||
YieldNow(false)
|
YieldNow(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Executor {
|
pub struct Executor<F: Future<Output = ()> + Send> {
|
||||||
tasks: Slab<Task>,
|
tasks: Slab<Task<F>>,
|
||||||
task_queue: Arc<TaskQueue>,
|
task_queue: Arc<TaskQueue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor {
|
impl<F: Future<Output = ()> + Send> Executor<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new(size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tasks: Slab::new(),
|
tasks: Slab::with_capacity(size),
|
||||||
task_queue: Arc::new(TaskQueue::new()),
|
task_queue: Arc::new(TaskQueue::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn spawn(&mut self, future: Pin<Box<dyn Future<Output = ()> + Send>>) -> usize {
|
pub fn spawn(&mut self, future: F) {
|
||||||
let id = self.tasks.insert(Task::new(future));
|
self.task_queue
|
||||||
self.task_queue.queue.push(id);
|
.queue
|
||||||
id
|
.push(self.tasks.insert(Task::new(future)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
|
@ -83,16 +83,16 @@ impl Executor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Task {
|
struct Task<F: Future<Output = ()> + Send> {
|
||||||
future: Pin<Box<dyn Future<Output = ()> + Send>>,
|
future: Pin<Box<F>>,
|
||||||
waker: Option<TaskWaker>,
|
waker: Option<TaskWaker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl<F: Future<Output = ()> + Send> Task<F> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new(future: Pin<Box<dyn Future<Output = ()> + Send>>) -> Self {
|
pub fn new(future: F) -> Self {
|
||||||
Self {
|
Self {
|
||||||
future,
|
future: Box::pin(future),
|
||||||
waker: None,
|
waker: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
/// Used when tab `\t` in hardware is not known and we will default to two spaces
|
/// Used when tab `\t` in hardware is not known and we will default to two spaces
|
||||||
pub const TAB: &str = " ";
|
pub const TAB: &str = " ";
|
||||||
|
|
||||||
|
|
||||||
// NOTE: this only reduces the code duplication in source code not in generated code!
|
// NOTE: this only reduces the code duplication in source code not in generated code!
|
||||||
// Written by Yours Truly: Munir
|
// Written by Yours Truly: Munir
|
||||||
/// A simple macro to reduce code duplication when we use TAB internally
|
/// A simple macro to reduce code duplication when we use TAB internally
|
||||||
|
@ -11,7 +12,7 @@ pub const TAB: &str = " ";
|
||||||
macro_rules! tab {
|
macro_rules! tab {
|
||||||
($num:expr) => {
|
($num:expr) => {
|
||||||
TAB.repeat($num)
|
TAB.repeat($num)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: this only reduces the code duplication in source code not in generated code!
|
// NOTE: this only reduces the code duplication in source code not in generated code!
|
||||||
|
@ -21,7 +22,7 @@ macro_rules! tab {
|
||||||
macro_rules! device_tree {
|
macro_rules! device_tree {
|
||||||
($devtree:expr, $dev_type_vec:expr) => {
|
($devtree:expr, $dev_type_vec:expr) => {
|
||||||
for each_device_type in $dev_type_vec {
|
for each_device_type in $dev_type_vec {
|
||||||
$devtree.devices.insert(each_device_type, Vec::new());
|
$devtree.devices.insert(each_device_type.to_string(), Vec::new());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"arch": "aarch64",
|
"arch": "aarch64",
|
||||||
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
|
"data-layout": "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128",
|
||||||
"disable-redzone": true,
|
"disable-redzone": true,
|
||||||
"env": "",
|
"env": "",
|
||||||
"executables": true,
|
"executables": true,
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"llvm-target": "x86_64-unknown-none",
|
|
||||||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
|
|
||||||
"arch": "x86_64",
|
|
||||||
"target-endian": "little",
|
|
||||||
"target-pointer-width": "64",
|
|
||||||
"target-c-int-width": "32",
|
|
||||||
"os": "none",
|
|
||||||
"executables": true,
|
|
||||||
"linker-flavor": "ld.lld",
|
|
||||||
"linker": "rust-lld",
|
|
||||||
"panic-strategy": "abort",
|
|
||||||
"disable-redzone": true,
|
|
||||||
"features": "+sse4.1,+avx,+aes,+fma,+popcnt,+bmi2,+avx2,+lzcnt,+xsave",
|
|
||||||
"code-model": "kernel",
|
|
||||||
"pre-link-args": {
|
|
||||||
"ld.lld": [
|
|
||||||
"--gc-sections",
|
|
||||||
"--script=kernel/lds/x86_64.ld"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
# i did not know where to put this
|
|
||||||
- memcpy / memset cause crash on debug builds due to ptr misalignment that is not present on release builds
|
|
|
@ -6,15 +6,24 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
str-reader = "0.1"
|
str-reader = "0.1"
|
||||||
derive_more = { version = "1", default-features = false, features = [
|
derive_more = { version = "1", default-features = false, features = [
|
||||||
|
"add",
|
||||||
|
"add_assign",
|
||||||
|
"constructor",
|
||||||
"display",
|
"display",
|
||||||
|
"from",
|
||||||
|
"into",
|
||||||
|
"mul",
|
||||||
|
"mul_assign",
|
||||||
|
"not",
|
||||||
|
"sum",
|
||||||
] }
|
] }
|
||||||
error-stack = "0.5"
|
error-stack = "0.5"
|
||||||
fatfs = { version = "0.3", default-features = false, features = [
|
fatfs = "0.3"
|
||||||
"std",
|
|
||||||
"alloc",
|
|
||||||
] }
|
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
|
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
log = "0.4"
|
|
||||||
raw-cpuid = "11"
|
[dependencies.reqwest]
|
||||||
ureq = { version = "2", default-features = false, features = ["tls"] }
|
version = "0.12"
|
||||||
|
default-features = false
|
||||||
|
features = ["rustls-tls", "blocking"]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
fmt::format,
|
fmt::format,
|
||||||
fs::{read_to_string, File},
|
fs::{read_to_string, File},
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
|
@ -14,7 +13,6 @@ pub struct Package {
|
||||||
name: String,
|
name: String,
|
||||||
binaries: Vec<String>,
|
binaries: Vec<String>,
|
||||||
build_cmd: String,
|
build_cmd: String,
|
||||||
args: HashMap<String, String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
|
@ -48,79 +46,57 @@ impl Package {
|
||||||
let mut binaries = vec![];
|
let mut binaries = vec![];
|
||||||
|
|
||||||
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
||||||
|
// if count != 0 {
|
||||||
|
println!("{}", name);
|
||||||
binaries.push(name.clone());
|
binaries.push(name.clone());
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
let build_table = data.get("build").unwrap();
|
let build_table = data.get("build").unwrap();
|
||||||
|
|
||||||
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
|
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
|
||||||
build_cmd.remove(0);
|
build_cmd.remove(0);
|
||||||
let mut args: HashMap<String, String> = match build_table.get("args") {
|
// build_cmd.pop();
|
||||||
None => HashMap::new(),
|
|
||||||
Some(v) => v
|
|
||||||
.as_table()
|
|
||||||
.unwrap()
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.to_string()))
|
|
||||||
.collect::<HashMap<String, String>>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
binaries,
|
binaries,
|
||||||
build_cmd,
|
build_cmd,
|
||||||
args,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
|
pub fn build(&self) {
|
||||||
if self.binaries.contains(&"hblang".to_string()) {
|
if self.binaries.contains(&"hblang".to_string()) {
|
||||||
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
|
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
|
||||||
|
|
||||||
let path = format!("sysdata/programs/{}/{}", self.name, file);
|
let path = format!("sysdata/programs/{}/{}", self.name, file);
|
||||||
|
let mut bytes = Vec::new();
|
||||||
// compile here
|
// compile here
|
||||||
|
|
||||||
let mut warnings = String::new();
|
let _ = hblang::run_compiler(
|
||||||
|
|
||||||
hblang::run_compiler(
|
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
fmt: true,
|
fmt: true,
|
||||||
in_house_regalloc: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
out,
|
&mut bytes,
|
||||||
&mut warnings,
|
);
|
||||||
)?;
|
let _ = hblang::run_compiler(&path, Default::default(), &mut bytes);
|
||||||
|
|
||||||
match std::fs::create_dir("target/programs") {
|
match std::fs::create_dir("target/programs") {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
}
|
}
|
||||||
|
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
|
||||||
hblang::run_compiler(
|
bytes.clear();
|
||||||
&path,
|
let _ = hblang::run_compiler(
|
||||||
Options {
|
|
||||||
in_house_regalloc: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
out,
|
|
||||||
&mut warnings,
|
|
||||||
)?;
|
|
||||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
|
|
||||||
out.clear();
|
|
||||||
|
|
||||||
hblang::run_compiler(
|
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
dump_asm: true,
|
dump_asm: true,
|
||||||
in_house_regalloc: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
out,
|
&mut bytes,
|
||||||
&mut warnings,
|
);
|
||||||
)?;
|
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
|
||||||
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
|
|
||||||
out.clear();
|
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
|
// #![allow(unused)]
|
||||||
|
|
||||||
mod dev;
|
mod dev;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
core::fmt::Write as _,
|
|
||||||
derive_more::Display,
|
derive_more::Display,
|
||||||
dev::Package,
|
dev::Package,
|
||||||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||||
std::{
|
std::{
|
||||||
|
// fmt::Display,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
process::{exit, Command, Stdio},
|
process::{exit, Command},
|
||||||
},
|
},
|
||||||
toml::Value,
|
toml::Value,
|
||||||
};
|
};
|
||||||
|
@ -19,9 +21,6 @@ fn main() -> Result<(), Error> {
|
||||||
let mut args = std::env::args();
|
let mut args = std::env::args();
|
||||||
args.next();
|
args.next();
|
||||||
|
|
||||||
log::set_logger(&hblang::Logger).unwrap();
|
|
||||||
log::set_max_level(log::LevelFilter::Error);
|
|
||||||
|
|
||||||
match args.next().as_deref() {
|
match args.next().as_deref() {
|
||||||
Some("build" | "b") => {
|
Some("build" | "b") => {
|
||||||
let mut release = false;
|
let mut release = false;
|
||||||
|
@ -36,8 +35,6 @@ fn main() -> Result<(), Error> {
|
||||||
target = Target::Riscv64Virt;
|
target = Target::Riscv64Virt;
|
||||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||||
target = Target::Aarch64;
|
target = Target::Aarch64;
|
||||||
} else if arg == "avx2" {
|
|
||||||
target = Target::X86_64Avx2;
|
|
||||||
} else {
|
} else {
|
||||||
return Err(report!(Error::InvalidSubCom));
|
return Err(report!(Error::InvalidSubCom));
|
||||||
}
|
}
|
||||||
|
@ -49,7 +46,6 @@ fn main() -> Result<(), Error> {
|
||||||
let mut release = false;
|
let mut release = false;
|
||||||
let mut debuginfo = false;
|
let mut debuginfo = false;
|
||||||
let mut target = Target::X86_64;
|
let mut target = Target::X86_64;
|
||||||
let mut do_accel = true;
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if arg == "-r" || arg == "--release" {
|
if arg == "-r" || arg == "--release" {
|
||||||
release = true;
|
release = true;
|
||||||
|
@ -59,17 +55,13 @@ fn main() -> Result<(), Error> {
|
||||||
target = Target::Riscv64Virt;
|
target = Target::Riscv64Virt;
|
||||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||||
target = Target::Aarch64;
|
target = Target::Aarch64;
|
||||||
} else if arg == "--noaccel" {
|
|
||||||
do_accel = false;
|
|
||||||
} else if arg == "avx2" {
|
|
||||||
target = Target::X86_64Avx2;
|
|
||||||
} else {
|
} else {
|
||||||
return Err(report!(Error::InvalidSubCom));
|
return Err(report!(Error::InvalidSubCom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
build(release, target, debuginfo)?;
|
build(release, target, debuginfo)?;
|
||||||
run(release, target, do_accel)
|
run(release, target)
|
||||||
}
|
}
|
||||||
Some("help" | "h") => {
|
Some("help" | "h") => {
|
||||||
println!(concat!(
|
println!(concat!(
|
||||||
|
@ -79,10 +71,8 @@ fn main() -> Result<(), Error> {
|
||||||
" help (h): Print this message\n",
|
" help (h): Print this message\n",
|
||||||
" run (r): Build and run AbleOS in QEMU\n\n",
|
" run (r): Build and run AbleOS in QEMU\n\n",
|
||||||
"Options for build and run:\n",
|
"Options for build and run:\n",
|
||||||
" -r / --release: build in release mode\n",
|
" -r: build in release mode",
|
||||||
" -d / --debuginfo: build with debug info\n",
|
" [target]: sets target"
|
||||||
" --noaccel: run without acceleration (e.g, no kvm)\n",
|
|
||||||
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
|
|
||||||
),);
|
),);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -205,12 +195,7 @@ TERM_BACKDROP={}
|
||||||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||||
// let mut real_modules = modules.clone();
|
// let mut real_modules = modules.clone();
|
||||||
|
|
||||||
let mut errors = String::new();
|
modules.into_iter().for_each(|(_, value)| {
|
||||||
let mut out = Vec::new();
|
|
||||||
|
|
||||||
modules
|
|
||||||
.into_iter()
|
|
||||||
.map(|(_, value)| -> Result<(), io::Error> {
|
|
||||||
if value.is_table() {
|
if value.is_table() {
|
||||||
let path = get_path_without_boot_prefix(
|
let path = get_path_without_boot_prefix(
|
||||||
value.get("path").expect("You must have `path` as a value"),
|
value.get("path").expect("You must have `path` as a value"),
|
||||||
|
@ -222,26 +207,9 @@ TERM_BACKDROP={}
|
||||||
let p = Package::load_from_file(
|
let p = Package::load_from_file(
|
||||||
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
||||||
);
|
);
|
||||||
match p.build(&mut out) {
|
p.build();
|
||||||
Ok(()) => {}
|
|
||||||
Err(_) => {
|
|
||||||
writeln!(errors, "========= while compiling {} =========", path)
|
|
||||||
.unwrap();
|
|
||||||
errors.push_str(core::str::from_utf8(&out).expect("no"));
|
|
||||||
out.clear();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.for_each(drop);
|
|
||||||
|
|
||||||
if !errors.is_empty() {
|
|
||||||
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
|
|
||||||
std::eprint!("{errors}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
modules.into_iter().for_each(|(_key, value)| {
|
modules.into_iter().for_each(|(_key, value)| {
|
||||||
if value.is_table() {
|
if value.is_table() {
|
||||||
let path = value.get("path").expect("You must have `path` as a value");
|
let path = value.get("path").expect("You must have `path` as a value");
|
||||||
|
@ -328,9 +296,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
if target == Target::Aarch64 {
|
if target == Target::Aarch64 {
|
||||||
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
||||||
}
|
}
|
||||||
if target == Target::X86_64Avx2 {
|
|
||||||
com.args(["--target", "targets/x86_64_v3-ableos.json"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
match com.status() {
|
match com.status() {
|
||||||
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
||||||
|
@ -344,10 +309,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
path.push_str("_x86-64");
|
path.push_str("_x86-64");
|
||||||
"target/x86_64-ableos"
|
"target/x86_64-ableos"
|
||||||
}
|
}
|
||||||
Target::X86_64Avx2 => {
|
|
||||||
path.push_str("_x86-64");
|
|
||||||
"target/x86_64_v3-ableos"
|
|
||||||
}
|
|
||||||
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
||||||
Target::Aarch64 => {
|
Target::Aarch64 => {
|
||||||
path.push_str("_aarch64");
|
path.push_str("_aarch64");
|
||||||
|
@ -370,67 +331,25 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
.change_context(Error::Io)
|
.change_context(Error::Io)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||||
let target_str = match target {
|
let mut com = match target {
|
||||||
Target::X86_64 | Target::X86_64Avx2 => "qemu-system-x86_64",
|
Target::X86_64 => Command::new("qemu-system-x86_64"),
|
||||||
Target::Riscv64Virt => "qemu-system-riscv64",
|
Target::Riscv64Virt => Command::new("qemu-system-riscv64"),
|
||||||
Target::Aarch64 => "qemu-system-aarch64",
|
Target::Aarch64 => Command::new("qemu-system-aarch64"),
|
||||||
};
|
};
|
||||||
let (mut com, mut com2) = (Command::new(target_str), Command::new(target_str));
|
|
||||||
let ovmf_path = fetch_ovmf(target);
|
let ovmf_path = fetch_ovmf(target);
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
let accel = if do_accel {
|
|
||||||
let supported = String::from_utf8(
|
|
||||||
com2.args(["--accel", "help"])
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.unwrap()
|
|
||||||
.wait_with_output()
|
|
||||||
.unwrap()
|
|
||||||
.stdout,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let cpuid = raw_cpuid::CpuId::new();
|
|
||||||
let vmx = cpuid.get_feature_info().unwrap().has_vmx();
|
|
||||||
let svm = cpuid.get_svm_info().is_some();
|
|
||||||
|
|
||||||
if supported.contains("kvm") && (vmx || svm) {
|
|
||||||
"accel=kvm"
|
|
||||||
} else if cpuid
|
|
||||||
.get_processor_brand_string()
|
|
||||||
.filter(|a| a.as_str() == "GenuineIntel")
|
|
||||||
.is_some()
|
|
||||||
&& supported.contains("hax")
|
|
||||||
&& vmx
|
|
||||||
{
|
|
||||||
"accel=hax"
|
|
||||||
} else if supported.contains("whpx") {
|
|
||||||
"accel=whpx"
|
|
||||||
} else {
|
|
||||||
"accel=tcg"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"accel=tcg"
|
|
||||||
};
|
|
||||||
#[cfg(not(target_arch = "x86_64"))]
|
|
||||||
let accel = "accel=tcg";
|
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
Target::X86_64 | Target::X86_64Avx2 => {
|
Target::X86_64 => {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
com.args([
|
com.args([
|
||||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||||
"-drive", "file=target/disk.img,format=raw",
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
"-device", "vmware-svga",
|
// "-device", "vmware-svga",
|
||||||
// "-serial", "stdio",
|
|
||||||
"-m", "2G",
|
"-m", "2G",
|
||||||
"-smp", "1",
|
"-smp", "1",
|
||||||
"-parallel", "none",
|
// "-machine", "accel=kvm",
|
||||||
"-monitor", "none",
|
"-cpu", "Broadwell",
|
||||||
"-machine", accel,
|
|
||||||
"-cpu", "max",
|
|
||||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -475,7 +394,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
||||||
|
|
||||||
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||||
let (ovmf_url, ovmf_path) = match target {
|
let (ovmf_url, ovmf_path) = match target {
|
||||||
Target::X86_64 | Target::X86_64Avx2 => (
|
Target::X86_64 => (
|
||||||
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
|
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
|
||||||
"target/RELEASEX64_OVMF.fd",
|
"target/RELEASEX64_OVMF.fd",
|
||||||
),
|
),
|
||||||
|
@ -497,12 +416,12 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||||
Ok(_) => return Ok(ovmf_path.to_owned()),
|
Ok(_) => return Ok(ovmf_path.to_owned()),
|
||||||
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
||||||
};
|
};
|
||||||
let req = ureq::get(ovmf_url)
|
let mut bytes = reqwest::blocking::get(ovmf_url)
|
||||||
.call()
|
|
||||||
.map_err(Report::from)
|
.map_err(Report::from)
|
||||||
.change_context(OvmfFetchError::Fetch)?;
|
.change_context(OvmfFetchError::Fetch)?;
|
||||||
|
|
||||||
std::io::copy(&mut req.into_reader(), &mut file)
|
bytes
|
||||||
|
.copy_to(&mut file)
|
||||||
.map_err(Report::from)
|
.map_err(Report::from)
|
||||||
.change_context(OvmfFetchError::Io)?;
|
.change_context(OvmfFetchError::Io)?;
|
||||||
|
|
||||||
|
@ -524,7 +443,6 @@ impl Context for OvmfFetchError {}
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
enum Target {
|
enum Target {
|
||||||
X86_64,
|
X86_64,
|
||||||
X86_64Avx2,
|
|
||||||
Riscv64Virt,
|
Riscv64Virt,
|
||||||
Aarch64,
|
Aarch64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
# old toolchain
|
channel = "nightly-2024-07-27"
|
||||||
# channel = "nightly-2024-07-27"
|
|
||||||
channel = "nightly"
|
|
||||||
components = ["rust-src", "llvm-tools"]
|
components = ["rust-src", "llvm-tools"]
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 100 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,10 +0,0 @@
|
||||||
Tamsyn font is free. You are hereby granted permission to use, copy, modify,
|
|
||||||
and distribute it as you see fit.
|
|
||||||
|
|
||||||
Tamsyn font is provided "as is" without any express or implied warranty.
|
|
||||||
|
|
||||||
The author makes no representations about the suitability of this font for
|
|
||||||
a particular purpose.
|
|
||||||
|
|
||||||
In no event will the author be held liable for damages arising from the use
|
|
||||||
of this font.
|
|
Binary file not shown.
Before Width: | Height: | Size: 100 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 66 B |
1
sysdata/libraries/dt_api/README.md
Normal file
1
sysdata/libraries/dt_api/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# dt_api
|
8
sysdata/libraries/dt_api/src/lib.hb
Normal file
8
sysdata/libraries/dt_api/src/lib.hb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
stn := @use("../../stn/src/lib.hb");
|
||||||
|
.{string, memory, buffer} := stn
|
||||||
|
|
||||||
|
dt_get := fn(query: ^u8): int {
|
||||||
|
message_length := string.length(query)
|
||||||
|
|
||||||
|
return @eca(3, 5, query, message_length)
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
(horizontal
|
|
||||||
spacing : 10
|
|
||||||
(label "hi")
|
|
||||||
(label "goodbye"))
|
|
|
@ -1 +0,0 @@
|
||||||
(label "hello")
|
|
|
@ -1,3 +0,0 @@
|
||||||
(vertical
|
|
||||||
(label "hello")
|
|
||||||
(label "hello" color:red))
|
|
|
@ -1,49 +1,25 @@
|
||||||
stn := @use("../../stn/src/lib.hb");
|
stn := @use("../../stn/src/lib.hb");
|
||||||
.{string, memory, buffer, log} := stn
|
.{string, memory, buffer} := stn
|
||||||
|
|
||||||
render := @use("../../../libraries/render/src/lib.hb")
|
|
||||||
|
|
||||||
input := @use("../../intouch/src/lib.hb")
|
input := @use("../../intouch/src/lib.hb")
|
||||||
|
|
||||||
widgets := @use("widgets/widgets.hb")
|
|
||||||
ui := @use("ui.hb")
|
|
||||||
|
|
||||||
WindowID := struct {
|
WindowID := struct {
|
||||||
host_id: int,
|
host_id: int,
|
||||||
window_id: int,
|
window_id: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
VoidWindowID := WindowID.(0, 0)
|
create_window := fn(channel: int): void {
|
||||||
|
|
||||||
create_window := fn(channel: int): ^render.Surface {
|
|
||||||
// get the horizon buffer
|
// get the horizon buffer
|
||||||
// request a new window and provide the callback buffer
|
// request a new window and provide the callback buffer
|
||||||
// wait to recieve a message
|
// wait to recieve a message
|
||||||
|
|
||||||
windowing_system_buffer := buffer.search("XHorizon\0")
|
windowing_system_buffer := buffer.search("XHorizon\0")
|
||||||
mem_buf := memory.request_page(1)
|
|
||||||
|
|
||||||
if windowing_system_buffer == 0 {
|
if windowing_system_buffer == 0 {
|
||||||
return @as(^render.Surface, idk)
|
return
|
||||||
} else {
|
} else {
|
||||||
// ! bad able, stop using string messages :ragey:
|
msg := "\{01}\0"
|
||||||
// msg := "\{01}\0"
|
msg_length := 2
|
||||||
// msg_length := 2
|
return @eca(3, windowing_system_buffer, msg, msg_length)
|
||||||
|
|
||||||
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
|
|
||||||
|
|
||||||
x := 0
|
|
||||||
loop if x > 1000 break else x += 1
|
|
||||||
|
|
||||||
ret := buffer.recv([u8; 4096], windowing_system_buffer, mem_buf)
|
|
||||||
if ret == null {
|
|
||||||
log.info("No messages\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if *mem_buf == 0 {
|
|
||||||
log.info("No messages\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return @as(^render.Surface, idk)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
|
||||||
.{string, log} := stn;
|
|
||||||
.{Vec2} := stn.math
|
|
||||||
|
|
||||||
render := @use("../../../libraries/render/src/lib.hb");
|
|
||||||
.{Surface} := render;
|
|
||||||
.{Font} := render.text
|
|
||||||
|
|
||||||
UI := struct {raw: ^u8, raw_length: uint, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
|
|
||||||
// children: ^^u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
render_ui := fn(surface: Surface, ui: UI): void {
|
|
||||||
if ui.is_dirty {
|
|
||||||
render.clear(ui.surface, render.black)
|
|
||||||
ui.is_dirty = false
|
|
||||||
}
|
|
||||||
pos := Vec2(uint).(0, 0)
|
|
||||||
render.put_surface(surface, ui.surface, pos, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
sexpr_parser := fn(sexpr: ^u8): UI {
|
|
||||||
cursor := sexpr
|
|
||||||
paren_balance := 0
|
|
||||||
loop {
|
|
||||||
if *cursor == 0 {
|
|
||||||
if paren_balance != 0 {
|
|
||||||
log.error("Unbalanced Parens\0")
|
|
||||||
}
|
|
||||||
break
|
|
||||||
} else if *cursor == 40 {
|
|
||||||
log.info("Open paren\0")
|
|
||||||
paren_balance += 1
|
|
||||||
} else if *cursor == 41 {
|
|
||||||
log.info("Closed paren\0")
|
|
||||||
paren_balance -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
length := string.length(sexpr)
|
|
||||||
|
|
||||||
ui_surface := render.new_surface(100, 100)
|
|
||||||
|
|
||||||
return UI.(sexpr, length, true, ui_surface)
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
render := @use("../../../../libraries/render/src/lib.hb");
|
|
||||||
.{Surface} := render
|
|
||||||
|
|
||||||
Image := struct {
|
|
||||||
magic: uint,
|
|
||||||
is_dirty: bool,
|
|
||||||
surface: Surface,
|
|
||||||
}
|
|
||||||
|
|
||||||
image_from_surface := fn(surface: Surface): Image {
|
|
||||||
img := Image.(4, true, surface)
|
|
||||||
return img
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
stn := @use("../../../../libraries/stn/src/lib.hb");
|
|
||||||
.{string, log} := stn;
|
|
||||||
.{Vec2} := stn.math
|
|
||||||
|
|
||||||
render := @use("../../../../libraries/render/src/lib.hb");
|
|
||||||
.{Surface, Color} := render;
|
|
||||||
.{Font} := render.text
|
|
||||||
|
|
||||||
Label := struct {
|
|
||||||
magic: uint,
|
|
||||||
is_dirty: bool,
|
|
||||||
surface: Surface,
|
|
||||||
text: ^u8,
|
|
||||||
text_length: uint,
|
|
||||||
bg: Color,
|
|
||||||
fg: Color,
|
|
||||||
}
|
|
||||||
|
|
||||||
set_label_text := fn(label: Label, text: ^u8): void {
|
|
||||||
text_length := string.length(text)
|
|
||||||
|
|
||||||
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 {
|
|
||||||
render.clear(label.surface, label.bg)
|
|
||||||
render.put_text(label.surface, font, .(0, 0), label.fg, label.text)
|
|
||||||
}
|
|
||||||
render.put_surface(surface, label.surface, pos, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
NoWidget := 0
|
|
||||||
|
|
||||||
VerticalWidgetType := 1
|
|
||||||
HorizontalWidgetType := 2
|
|
||||||
|
|
||||||
LabelWidgetType := 3
|
|
||||||
ImageWidgetType := 4
|
|
|
@ -1,36 +0,0 @@
|
||||||
// Widget types
|
|
||||||
|
|
||||||
// End types
|
|
||||||
stn := @use("../../../../libraries/stn/src/lib.hb");
|
|
||||||
.{string, log} := stn;
|
|
||||||
.{Vec2} := stn.math
|
|
||||||
|
|
||||||
render := @use("../../../../libraries/render/src/lib.hb");
|
|
||||||
.{Surface} := render;
|
|
||||||
.{Font} := render.text
|
|
||||||
|
|
||||||
widget_types := @use("widget_types.hb")
|
|
||||||
label := @use("label.hb")
|
|
||||||
image := @use("image.hb")
|
|
||||||
|
|
||||||
Size := struct {
|
|
||||||
min_width: int,
|
|
||||||
max_width: int,
|
|
||||||
min_height: int,
|
|
||||||
max_height: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
Vertical := packed struct {
|
|
||||||
magic: uint,
|
|
||||||
// array of children, idk
|
|
||||||
// use a vec or linked list or whatever
|
|
||||||
|
|
||||||
children: ^^u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
Horizontal := packed struct {
|
|
||||||
magic: uint,
|
|
||||||
// array of children, idk
|
|
||||||
// use a vec or linked list or whatever
|
|
||||||
children: ^^u8,
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ ApplicationInfo := struct {
|
||||||
pNext: ^int,
|
pNext: ^int,
|
||||||
application_name: ^u8,
|
application_name: ^u8,
|
||||||
application_version: int,
|
application_version: int,
|
||||||
engine_name: ^u8,
|
engine_name: int,
|
||||||
engine_version: int,
|
engine_version: int,
|
||||||
api_version: int,
|
api_version: int,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
keycodes := @use("keycodes.hb");
|
|
||||||
.{KeyCode} := keycodes
|
|
||||||
|
|
||||||
KeyEvent := packed struct {
|
|
||||||
up: bool,
|
|
||||||
just_triggered: bool,
|
|
||||||
key: KeyCode,
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseEvent := packed struct {
|
|
||||||
x_change: i8,
|
|
||||||
y_change: i8,
|
|
||||||
left: bool,
|
|
||||||
middle: bool,
|
|
||||||
right: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
GamepadEvent := struct {}
|
|
|
@ -1,121 +1,67 @@
|
||||||
/*
|
|
||||||
Originally I was modelling this after the following(1). I have since changed my mind.
|
|
||||||
I am now modelling it as I see fit. This is likely not the final version.
|
|
||||||
|
|
||||||
1) https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
KeyCode := u32
|
KeyCode := u32
|
||||||
|
|
||||||
// Typically this is not a keycode you will ever recieve.
|
// https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
||||||
None := KeyCode.(0)
|
Backspace := KeyCode.(8)
|
||||||
|
Tab := KeyCode.(9)
|
||||||
|
Clear := KeyCode.(12)
|
||||||
|
Return := KeyCode.(13)
|
||||||
|
Pause := KeyCode.(19)
|
||||||
|
Escape := KeyCode.(27)
|
||||||
|
Space := KeyCode.(32)
|
||||||
|
|
||||||
Escape := KeyCode.(1)
|
A := KeyCode.(97)
|
||||||
/* Alphabet keycodes */
|
/*
|
||||||
|
ETC
|
||||||
|
*/
|
||||||
|
Z := KeyCode.(122)
|
||||||
|
|
||||||
A := KeyCode.(2)
|
Delete := KeyCode.(127)
|
||||||
B := KeyCode.(3)
|
|
||||||
C := KeyCode.(4)
|
|
||||||
D := KeyCode.(5)
|
|
||||||
E := KeyCode.(6)
|
|
||||||
F := KeyCode.(7)
|
|
||||||
G := KeyCode.(8)
|
|
||||||
H := KeyCode.(9)
|
|
||||||
I := KeyCode.(10)
|
|
||||||
J := KeyCode.(11)
|
|
||||||
K := KeyCode.(12)
|
|
||||||
L := KeyCode.(13)
|
|
||||||
M := KeyCode.(14)
|
|
||||||
N := KeyCode.(15)
|
|
||||||
O := KeyCode.(16)
|
|
||||||
P := KeyCode.(17)
|
|
||||||
Q := KeyCode.(18)
|
|
||||||
R := KeyCode.(19)
|
|
||||||
S := KeyCode.(20)
|
|
||||||
T := KeyCode.(21)
|
|
||||||
U := KeyCode.(22)
|
|
||||||
V := KeyCode.(23)
|
|
||||||
W := KeyCode.(24)
|
|
||||||
X := KeyCode.(25)
|
|
||||||
Y := KeyCode.(26)
|
|
||||||
Z := KeyCode.(27)
|
|
||||||
|
|
||||||
/* Numeric keycodes*/
|
|
||||||
|
|
||||||
Number0 := KeyCode.(28)
|
|
||||||
Number1 := KeyCode.(29)
|
|
||||||
Number2 := KeyCode.(30)
|
|
||||||
Number3 := KeyCode.(31)
|
|
||||||
Number4 := KeyCode.(32)
|
|
||||||
Number5 := KeyCode.(33)
|
|
||||||
Number6 := KeyCode.(34)
|
|
||||||
Number7 := KeyCode.(35)
|
|
||||||
Number8 := KeyCode.(36)
|
|
||||||
Number9 := KeyCode.(37)
|
|
||||||
|
|
||||||
KeypadNumber0 := KeyCode.(38)
|
|
||||||
KeypadNumber1 := KeyCode.(39)
|
|
||||||
KeypadNumber2 := KeyCode.(40)
|
|
||||||
KeypadNumber3 := KeyCode.(41)
|
|
||||||
KeypadNumber4 := KeyCode.(42)
|
|
||||||
KeypadNumber5 := KeyCode.(43)
|
|
||||||
KeypadNumber6 := KeyCode.(44)
|
|
||||||
KeypadNumber7 := KeyCode.(45)
|
|
||||||
KeypadNumber8 := KeyCode.(46)
|
|
||||||
KeypadNumber9 := KeyCode.(47)
|
|
||||||
|
|
||||||
KeypadPeriod := KeyCode.(48)
|
|
||||||
KeypadDivide := KeyCode.(49)
|
|
||||||
KeypadMultiply := KeyCode.(50)
|
|
||||||
KeypadMinus := KeyCode.(51)
|
|
||||||
KeypadPlus := KeyCode.(52)
|
|
||||||
KeypadEnter := KeyCode.(53)
|
|
||||||
KeypadEquals := KeyCode.(54)
|
|
||||||
|
|
||||||
Delete := KeyCode.(55)
|
|
||||||
/* Locking Keys */
|
|
||||||
NumLock := KeyCode.(56)
|
|
||||||
CapsLock := KeyCode.(57)
|
|
||||||
ScrollLock := KeyCode.(58)
|
|
||||||
|
|
||||||
/* "Alt Gr" key */
|
|
||||||
Mode := KeyCode.(59)
|
|
||||||
|
|
||||||
/* Multi-key compose key */
|
|
||||||
Compose := KeyCode.(60)
|
|
||||||
|
|
||||||
LeftAlt := KeyCode.(61)
|
|
||||||
LeftControl := KeyCode.(62)
|
|
||||||
LeftMeta := KeyCode.(63)
|
|
||||||
LeftShift := KeyCode.(64)
|
|
||||||
/* Left "Windows" key */
|
|
||||||
LeftSuper := KeyCode.(65)
|
|
||||||
|
|
||||||
RightAlt := KeyCode.(66)
|
|
||||||
RightControl := KeyCode.(67)
|
|
||||||
RightMeta := KeyCode.(68)
|
|
||||||
RightShift := KeyCode.(69)
|
|
||||||
/* Right "Windows" key */
|
|
||||||
RightSuper := KeyCode.(70)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This block of any triggers on any press of any of the keys.
|
ETC
|
||||||
Typically this is the event to care about.
|
|
||||||
*/
|
*/
|
||||||
AnyNumber0 := KeyCode.(71)
|
|
||||||
AnyNumber1 := KeyCode.(72)
|
|
||||||
AnyNumber2 := KeyCode.(73)
|
|
||||||
AnyNumber3 := KeyCode.(74)
|
|
||||||
AnyNumber4 := KeyCode.(75)
|
|
||||||
AnyNumber5 := KeyCode.(76)
|
|
||||||
AnyNumber6 := KeyCode.(77)
|
|
||||||
AnyNumber7 := KeyCode.(78)
|
|
||||||
AnyNumber8 := KeyCode.(79)
|
|
||||||
AnyNumber9 := KeyCode.(80)
|
|
||||||
|
|
||||||
AnyAlt := KeyCode.(81)
|
KeypadNumber0 := KeyCode.(256)
|
||||||
AnyControl := KeyCode.(82)
|
KeypadNumber1 := KeyCode.(257)
|
||||||
AnyMeta := KeyCode.(83)
|
KeypadNumber2 := KeyCode.(258)
|
||||||
AnyShift := KeyCode.(84)
|
KeypadNumber3 := KeyCode.(259)
|
||||||
/* Any "Windows" key */
|
KeypadNumber4 := KeyCode.(260)
|
||||||
AnySuper := KeyCode.(85)
|
KeypadNumber5 := KeyCode.(261)
|
||||||
|
KeypadNumber6 := KeyCode.(262)
|
||||||
|
KeypadNumber7 := KeyCode.(263)
|
||||||
|
KeypadNumber8 := KeyCode.(264)
|
||||||
|
KeypadNumber9 := KeyCode.(265)
|
||||||
|
|
||||||
|
KeypadPeriod := KeyCode.(266)
|
||||||
|
KeypadDivide := KeyCode.(267)
|
||||||
|
KeypadMultiply := KeyCode.(268)
|
||||||
|
KeypadMinus := KeyCode.(269)
|
||||||
|
KeypadPlus := KeyCode.(270)
|
||||||
|
KeypadEnter := KeyCode.(271)
|
||||||
|
KeypadEquals := KeyCode.(272)
|
||||||
|
|
||||||
|
NumLock := KeyCode.(300)
|
||||||
|
CapsLock := KeyCode.(301)
|
||||||
|
ScrollLock := KeyCode.(302)
|
||||||
|
|
||||||
|
RightShift := KeyCode.(303)
|
||||||
|
LeftShift := KeyCode.(304)
|
||||||
|
|
||||||
|
RightControl := KeyCode.(305)
|
||||||
|
LeftControl := KeyCode.(306)
|
||||||
|
RightAlt := KeyCode.(307)
|
||||||
|
LeftAlt := KeyCode.(308)
|
||||||
|
RightMeta := KeyCode.(309)
|
||||||
|
LeftMeta := KeyCode.(310)
|
||||||
|
|
||||||
|
/* Left "Windows" key */
|
||||||
|
LeftSuper := KeyCode.(311)
|
||||||
|
|
||||||
|
/* Right "Windows" key */
|
||||||
|
RightSuper := KeyCode.(312)
|
||||||
|
|
||||||
|
/* "Alt Gr" key */
|
||||||
|
Mode := KeyCode.(313)
|
||||||
|
|
||||||
|
/* Multi-key compose key */
|
||||||
|
Compose := KeyCode.(314)
|
||||||
|
|
|
@ -1,36 +1,22 @@
|
||||||
stn := @use("../../stn/src/lib.hb");
|
keycodes := @use("keycodes.hb");
|
||||||
.{log, buffer, memory} := stn
|
.{KeyCode} := keycodes
|
||||||
keycodes := @use("keycodes.hb")
|
|
||||||
|
|
||||||
events := @use("events.hb");
|
MouseEvent := struct {
|
||||||
.{KeyEvent, MouseEvent} := events
|
x_change: u8,
|
||||||
|
y_change: u8,
|
||||||
recieve_key_event := fn(): ?KeyEvent {
|
left: u8,
|
||||||
kevent := KeyEvent.(false, false, 0)
|
middle: u8,
|
||||||
|
right: u8,
|
||||||
buf_id := buffer.search("PS/2 Keyboard\0")
|
|
||||||
|
|
||||||
// Read out of the Keyboard buffer here
|
|
||||||
buffer.recv(KeyEvent, buf_id, &kevent)
|
|
||||||
|
|
||||||
if kevent.just_triggered {
|
|
||||||
return kevent
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recieve_mouse_event := fn(): ?MouseEvent {
|
KeyEvent := struct {
|
||||||
mevent := MouseEvent.(0, 0, false, false, false)
|
// 0 if down
|
||||||
|
// 1 if up
|
||||||
buf_id := buffer.search("PS/2 Mouse\0")
|
up: u8,
|
||||||
|
// 0 if not just triggered
|
||||||
// Read out of the Mouse buffer here
|
// 1 if just triggered
|
||||||
buffer.recv(MouseEvent, buf_id, &mevent)
|
just_triggered: u8,
|
||||||
|
key: KeyCode,
|
||||||
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
|
|
||||||
return mevent
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GamepadEvent := struct {}
|
|
@ -1,27 +0,0 @@
|
||||||
# Images
|
|
||||||
- Animation
|
|
||||||
|
|
||||||
# API
|
|
||||||
- Colour operations:
|
|
||||||
- Alpha Composite
|
|
||||||
- Invert
|
|
||||||
- Surface Operations:
|
|
||||||
- FlipH
|
|
||||||
- Resize
|
|
||||||
- Wrap the colour operations
|
|
||||||
- Tile
|
|
||||||
- Gradient overlay
|
|
||||||
- Draw operations:
|
|
||||||
- Curve raster algorithm
|
|
||||||
- VGA font fast blit
|
|
||||||
- Polygon
|
|
||||||
- Rounded rects
|
|
||||||
|
|
||||||
# Backend
|
|
||||||
- SVGA Driver
|
|
||||||
- Support whatever vulkan stuff able is cooking
|
|
||||||
|
|
||||||
# Bits and bobs on the table
|
|
||||||
- Funny 3D Renderer
|
|
||||||
- stn.memory.swap & kernel message
|
|
||||||
- Make memory.{copy, set} smart
|
|
|
@ -1,49 +0,0 @@
|
||||||
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
|
|
||||||
.{log} := @use("../../../stn/src/lib.hb")
|
|
||||||
|
|
||||||
BitmapFileHeader := packed struct {
|
|
||||||
magic: u16,
|
|
||||||
size: u32,
|
|
||||||
reserved_1: u16,
|
|
||||||
reserved_2: u16,
|
|
||||||
offset: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
BitmapInfoHeader := packed struct {
|
|
||||||
size: u32,
|
|
||||||
width: i32,
|
|
||||||
height: i32,
|
|
||||||
planes: u16,
|
|
||||||
bits: u16,
|
|
||||||
compression: u32,
|
|
||||||
image_size: u32,
|
|
||||||
x_resolution: i32,
|
|
||||||
y_resolution: i32,
|
|
||||||
n_colours: u32,
|
|
||||||
important_colours: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
BitmapColorHeader := packed struct {
|
|
||||||
red_mask: u32,
|
|
||||||
green_mask: u32,
|
|
||||||
blue_mask: u32,
|
|
||||||
alpha_mask: u32,
|
|
||||||
color_space_type: u32,
|
|
||||||
unused: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
from := fn(bmp: ^u8): ?Surface {
|
|
||||||
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
|
||||||
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
|
|
||||||
|
|
||||||
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
|
|
||||||
log.error("Invalid BMP image.\0")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
|
|
||||||
rhs := new_surface(info_header.width, info_header.height)
|
|
||||||
put_surface(rhs, lhs, .(0, 0), true)
|
|
||||||
|
|
||||||
return rhs
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
.{log} := @use("../../../stn/src/lib.hb");
|
|
||||||
.{Surface} := @use("../lib.hb")
|
|
||||||
bmp := @use("bmp.hb")
|
|
||||||
qoi := @use("qoi.hb")
|
|
||||||
$BMP := 0x4D42
|
|
||||||
$QOI := 0x66696F71
|
|
||||||
|
|
||||||
get_format := fn(file: ^u8): ?uint {
|
|
||||||
if *@as(^u16, @bitcast(file)) == BMP {
|
|
||||||
return BMP
|
|
||||||
} else if *@as(^u32, @bitcast(file)) == QOI {
|
|
||||||
return QOI
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
from := fn(file: ^u8): ?Surface {
|
|
||||||
format := get_format(file)
|
|
||||||
|
|
||||||
if format == null {
|
|
||||||
log.error("Could not detect image format.\0")
|
|
||||||
return null
|
|
||||||
} else if format == BMP {
|
|
||||||
return bmp.from(file)
|
|
||||||
} else if format == QOI {
|
|
||||||
return qoi.from(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
.{Color, Surface, new_surface} := @use("../lib.hb");
|
|
||||||
.{log} := @use("../../../stn/src/lib.hb")
|
|
||||||
|
|
||||||
/* source:
|
|
||||||
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
|
||||||
|
|
||||||
$QOI_SRGB := 0
|
|
||||||
$QOI_LINEAR := 1
|
|
||||||
$QOI_OP_INDEX := 0x0
|
|
||||||
$QOI_OP_DIFF := 0x40
|
|
||||||
$QOI_OP_LUMA := 0x80
|
|
||||||
$QOI_OP_RUN := 0xC0
|
|
||||||
$QOI_OP_RGB := 0xFE
|
|
||||||
$QOI_OP_RGBA := 0xFF
|
|
||||||
$QOI_MASK_2 := 0xC0
|
|
||||||
$QOI_COLOR_HASH := fn(c: Color): u8 {
|
|
||||||
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
|
|
||||||
}
|
|
||||||
$QOI_MAGIC := 0x716F6966
|
|
||||||
$QOI_PIXELS_MAX := 400000000
|
|
||||||
|
|
||||||
QuiteOkayHeader := packed struct {
|
|
||||||
magic: u32,
|
|
||||||
width: u32,
|
|
||||||
height: u32,
|
|
||||||
channels: u8,
|
|
||||||
colorspace: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
be_to_le := fn(big: u32): u32 {
|
|
||||||
return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24
|
|
||||||
}
|
|
||||||
|
|
||||||
from := fn(qoi: ^u8): ?Surface {
|
|
||||||
header := @as(^QuiteOkayHeader, @bitcast(qoi))
|
|
||||||
|
|
||||||
qoi += @sizeof(QuiteOkayHeader)
|
|
||||||
|
|
||||||
width := be_to_le(header.width)
|
|
||||||
height := be_to_le(header.height)
|
|
||||||
|
|
||||||
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
|
|
||||||
log.error("Invalid QOI image.\0")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
surface := new_surface(width, height)
|
|
||||||
index := @as([Color; 64], idk)
|
|
||||||
|
|
||||||
run := 0
|
|
||||||
px := Color.(0, 0, 0, 255)
|
|
||||||
px_pos := 0
|
|
||||||
|
|
||||||
total_pixels := width * height
|
|
||||||
|
|
||||||
loop if px_pos >= total_pixels break else {
|
|
||||||
if run > 0 {
|
|
||||||
run -= 1
|
|
||||||
} else {
|
|
||||||
b1 := *qoi
|
|
||||||
qoi += 1
|
|
||||||
|
|
||||||
if b1 == QOI_OP_RGB {
|
|
||||||
px.r = *qoi
|
|
||||||
px.g = *(qoi + 1)
|
|
||||||
px.b = *(qoi + 2)
|
|
||||||
qoi += 3
|
|
||||||
} else if b1 == QOI_OP_RGBA {
|
|
||||||
px.r = *qoi
|
|
||||||
px.g = *(qoi + 1)
|
|
||||||
px.b = *(qoi + 2)
|
|
||||||
px.a = *(qoi + 3)
|
|
||||||
qoi += 4
|
|
||||||
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
|
|
||||||
px = index[b1 & 0x3F]
|
|
||||||
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
|
|
||||||
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
|
|
||||||
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
|
|
||||||
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
|
|
||||||
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
|
|
||||||
b2 := *qoi
|
|
||||||
vg := (b1 & 0x3F) - 32
|
|
||||||
|
|
||||||
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
|
|
||||||
px.g = px.g + vg & 0xFF
|
|
||||||
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
|
|
||||||
qoi += 1
|
|
||||||
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
|
|
||||||
run = b1 & 0x3F
|
|
||||||
}
|
|
||||||
|
|
||||||
index[QOI_COLOR_HASH(px)] = px
|
|
||||||
};
|
|
||||||
|
|
||||||
*(surface.buf + px_pos) = px
|
|
||||||
|
|
||||||
px_pos += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface
|
|
||||||
}
|
|
|
@ -1,57 +1,47 @@
|
||||||
|
svga := @use("svga.hb")
|
||||||
software := @use("software.hb")
|
software := @use("software.hb")
|
||||||
image := @use("image/lib.hb")
|
|
||||||
text := @use("text.hb")
|
|
||||||
|
|
||||||
// default mode
|
// default mode
|
||||||
mode := software
|
mode := software
|
||||||
|
|
||||||
init := mode.init
|
init := mode.init
|
||||||
doublebuffer := mode.doublebuffer
|
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
|
// Colours
|
||||||
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
|
Color := mode.Color
|
||||||
$white := Color.(255, 255, 255, 255)
|
white := mode.white
|
||||||
$black := Color.(0, 0, 0, 255)
|
black := mode.black
|
||||||
$gray := Color.(127, 127, 127, 255)
|
gray := mode.gray
|
||||||
$red := Color.(0, 0, 205, 255)
|
red := mode.red
|
||||||
$green := Color.(0, 205, 0, 255)
|
green := mode.green
|
||||||
$yellow := Color.(0, 205, 205, 255)
|
yellow := mode.yellow
|
||||||
$blue := Color.(205, 0, 0, 255)
|
blue := mode.blue
|
||||||
$magenta := Color.(205, 0, 205, 255)
|
magenta := mode.magenta
|
||||||
$cyan := Color.(205, 205, 0, 255)
|
cyan := mode.cyan
|
||||||
$light_gray := Color.(229, 229, 229, 255)
|
light_gray := mode.light_gray
|
||||||
$light_red := Color.(0, 0, 255, 255)
|
light_red := mode.light_red
|
||||||
$light_green := Color.(0, 255, 0, 255)
|
light_green := mode.light_green
|
||||||
$light_yellow := Color.(0, 255, 255, 255)
|
light_yellow := mode.light_yellow
|
||||||
$light_blue := Color.(255, 0, 0, 255)
|
light_blue := mode.light_blue
|
||||||
$light_magenta := Color.(255, 0, 255, 255)
|
light_magenta := mode.light_magenta
|
||||||
$light_cyan := Color.(255, 255, 0, 255)
|
light_cyan := mode.light_cyan
|
||||||
|
|
||||||
// Drawing
|
// Drawing
|
||||||
put_pixel := mode.put_pixel
|
put_pixel := mode.put_pixel
|
||||||
put_rect := mode.put_rect
|
put_rect := mode.put_rect
|
||||||
put_filled_rect := mode.put_filled_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_line := mode.put_line
|
||||||
put_vline := mode.put_vline
|
|
||||||
put_hline := mode.put_hline
|
|
||||||
clear := mode.clear
|
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
|
// Display
|
||||||
|
width := mode.width
|
||||||
|
height := mode.height
|
||||||
|
dimensions := mode.dimensions
|
||||||
|
set_height := mode.set_height
|
||||||
|
set_width := mode.set_width
|
||||||
|
set_dimensions := mode.set_dimensions
|
||||||
sync := mode.sync
|
sync := mode.sync
|
||||||
|
|
||||||
|
// Math
|
||||||
|
UVec2 := struct {x: uint, y: uint}
|
||||||
|
IVec2 := struct {x: int, y: int}
|
|
@ -1,116 +1,197 @@
|
||||||
.{math, memory, dt} := @use("../../stn/src/lib.hb");
|
.{math, memory} := @use("../../stn/src/lib.hb");
|
||||||
.{Color, text} := @use("lib.hb");
|
.{dt_get} := @use("../../dt_api/src/lib.hb");
|
||||||
.{get_glyph, get_glyph_unicode, Font, UNC_TABLE_SIZE} := text;
|
.{IVec2} := @use("lib.hb")
|
||||||
.{Vec2} := math
|
|
||||||
|
|
||||||
// safety: don't use before init() or you will get a memory access violation
|
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
||||||
framebuffer := memory.dangling(Color)
|
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)
|
||||||
|
|
||||||
Surface := struct {
|
// might not work for some resolutions, but needs to be comptime because...
|
||||||
|
copy_pixels := 0xC000 >> 2
|
||||||
|
|
||||||
|
ctx := @as(Context, idk)
|
||||||
|
|
||||||
|
// some of these are redudant holdovers from fb_driver
|
||||||
|
// will keep them for future work if necessary
|
||||||
|
Context := struct {
|
||||||
|
fb: ^Color,
|
||||||
|
bb: ^Color,
|
||||||
buf: ^Color,
|
buf: ^Color,
|
||||||
width: uint,
|
width: int,
|
||||||
height: uint,
|
height: int,
|
||||||
size: uint,
|
partitions: int,
|
||||||
|
pixels: int,
|
||||||
|
bb_pages: int,
|
||||||
|
double_buffer: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_surface := fn(width: uint, height: uint): Surface {
|
init := fn(): void {
|
||||||
return .(
|
width := dt_get("framebuffer/fb0/width\0")
|
||||||
memory.alloc(Color, width * height),
|
height := dt_get("framebuffer/fb0/height\0")
|
||||||
|
// width := 1024
|
||||||
|
// height := 768
|
||||||
|
pixels := width * height
|
||||||
|
bytes := pixels << 2
|
||||||
|
partitions := pixels / copy_pixels
|
||||||
|
pages := 1 + bytes >> 12
|
||||||
|
back_buffer := create_back_buffer(pages)
|
||||||
|
ctx = Context.{
|
||||||
|
fb: dt_get("framebuffer/fb0/ptr\0"),
|
||||||
|
bb: back_buffer,
|
||||||
|
buf: back_buffer,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
width * height,
|
partitions,
|
||||||
)
|
pixels,
|
||||||
|
bb_pages: pages,
|
||||||
|
double_buffer: true,
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
clone_surface := fn(surface: ^Surface): Surface {
|
doublebuffer := fn(enable: bool): void {
|
||||||
new := new_surface(surface.width, surface.height)
|
if enable {
|
||||||
memory.copy(Color, surface.buf, new.buf, @intcast(surface.size))
|
ctx.buf = ctx.bb
|
||||||
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 {
|
} else {
|
||||||
return .(framebuffer, width, height, width * height)
|
ctx.buf = ctx.fb
|
||||||
}
|
}
|
||||||
}
|
ctx.double_buffer = enable
|
||||||
|
|
||||||
$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
|
|
||||||
}
|
|
||||||
|
|
||||||
if rows_to_fill == 1 {
|
|
||||||
memory.set(Color, &color, top_start_idx, tr.x)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
create_back_buffer := fn(pages: int): ^Color {
|
||||||
start_idx := indexptr(surface, pos.x, pos.y)
|
if pages <= 0xFF {
|
||||||
end_idx := indexptr(surface, pos.x, pos.y + tr.y)
|
return @bitcast(@inline(memory.request_page, pages))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
ptr := @inline(memory.request_page, 255)
|
||||||
|
remaining := pages - 0xFF
|
||||||
|
loop if remaining <= 0 break else {
|
||||||
|
if remaining < 0xFF {
|
||||||
|
memory.request_page(remaining)
|
||||||
|
} else {
|
||||||
|
memory.request_page(0xFF)
|
||||||
|
}
|
||||||
|
remaining -= 0xFF
|
||||||
|
}
|
||||||
|
return @bitcast(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
memory.set(Color, &color, indexptr(surface, pos.x, pos.y), @bitcast(tr.x + 1))
|
clear := fn(color: Color): void {
|
||||||
memory.set(Color, &color, indexptr(surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
|
cursor := ctx.buf
|
||||||
|
boundary := cursor + 512
|
||||||
|
loop if cursor == boundary break else {
|
||||||
|
*cursor = color
|
||||||
|
cursor += 1
|
||||||
|
}
|
||||||
|
boundary += 512 * 7
|
||||||
|
loop if cursor == boundary break else {
|
||||||
|
*@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(ctx.buf))
|
||||||
|
cursor += 512
|
||||||
|
}
|
||||||
|
boundary += copy_pixels - 4096
|
||||||
|
loop if cursor == boundary break else {
|
||||||
|
*@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(ctx.buf))
|
||||||
|
cursor += 4096
|
||||||
|
}
|
||||||
|
boundary += (ctx.partitions - 1) * copy_pixels
|
||||||
|
loop if cursor == boundary break else {
|
||||||
|
*@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(ctx.buf))
|
||||||
|
cursor += @sizeof([u8; copy_pixels])
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
sync := fn(): void {
|
||||||
dx := @as(int, @bitcast(p1.x - p0.x))
|
if ctx.double_buffer {
|
||||||
dy := @as(int, @bitcast(p1.y - p0.y))
|
bb := ctx.buf
|
||||||
|
fb := ctx.fb
|
||||||
|
boundary := bb + ctx.pixels
|
||||||
|
loop if bb == boundary break else {
|
||||||
|
*@as(^[Color; copy_pixels], @bitcast(fb)) = *@as(^[Color; copy_pixels], @bitcast(bb))
|
||||||
|
bb += copy_pixels
|
||||||
|
fb += copy_pixels
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
width := fn(): int {
|
||||||
|
return ctx.width
|
||||||
|
}
|
||||||
|
|
||||||
|
height := fn(): int {
|
||||||
|
return ctx.height
|
||||||
|
}
|
||||||
|
|
||||||
|
screenidx := fn(x: int, y: int): int {
|
||||||
|
return x + ctx.width * y
|
||||||
|
}
|
||||||
|
|
||||||
|
put_pixel := fn(pos: IVec2, color: Color): void {
|
||||||
|
*(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||||
|
x := pos.x
|
||||||
|
y := pos.y
|
||||||
|
end := pos + tr
|
||||||
|
loop if x == end.x break else {
|
||||||
|
loop if y == end.y break else {
|
||||||
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
x += 1
|
||||||
|
y = pos.y
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||||
|
x := pos.x
|
||||||
|
y := pos.y
|
||||||
|
end := pos + tr
|
||||||
|
loop if y == end.y break else {
|
||||||
|
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
||||||
|
*(ctx.buf + @inline(screenidx, x + tr.x, y)) = color
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
y = pos.y
|
||||||
|
loop if x == end.x break else {
|
||||||
|
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
||||||
|
*(ctx.buf + @inline(screenidx, x, y + tr.y)) = color
|
||||||
|
x += 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
|
dx := p1.x - p0.x
|
||||||
|
dy := p1.y - p0.y
|
||||||
yi := 1
|
yi := 1
|
||||||
if dy < 0 {
|
if dy < 0 {
|
||||||
yi = -1
|
yi = -1
|
||||||
dy = -dy
|
dy = -dy
|
||||||
}
|
}
|
||||||
D := @as(int, 2) * dy - dx
|
D := 2 * dy - dx
|
||||||
y := p0.y
|
y := p0.y
|
||||||
x := p0.x
|
x := p0.x
|
||||||
loop if x == p1.x break else {
|
loop if x == p1.x break else {
|
||||||
*indexptr(surface, x, y) = color
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
y += yi
|
y += yi
|
||||||
D += 2 * (dy - dx)
|
D += 2 * (dy - dx)
|
||||||
|
@ -122,19 +203,19 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
dx := @as(int, @bitcast(p1.x - p0.x))
|
dx := p1.x - p0.x
|
||||||
dy := @as(int, @bitcast(p1.y - p0.y))
|
dy := p1.y - p0.y
|
||||||
xi := 1
|
xi := 1
|
||||||
if dy < 0 {
|
if dy < 0 {
|
||||||
xi = -1
|
xi = -1
|
||||||
dx = -dx
|
dx = -dx
|
||||||
}
|
}
|
||||||
D := @as(int, 2) * dx - dy
|
D := 2 * dx - dy
|
||||||
x := p0.x
|
x := p0.x
|
||||||
y := p0.y
|
y := p0.y
|
||||||
loop if y == p1.y break else {
|
loop if y == p1.y break else {
|
||||||
*indexptr(surface, x, y) = color
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
x += xi
|
x += xi
|
||||||
D += 2 * (dx - dy)
|
D += 2 * (dx - dy)
|
||||||
|
@ -146,327 +227,35 @@ put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Col
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
if math.abs(uint, p1.y - p0.y) < math.abs(uint, p1.x - p0.x) {
|
if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) {
|
||||||
if p0.x > p1.x {
|
if p0.x > p1.x {
|
||||||
@inline(put_line_low, surface, p1, p0, color)
|
@inline(put_line_low, p1, p0, color)
|
||||||
} else {
|
} else {
|
||||||
@inline(put_line_low, surface, p0, p1, color)
|
@inline(put_line_low, p0, p1, color)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if p0.y > p1.y {
|
if p0.y > p1.y {
|
||||||
@inline(put_line_high, surface, p1, p0, color)
|
@inline(put_line_high, p1, p0, color)
|
||||||
} else {
|
} else {
|
||||||
@inline(put_line_high, surface, p0, p1, color)
|
@inline(put_line_high, p0, p1, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void {
|
set_height := fn(new: int): void {
|
||||||
src_top_cursor := top.buf
|
|
||||||
src_bottom_cursor := top.buf + top.width * (top.height - 1)
|
|
||||||
|
|
||||||
dst_top_idx := indexptr(surface, pos.x, pos.y)
|
|
||||||
dst_bottom_idx := indexptr(surface, pos.x, pos.y + top.height - 1)
|
|
||||||
|
|
||||||
dst_increment := surface.width
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// peony-made
|
set_width := fn(new: int): void {
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// peony-made
|
dimensions := fn(): IVec2 {
|
||||||
put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): void {
|
return .(ctx.width, ctx.height)
|
||||||
if y1 < y0 {
|
|
||||||
tmp := y0
|
|
||||||
y0 = y1
|
|
||||||
y1 = tmp
|
|
||||||
}
|
|
||||||
y := y0
|
|
||||||
|
|
||||||
loop if y == y1 break else {
|
|
||||||
*indexptr(surface, x, y) = color
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// peony-made
|
set_dimensions := fn(new: IVec2): void {
|
||||||
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))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
|
||||||
x := 0
|
|
||||||
y := radius
|
|
||||||
error := @as(int, 3) - @intcast(2 * radius);
|
|
||||||
*indexptr(surface, pos.x + radius, pos.y) = color;
|
|
||||||
*indexptr(surface, pos.x - radius, pos.y) = color;
|
|
||||||
*indexptr(surface, pos.x, pos.y + radius) = color;
|
|
||||||
*indexptr(surface, pos.x, pos.y - radius) = color
|
|
||||||
|
|
||||||
loop if y < x break else {
|
|
||||||
x += 1
|
|
||||||
|
|
||||||
if error > 0 {
|
|
||||||
y -= 1
|
|
||||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
|
||||||
} else {
|
|
||||||
error += 4 * @intcast(x) + 6
|
|
||||||
};
|
|
||||||
*indexptr(surface, pos.x + x, pos.y + y) = color;
|
|
||||||
*indexptr(surface, pos.x + y, pos.y + x) = color;
|
|
||||||
*indexptr(surface, pos.x - x, pos.y + y) = color;
|
|
||||||
*indexptr(surface, pos.x - y, pos.y + x) = color;
|
|
||||||
*indexptr(surface, pos.x + x, pos.y - y) = color;
|
|
||||||
*indexptr(surface, pos.x + y, pos.y - x) = color;
|
|
||||||
*indexptr(surface, pos.x - x, pos.y - y) = color;
|
|
||||||
*indexptr(surface, pos.x - y, pos.y - x) = color
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
|
||||||
x := 0
|
|
||||||
y := radius
|
|
||||||
error := @as(int, 3) - @intcast(2 * radius)
|
|
||||||
put_hline(surface, pos.y - x, pos.x - radius, pos.x + radius, color);
|
|
||||||
*indexptr(surface, pos.x, pos.y + radius) = color;
|
|
||||||
*indexptr(surface, pos.x, pos.y - radius) = color
|
|
||||||
|
|
||||||
loop if y < x break else {
|
|
||||||
x += 1
|
|
||||||
|
|
||||||
if error > 0 {
|
|
||||||
put_hline(surface, pos.y + y, pos.x - x, pos.x + x, color)
|
|
||||||
put_hline(surface, pos.y - y, pos.x - x, pos.x + x, color)
|
|
||||||
y -= 1
|
|
||||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
|
||||||
} else {
|
|
||||||
error += 4 * @intcast(x) + 6
|
|
||||||
}
|
|
||||||
put_hline(surface, pos.y + x, pos.x - y, pos.x + y, color)
|
|
||||||
put_hline(surface, pos.y - x, pos.x - y, pos.x + y, color)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
|
|
||||||
x := 0
|
|
||||||
y := radius
|
|
||||||
error := @as(int, 3) - @intcast(2 * radius)
|
|
||||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y), indexptr(surface, pos.x - y, pos.y), 2 * y);
|
|
||||||
*indexptr(surface, pos.x, pos.y + y) = *indexptr(source, source_pos.x, source_pos.y + y);
|
|
||||||
*indexptr(surface, pos.x, pos.y - y) = *indexptr(source, source_pos.x, source_pos.y - y)
|
|
||||||
|
|
||||||
loop if y < x break else {
|
|
||||||
x += 1
|
|
||||||
|
|
||||||
if error > 0 {
|
|
||||||
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y + y), indexptr(surface, pos.x - x, pos.y + y), 2 * x)
|
|
||||||
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y - y), indexptr(surface, pos.x - x, pos.y - y), 2 * x)
|
|
||||||
y -= 1
|
|
||||||
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
|
||||||
} else {
|
|
||||||
error += 4 * @intcast(x) + 6
|
|
||||||
}
|
|
||||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y + x), indexptr(surface, pos.x - y, pos.y + x), 2 * y)
|
|
||||||
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y - x), indexptr(surface, pos.x - y, pos.y - x), 2 * y)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
utf8_len_table := [u8].(0, 0, 2, 3)
|
|
||||||
|
|
||||||
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
|
|
||||||
cursor := Vec2(uint).(pos.x, pos.y)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
loop if *str == 0 break else {
|
|
||||||
if cursor.y > max_y break
|
|
||||||
|
|
||||||
glyph_data := @as(^u8, idk)
|
|
||||||
code_point := @as(uint, 0)
|
|
||||||
|
|
||||||
if (*str & 0x80) == 0 {
|
|
||||||
if *str == 10 {
|
|
||||||
cursor.x = pos.x
|
|
||||||
cursor.y += next_line_y
|
|
||||||
str += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if font.unicode == null {
|
|
||||||
if *str > font.num_glyphs {
|
|
||||||
str += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return
|
||||||
}
|
}
|
80
sysdata/libraries/render/src/svga.hb
Normal file
80
sysdata/libraries/render/src/svga.hb
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
.{IVec2} := @use("lib.hb")
|
||||||
|
// .{pci, memory, string, log} := @use("../../stn/src/lib.hb");
|
||||||
|
|
||||||
|
Color := 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)
|
||||||
|
|
||||||
|
clear := fn(color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
width := fn(): int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
height := fn(): int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
dimensions := fn(): IVec2 {
|
||||||
|
return .(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
put_pixel := fn(position: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_filled_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_rect := fn(pos: IVec2, tr: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_line_low := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// do not use, use line() instead
|
||||||
|
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set_height := fn(new: int): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set_width := fn(new: int): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
set_dimensions := fn(new: IVec2): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sync := fn(): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
init := fn(): void {
|
||||||
|
return
|
||||||
|
}
|
|
@ -1,160 +0,0 @@
|
||||||
.{log, memory} := @use("../../stn/src/lib.hb")
|
|
||||||
|
|
||||||
PSF1Header := packed struct {
|
|
||||||
magic: u16,
|
|
||||||
font_mode: u8,
|
|
||||||
character_size: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
PSF2Header := packed struct {
|
|
||||||
magic: u32,
|
|
||||||
version: u32,
|
|
||||||
header_size: u32,
|
|
||||||
flags: u32,
|
|
||||||
num_glyph: u32,
|
|
||||||
bytes_per_glyph: u32,
|
|
||||||
height: u32,
|
|
||||||
width: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
Font := struct {
|
|
||||||
data: ^u8,
|
|
||||||
width: uint,
|
|
||||||
height: uint,
|
|
||||||
num_glyphs: uint,
|
|
||||||
bytes_per_glyph: uint,
|
|
||||||
line_gap: uint,
|
|
||||||
char_gap: uint,
|
|
||||||
unicode: ?^u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
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\0")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
psf += @sizeof(PSF1Header)
|
|
||||||
|
|
||||||
return .(
|
|
||||||
psf,
|
|
||||||
8,
|
|
||||||
header.character_size,
|
|
||||||
256,
|
|
||||||
header.character_size,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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\0")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
psf += header.header_size
|
|
||||||
|
|
||||||
font := Font.(
|
|
||||||
psf,
|
|
||||||
header.width,
|
|
||||||
header.height,
|
|
||||||
header.num_glyph,
|
|
||||||
header.bytes_per_glyph,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
if (header.flags & 1) != 0 & unicode {
|
|
||||||
init_unicode(&font)
|
|
||||||
}
|
|
||||||
return font
|
|
||||||
}
|
|
||||||
|
|
||||||
$get_glyph := fn(font: Font, index: u8): ^u8 {
|
|
||||||
return font.data + @as(uint, index) * font.bytes_per_glyph
|
|
||||||
}
|
|
||||||
|
|
||||||
$UNC_TABLE_SIZE := 1 << 16
|
|
||||||
|
|
||||||
init_unicode := fn(font: ^Font): void {
|
|
||||||
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
|
|
||||||
|
|
||||||
memory.set(u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
|
|
||||||
|
|
||||||
table := font.data + font.num_glyphs * font.bytes_per_glyph
|
|
||||||
curr_glyph := @as(u16, 0)
|
|
||||||
|
|
||||||
loop if curr_glyph >= font.num_glyphs break else {
|
|
||||||
loop {
|
|
||||||
byte := *table
|
|
||||||
table += 1
|
|
||||||
|
|
||||||
if byte == 0xFF break
|
|
||||||
if byte == 0xFE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
unicode := @as(uint, 0)
|
|
||||||
bytes_to_read := @as(uint, 1)
|
|
||||||
|
|
||||||
if (byte & 0x80) == 0 {
|
|
||||||
unicode = byte
|
|
||||||
} else if (byte & 0xE0) == 0xC0 {
|
|
||||||
unicode = byte & 0x1F
|
|
||||||
bytes_to_read = 2
|
|
||||||
} else if (byte & 0xF0) == 0xE0 {
|
|
||||||
unicode = byte & 0xF
|
|
||||||
bytes_to_read = 3
|
|
||||||
} else if (byte & 0xF8) == 0xF0 {
|
|
||||||
unicode = byte & 0x7
|
|
||||||
bytes_to_read = 4
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
valid := true
|
|
||||||
loop if bytes_to_read <= 1 break else {
|
|
||||||
next_byte := *table
|
|
||||||
if (next_byte & 0xC0) != 0x80 {
|
|
||||||
valid = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
unicode = unicode << 6 | next_byte & 0x3F
|
|
||||||
table += 1
|
|
||||||
bytes_to_read -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if valid == false continue
|
|
||||||
|
|
||||||
if bytes_to_read == 4 {
|
|
||||||
if unicode < 0x10000 | unicode > 0x10FFFF continue
|
|
||||||
|
|
||||||
if unicode <= 0xFFFF {
|
|
||||||
if unicode < UNC_TABLE_SIZE {
|
|
||||||
*(@unwrap(font.unicode) + unicode) = curr_glyph
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unicode -= 0x10000
|
|
||||||
high_surrogate := 0xD800 | unicode >> 10 & 0x3FF
|
|
||||||
low_surrogate := 0xDC00 | unicode & 0x3FF
|
|
||||||
|
|
||||||
if high_surrogate < UNC_TABLE_SIZE {
|
|
||||||
*(@unwrap(font.unicode) + high_surrogate) = curr_glyph
|
|
||||||
}
|
|
||||||
if low_surrogate < UNC_TABLE_SIZE {
|
|
||||||
*(@unwrap(font.unicode) + low_surrogate) = curr_glyph
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if unicode < UNC_TABLE_SIZE {
|
|
||||||
*(@unwrap(font.unicode) + unicode) = curr_glyph
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
curr_glyph += 1
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +1,22 @@
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
|
|
||||||
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
|
receive_message := fn(buffer_id: int, memory_map_location: ^u8, length: int): ^u8 {
|
||||||
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
|
|
||||||
}
|
|
||||||
|
|
||||||
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void {
|
|
||||||
return @eca(3, buffer_id, msg, @sizeof(Expr))
|
|
||||||
}
|
|
||||||
|
|
||||||
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void {
|
|
||||||
return @eca(4, buffer_id, memory_map_location, length)
|
return @eca(4, buffer_id, memory_map_location, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void {
|
send_message := fn(msg: ^u8, buffer_id: int, length: int): void {
|
||||||
return @eca(3, buffer_id, msg, length)
|
return @eca(3, buffer_id, msg, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
|
create := fn(msg: ^u8): int {
|
||||||
|
msg_length := @inline(string.length, msg);
|
||||||
create := fn(msg: ^u8): uint {
|
*msg = 0
|
||||||
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
return @eca(3, 0, msg, msg_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
$create_nameless := fn(): uint {
|
search := fn(msg: ^u8): int {
|
||||||
return @eca(1, 0)
|
msg_length := @inline(string.length, msg);
|
||||||
}
|
*msg = 3
|
||||||
|
|
||||||
$delete_buffer := fn(buffer_id: uint): void {
|
return @eca(3, 0, msg, msg_length)
|
||||||
return @eca(2, buffer_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
search := fn(msg: ^u8): uint {
|
|
||||||
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
|
||||||
}
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
.{string} := @use("../../stn/src/lib.hb")
|
|
||||||
|
|
||||||
get := fn($Expr: type, query: ^u8): Expr {
|
|
||||||
return @eca(3, 5, query, @inline(string.length, query))
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
acs := @use("acs.hb")
|
acs := @use("acs.hb")
|
||||||
|
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
log := @use("log.hb")
|
log := @use("log.hb")
|
||||||
memory := @use("memory.hb")
|
memory := @use("memory.hb")
|
||||||
|
@ -6,15 +7,3 @@ buffer := @use("buffer.hb")
|
||||||
math := @use("math.hb")
|
math := @use("math.hb")
|
||||||
random := @use("random.hb")
|
random := @use("random.hb")
|
||||||
file := @use("file_io.hb")
|
file := @use("file_io.hb")
|
||||||
dt := @use("dt.hb")
|
|
||||||
process := @use("process.hb")
|
|
||||||
|
|
||||||
panic := fn(message: ?^u8): never {
|
|
||||||
log.error("Error: Panic Called, Message:\0")
|
|
||||||
if message == null {
|
|
||||||
log.error("None\0")
|
|
||||||
} else {
|
|
||||||
log.error(message)
|
|
||||||
}
|
|
||||||
die
|
|
||||||
}
|
|
|
@ -1,13 +1,15 @@
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
|
buffer := @use("buffer.hb")
|
||||||
|
|
||||||
LogMsg := packed struct {level: u8, string: ^u8, strlen: uint}
|
log := fn(message: ^u8, level: u8): void {
|
||||||
|
message_length := @inline(string.length, message);
|
||||||
|
*(message + message_length) = level
|
||||||
|
|
||||||
log := fn(level: u8, message: ^u8): void {
|
return @eca(3, 1, message, message_length + 1)
|
||||||
return @eca(3, 1, LogMsg.(level, message, @inline(string.length, message)), @sizeof(LogMsg))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error := fn(message: ^u8): void return @inline(log, 0, message)
|
error := fn(message: ^u8): void return log(message, 0)
|
||||||
warn := fn(message: ^u8): void return @inline(log, 1, message)
|
warn := fn(message: ^u8): void return log(message, 1)
|
||||||
info := fn(message: ^u8): void return @inline(log, 2, message)
|
info := fn(message: ^u8): void return log(message, 2)
|
||||||
debug := fn(message: ^u8): void return @inline(log, 3, message)
|
debug := fn(message: ^u8): void return log(message, 3)
|
||||||
trace := fn(message: ^u8): void return @inline(log, 4, message)
|
trace := fn(message: ^u8): void return log(message, 4)
|
File diff suppressed because one or more lines are too long
|
@ -1,76 +1,39 @@
|
||||||
$PAGE_SIZE := 4096
|
request_page := fn(page_count: u8): ^u8 {
|
||||||
$MAX_ALLOC := 0xFF
|
msg := "\{00}\{01}xxxxxxxx\0"
|
||||||
$MAX_FREE := 0xFF
|
msg_page_count := msg + 1;
|
||||||
|
*msg_page_count = page_count
|
||||||
$uninit := fn($Expr: type): ?Expr {
|
return @eca(3, 2, msg, 12)
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$dangling := fn($Expr: type): ^Expr {
|
release_page := fn(ptr: ^u8, page_count: u8): void {
|
||||||
return @bitcast(@alignof(Expr))
|
msg := "\{01}\{00}xxxxxxxx\0"
|
||||||
|
|
||||||
|
msg_page_count := msg + 1;
|
||||||
|
*msg_page_count = page_count
|
||||||
|
|
||||||
|
msg_ptr := @as(^^u8, @bitcast(msg + 2));
|
||||||
|
*msg_ptr = ptr
|
||||||
|
|
||||||
|
return @eca(3, 2, msg, 12)
|
||||||
}
|
}
|
||||||
|
|
||||||
$calc_pages := fn($Expr: type, num: uint): uint {
|
OutbMsg := struct {a: u8, b: u8, addr: u16, value: u8}
|
||||||
return 1 + @sizeof(Expr) * num / PAGE_SIZE
|
InbMsg := struct {a: u8, b: u8, addr: u16}
|
||||||
}
|
OutlMsg := struct {a: u8, b: u8, addr: u16, value: u32}
|
||||||
|
InlMsg := struct {a: u8, b: u8, addr: u16}
|
||||||
|
|
||||||
// ! will be replaced, don't get attached
|
outb := fn(addr: u16, value: u8): void {
|
||||||
alloc := fn($Expr: type, num: uint): ^Expr {
|
|
||||||
pages := calc_pages(Expr, num)
|
|
||||||
if pages <= MAX_ALLOC {
|
|
||||||
return @bitcast(request_page(@intcast(pages)))
|
|
||||||
}
|
|
||||||
ptr := request_page(MAX_ALLOC)
|
|
||||||
remaining := pages - MAX_ALLOC
|
|
||||||
loop if remaining < MAX_ALLOC break else {
|
|
||||||
_ = request_page(MAX_ALLOC)
|
|
||||||
remaining -= MAX_ALLOC
|
|
||||||
}
|
|
||||||
_ = request_page(@intcast(remaining))
|
|
||||||
return @bitcast(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ! stub
|
|
||||||
$free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
RqPageMsg := packed struct {a: u8, count: u8}
|
|
||||||
$request_page := fn(count: u8): ^u8 {
|
|
||||||
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
|
|
||||||
$release_page := fn(ptr: ^u8, count: u8): void {
|
|
||||||
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
|
|
||||||
$outb := fn(addr: u16, value: u8): void {
|
|
||||||
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
|
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
InbMsg := packed struct {a: u8, b: u8, addr: u16}
|
inb := fn(addr: u16): u8 {
|
||||||
$inb := fn(addr: u16): u8 {
|
|
||||||
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
|
outl := fn(addr: u16, value: u32): void {
|
||||||
$outl := fn(addr: u16, value: u32): void {
|
|
||||||
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
InlMsg := packed struct {a: u8, b: u8, addr: u16}
|
inl := fn(addr: u16): u32 {
|
||||||
$inl := fn(addr: u16): u32 {
|
|
||||||
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
|
|
||||||
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
|
||||||
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
|
|
||||||
}
|
|
||||||
|
|
||||||
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
|
|
||||||
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
|
||||||
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
// ! will be rewritten to take a file object when filesystem is exist
|
|
||||||
// returns PID
|
|
||||||
$spawn := fn(proc_exe: ^u8, length: uint): uint {
|
|
||||||
return @eca(3, 6, proc_exe, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
- Spawn an empty process
|
|
||||||
- Call a function to load bytes into that process from a function
|
|
||||||
Or
|
|
||||||
- Manually fill the bytes in
|
|
||||||
- Execute the process via a run type command */
|
|
|
@ -1,7 +1,7 @@
|
||||||
any := fn($Expr: type): Expr {
|
integer := fn(): int {
|
||||||
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
|
return @eca(3, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
range := fn($Expr: type, min: Expr, max: Expr): Expr {
|
integer_range := fn(min: int, max: int): int {
|
||||||
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr)) % (max - min) + *@bitcast(&1) + min
|
return @eca(3, 4) % (max - min + 1) + min
|
||||||
}
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
subscribe_to_interrupt := fn(interrupt_number: u8): bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Pauses execution until the interrupt occures
|
|
||||||
sleep_until_interrupt := fn(interrupt_number: u8): void {
|
|
||||||
}
|
|
|
@ -1,63 +1,48 @@
|
||||||
length := fn(ptr: ^u8): uint {
|
length := fn(ptr: ^u8): int {
|
||||||
len := 0
|
len := 0
|
||||||
loop if *(ptr + len) == 0 return len else len += 1
|
loop if *(ptr + len) == 0 break else len += 1
|
||||||
|
return len
|
||||||
}
|
}
|
||||||
|
|
||||||
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
|
// WTFFF is wrong with display_int
|
||||||
is_negative := num < 0
|
display_int := fn(num: int, p: ^u8): ^u8 {
|
||||||
if is_negative num = -num
|
|
||||||
|
|
||||||
ptr := p
|
ptr := p
|
||||||
|
negative := num < 0
|
||||||
|
if negative {
|
||||||
|
num = -num
|
||||||
|
}
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
*ptr = 0x30;
|
*ptr = 48
|
||||||
*(ptr + 1) = 0
|
ptr += 1
|
||||||
return p
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
loop if num == 0 break else {
|
loop if num == 0 break else {
|
||||||
remainder := num % @bitcast(radix)
|
*ptr = num % 10 + 48
|
||||||
num /= @bitcast(radix);
|
|
||||||
*ptr = @intcast(remainder + 0x30)
|
|
||||||
if remainder > 9 {
|
|
||||||
*ptr = @intcast(remainder - 10 + 0x41)
|
|
||||||
}
|
|
||||||
ptr += 1
|
ptr += 1
|
||||||
|
num /= 10
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if is_negative {
|
if negative {
|
||||||
*ptr = 0x2D
|
*ptr = 45
|
||||||
ptr += 1
|
ptr += 1
|
||||||
}
|
};
|
||||||
// ! it gets broked when you do this ??
|
*ptr = 0
|
||||||
// *ptr = 0
|
|
||||||
|
|
||||||
@inline(reverse, p)
|
@inline(reverse, p)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse := fn(s: ^u8): void {
|
reverse := fn(s: ^u8): void {
|
||||||
j := s + @inline(length, s) - 1
|
//reverse a string, don't remove digits
|
||||||
temp := @as(u8, 0)
|
len := 0
|
||||||
loop if s < j {
|
loop if *(s + len) == 0 break else len += 1
|
||||||
temp = *s;
|
i := 0
|
||||||
*s = *j;
|
j := len - 1
|
||||||
*j = temp
|
temp := 0
|
||||||
s += 1
|
loop if i >= j break else {
|
||||||
|
temp = *(s + i);
|
||||||
|
*(s + i) = *(s + j);
|
||||||
|
*(s + j) = temp
|
||||||
|
i += 1
|
||||||
j -= 1
|
j -= 1
|
||||||
} else return
|
|
||||||
}
|
|
||||||
|
|
||||||
equals := fn(lhs: ^u8, rhs: ^u8): bool {
|
|
||||||
if lhs == rhs {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
loop if *lhs != *rhs {
|
|
||||||
return false
|
|
||||||
} else if *lhs == 0 {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
lhs += 1
|
|
||||||
rhs += 1
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
|
@ -1,63 +0,0 @@
|
||||||
.{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
|
|
||||||
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
|
|
||||||
.{new_surface, Color} := @use("../../render/src/lib.hb")
|
|
||||||
|
|
||||||
// ! in the future this should be safely handled
|
|
||||||
channel := Channel.(0, 0)
|
|
||||||
|
|
||||||
find_server := fn(): void {
|
|
||||||
log.info("client: locating server\0")
|
|
||||||
channel2 := await_channel()
|
|
||||||
channel.server = channel2.server
|
|
||||||
channel.client = channel2.client
|
|
||||||
log.info("client: server located\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
new := fn(props: WindowProps): ?Window {
|
|
||||||
send_header(message.syn, channel.server)
|
|
||||||
response := await_message(Channel, channel.client)
|
|
||||||
if response.header.kind != message.ack {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
log.info("client: recv ack\0")
|
|
||||||
send_message(WindowProps, message.props, props, response.body.server)
|
|
||||||
windowdata := await_message(WindowData, response.body.client)
|
|
||||||
if windowdata.header.kind != message.ack {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
log.info("client: recv windowdata\0")
|
|
||||||
surface := new_surface(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
|
|
||||||
return .(windowdata.body, surface)
|
|
||||||
}
|
|
||||||
|
|
||||||
quit := fn(client: Window): void {
|
|
||||||
send_header(message.quit, client.data.channel.server)
|
|
||||||
}
|
|
||||||
|
|
||||||
connected := fn(client: Window): bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
shutdown_server := fn(client: Window): bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
update_props := fn(client: Window): bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
update_permissions := fn(client: Window): bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
send_frame := fn(client: Window): bool {
|
|
||||||
send_header(message.frame_ready, client.data.channel.server)
|
|
||||||
response := await_message(uint, client.data.channel.client)
|
|
||||||
if response.header.kind != message.ack {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// ! FOR NOW, server will ALWAYS be local,
|
|
||||||
// ! so we can send pointer to surface.
|
|
||||||
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
|
|
||||||
return true
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb");
|
|
||||||
.{Surface} := @use("../../render/src/lib.hb")
|
|
||||||
|
|
||||||
$BUFFER_SERVER := "sunset_server\0"
|
|
||||||
$BUFFER_CLIENT := "sunset_client\0"
|
|
||||||
|
|
||||||
Channel := packed struct {
|
|
||||||
client: uint,
|
|
||||||
server: uint,
|
|
||||||
}
|
|
||||||
|
|
||||||
client := @use("./client.hb")
|
|
||||||
server := @use("./server.hb")
|
|
||||||
message := @use("./message.hb")
|
|
||||||
permissions := @use("./permissions.hb")
|
|
||||||
|
|
||||||
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
|
|
||||||
buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
|
|
||||||
}
|
|
||||||
|
|
||||||
$send_header := fn(kind: MessageKind, buffer_id: uint): void {
|
|
||||||
buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
|
|
||||||
}
|
|
||||||
|
|
||||||
$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
|
|
||||||
response := @as(?Message(Expr), null)
|
|
||||||
buffer.recv(?Message(Expr), buffer_id, &response)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
$recv_header := fn(buffer_id: uint): ?MessageHeader {
|
|
||||||
response := @as(?MessageHeader, null)
|
|
||||||
buffer.recv(?MessageHeader, buffer_id, &response)
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
await_channel := fn(): Channel {
|
|
||||||
channel := Channel.(0, 0)
|
|
||||||
loop if channel.server != 0 break else {
|
|
||||||
channel.server = buffer.search(BUFFER_SERVER)
|
|
||||||
}
|
|
||||||
loop if channel.client != 0 break else {
|
|
||||||
channel.client = buffer.search(BUFFER_CLIENT)
|
|
||||||
}
|
|
||||||
return channel
|
|
||||||
}
|
|
||||||
|
|
||||||
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
|
|
||||||
response := @as(?Message(Expr), null)
|
|
||||||
loop {
|
|
||||||
buffer.recv(?Message(Expr), buffer_id, &response)
|
|
||||||
if response != null {
|
|
||||||
return @as(Message(Expr), response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await_header := fn(buffer_id: uint): MessageHeader {
|
|
||||||
response := @as(?MessageHeader, null)
|
|
||||||
loop {
|
|
||||||
buffer.recv(?MessageHeader, buffer_id, &response)
|
|
||||||
if response != null {
|
|
||||||
return @as(?MessageHeader, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageKind := u8
|
|
||||||
|
|
||||||
MessageHeader := packed struct {
|
|
||||||
kind: MessageKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
Message := fn($Expr: type): type {
|
|
||||||
return packed struct {
|
|
||||||
header: MessageHeader,
|
|
||||||
body: Expr,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowProps := struct {
|
|
||||||
position: Vec2(uint),
|
|
||||||
dimensions: Vec2(uint),
|
|
||||||
// ! replace with owned string type later
|
|
||||||
title: ^u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowData := struct {
|
|
||||||
props: WindowProps,
|
|
||||||
channel: Channel,
|
|
||||||
permissions: uint,
|
|
||||||
}
|
|
||||||
|
|
||||||
Window := struct {
|
|
||||||
data: WindowData,
|
|
||||||
surface: Surface,
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
// ! all values in this file are subject to change.
|
|
||||||
$syn := 1
|
|
||||||
$ack := 2
|
|
||||||
$refused := 3
|
|
||||||
$quit := 4
|
|
||||||
$props := 5
|
|
||||||
$shutdown := 6
|
|
||||||
$frame_ready := 7
|
|
|
@ -1,5 +0,0 @@
|
||||||
$none := 0b0
|
|
||||||
$exclusive_framebuffer := 0b1
|
|
||||||
$shutdown := 0b100
|
|
||||||
|
|
||||||
$default := none
|
|
|
@ -1,135 +0,0 @@
|
||||||
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
|
|
||||||
.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("../../render/src/lib.hb");
|
|
||||||
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb")
|
|
||||||
|
|
||||||
WindowServer := struct {
|
|
||||||
window_count: uint,
|
|
||||||
channel: Channel,
|
|
||||||
// ! replace this with a collection when we get an allocator
|
|
||||||
windows: [?Window; 10],
|
|
||||||
font: text.Font,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ! in the future this should be safely handled
|
|
||||||
server := @as(WindowServer, idk)
|
|
||||||
|
|
||||||
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
|
|
||||||
|
|
||||||
start := fn(): void {
|
|
||||||
font := text.font_from_psf2(@bitcast(&psf), false)
|
|
||||||
if font == null {
|
|
||||||
log.error("server: failed to load asset\0")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
server = .(
|
|
||||||
0,
|
|
||||||
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
|
|
||||||
.(null, null, null, null, null, null, null, null, null, null),
|
|
||||||
@as(text.Font, font),
|
|
||||||
)
|
|
||||||
log.info("server: started server\0")
|
|
||||||
}
|
|
||||||
|
|
||||||
incoming := fn(): bool {
|
|
||||||
msg := recv_header(server.channel.server)
|
|
||||||
if msg == null {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if msg.kind == message.syn {
|
|
||||||
log.info("server: recv syn\0")
|
|
||||||
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
|
|
||||||
send_message(Channel, message.ack, channel, server.channel.client)
|
|
||||||
props := await_message(WindowProps, channel.server)
|
|
||||||
if props.header.kind != message.props {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
log.info("server: recv props\0")
|
|
||||||
// ! do inspection of requested props here
|
|
||||||
data := WindowData.(props.body, channel, permissions.default)
|
|
||||||
send_message(WindowData, message.ack, data, channel.client)
|
|
||||||
surface := new_window_decorations(data.props.dimensions)
|
|
||||||
// decorations
|
|
||||||
{
|
|
||||||
title := data.props.title
|
|
||||||
title_length := string.length(title)
|
|
||||||
deco_length := title_length * 10
|
|
||||||
// draw the window tab bar
|
|
||||||
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
|
|
||||||
// Draw the window tab
|
|
||||||
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
|
|
||||||
|
|
||||||
// Draw the outside box
|
|
||||||
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
|
|
||||||
|
|
||||||
put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
|
|
||||||
}
|
|
||||||
server.windows[server.window_count] = .(data, surface)
|
|
||||||
server.window_count += 1
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
$DECO_WIDTH := 2
|
|
||||||
$DECO_HEIGHT_TOP := 20
|
|
||||||
$DECO_HEIGHT_BOTTOM := 1
|
|
||||||
$DECO_COLOUR := Color.(100, 200, 255, 255)
|
|
||||||
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
|
|
||||||
|
|
||||||
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
|
|
||||||
return new_surface(
|
|
||||||
dimensions.x + DECO_WIDTH,
|
|
||||||
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ! compositor code. this currently disallows tearing.
|
|
||||||
|
|
||||||
collect_frames := fn(): void {
|
|
||||||
i := 0
|
|
||||||
loop if i == 10 break else {
|
|
||||||
window := server.windows[i]
|
|
||||||
if window == null {
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
header := recv_header(window.data.channel.server)
|
|
||||||
if header == null {
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if header.kind != message.frame_ready {
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
send_header(message.ack, window.data.channel.client)
|
|
||||||
ptr := await_message(^Color, window.data.channel.server)
|
|
||||||
if ptr.header.kind != message.ack {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
put_surface(
|
|
||||||
window.surface,
|
|
||||||
Surface.(
|
|
||||||
ptr.body,
|
|
||||||
window.data.props.dimensions.x,
|
|
||||||
window.data.props.dimensions.y,
|
|
||||||
window.data.props.dimensions.x * window.data.props.dimensions.y,
|
|
||||||
),
|
|
||||||
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render_clients := fn(screen: Surface): void {
|
|
||||||
i := 0
|
|
||||||
loop if i == 10 break else {
|
|
||||||
window := server.windows[i]
|
|
||||||
if window == null {
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
put_surface(screen, window.surface, window.data.props.position, false)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,14 @@
|
||||||
.{dt} := @use("../../../libraries/stn/src/lib.hb")
|
dt_api := @use("../../../libraries/dt_api/src/lib.hb");
|
||||||
|
.{dt_get} := dt_api
|
||||||
|
|
||||||
main := fn(): void {
|
main := fn(): int {
|
||||||
dt.get(void, "framebuffer/fb0/width\0")
|
dt_api.dt_get("framebuffer/fb0/width\0")
|
||||||
dt.get(void, "cpu/cpu0/architecture\0")
|
dt_api.dt_get("cpu/cpu0/architecture\0")
|
||||||
|
|
||||||
// Checking if the first detected serial port is memory mapped or port mapped
|
// Checking if the first detected serial port is memory mapped or port mapped
|
||||||
// 0 -> memory mapped
|
// 0 -> memory mapped
|
||||||
// 1 -> port mapped
|
// 1 -> port mapped
|
||||||
dt.get(void, "serial_ports/sp0/mapping\0")
|
dt_get("serial_ports/sp0/mapping\0")
|
||||||
|
|
||||||
return
|
return 0
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
READ_ONLY := @as(u32, 0x1)
|
READ_ONLY := 0x1
|
||||||
HIDDEN := @as(u32, 0x2)
|
HIDDEN := 0x2
|
||||||
SYSTEM := @as(u32, 0x4)
|
SYSTEM := 0x4
|
||||||
VOLUME_ID := @as(u32, 0x8)
|
VOLUME_ID := 0x8
|
||||||
DIRECTORY := @as(u32, 0x10)
|
DIRECTORY := 0x10
|
||||||
ARCHIVE := @as(u32, 0x20)
|
ARCHIVE := 0x20
|
||||||
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID
|
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID
|
|
@ -9,7 +9,8 @@ OemIdent := struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
new_oem_ident := fn(major: int, minor: int): OemIdent {
|
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))
|
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
return OemIdent.(ver, ver)
|
||||||
}
|
}
|
||||||
|
|
||||||
BiosParameterBlock := struct {
|
BiosParameterBlock := struct {
|
||||||
|
@ -37,7 +38,9 @@ bpb_sanity_check := fn(bpb: BiosParameterBlock): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
new_bpb := fn(): BiosParameterBlock {
|
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)
|
oem := new_oem_ident(0, 0)
|
||||||
|
|
||||||
|
return BiosParameterBlock.(VALID_JUMP_BYTES, oem, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
||||||
|
@ -60,7 +63,7 @@ VolumeName := [u8; 11]
|
||||||
|
|
||||||
SystemIdentifierString := [u8; 8]
|
SystemIdentifierString := [u8; 8]
|
||||||
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
||||||
BOOTABLE_PARTITION_SIGNATURE := @as(u32, 0xAA55)
|
BOOTABLE_PARTITION_SIGNATURE := 0xAA55
|
||||||
|
|
||||||
BootCode := [u8; 420]
|
BootCode := [u8; 420]
|
||||||
|
|
||||||
|
@ -97,10 +100,9 @@ ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
|
||||||
log.warn("EBR-Signature sanity check failed\0")
|
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 {
|
||||||
// if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
|
log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
||||||
// log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
}
|
||||||
// }
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,8 +131,8 @@ new_ebr := fn(): ExtendedBootRecord {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALID_LEAD_FS_INFO := @as(u32, 0x41615252)
|
VALID_LEAD_FS_INFO := 0x41615252
|
||||||
VALID_TRAIL_FS_INFO := @as(u32, 0xAA550000)
|
VALID_TRAIL_FS_INFO := 0xAA550000
|
||||||
|
|
||||||
FSInfo := struct {
|
FSInfo := struct {
|
||||||
// Must be 0x41615252 to indicate a valid FSInfo structure
|
// Must be 0x41615252 to indicate a valid FSInfo structure
|
||||||
|
@ -143,7 +145,7 @@ FSInfo := struct {
|
||||||
trail_signature: u32,
|
trail_signature: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_info_sanity_check := fn(fs_info: FSInfo): uint {
|
fs_info_sanity_check := fn(fs_info: FSInfo): int {
|
||||||
ret := 0
|
ret := 0
|
||||||
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
|
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
|
||||||
ret &= 1
|
ret &= 1
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue