1
0
Fork 0
forked from AbleOS/ableos

Compare commits

..

2 commits

Author SHA1 Message Date
Tristan Poland (Trident_For_U) d979150be3 Update main.rs 2024-09-25 17:57:28 -04:00
Tristan Poland (Trident_For_U) 6efff7a274 Added a reust devcontainer for windows development 2024-09-25 17:50:33 -04:00
98 changed files with 1652 additions and 1737 deletions

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

926
Cargo.lock generated

File diff suppressed because it is too large Load diff

69
HELP.md
View file

@ -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)

View file

@ -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">
# 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
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.

View file

@ -138,8 +138,8 @@ fn build(name: String) {
}
}
pub fn build_program(_name: String) {}
pub fn build_library(_name: String) {}
pub fn build_program(name: String) {}
pub fn build_library(name: String) {}
fn help() {
println!(

1
installers-deb.sh Normal file
View file

@ -0,0 +1 @@
sudo apt-get update && sudo apt install -y qemu-utils qemu-system-x86 qemu-system-gui clang

View file

@ -4,3 +4,6 @@ build-std-features = ["compiler-builtins-mem"]
[build]
target = "./targets/x86_64-ableos.json"
[target.'cfg(target_arch = "x86_64")']
rustflags = ["-C", "target-feature=+rdrand"]

View file

@ -5,10 +5,8 @@ version = "0.2.0"
[dependencies]
# embedded-graphics = "0.8"
hbvm = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"nightly",
] }
embedded-graphics = "0.8"
hbvm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
log = "0.4"
spin = "0.9"
slab = { version = "0.4", default-features = false }
@ -16,8 +14,11 @@ uart_16550 = { version = "0.3", features = ["nightly"] }
xml.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"
hashbrown = { version = "0.15", features = ["nightly"] }
limine = "0.1"
hashbrown = { version = "0.14", features = ["nightly"] }
[dependencies.limine]
version = "0.1"
#git = "https://github.com/limine-bootloader/limine-rs"
[dependencies.crossbeam-queue]
version = "0.3"
@ -32,23 +33,23 @@ features = ["alloc", "nightly"]
version = "1"
default-features = false
features = [
"add",
"add_assign",
"constructor",
"display",
"from",
"into",
"mul",
"mul_assign",
"not",
"sum",
"add",
"add_assign",
"constructor",
"display",
"from",
"into",
"mul",
"mul_assign",
"not",
"sum",
]
[target.'cfg(target_arch = "x86_64")'.dependencies]
x86_64 = "0.15"
x2apic = "0.4"
# virtio-drivers = "0.7"
virtio-drivers = "0.7"
[target.'cfg(target_arch = "riscv64")'.dependencies]
sbi = "0.2.0"

View file

@ -1,5 +1,6 @@
use {
crate::{device_tree::DeviceTree, kmain::DEVICE_TREE},
crate::{alloc::string::ToString, device_tree::DeviceTree, kmain::DEVICE_TREE},
alloc::string::String,
core::arch::asm,
xml::XMLElement,
};
@ -27,7 +28,7 @@ fn collect_cpu_info(device_tree: &mut DeviceTree) {
cpus.push(cpu);
}
fn cpu_id<'a>() -> (&'a str, u64) {
fn cpu_id() -> (String, u64) {
let mut cpu_id: u64;
unsafe {
asm!("mrs {cpu_id}, MIDR_EL1",
@ -38,11 +39,11 @@ fn cpu_id<'a>() -> (&'a str, u64) {
let cpu_name = match cpu_id {
// the source of these two was a stackoverflow question
// https://raspberrypi.stackexchange.com/questions/117175/how-do-i-read-the-cpuid-in-aarch64-asm
0x410FD034 => "Cortex-A53",
0x410FD083 => "Cortex-A72",
0x410FD034 => "Cortex-A53".to_string(),
0x410FD083 => "Cortex-A72".to_string(),
// the source of this one was checking the cpu id :thinking:
0x410FD493 => "Neoverse N2",
_ => "Unknown",
0x410FD493 => "Neoverse N2".to_string(),
_ => "Unknown".to_string(),
};
log::trace!("CPU Name: {cpu_name} - CPU ID: 0x{:X}", cpu_id);

View file

@ -3,7 +3,7 @@ pub static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
uart: 0x09000000 as *mut u8,
});
pub struct SerialConsole {
struct SerialConsole {
uart: *mut u8,
}

View file

@ -10,7 +10,7 @@ pub mod graphics;
pub(crate) mod interrupts;
pub mod logging;
pub mod pci;
// pub mod virtio;
pub mod virtio;
pub use {logging::log, memory::PAGE_SIZE};
@ -30,11 +30,9 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
#[no_mangle]
#[naked]
#[cfg(not(target_feature = "avx2"))]
unsafe extern "C" fn _kernel_start() -> ! {
// Initialise SSE, then jump to kernel entrypoint
// Initialise SSE and jump to kernel entrypoint
core::arch::asm!(
// Initialise SSE
"mov rax, cr0",
"and ax, 0xfffb",
"or ax, 0x2",
@ -42,72 +40,12 @@ unsafe extern "C" fn _kernel_start() -> ! {
"mov rax, cr4",
"or ax, 3 << 9",
"mov cr4, rax",
// Jump to the kernel entry point
"jmp {}",
sym start,
options(noreturn),
)
}
#[no_mangle]
#[naked]
#[cfg(target_feature = "avx2")]
unsafe extern "C" fn _kernel_start() -> ! {
core::arch::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,
options(noreturn),
)
}
unsafe extern "C" fn oops() -> ! {
panic!("your cpu is ancient >:(")
}
unsafe extern "C" fn start() -> ! {
logging::init();
crate::logger::init().expect("failed to set logger");
@ -251,7 +189,6 @@ unsafe extern "C" fn start() -> ! {
/// Spin loop
pub fn spin_loop() -> ! {
loop {
core::hint::spin_loop();
x86_64::instructions::hlt()
}
}

View file

@ -8,12 +8,13 @@ pub struct PciDeviceInfo {
pub full_class: PciFullClass,
pub rev_id: u8,
}
use crate::alloc::string::ToString;
/// Enumerate PCI devices and run initialisation routines on ones we support
pub fn init(device_tree: &mut DeviceTree) {
device_tree
.devices
.insert("Unidentified PCI", alloc::vec![]);
.insert("Unidentified PCI".to_string(), alloc::vec![]);
let mut devices = alloc::vec![];
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("vendor", vendor);
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);
devices.push((dev_type, dev));
}

View file

@ -1,5 +1,5 @@
use {
core::ptr::NonNull,
core::{ptr::NonNull},
virtio_drivers::{BufferDirection, Hal, PhysAddr},
};

View file

@ -1,6 +1,11 @@
//! 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.
/// TODO define device
@ -9,11 +14,11 @@ pub type Device = xml::XMLElement;
/// A tree of devices
// TODO: alphabetize this list
#[derive(Debug)]
pub struct DeviceTree<'a> {
pub struct DeviceTree {
/// 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
pub fn new() -> Self {
let mut dt = Self {
@ -42,7 +47,7 @@ impl<'a> DeviceTree<'a> {
}
}
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 {
writeln!(f)?;
for (device_type, devices) in &self.devices {

View file

@ -8,24 +8,14 @@ use crate::holeybytes::kernel_services::{
use {
super::Vm,
crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
hbvm::value::Value,
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) {
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 {
0 => {
@ -38,9 +28,9 @@ pub fn handler(vm: &mut Vm) {
1 => {
// Make buffer
let bounded = match vm.registers[3] {
Value(0) => false,
Value(1) => true,
let bounded = match vm.registers[3].cast::<u64>() {
0 => false,
1 => true,
_ => {
panic!("Bad");
}
@ -49,15 +39,18 @@ pub fn handler(vm: &mut Vm) {
let length = vm.registers[4].cast::<u64>();
let mut buffs = IPC_BUFFERS.lock();
let abc;
match bounded {
false => {
abc = IpcBuffer::new(false, 0);
}
true => {
abc = IpcBuffer::new(true, length);
}
};
let buff_id = arch::hardware_random_u64();
buffs.insert(
buff_id,
match bounded {
false => IpcBuffer::new(false, 0),
true => IpcBuffer::new(true, length),
},
);
buffs.insert(buff_id, abc);
info!("Buffer ID: {}", buff_id);
vm.registers[1] = hbvm::value::Value(buff_id);
}
@ -70,6 +63,7 @@ pub fn handler(vm: &mut Vm) {
let mem_addr = vm.registers[4].cast::<u64>();
let length = vm.registers[5].cast::<u64>() as usize;
trace!("IPC address: {:?}", mem_addr);
use alloc::vec::Vec;
match buffer_id {
0 => match sds_msg_handler(vm, mem_addr, length) {
@ -87,15 +81,25 @@ pub fn handler(vm: &mut Vm) {
Err(_) => {}
}
}
#[cfg(not(target_arch = "x86_64"))]
3 => info!("TODO: implement whatever buffer 3 does for no x86_64"),
#[cfg(target_arch = "x86_64")]
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_type = msg_vec[0];
match msg_type {
0 => unsafe {
let size = msg_vec[1];
let addr =
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
let value = match size {
0 => x86_in::<u8>(addr) as u64,
1 => x86_in::<u16>(addr) as u64,
@ -107,8 +111,7 @@ pub fn handler(vm: &mut Vm) {
},
1 => unsafe {
let size = msg_vec[1];
let addr =
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
// info!("Setting address {}", addr);
match size {
@ -131,58 +134,68 @@ pub fn handler(vm: &mut Vm) {
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
// source of rng
4 => {
let block = block_read(mem_addr, length);
block.chunks_mut(8.min(length)).for_each(|chunk| {
chunk.clone_from_slice(
&crate::arch::hardware_random_u64().to_le_bytes()[..chunk.len()],
);
});
vm.registers[1] = hbvm::value::Value(mem_addr);
// limit to last 32 bits
vm.registers[1] =
hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF);
}
5 => match dt_msg_handler(vm, mem_addr, length) {
Ok(()) => {}
Err(_) => log::error!("Improper dt query"),
},
buffer_id => {
let mut buffs = IPC_BUFFERS.lock();
match buffs.get_mut(&buffer_id) {
Some(buff) => {
let msg_vec = block_read(mem_addr, length);
buff.push(msg_vec.to_vec());
debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer_id);
let mut msg_vec = Vec::with_capacity(length);
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 => {
log::error!("Access of non-existent buffer {}", buffer_id)
}
}
drop(buffs);
}
}
}
4 => {
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 mut buffs = IPC_BUFFERS.lock();
let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
Some(buff) => buff,
None => panic!(
"Failed to get buffer: id={buffer_id}, ptr={map_ptr}, length={max_length}"
),
};
let buff: &mut IpcBuffer;
let msg = match buff.pop() {
Ok(msg) => msg,
Err(_) => return,
};
if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } {
if buffs.get_mut(&buffer_id).is_some() {
buff = buffs.get_mut(&buffer_id).unwrap();
} else {
// info!("AHHH");
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);
error!("Message is too long to map in.");
} else {
unsafe {
let ptr = map_ptr as *mut u8;
ptr.copy_from(msg.as_ptr(), msg.len());
let ptr: *mut u64 = &mut map_ptr;
for (index, byte) in msg.iter().enumerate() {
ptr.offset(index.try_into().unwrap()).write_bytes(*byte, 1);
}
}
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
@ -192,7 +205,13 @@ pub fn handler(vm: &mut Vm) {
#[cfg(target_arch = "x86_64")]
{
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);
vm.registers[3] = x
}
@ -208,3 +227,15 @@ pub enum LogError {
NoMessages,
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(())
// }

View file

@ -1,6 +1,9 @@
use {
crate::holeybytes::{kernel_services::block_read, Vm},
alloc::vec::Vec,
alloc::{
string::{String, ToString},
vec::Vec,
},
};
pub enum DtError {
QueryFailure,
@ -8,13 +11,14 @@ pub enum 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 query_string = core::str::from_utf8(
msg_vec
.split_once(|&byte| byte == 0)
.unwrap_or((msg_vec, &[]))
.0,
)
.unwrap();
let mut bytes: Vec<u8> = Vec::new();
for byte in msg_vec {
if *byte == 0 {
break;
}
bytes.push(*byte)
}
let query_string = String::from_utf8(bytes).unwrap();
log::trace!("Query {}", 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(())
}
fn query_parse(query_string: &str) -> u64 {
let query = query_string.split('/').collect::<Vec<&str>>();
fn query_parse(query_string: String) -> u64 {
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 {
"framebuffer" => framebuffer_parse(query),
"cpu" => cpu_parse(query),
"framebuffer" => framebuffer_parse(qt_parse_step_two),
"cpu" => cpu_parse(qt_parse_step_two),
_ => 0,
};
@ -39,8 +47,8 @@ fn query_parse(query_string: &str) -> u64 {
return ret;
}
fn cpu_parse(qt_parse_step_two: Vec<&str>) -> u64 {
let second_fragment: &str = qt_parse_step_two[1];
fn cpu_parse(qt_parse_step_two: Vec<String>) -> u64 {
let second_fragment: &str = &qt_parse_step_two[1];
match second_fragment {
// "architecture" => {
// 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;
let fbs = &mut FB_REQ.get_response().get().unwrap().framebuffers();
let second_fragment: &str = qt_parse_step_two[1];
let fbs = &FB_REQ.get_response().get().unwrap().framebuffers();
let second_fragment: &str = &qt_parse_step_two[1];
match second_fragment {
"fb0" => {
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 {
"ptr" => {
let ptr = fb_front.address.as_ptr().unwrap();

View file

@ -9,16 +9,12 @@ use log::Record;
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
let msg_vec = block_read(mem_addr, length);
let log_level = msg_vec[0];
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 log_level = msg_vec.last().unwrap();
let file_name = "None";
let line_number = 0;
match core::str::from_utf8(&str) {
match core::str::from_utf8(&msg_vec[..msg_vec.len()]) {
Ok(strr) => {
use log::Level::*;
let log_level = match log_level {

View file

@ -17,54 +17,13 @@ pub enum MemoryQuotaType {
}
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);
vm.registers[1] = hbvm::value::Value(ptr as u64);
vm.registers[2] = hbvm::value::Value(4096);
Ok(())
}
#[inline(always)]
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
const BLOCK_SIZE: usize = 64;
let mut remaining = count * size;
if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
let mut buffer = [0u8; BLOCK_SIZE];
let mut buffer_size = size;
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
buffer
.as_mut_ptr()
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
buffer_size *= 2;
}
let buffer_ptr = buffer.as_ptr() as *const u64;
while (dest as usize) & 7 != 0 && remaining >= 8 {
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
dest = dest.add(1);
remaining -= 1;
}
while core::intrinsics::likely(remaining >= 8) {
*(dest as *mut u64) = *buffer_ptr;
dest = dest.add(8);
remaining -= 8;
}
if remaining > 0 {
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
}
}
#[inline(always)]
pub fn memory_msg_handler(
vm: &mut Vm,
mem_addr: u64,
@ -73,35 +32,40 @@ pub fn memory_msg_handler(
let msg_vec = block_read(mem_addr, length);
let msg_type = msg_vec[0];
match msg_type {
0 => unsafe {
0 => {
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(
page_count as usize * 4096,
8,
));
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
let ptr = unsafe {
alloc(Layout::from_size_align_unchecked(
page_count as usize * 4096,
4096,
))
};
vm.registers[1] = hbvm::value::Value(ptr as u64);
log::debug!("Kernel ptr: {:x}", ptr as u64);
},
}
1 => unsafe {
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);
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
dealloc(
mptr as *mut u8,
Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
)
},
unsafe {
dealloc(
mptr as *mut u8,
Layout::from_size_align_unchecked(page_count as usize * 4096, 4096),
)
}
}
2 => {
use MemoryQuotaType::*;
let quota_type = match msg_vec[1] {
let quota_type = match msg_vec[0] {
0 => NoQuota,
1 => SoftQuota,
2 => HardQuota,
@ -118,24 +82,10 @@ pub fn memory_msg_handler(
)
}
3 => {
let page_count = msg_vec[1];
let page_count = msg_vec[0];
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);
}

View file

@ -22,19 +22,21 @@ pub enum 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 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;
let string_vec = block_read(strptr, strlen);
let string = core::str::from_utf8(string_vec).expect("Our bytes should be valid utf8");
// info!("Length {}", msg_vec.len());
use ServiceEventType::*;
match sds_event_type {
CreateService => {
let string =
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
let ret = sds_create_service(string);
vm.registers[1] = hbvm::value::Value(ret as u64);
}
DeleteService => todo!(),
SearchServices => {
let string =
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
let ret = sds_search_service(string);
vm.registers[1] = hbvm::value::Value(ret as u64);
}

View file

@ -30,29 +30,30 @@ impl Memory {
}
impl hbvm::mem::Memory for Memory {
#[inline(always)]
#[inline]
unsafe fn load(
&mut self,
addr: Address,
target: *mut u8,
count: usize,
) -> 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(())
}
#[inline(always)]
#[inline]
unsafe fn store(
&mut self,
addr: Address,
source: *const u8,
count: usize,
) -> 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(())
}
#[inline(always)]
#[inline]
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
(addr.get() as *const T).read()
}

View file

@ -97,7 +97,7 @@ impl HandlePageFault for PageFaultHandler {
#[inline(always)]
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)]

View file

@ -49,7 +49,9 @@ impl<'a> IpcBuffer<'a> {
pub fn push(&mut self, msg: Message) {
match &self.buffer {
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> {

View file

@ -1,15 +1,18 @@
use {alloc::vec::Vec, hashbrown::HashMap};
use {
alloc::{string::String, vec::Vec},
hashbrown::HashMap,
};
#[derive(Debug, PartialEq, Clone)]
pub struct Type {}
#[derive(Debug, PartialEq, Clone)]
pub struct Funct<'a> {
takes: Vec<&'a str>,
gives: Vec<&'a str>,
pub struct Funct {
takes: Vec<String>,
gives: Vec<String>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Protocol<'a> {
types: HashMap<&'a str, Type>,
fns: HashMap<&'a str, Funct<'a>>,
fns: HashMap<&'a str, Funct>,
}
impl<'a> Protocol<'a> {
pub fn void() -> Self {

View file

@ -50,6 +50,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
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 disp = xml::XMLElement::new("display_0");
@ -57,7 +58,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
disp.set_attribute("height", fb1.height);
disp.set_attribute("bpp", fb1.bpp);
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!(

View file

@ -3,10 +3,8 @@
//! 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]
#![feature(
slice_split_once,
exclusive_wrapper,
new_uninit,
core_intrinsics,
abi_x86_interrupt,
alloc_error_handler,
ptr_sub_ptr,
@ -15,7 +13,8 @@
pointer_is_aligned_to
)]
#![test_runner(crate::test_runner)]
#![allow(dead_code, internal_features)]
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
#![allow(dead_code)]
extern crate alloc;
mod allocator;

View file

@ -4,14 +4,15 @@
/// Used when tab `\t` in hardware is not known and we will default to two spaces
pub const TAB: &str = " ";
// NOTE: this only reduces the code duplication in source code not in generated code!
// Written by Yours Truly: Munir
/// A simple macro to reduce code duplication when we use TAB internally
#[macro_export]
macro_rules! tab {
($num:expr) => {
($num:expr) => {
TAB.repeat($num)
};
}
}
// 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 {
($devtree:expr, $dev_type_vec:expr) => {
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());
}
};
}
@ -49,4 +50,4 @@ macro_rules! cpu_features {
$result_vec.push(("rdseed", rdseed));
$result_vec.push(("x2apic", x2));
};
}
}

View file

@ -1,22 +1,22 @@
{
"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": "",
"code-model": "kernel",
"pre-link-args": {
"ld.lld": [
"--gc-sections",
"--script=kernel/lds/x86_64.ld"
]
}
"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": "",
"code-model": "kernel",
"pre-link-args": {
"ld.lld": [
"--gc-sections",
"--script=kernel/lds/x86_64.ld"
]
}
}

View file

@ -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"
]
}
}

View file

@ -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

View file

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

View file

@ -63,7 +63,7 @@ impl Package {
build_cmd,
}
}
pub fn build(&self) -> std::io::Result<()> {
pub fn build(&self) {
if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
@ -71,24 +71,15 @@ impl Package {
let mut bytes = Vec::new();
// compile here
hblang::run_compiler(
let _ = hblang::run_compiler(
&path,
Options {
fmt: true,
optimize: true,
..Default::default()
},
&mut bytes,
)?;
hblang::run_compiler(
&path,
Options {
optimize: true,
..Default::default()
},
&mut bytes,
)?;
);
let _ = hblang::run_compiler(&path, Default::default(), &mut bytes);
match std::fs::create_dir("target/programs") {
Ok(_) => (),
@ -97,17 +88,15 @@ impl Package {
}
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
bytes.clear();
hblang::run_compiler(
let _ = hblang::run_compiler(
&path,
Options {
dump_asm: true,
optimize: true,
..Default::default()
},
&mut bytes,
)?;
);
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
}
Ok(())
}
}

View file

@ -1,3 +1,5 @@
// #![allow(unused)]
mod dev;
use {
@ -6,10 +8,11 @@ use {
error_stack::{bail, report, Context, Report, Result, ResultExt},
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
std::{
// fmt::Display,
fs::{self, File},
io::{self, Write},
path::Path,
process::{exit, Command, Stdio},
process::{exit, Command},
},
toml::Value,
};
@ -18,9 +21,6 @@ fn main() -> Result<(), Error> {
let mut args = std::env::args();
args.next();
log::set_logger(&hblang::Logger).unwrap();
log::set_max_level(log::LevelFilter::Error);
match args.next().as_deref() {
Some("build" | "b") => {
let mut release = false;
@ -35,8 +35,6 @@ fn main() -> Result<(), Error> {
target = Target::Riscv64Virt;
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
target = Target::Aarch64;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else {
return Err(report!(Error::InvalidSubCom));
}
@ -48,7 +46,6 @@ fn main() -> Result<(), Error> {
let mut release = false;
let mut debuginfo = false;
let mut target = Target::X86_64;
let mut do_accel = true;
for arg in args {
if arg == "-r" || arg == "--release" {
release = true;
@ -58,17 +55,13 @@ fn main() -> Result<(), Error> {
target = Target::Riscv64Virt;
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
target = Target::Aarch64;
} else if arg == "--noaccel" {
do_accel = false;
} else if arg == "avx2" {
target = Target::X86_64Avx2;
} else {
return Err(report!(Error::InvalidSubCom));
}
}
build(release, target, debuginfo)?;
run(release, target, do_accel)
run(release, target)
}
Some("help" | "h") => {
println!(concat!(
@ -78,10 +71,8 @@ fn main() -> Result<(), Error> {
" help (h): Print this message\n",
" run (r): Build and run AbleOS in QEMU\n\n",
"Options for build and run:\n",
" -r / --release: build in release mode\n",
" -d / --debuginfo: build with debug info\n",
" --noaccel: run without acceleration (e.g, no kvm)\n",
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
" -r: build in release mode",
" [target]: sets target"
),);
Ok(())
}
@ -204,25 +195,21 @@ TERM_BACKDROP={}
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
// let mut real_modules = modules.clone();
modules
.into_iter()
.map(|(_, value)| -> Result<(), io::Error> {
if value.is_table() {
let path = get_path_without_boot_prefix(
value.get("path").expect("You must have `path` as a value"),
)
.unwrap()
.split(".")
.next()
.unwrap();
let p = Package::load_from_file(
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
);
p.build()?;
}
Ok(())
})
.for_each(drop);
modules.into_iter().for_each(|(_, value)| {
if value.is_table() {
let path = get_path_without_boot_prefix(
value.get("path").expect("You must have `path` as a value"),
)
.unwrap()
.split(".")
.next()
.unwrap();
let p = Package::load_from_file(
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
);
p.build();
}
});
modules.into_iter().for_each(|(_key, value)| {
if value.is_table() {
let path = value.get("path").expect("You must have `path` as a value");
@ -309,9 +296,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
if target == Target::Aarch64 {
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() {
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
@ -325,10 +309,6 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
path.push_str("_x86-64");
"target/x86_64-ableos"
}
Target::X86_64Avx2 => {
path.push_str("_x86-64");
"target/x86_64_v3-ableos"
}
Target::Riscv64Virt => "target/riscv64-virt-ableos",
Target::Aarch64 => {
path.push_str("_aarch64");
@ -351,63 +331,25 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
.change_context(Error::Io)
}
fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
let target_str = match target {
Target::X86_64 | Target::X86_64Avx2 => "qemu-system-x86_64",
Target::Riscv64Virt => "qemu-system-riscv64",
Target::Aarch64 => "qemu-system-aarch64",
fn run(release: bool, target: Target) -> Result<(), Error> {
let mut com = match target {
Target::X86_64 => Command::new("qemu-system-x86_64"),
Target::Riscv64Virt => Command::new("qemu-system-riscv64"),
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 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"
};
match target {
Target::X86_64 | Target::X86_64Avx2 => {
Target::X86_64 => {
#[rustfmt::skip]
com.args([
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
"-drive", "file=target/disk.img,format=raw",
"-device", "vmware-svga",
// "-device", "vmware-svga",
"-m", "2G",
"-smp", "1",
"-parallel", "none",
"-monitor", "none",
"-machine", accel,
"-cpu", "max",
// "-machine", "accel=kvm",
"-cpu", "Broadwell",
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
]);
}
@ -452,7 +394,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
let (ovmf_url, ovmf_path) = match target {
Target::X86_64 | Target::X86_64Avx2 => (
Target::X86_64 => (
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
"target/RELEASEX64_OVMF.fd",
),
@ -474,12 +416,12 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
Ok(_) => return Ok(ovmf_path.to_owned()),
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
};
let req = ureq::get(ovmf_url)
.call()
let mut bytes = reqwest::blocking::get(ovmf_url)
.map_err(Report::from)
.change_context(OvmfFetchError::Fetch)?;
std::io::copy(&mut req.into_reader(), &mut file)
bytes
.copy_to(&mut file)
.map_err(Report::from)
.change_context(OvmfFetchError::Io)?;
@ -501,7 +443,6 @@ impl Context for OvmfFetchError {}
#[derive(Clone, Copy, PartialEq, Eq)]
enum Target {
X86_64,
X86_64Avx2,
Riscv64Virt,
Aarch64,
}

Binary file not shown.

Binary file not shown.

View file

@ -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: 66 B

View file

@ -0,0 +1 @@
# dt_api

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@ ApplicationInfo := struct {
pNext: ^int,
application_name: ^u8,
application_version: int,
engine_name: ^u8,
engine_name: int,
engine_version: int,
api_version: int,
}

View file

@ -64,4 +64,4 @@ RightSuper := KeyCode.(312)
Mode := KeyCode.(313)
/* Multi-key compose key */
Compose := KeyCode.(314)
Compose := KeyCode.(314)

View file

@ -1,30 +0,0 @@
# Images
- General over image format
- Support formats:
- PNG
- 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

View file

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

View file

@ -1,38 +1,30 @@
svga := @use("svga.hb")
software := @use("software.hb")
image := @use("image.hb")
text := @use("text.hb")
// default mode
mode := software
init := mode.init
doublebuffer := mode.doublebuffer
Surface := mode.Surface
new_surface := mode.new_surface
surface_from_ptr := mode.surface_from_ptr
clone_surface := mode.clone_surface
free_surface := mode.free_surface
index := mode.index
indexptr := mode.indexptr
// Colours
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
white := Color.(255, 255, 255, 255)
black := Color.(0, 0, 0, 255)
gray := Color.(127, 127, 127, 255)
red := Color.(0, 0, 205, 255)
green := Color.(0, 205, 0, 255)
yellow := Color.(0, 205, 205, 255)
blue := Color.(205, 0, 0, 255)
magenta := Color.(205, 0, 205, 255)
cyan := Color.(205, 205, 0, 255)
light_gray := Color.(229, 229, 229, 255)
light_red := Color.(0, 0, 255, 255)
light_green := Color.(0, 255, 0, 255)
light_yellow := Color.(0, 255, 255, 255)
light_blue := Color.(255, 0, 0, 255)
light_magenta := Color.(255, 0, 255, 255)
light_cyan := Color.(255, 255, 0, 255)
Color := mode.Color
white := mode.white
black := mode.black
gray := mode.gray
red := mode.red
green := mode.green
yellow := mode.yellow
blue := mode.blue
magenta := mode.magenta
cyan := mode.cyan
light_gray := mode.light_gray
light_red := mode.light_red
light_green := mode.light_green
light_yellow := mode.light_yellow
light_blue := mode.light_blue
light_magenta := mode.light_magenta
light_cyan := mode.light_cyan
// Drawing
put_pixel := mode.put_pixel
@ -40,12 +32,16 @@ put_rect := mode.put_rect
put_filled_rect := mode.put_filled_rect
put_line := mode.put_line
clear := mode.clear
put_surface := mode.put_surface
put_text := mode.put_text
// thanks peony for these three!
put_trirect := mode.put_trirect
put_vline := mode.put_vline
put_hline := mode.put_hline
// Display
sync := mode.sync
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
// Math
UVec2 := struct {x: uint, y: uint}
IVec2 := struct {x: int, y: int}

View file

@ -1,131 +1,197 @@
.{math, memory, dt} := @use("../../stn/src/lib.hb");
.{Color, text} := @use("lib.hb");
.{get_glyph, Font} := text;
.{Vec2} := math
.{math, memory} := @use("../../stn/src/lib.hb");
.{dt_get} := @use("../../dt_api/src/lib.hb");
.{IVec2} := @use("lib.hb")
Surface := struct {
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)
// 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,
width: uint,
height: uint,
width: int,
height: int,
partitions: int,
pixels: int,
bb_pages: int,
double_buffer: bool,
}
new_surface := fn(width: uint, height: uint): Surface {
return .(
@inline(memory.alloc, Color, width * height),
init := fn(): void {
width := dt_get("framebuffer/fb0/width\0")
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,
height,
)
partitions,
pixels,
bb_pages: pages,
double_buffer: true,
}
return
}
surface_from_ptr := fn(ptr: ^Color, width: uint, height: uint): Surface {
return .(
ptr,
width,
height,
)
}
clone_surface := fn(surface: ^Surface): Surface {
new := new_surface(surface.width, surface.height)
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
return new
}
// ! is broken, check memory.free function
free_surface := fn(surface: Surface): void {
return @inline(memory.free, Color, surface.buf, @intcast(surface.width * surface.height), false)
}
framebuffer := @as(^Color, idk)
init := fn(doublebuffer: bool): Surface {
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
width := dt.get(uint, "framebuffer/fb0/width\0")
height := dt.get(uint, "framebuffer/fb0/height\0")
if doublebuffer {
return new_surface(width, height)
doublebuffer := fn(enable: bool): void {
if enable {
ctx.buf = ctx.bb
} else {
return .(framebuffer, width, height)
ctx.buf = ctx.fb
}
}
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
}
sync := fn(surface: Surface): void {
// vague safety
if surface.buf == framebuffer {
return
}
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
}
index := fn(surface: Surface, x: uint, y: uint): uint {
return x + surface.width * y
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + @inline(index, surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
*@inline(indexptr, surface, pos.x, pos.y) = color
ctx.double_buffer = enable
return
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
@inline(memory.set, Color, &color, bottom_start_idx, @bitcast(tr.x))
top_start_idx += surface.width
bottom_start_idx -= surface.width
rows_to_fill -= 2
create_back_buffer := fn(pages: int): ^Color {
if pages <= 0xFF {
return @bitcast(@inline(memory.request_page, pages))
}
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, @bitcast(tr.x))
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)
}
clear := fn(color: Color): void {
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
}
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
*right_start_idx = color
start_idx += surface.width
right_start_idx += surface.width
sync := fn(): void {
if ctx.double_buffer {
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
}
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return
}
put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
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
if dy < 0 {
yi = -1
dy = -dy
}
D := @as(int, 2) * dy - dx
D := 2 * dy - dx
y := p0.y
x := p0.x
loop if x == p1.x break else {
*@inline(indexptr, surface, x, y) = color
*(ctx.buf + @inline(screenidx, x, y)) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
@ -137,19 +203,19 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
return
}
put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
dx := @as(int, @bitcast(p1.x - p0.x))
dy := @as(int, @bitcast(p1.y - p0.y))
put_line_high := fn(p0: IVec2, p1: IVec2, color: Color): void {
dx := p1.x - p0.x
dy := p1.y - p0.y
xi := 1
if dy < 0 {
xi = -1
dx = -dx
}
D := @as(int, 2) * dx - dy
D := 2 * dx - dy
x := p0.x
y := p0.y
loop if y == p1.y break else {
*@inline(indexptr, surface, x, y) = color
*(ctx.buf + @inline(screenidx, x, y)) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
@ -161,160 +227,35 @@ put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Col
return
}
put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
if math.abs(uint, p1.y - p0.y) < math.abs(uint, p1.x - p0.x) {
put_line := fn(p0: IVec2, p1: IVec2, color: Color): void {
if @inline(math.abs, p1.y - p0.y) < @inline(math.abs, p1.x - p0.x) {
if p0.x > p1.x {
@inline(put_line_low, surface, p1, p0, color)
@inline(put_line_low, p1, p0, color)
} else {
@inline(put_line_low, surface, p0, p1, color)
@inline(put_line_low, p0, p1, color)
}
} else {
if p0.y > p1.y {
@inline(put_line_high, surface, p1, p0, color)
@inline(put_line_high, p1, p0, color)
} else {
@inline(put_line_high, surface, p0, p1, color)
@inline(put_line_high, p0, p1, color)
}
}
return
}
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
rows_to_copy := top.height
top_cursor := top.buf
bottom_cursor := top.buf + top.width * (top.height - 1)
loop if rows_to_copy <= 1 break else {
if flip_v {
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width))
} else {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width))
}
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += top.width
bottom_cursor -= top.width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
}
set_height := fn(new: int): void {
return
}
// peony-made
put_trirect := fn(surface: Surface, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void {
step := Vec2(int).(1, 1)
if size.x < 0 {
step.x = -1
}
if size.y < 0 {
step.y /= @bitcast(size.x)
}
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)
}
set_width := fn(new: int): void {
return
}
// peony-made
put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): void {
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
loop if y == y1 break else {
*@inline(indexptr, surface, x, y) = color
y += 1
}
return
dimensions := fn(): IVec2 {
return .(ctx.width, ctx.height)
}
// peony-made
put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): void {
if x1 < x0 {
tmp := x0
x0 = x1
x1 = tmp
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
return
}
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
cursor := Vec2(uint).(pos.x, pos.y)
current_char := str
loop if *current_char == 0 break else {
if *current_char == 10 {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
current_char += 1
continue
}
glyph_data := @inline(get_glyph, font, @intcast(*current_char))
if glyph_data == idk {
current_char += 1
continue
}
if cursor.x % surface.width + font.width >= surface.width {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
}
if cursor.y + font.height > surface.height break
dest := @inline(indexptr, surface, cursor.x, cursor.y)
src := glyph_data
rows_remaining := font.height
loop if rows_remaining == 0 break else {
byte := *glyph_data
pixel_dest := dest
mask := @as(u8, 0x80)
bits_remaining := font.width
loop if bits_remaining == 0 break else {
if (byte & mask) != 0 {
*pixel_dest = color
}
pixel_dest += 1
mask >>= 1
if mask == 0 {
glyph_data += 1
byte = *glyph_data
mask = 0x80
}
bits_remaining -= 1
}
glyph_data += 1
dest += surface.width
rows_remaining -= 1
}
cursor.x += font.width + font.char_gap
current_char += 1
}
set_dimensions := fn(new: IVec2): void {
return
}

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

View file

@ -1,75 +0,0 @@
.{log} := @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,
has_unicode_table: bool,
line_gap: uint,
char_gap: uint,
}
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 idk
}
psf += @sizeof(PSF1Header)
return .(
psf,
8,
@intcast(header.character_size),
256,
@intcast(header.character_size),
false,
0,
0,
)
}
font_from_psf2 := fn(psf: ^u8): Font {
header := @as(^PSF2Header, @bitcast(psf))
if header.magic != 0x864AB572 {
log.error("failed to load psf font: not a psf2 font, idiot\0")
return idk
}
psf += header.header_size
return .(
psf,
@intcast(header.width),
@intcast(header.height),
@intcast(header.num_glyph),
@intcast(header.bytes_per_glyph),
(header.flags & 1) != 0,
0,
0,
)
}
get_glyph := fn(font: Font, index: uint): ^u8 {
return font.data + index * font.bytes_per_glyph
}

View file

@ -1,27 +1,22 @@
string := @use("string.hb")
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): ^Expr {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
}
write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
return @eca(3, buffer_id, msg, @sizeof(Expr))
}
recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
receive_message := fn(buffer_id: int, memory_map_location: ^u8, length: int): ^u8 {
return @eca(4, buffer_id, memory_map_location, length)
}
write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
send_message := fn(msg: ^u8, buffer_id: int, length: int): void {
return @eca(3, buffer_id, msg, length)
}
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
create := fn(msg: ^u8): int {
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
msg_length := @inline(string.length, msg);
*msg = 0
return @eca(3, 0, msg, msg_length)
}
search := fn(msg: ^u8): int {
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
msg_length := @inline(string.length, msg);
*msg = 3
return @eca(3, 0, msg, msg_length)
}

View file

@ -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))
}

View file

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

View file

@ -1,9 +1,9 @@
acs := @use("acs.hb")
string := @use("string.hb")
log := @use("log.hb")
memory := @use("memory.hb")
buffer := @use("buffer.hb")
math := @use("math.hb")
random := @use("random.hb")
file := @use("file_io.hb")
dt := @use("dt.hb")
file := @use("file_io.hb")

View file

@ -1,13 +1,15 @@
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, LogMsg.(level, message, @inline(string.length, message)), @sizeof(LogMsg))
return @eca(3, 1, message, message_length + 1)
}
error := fn(message: ^u8): void return @inline(log, 0, message)
warn := fn(message: ^u8): void return @inline(log, 1, message)
info := fn(message: ^u8): void return @inline(log, 2, message)
debug := fn(message: ^u8): void return @inline(log, 3, message)
trace := fn(message: ^u8): void return @inline(log, 4, message)
error := fn(message: ^u8): void return log(message, 0)
warn := fn(message: ^u8): void return log(message, 1)
info := fn(message: ^u8): void return log(message, 2)
debug := fn(message: ^u8): void return log(message, 3)
trace := fn(message: ^u8): void return log(message, 4)

View file

@ -1,59 +1,15 @@
abs := fn($Expr: type, x: Expr): Expr {
mask := x >> @intcast(@sizeof(Expr) - 1)
shift := 31
// following only work for: int
abs := fn(x: int): int {
mask := x >> shift
return (x ^ mask) - mask
}
min := fn($Expr: type, a: Expr, b: Expr): Expr {
min := fn(a: int, b: int): int {
c := a - b
return b + (c & c >> @intcast(@sizeof(Expr) - 1))
return b + (c & c >> shift)
}
max := fn($Expr: type, a: Expr, b: Expr): Expr {
max := fn(a: int, b: uint): int {
c := a - b
return a - (c & c >> @intcast(@sizeof(Expr) - 1))
}
signum := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
} else if x < @as(Expr, @intcast(0)) {
return -1
} else {
return 0
}
}
signincl := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
}
return -1
}
Vec2 := fn($Expr: type): type {
return struct {x: Expr, y: Expr}
}
SIN_TABLE := @as([int; 91], @bitcast(@embed("./assets/sin_table")))
sin := fn(theta: int, amplitude: uint): int {
if theta < 0 {
theta += (-theta / 360 + 1) * 360
} else if theta >= 360 {
theta -= theta / 360 * 360
}
quadrant := theta / 90
index := theta % 90
if @as(u8, @intcast(quadrant)) == @as(u8, 1) {
index = 90 - index
}
value := SIN_TABLE[@bitcast(index)]
if quadrant >= 2 {
value = -value
}
return (value * @bitcast(amplitude) + 5000) / 10000
}
cos := fn(theta: int, amplitude: uint): int {
return @inline(sin, theta + 90, amplitude)
return a - (c & c >> shift)
}

View file

@ -1,67 +1,39 @@
PAGE_SIZE := 4096
MAX_ALLOC := 0xFF
MAX_FREE := 0xFF
calc_pages := fn($Expr: type, num: uint): uint {
return 1 + @sizeof(Expr) * num / PAGE_SIZE
request_page := fn(page_count: u8): ^u8 {
msg := "\{00}\{01}xxxxxxxx\0"
msg_page_count := msg + 1;
*msg_page_count = page_count
return @eca(3, 2, msg, 12)
}
alloc := fn($Expr: type, num: uint): ^Expr {
pages := @inline(calc_pages, Expr, num)
if pages <= MAX_ALLOC {
return @bitcast(request_page(@intcast(pages)))
}
ptr := request_page(0xFF)
remaining := pages - MAX_ALLOC
loop if remaining < MAX_ALLOC break else {
_ := request_page(@intcast(MAX_ALLOC))
remaining -= MAX_ALLOC
}
_ := request_page(@intcast(remaining))
return @bitcast(ptr)
release_page := fn(ptr: ^u8, page_count: u8): void {
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)
}
// ! stub
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
return
}
OutbMsg := struct {a: u8, b: u8, addr: u16, value: u8}
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}
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))
}
InbMsg := packed struct {a: u8, b: u8, addr: u16}
inb := fn(addr: u16): u8 {
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
}
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
outl := fn(addr: u16, value: u32): void {
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 {
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))
}

View file

@ -1,7 +1,7 @@
any := fn($Expr: type): Expr {
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
integer := fn(): int {
return @eca(3, 4)
}
range := fn($Expr: type, min: Expr, max: Expr): Expr {
return @inline(any, Expr) % (max - min) + @intcast(1) + min
integer_range := fn(min: int, max: int): int {
return @eca(3, 4) % (max - min + 1) + min
}

View file

@ -1,66 +1,42 @@
length := fn(ptr: ^u8): uint {
len := @as(uint, 0)
// loop if *(ptr + len) == 0 return len else len += 1
length := fn(ptr: ^u8): int {
len := 0
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
display_int := fn(num: int, p: ^u8): ^u8 {
ptr := p
negative := num < 0
if negative {
num = -num
}
if radix == 2 {
*ptr = 48
ptr += 1;
*ptr = 98
ptr += 1
} else if radix == 16 {
*ptr = 48
ptr += 1;
*ptr = 120
ptr += 1
} else if radix == 8 {
*ptr = 48
ptr += 1;
*ptr = 111
ptr += 1
}
digits_start := ptr
if num == 0 {
*ptr = 48
ptr += 1
} else {
loop if num == 0 break else {
digit := num % @bitcast(radix)
if digit < 10 {
*ptr = @intcast(digit) + 48
} else {
*ptr = @intcast(digit) + 55
}
*ptr = num % 10 + 48
ptr += 1
num /= @bitcast(radix)
num /= 10
}
}
if negative {
*ptr = 45
ptr += 1
};
*ptr = 0
@inline(reverse, digits_start)
@inline(reverse, p)
return p
}
reverse := fn(s: ^u8): void {
i := @as(uint, 0)
j := @inline(length, s) - 1
temp := @as(u8, 0)
//reverse a string, don't remove digits
len := 0
loop if *(s + len) == 0 break else len += 1
i := 0
j := len - 1
temp := 0
loop if i >= j break else {
temp = *(s + i);
*(s + i) = *(s + j);

View file

@ -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 {
dt.get(void, "framebuffer/fb0/width\0")
dt.get(void, "cpu/cpu0/architecture\0")
main := fn(): int {
dt_api.dt_get("framebuffer/fb0/width\0")
dt_api.dt_get("cpu/cpu0/architecture\0")
// Checking if the first detected serial port is memory mapped or port mapped
// 0 -> memory mapped
// 1 -> port mapped
dt.get(void, "serial_ports/sp0/mapping\0")
dt_get("serial_ports/sp0/mapping\0")
return
return 0
}

View file

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

View file

@ -63,7 +63,7 @@ VolumeName := [u8; 11]
SystemIdentifierString := [u8; 8]
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]
@ -100,10 +100,9 @@ ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
log.warn("EBR-Signature sanity check failed\0")
}
// ! comparison between [u8] is not supported in hblang
// if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
// log.warn("EBR-Signature-Identifier-String sanity check failed\0")
// }
if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
log.warn("EBR-Signature-Identifier-String sanity check failed\0")
}
return 0
}
@ -132,21 +131,21 @@ new_ebr := fn(): ExtendedBootRecord {
)
}
VALID_LEAD_FS_INFO := @as(u32, 0x41615252)
VALID_TRAIL_FS_INFO := @as(u32, 0xAA550000)
VALID_LEAD_FS_INFO := 0x41615252
VALID_TRAIL_FS_INFO := 0xAA550000
FSInfo := struct {
// Must be 0x41615252 to indicate a valid FSInfo structure
lead_signature: u32,
lead_reserved: [u8; 480],
// If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. However, this value might be incorrect and should at least be range checked (<= volume cluster count)
// If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. However, this value might be incorrect and should at least be range checked (<= volume cluster count)
last_known_free_cluster_count: u32,
last_known_avalible_cluster: u32,
trail_reserved: [u8; 12],
trail_signature: u32,
}
fs_info_sanity_check := fn(fs_info: FSInfo): uint {
fs_info_sanity_check := fn(fs_info: FSInfo): int {
ret := 0
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
ret &= 1

View file

@ -7,7 +7,7 @@ FileName := [u8; 11]
FileEntry := struct {
file_name: FileName,
attributes: u8,
// We could use this byte for something but we likely will not
// We could use this byte for something but we likely will not
nt_reserved: u8,
hundredths_seconds_creation: u8,
creation_time: datetime.time,

View file

@ -16,7 +16,7 @@ FAT12 := 1
FAT16 := 2
FAT32 := 3
calculate_fat_type := fn(sector_size: uint, total_clusters: uint): uint {
calculate_fat_type := fn(sector_size: int, total_clusters: int): int {
if sector_size == 0 {
return ExFAT
} else if total_clusters < 4085 {

View file

@ -1,88 +1,11 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, random, log} := stn;
.{Vec2} := stn.math
.{string, memory, buffer} := stn
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
Window := struct {
// TODO: Replace this with widgets
implicit_framebuffer: render.Surface,
width: int,
height: int,
x: int,
y: int,
}
main := fn(): int {
win_buff := buffer.create("XHorizon\0")
screen := render.init(true)
// Clear the screen to black.
render.clear(screen, render.black)
window := render.new_surface(screen.width / 3, screen.height / 3)
x := 0
mem_buf := memory.request_page(1)
color := random.any(render.Color)
side := window.width / 8
vel_inner := Vec2(int).(1, 1)
pos_inner := Vec2(uint).((window.width - side) / 2, (window.height - side) / 2)
a := buffer.create("XHorizon\0")
loop {
// Clear the screen
render.clear(screen, render.black)
// TODO: Read the window buffer here
{
ret := buffer.recv([u8; 4096], win_buff, mem_buf)
if ret == 0 {
log.info("No messages\0")
}
}
if pos_inner.x == 0 | pos_inner.x == window.width - side {
vel_inner.x = -vel_inner.x
color = random.any(render.Color)
}
if pos_inner.y == 20 | pos_inner.y == window.height - side {
vel_inner.y = -vel_inner.y
color = random.any(render.Color)
}
// TODO: Get windows out of a collection and iter through
window_count := 0
loop {
render.clear(window, render.black)
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
// Draw the decorators
{
render.put_rect(window, .(0, 0), .(window.width - 1, window.height - 1), render.white)
render.put_rect(window, .(0, 0), .(window.width - 1, 20), render.white)
}
render.put_filled_rect(window, pos_inner, .(side, side), color)
// Apply the image to the screen
pos := Vec2(uint).(x, 100)
render.put_surface(screen, window, pos, false)
if window_count >= 1 {
x = 0
break
}
window_count += 1
x += screen.width / 2
}
pos_inner += @bitcast(vel_inner)
// Sync the screen
render.sync(screen)
}
return 0

View file

@ -8,33 +8,28 @@ ignim := @use("../../../libraries/ignim/src/lib.hb");
.{errors} := ignim
main := fn(): int {
x := 0
// loop if x > 10000 break else x += 1
windowing_system_buffer := buffer.create("XHorizon\0")
windowing_system_buffer := buffer.search("XHorizon\0")
// TODO: get WindowID
wid := create_window(windowing_system_buffer)
if false {
program_name := "Horizon Testing Program\0"
program_version := ignim.version.make_version(0, 1, 0)
engine_name := "None\0"
engine_version := ignim.version.make_version(0, 0, 0)
api_version := ignim.version.make_api_version(0, 1, 0, 0)
create_window(windowing_system_buffer)
app_info := ignim.application.new_application_info(program_name, program_version, engine_name, engine_version, api_version)
program_name := "Horizon Testing Program\0"
program_version := ignim.version.make_version(0, 1, 0)
engine_name := "None\0"
engine_version := ignim.version.make_version(0, 0, 0)
api_version := ignim.version.make_api_version(0, 1, 0, 0)
create_info := ignim.instance.new_create_info(&app_info)
app_info := ignim.application.new_application_info(program_name, program_version, engine_name, engine_version, api_version)
instance := ignim.instance.void_instance()
create_info := ignim.instance.new_create_info(&app_info)
// // TODO: recursively follow this https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
ret := ignim.instance.create_instance(&create_info, 0, &instance)
if ret == errors.IncompatibleDriver {
log.error("Driver Incompatible with Vulkan\0")
}
instance := ignim.instance.void_instance()
// TODO: recursively follow this https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
ret := ignim.instance.create_instance(&create_info, 0, &instance)
if ret == errors.IncompatibleDriver {
log.error("Driver Incompatible with Vulkan\0")
}
// TODO: get window from the window system and draw to the surface
return 0
}

View file

@ -1,4 +1,4 @@
.{memory, log, buffer} := @use("../../../libraries/stn/src/lib.hb")
.{memory, log, string, buffer} := @use("../../../libraries/stn/src/lib.hb")
send_byte := fn(byte: u8): u8 {
memory.outb(96, byte)
@ -6,15 +6,18 @@ send_byte := fn(byte: u8): u8 {
}
main := fn(): int {
buf := buffer.create("XKeyboard\0")
_ := send_byte(238)
send_byte(238)
log.info("PS/2 Driver Loaded\0")
if send_byte(238) == 238 {
log.info("PS/2 Keyboard Echoed\0")
}
a := 0
// a += 1
if send_byte(244) == 250 {
log.info("Enabled scanning\0")
}
buf := buffer.create("XKeyboard\0")
ptr := memory.request_page(1)
prev_input := 250
loop {
input := memory.inb(96)
@ -22,7 +25,9 @@ main := fn(): int {
continue
}
prev_input = input
buffer.write(u8, &input, buf)
keycode_str := string.display_int(input, ptr)
log.info(keycode_str)
buffer.send_message(&input, buf, 1)
}
return 0
}

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

View file

@ -6,12 +6,12 @@ render := @use("../../../../libraries/render/src/lib.hb")
note that this may happen too fast for you to notice... */
example := fn(): void {
screen := render.init(true)
render.init()
color := render.light_cyan
n := @as(u8, 1)
loop {
render.clear(screen, color)
render.sync(screen)
render.clear(color)
render.sync()
if (color.b & 255) == 255 | (color.b & 255) == 0 {
n = -n
}

View file

@ -1,37 +0,0 @@
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
a cute image bounces around the screen */
bmp_1 := @embed("./assets/able.bmp")
bmp_2 := @embed("./assets/mini.bmp")
example := fn(): void {
images := [render.Surface].(
render.image.surface_from_bmp(@bitcast(&bmp_1)),
render.image.surface_from_bmp(@bitcast(&bmp_2)),
)
screen := render.init(true)
vel := Vec2(int).(1, 1)
pos := Vec2(uint).(100, 100)
n := 0
loop {
image := images[n]
render.put_surface(screen, image, pos, false)
render.sync(screen)
render.clear(screen, render.black)
if pos.x == 0 | pos.x == screen.width - image.width {
vel.x = -vel.x
n = 1 - n
}
if pos.y == 0 | pos.y == screen.height - image.height {
vel.y = -vel.y
n = 1 - n
}
pos += @bitcast(vel)
}
return
}

View file

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

View file

@ -2,15 +2,16 @@
render := @use("../../../../libraries/render/src/lib.hb")
example := fn(): void {
screen := render.init(false)
render.clear(screen, render.black)
render.init()
render.doublebuffer(false)
render.clear(render.black)
loop {
x := random.range(uint, 0, screen.width)
y := random.range(uint, 0, screen.height)
r := random.range(u8, 0, 255)
g := random.range(u8, 0, 75)
b := random.range(u8, 0, 155)
render.put_pixel(screen, .(x, y), .(b, g, r, 255))
x := random.integer_range(0, 1024)
y := random.integer_range(0, 768)
r := random.integer_range(0, 255)
g := random.integer_range(0, 75)
b := random.integer_range(0, 155)
render.put_pixel(.(x, y), .(b, g, r, 255))
}
return
}

View file

@ -1,31 +1,27 @@
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math;
.{random} := @use("../../../../libraries/stn/src/lib.hb")
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
a square that changes colour bounces around the screen */
the white outline of a square bounces around the screen */
example := fn(): void {
screen := render.init(true)
vel := Vec2(int).(1, 1)
side := screen.width / 8
pos := Vec2(uint).((screen.width - side) / 2, (screen.height - side) / 2)
color := random.any(render.Color)
render.init()
vel := render.IVec2.(1, 1)
pos := render.IVec2.(100, 100)
width := render.width()
height := render.height()
loop {
render.put_filled_rect(screen, pos, .(side, side), color)
render.sync(screen)
render.clear(screen, render.black)
render.put_rect(pos, .(100, 100), render.white)
render.sync()
render.clear(render.black)
if pos.x == 0 | pos.x == screen.width - side {
if pos.x == 0 | pos.x == width - 100 {
vel.x = -vel.x
color = random.any(render.Color)
}
if pos.y == 0 | pos.y == screen.height - side {
if pos.y == 0 | pos.y == height - 100 {
vel.y = -vel.y
color = random.any(render.Color)
}
pos += @bitcast(vel)
pos += vel
}
return
}

View file

@ -0,0 +1,15 @@
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result: (EPILEPSY WARNING)
the screen rapidly flashes red then black */
example := fn(): void {
render.init()
loop {
render.clear(render.red)
render.sync()
render.clear(render.yellow)
render.sync()
}
return
}

View file

@ -1,55 +0,0 @@
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math;
.{random} := @use("../../../../libraries/stn/src/lib.hb")
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
bouncing gradient square inside coloured bouncing box inside black screen */
example := fn(): void {
screen := render.init(true)
image := render.new_surface(screen.width / 3, screen.height / 3)
vel := Vec2(int).(-1, -1)
pos := Vec2(uint).(100, 100)
side := image.width / 8
vel_inner := Vec2(int).(1, 1)
pos_inner := Vec2(uint).((image.width - side) / 2, (image.height - side) / 2)
color := random.any(render.Color)
target_color := random.any(render.Color)
loop {
render.clear(screen, render.black)
render.put_filled_rect(image, pos_inner, .(side, side), color)
render.put_rect(image, pos_inner, .(side, side), render.black)
render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), color)
render.put_surface(screen, image, pos, false)
render.put_rect(image, pos_inner, .(side, side), color)
render.sync(screen)
if pos_inner.x == 0 | pos_inner.x == image.width - side {
vel_inner.x = -vel_inner.x
target_color = random.any(render.Color)
}
if pos_inner.y == 0 | pos_inner.y == image.height - side {
vel_inner.y = -vel_inner.y
target_color = random.any(render.Color)
}
if pos.x == 0 | pos.x == screen.width - image.width {
vel.x = -vel.x
}
if pos.y == 0 | pos.y == screen.height - image.height {
vel.y = -vel.y
}
color += .(
@bitcast(color.b < target_color.b) - @bitcast(color.b > target_color.b),
@bitcast(color.g < target_color.g) - @bitcast(color.g > target_color.g),
@bitcast(color.r < target_color.r) - @bitcast(color.r > target_color.r),
0,
)
pos += @bitcast(vel)
pos_inner += @bitcast(vel_inner)
}
return
}

View file

@ -0,0 +1,8 @@
render := @use("../../../../libraries/render/src/lib.hb")
render.mode = render.svga
example := fn(): void {
render.init()
return
}

View file

@ -1,83 +0,0 @@
render := @use("../../../../libraries/render/src/lib.hb");
.{math, random} := @use("../../../../libraries/stn/src/lib.hb")
Vec2 := math.Vec2
/* expected result:
a grid of green lines scrolling from the left top corner to the right bottom one
with a "target" randomly apperaing in one of them and a "seeker" "catching" it */
example := fn(): void {
screen := render.init(true)
width := screen.width
height := screen.height
cell_size := 0
range := Vec2(uint).(0, 0)
if width > height {
cell_size = width / 40
range = .(39, height / cell_size - 1)
} else {
cell_size = height / 40
range = .(width / cell_size - 1, 39)
}
width -= 1
height -= 1
scroll := 0
target := Vec2(uint).(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
halfcell := cell_size / 2
octcell := cell_size / 8
sevenoctcell := cell_size - octcell
seeker := Vec2(uint).(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
loop {
render.clear(screen, render.black)
target_pixel_coord := target * .(@bitcast(cell_size), @bitcast(cell_size)) + .(scroll, scroll)
render.put_trirect(screen, target_pixel_coord, .(@bitcast(cell_size), @bitcast(cell_size)), render.red, render.light_red)
render.put_hline(screen, target_pixel_coord.y + halfcell, target_pixel_coord.x - octcell, target_pixel_coord.x - sevenoctcell, render.light_red)
render.put_hline(screen, target_pixel_coord.y + halfcell, target_pixel_coord.x + cell_size + octcell, target_pixel_coord.x + cell_size + sevenoctcell, render.light_red)
render.put_vline(screen, target_pixel_coord.x + halfcell, target_pixel_coord.y - octcell, target_pixel_coord.y - sevenoctcell, render.light_red)
render.put_vline(screen, target_pixel_coord.x + halfcell, target_pixel_coord.y + cell_size + octcell, target_pixel_coord.y + cell_size + sevenoctcell, render.light_red)
x := scroll
loop if x > width break else {
render.put_vline(screen, x, 0, height, .(0, 127, 0, 127))
x += cell_size
}
y := scroll
loop if y > height break else {
render.put_hline(screen, y, 0, width, .(0, 127, 0, 127))
y += cell_size
}
render.put_hline(screen, seeker.y * cell_size + halfcell + scroll, 0, width, render.blue)
render.put_vline(screen, seeker.x * cell_size + halfcell + scroll, 0, height, render.blue)
render.sync(screen)
if seeker.x < target.x {
seeker.x += 1
} else if seeker.x > target.x {
seeker.x -= 1
} else if seeker.y < target.y {
seeker.y += 1
} else if seeker.y > target.y {
seeker.y -= 1
} else {
target = .(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
}
scroll += 1
if scroll > cell_size {
scroll = 0
target += .(1, 1)
seeker += .(1, 1)
}
}
return
}

View file

@ -1,23 +0,0 @@
.{Vec2, sin, cos} := @use("../../../../libraries/stn/src/lib.hb").math
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
words */
psf := @embed("../../../../consolefonts/tamsyn/10x20r.psf")
example := fn(): void {
screen := render.init(true)
font := render.text.font_from_psf2(@bitcast(&psf))
t := 0
str := "Hello, World!
This is a test
of multiline rendering\0"
loop {
render.clear(screen, render.black)
render.put_text(screen, font, .(t, t % screen.height), render.red, str)
render.sync(screen)
t += 1
}
return
}

View file

@ -1,3 +1,6 @@
.{example} := @use("./examples/text.hb")
.{example} := @use("./examples/amogus.hb")
main := example
main := fn(): void {
@inline(example)
return
}

View file

@ -1,7 +1,7 @@
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
serial_print := fn(ptr: ^u8): void {
letter := @as(u8, 0)
letter := 0
loop if *ptr == 0 break else {
letter = *ptr
memory.outb(0xF803, letter)
@ -25,7 +25,7 @@ main := fn(): int {
mem := memory.request_page(1)
loop {
ptr := @as(^u8, @eca(4, a, mem, 0x1000))
ptr := @eca(4, a, mem, 0x1000)
if ptr == 0 {
serial_println("No message\0")
}

View file

@ -6,7 +6,7 @@ log_info := fn(): void {
} else {
msg := "XABC\0"
msg_length := @inline(string.length, msg)
@as(void, @eca(3, a, msg, msg_length))
@eca(3, a, msg, msg_length)
}
return

View file

@ -2,7 +2,9 @@ stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, log} := stn
pci := @use("../../../libraries/pci/src/lib.hb");
.{PCIAddress, get_ids, config_read32} := pci
.{PCIAddress, get_ids, config_read32} := pci;
.{dt_get} := @use("../../../libraries/dt_api/src/lib.hb")
reg := @use("./reg.hb")

View file

@ -9,11 +9,5 @@ service_search := fn(): void {
main := fn(): int {
//service_search()
buf := "\0\0\0\0"
x := @as(int, 0)
loop if x > 255 break else {
log.info(string.display_int(x, buf, 2))
x += 1
}
return 0
}

View file

@ -3,12 +3,9 @@
default_entry = 1
timeout = 0
verbose = false
# interface_resolution = "1920x1080x24"
interface_resolution = "1024x768x24"
# interface_resolution = "640x480x24"
# Terminal related settings
# term_wallpaper = "boot:///background.bmp"
term_wallpaper = "boot:///empty-background.bmp"
term_wallpaper = "boot:///background.bmp"
term_background = "008080"
[boot.limine.ableos]
@ -16,24 +13,22 @@ comment = "Default AbleOS boot entry."
protocol = "limine"
kernel_path = "boot:///kernel_${ARCH}"
kernel_cmdline = ""
# resolution = "1920x1080x24"
resolution = "1024x768x24"
# resolution = "640x480x24"
[boot.limine.ableos.modules]
# [boot.limine.ableos.modules.tests]
# path = "boot:///tests.hbf"
# [boot.limine.ableos.modules.serial_driver]
# path = "boot:///serial_driver.hbf"
# [boot.limine.ableos.modules.diskio_driver]
# path = "boot:///diskio_driver.hbf"
[boot.limine.ableos.modules.render_example]
path = "boot:///render_example.hbf"
# [boot.limine.ableos.modules.serial_driver]
# path = "boot:///serial_driver.hbf"
# [boot.limine.ableos.modules.serial_driver_test]
# path = "boot:///serial_driver_test.hbf"
@ -49,8 +44,8 @@ path = "boot:///render_example.hbf"
# [boot.limine.ableos.modules.svga_driver]
# path = "boot:///svga_driver.hbf"
# [boot.limine.ableos.modules.ps2_driver]
# path = "boot:///ps2_driver.hbf"
[boot.limine.ableos.modules.ps2_driver]
path = "boot:///ps2_driver.hbf"
# [boot.limine.ableos.modules.filesystem_fat32]
# path = "boot:///filesystem_fat32.hbf"