diff --git a/.vscode/settings.json b/.vscode/settings.json index e0c3d059..89377283 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,6 @@ { + "editor.insertSpaces": false, + "editor.detectIndentation": false, "rust-analyzer.checkOnSave.allTargets": false, "rust-analyzer.showUnlinkedFileNotification": false, "C_Cpp.errorSquiggles": "disabled" diff --git a/STYLE_GUIDE.md b/STYLE_GUIDE.md new file mode 100644 index 00000000..6298d0e6 --- /dev/null +++ b/STYLE_GUIDE.md @@ -0,0 +1,77 @@ +# Style Guide +This style guide has two modes that a guideline may be. + +`strict` means that prs will be rejected if they do not follow the guideline. + +`loose` means that a pr would be accepted but should later be fixed. + +## Empty Functions | loose +Empty functions are typically a sign of an unfinished program or driver. + +In cases where there is a clear reason to have an empty function it will be allowed. +For example FakeAlloc is only empty functions because it is a example of an the allocator api. + +### Allowed +```rust +/// in example.hb +a := fn(): void {} +``` +### Not Allowed +```rust +/// in fat32.hb +a := fn(): void {} +``` +## Magic Functions | loose +'Magic functions' are what I am calling small helper functions that do one or two things. +### Example +```rust +a := null +magic_a := fn(){ + a = 10 +} +``` +The exact policy I want to have here is a bit fuzzy. I think that functions like this are nice in certain situations and not in others. +Regardless of if you use them or not, put a comment above the function explaining rational. + + +## Magic Numbers | loose +The policy on magic numbers is make them const and have a comment above them. Typically linking to a source of information about the magic number. + +This helps cut down on magic numbers while making acceptable names and atleast half assed documentation. + +Constants are inlined anyways, so its the same thing in the binary. + +```rust +// The standard vga port is mapped at 0xB8000 +$VGA_PTR := 0xB8000 +``` + +## Tabs Vs Spaces | strict +I prefer for hblang code to use hard tabs. + +The rational behind this is that a tab is `1 Indent` which some developers might want to be various different sizes when displayed + +Soft tabs do not allow this user/editor specific as soft tabs always become spaces. + +Bottom line is this is an accessibility feature. + +There are some samples below. +``` +\t means hard tab +\n means new line +\0x20 means space +``` + +### Allowed +```rust +if x == y {\n +\tlog(z)\n +}\n +``` + +### Not Allowed +```rust +if x == y {\n +\0x20\0x20\0x20\0x20log(z)\n +}\n +``` \ No newline at end of file diff --git a/kernel/ktest_macro/src/lib.rs b/kernel/ktest_macro/src/lib.rs index c1c3a8a3..ebff0402 100644 --- a/kernel/ktest_macro/src/lib.rs +++ b/kernel/ktest_macro/src/lib.rs @@ -1,28 +1,85 @@ extern crate proc_macro; extern crate quote; extern crate syn; + use { proc_macro::TokenStream, quote::quote, - syn::{parse_macro_input, ItemFn} + syn::{parse::Parse, parse_macro_input, Expr, ItemFn, Token} }; +struct KtestInput { + lhs: Expr, + _comma: Token![,], + rhs: Expr, +} + +impl Parse for KtestInput { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + Ok(Self { + lhs: input.parse()?, + _comma: input.parse()?, + rhs: input.parse()?, + }) + } +} + +#[proc_macro] +pub fn ktest_eq(item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as KtestInput); + + let lhs = input.lhs; + let rhs = input.rhs; + + let out = quote! { + if #lhs != #rhs { + return Err(name); + } + }; + TokenStream::from(out) +} + +#[proc_macro] +pub fn ktest_neq(item: TokenStream) -> TokenStream { + let input = parse_macro_input!(item as KtestInput); + + let lhs = input.lhs; + let rhs = input.rhs; + + let out = quote! { + if #lhs == #rhs { + return Err(name); + } + }; + TokenStream::from(out) +} + #[proc_macro_attribute] pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as ItemFn); let test_name = &input.sig.ident; + let test_string = test_name.to_string(); let static_var_name = syn::Ident::new( - &format!("__ktest_{}", test_name), + &format!("__ktest_{}", test_name).to_uppercase(), test_name.span(), ); - let out = quote! { - // #[cfg(feature = "ktest")] - #input - // #[cfg(feature = "ktest")] + let block = &input.block; + let out = quote! { + #[cfg(feature = "ktest")] + fn #test_name() -> Result { + use crate::alloc::string::ToString; + let name = #test_string.to_string(); + + #block + + return Ok(name); + } + + #[cfg(feature = "ktest")] #[unsafe(link_section = ".note.ktest")] #[used] - pub static #static_var_name: fn() = #test_name; + pub static #static_var_name: fn() -> Result = #test_name; }; TokenStream::from(out) diff --git a/kernel/lds/aarch64-qemu.ld b/kernel/lds/aarch64-qemu.ld index dbcbacf9..adf13fbc 100644 --- a/kernel/lds/aarch64-qemu.ld +++ b/kernel/lds/aarch64-qemu.ld @@ -6,6 +6,11 @@ SECTIONS .text.boot : { *(.text.boot) } .text : { *(.text) } .data : { *(.data) } + .note.ktest : { + __ktest_start = .; + *(.note.ktest) + __ktest_end = .; + } .rodata : { *(.rodata) } .bss : { *(COMMON) diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 4bd3c8a9..336f0c89 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -62,7 +62,7 @@ extern "x86-interrupt" fn page_fault( } extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) { - // interrupt(Interrupt::Timer); + interrupt(Interrupt::Timer); unsafe { LAPIC.end_of_interrupt(); @@ -83,28 +83,31 @@ extern "x86-interrupt" fn spurious(_: InterruptStackFrame) { } } +#[allow(unused_imports)] fn interrupt(interrupt_type: Interrupt) { - use crate::arch::INTERRUPT_LIST; - let il = INTERRUPT_LIST.lock(); - let val = il.list.get(&interrupt_type).unwrap(); + use crate::{arch::INTERRUPT_LIST, kmain::EXECUTOR}; + // let il = INTERRUPT_LIST.lock(); + // let val = il.list.get(&interrupt_type).unwrap(); - use crate::holeybytes::kernel_services::service_definition_service::sds_search_service; - let buffer = sds_search_service(val); - if buffer != 0 { - use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec}; - let mut buffs = IPC_BUFFERS.lock(); - match buffs.get_mut(&buffer) { - Some(buff) => { - let mut msg_vec = Vec::new(); - msg_vec.push(0xFF); - buff.push(msg_vec.to_vec()); - log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer); - } - None => { - log::error!("Access of non-existent buffer {}", buffer) - } - } + // use crate::holeybytes::kernel_services::service_definition_service::sds_search_service; + // let buffer = sds_search_service(val); + // if buffer != 0 { + // use {crate::kmain::IPC_BUFFERS, alloc::vec::Vec}; + // let mut buffs = IPC_BUFFERS.lock(); + // match buffs.get_mut(&buffer) { + // Some(buff) => { + // let mut msg_vec = Vec::new(); + // msg_vec.push(0xFF); + // buff.push(msg_vec.to_vec()); + // log::debug!("Sent Message {:?} to Buffer({})", msg_vec, buffer); + // } + // None => { + // log::error!("Access of non-existent buffer {}", buffer) + // } + // } + // } - // log::info!("{}", buffer); + unsafe { + EXECUTOR.send_interrupt(interrupt_type as u8); } } diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs index 67576f47..ab540d6b 100644 --- a/kernel/src/holeybytes/ecah.rs +++ b/kernel/src/holeybytes/ecah.rs @@ -33,7 +33,7 @@ unsafe fn x86_in(address: u16) -> T { } #[inline(always)] -pub fn handler(vm: &mut Vm) { +pub fn handler(vm: &mut Vm, pid: &usize) { let ecall_number = vm.registers[2].cast::(); match ecall_number { @@ -80,6 +80,10 @@ pub fn handler(vm: &mut Vm) { let length = vm.registers[5].cast::() as usize; trace!("IPC address: {:?}", mem_addr); + unsafe { LazyCell::::get_mut(&mut EXECUTOR) } + .unwrap() + .send_buffer(buffer_id as usize); + match buffer_id { 0 => match sds_msg_handler(vm, mem_addr, length) { Ok(()) => {} @@ -209,7 +213,6 @@ pub fn handler(vm: &mut Vm) { let buffer_id = vm.registers[3].cast::(); let map_ptr = vm.registers[4].cast::(); let max_length = vm.registers[5].cast::(); - let mut buffs = IPC_BUFFERS.lock(); let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) { Some(buff) => buff, @@ -243,6 +246,28 @@ pub fn handler(vm: &mut Vm) { vm.registers[3] = x } } + 6 => { + // Wait till interrupt + use crate::kmain::EXECUTOR; + let interrupt_type = vm.registers[3].cast::(); + debug!("Interrupt subscribed: {}", interrupt_type); + unsafe { + LazyCell::::get_mut(&mut EXECUTOR) + .unwrap() + .interrupt_subscribe(*pid, interrupt_type); + } + } + 7 => { + // Wait till buffer + use crate::kmain::EXECUTOR; + let buffer_id = vm.registers[3].cast::() as usize; + debug!("Buffer subscribed: {}", buffer_id); + unsafe { + LazyCell::::get_mut(&mut EXECUTOR) + .unwrap() + .buffer_subscribe(*pid, buffer_id); + } + } _ => { log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers); } diff --git a/kernel/src/holeybytes/mod.rs b/kernel/src/holeybytes/mod.rs index 2c4dbab4..ab68d04f 100644 --- a/kernel/src/holeybytes/mod.rs +++ b/kernel/src/holeybytes/mod.rs @@ -65,7 +65,12 @@ impl<'p> Future for ExecThread { return Poll::Ready(Err(err)); } Ok(VmRunOk::End) => return Poll::Ready(Ok(())), - Ok(VmRunOk::Ecall) => ecah::handler(&mut self.vm), + Ok(VmRunOk::Ecall) => ecah::handler( + &mut self.vm, + cx.ext() + .downcast_ref() + .expect("PID did not exist in Context"), + ), Ok(VmRunOk::Timer) => (), Ok(VmRunOk::Breakpoint) => { log::error!( diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs index 625b9cd7..8d9d3989 100644 --- a/kernel/src/kmain.rs +++ b/kernel/src/kmain.rs @@ -22,12 +22,16 @@ use { pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { debug!("Entered kmain"); - #[cfg(feature = "ktest")] { - use crate::ktest; - debug!("TESTING"); + #[cfg(feature = "ktest")] + { + use { + crate::ktest, + log::info, + }; + info!("Running tests"); ktest::test_main(); - loop {}; + loop {} } // let kcmd = build_cmd("Kernel Command Line", cmdline); @@ -75,6 +79,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { "Graphics front ptr {:?}", fb1.address.as_ptr().unwrap() as *const u8 ); + log::info!("Started AbleOS"); unsafe { let executor = LazyCell::::force_mut(&mut EXECUTOR); @@ -120,7 +125,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { if cmd_len > 0 { thr.set_arguments(cmd.as_ptr() as u64, cmd_len); } - executor.spawn(Box::pin(async move { + executor.spawn(Box::pin(async { if let Err(e) = thr.await { log::error!("{e:?}"); } @@ -131,7 +136,6 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { executor.run(); }; - crate::arch::spin_loop() } diff --git a/kernel/src/ktest.rs b/kernel/src/ktest.rs index 43a2a11a..c1944452 100644 --- a/kernel/src/ktest.rs +++ b/kernel/src/ktest.rs @@ -1,38 +1,51 @@ -pub use ktest_macro::ktest; -use log::debug; +pub use ktest_macro::*; + +use { + alloc::string::String, + log::{error, info}, +}; extern "C" { - static __ktest_start: fn(); - static __ktest_end: fn(); + static __ktest_start: fn() -> Result; + static __ktest_end: fn() -> Result; } -// TODO: Get test_fn linker name (may require no_mangle in macro) -// More info on tests (run the rest even if panic) -// Implement ktest for arm and riscv (Later problems, see below) +// TODO: Implement ktest for arm and riscv (Later problems, see below) // Allow for arch specific tests (Leave for now) -// Allow for ktest test name attr -// Usefull message at the end of testing +// Should panic tests +// Test specific panic handler pub fn test_main() { unsafe { - let mut current_test = &__ktest_start as *const fn(); - let mut current = 1; - let test_end = &__ktest_end as *const fn(); + let mut current_test = &__ktest_start as *const fn() -> Result; + let test_end = &__ktest_end as *const fn() -> Result; + + let mut pass = 0; + let mut fail = 0; while current_test < test_end { let test_fn = *current_test; - debug!("Running test {}", current); - - test_fn(); - debug!("Test {} passed", current); + let test_name = test_fn(); + match test_name { + Ok(name) => { + info!("Test: {} passed", name); + pass += 1; + }, + Err(name) => { + error!("Test: {} failed", name); + fail += 1; + } + } current_test = current_test.add(1); - current += 1; } + + info!("{}/{} tests passed", pass, pass + fail); } } #[ktest] pub fn trivial_assertion() { - assert_eq!(1, 1); -} \ No newline at end of file + ktest_eq!(1, 1); + ktest_neq!(0, 1); +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 52956ecd..b0005d81 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -10,9 +10,11 @@ abi_x86_interrupt, lazy_get, alloc_error_handler, + local_waker, + context_ext, ptr_sub_ptr, naked_functions, - pointer_is_aligned_to, + pointer_is_aligned_to )] #![allow(dead_code, internal_features, static_mut_refs)] extern crate alloc; @@ -32,10 +34,9 @@ mod memory; mod task; mod utils; -// #[cfg(feature = "tests")] +#[allow(improper_ctypes, non_upper_case_globals)] mod ktest; -use alloc::string::ToString; use versioning::Version; /// Kernel's version @@ -48,6 +49,7 @@ pub const VERSION: Version = Version { #[panic_handler] #[cfg(target_os = "none")] fn panic(info: &core::panic::PanicInfo) -> ! { + use alloc::string::ToString; arch::register_dump(); if let Some(loc) = info.location() { diff --git a/kernel/src/task.rs b/kernel/src/task.rs index 3326871b..8807505a 100644 --- a/kernel/src/task.rs +++ b/kernel/src/task.rs @@ -1,9 +1,14 @@ use { - alloc::{boxed::Box, sync::Arc}, + alloc::{ + boxed::Box, + collections::{BTreeMap, BTreeSet}, + sync::Arc, + }, core::{ future::Future, pin::Pin, - task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, + sync::atomic::{AtomicBool, Ordering}, + task::{Context, ContextBuilder, Poll, RawWaker, RawWakerVTable, Waker}, }, crossbeam_queue::SegQueue, slab::Slab, @@ -14,7 +19,6 @@ pub fn yield_now() -> impl Future { impl Future for YieldNow { type Output = (); - #[inline(always)] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.0 { Poll::Ready(()) @@ -29,150 +33,184 @@ pub fn yield_now() -> impl Future { YieldNow(false) } +pub trait Process: Future + Send {} +impl + Send> Process for T {} + pub struct Executor { - tasks: Slab, - task_queue: Arc, + tasks: Slab, + task_queue: Arc>, + interrupt_lookup: [Option; u8::MAX as usize], + buffer_lookup: BTreeMap>, } impl Executor { pub fn new() -> Self { Self { - tasks: Slab::new(), - task_queue: Arc::new(TaskQueue::new()), + tasks: Slab::new(), + task_queue: Arc::new(SegQueue::new()), + interrupt_lookup: [None; u8::MAX as usize], + buffer_lookup: BTreeMap::new(), } } - #[inline] - pub fn spawn(&mut self, future: Pin + Send>>) -> usize { + pub fn spawn(&mut self, future: Pin>) -> usize { let id = self.tasks.insert(Task::new(future)); - self.task_queue.queue.push(id); + self.task_queue.push(id); + id } + pub fn pause(&self, id: usize) { + if let Some(task) = self.tasks.get(id) { + task.set_paused(true); + } + } + + pub fn unpause(&self, id: usize) { + if let Some(task) = self.tasks.get(id) { + task.set_paused(false); + self.task_queue.push(id); + } + } + + pub fn interrupt_subscribe(&mut self, pid: usize, interrupt_type: u8) { + self.pause(pid); + self.interrupt_lookup[interrupt_type as usize] = Some(pid); + } + + pub fn buffer_subscribe(&mut self, pid: usize, buffer_id: usize) { + self.pause(pid); + if let Some(buf) = self.buffer_lookup.get_mut(&buffer_id) { + buf.insert(pid); + } else { + self.buffer_lookup.insert(buffer_id, BTreeSet::from([pid])); + } + } + pub fn run(&mut self) { let mut task_batch = [0; 32]; - let mut batch_len = 0; - loop { - self.task_queue.batch_pop(&mut task_batch, &mut batch_len); + let mut batch_len = 0; - if batch_len == 0 { - if self.task_queue.is_empty() { + while let Some(id) = self.task_queue.pop() { + task_batch[batch_len] = id; + batch_len += 1; + if batch_len == task_batch.len() { break; - } else { - continue; } } - for &id in &task_batch[..batch_len] { - if let Some(task) = self.tasks.get_mut(id) { - let waker = task - .waker - .get_or_insert_with(|| TaskWaker::new(id, Arc::clone(&self.task_queue))); + if batch_len == 0 { + // break; + continue; + } - let waker = unsafe { Waker::from_raw(TaskWaker::into_raw_waker(waker)) }; - let mut cx = Context::from_waker(&waker); + for &(mut id) in &task_batch[..batch_len] { + if let Some(task) = self.tasks.get_mut(id) { + if task.is_paused() { + continue; + } + + let waker = create_waker(id, Arc::clone(&self.task_queue)); + let mut cx = ContextBuilder::from_waker(&waker).ext(&mut id).build(); if let Poll::Ready(()) = task.poll(&mut cx) { self.tasks.remove(id); - self.task_queue.free_tasks.push(id); + self.interrupt_lookup.map(|pid| { + if let Some(pid) = pid { + if pid == id { + return None; + } + } + return pid; + }); + self.buffer_lookup.iter_mut().for_each(|(_, pid_set)| { + pid_set.remove(&id); + }); } } } } } + + pub fn send_interrupt(&self, interrupt: u8) { + let id = self.interrupt_lookup[interrupt as usize]; + if let Some(id) = id { + self.unpause(id); + } + } + pub fn send_buffer(&self, id: usize) { + if let Some(buf) = self.buffer_lookup.get(&id) { + buf.iter().for_each(|pid| self.unpause(*pid)); + } + } } struct Task { - future: Pin + Send>>, - waker: Option, + future: Pin>, + paused: AtomicBool, } impl Task { - #[inline(always)] - pub fn new(future: Pin + Send>>) -> Self { + fn new(future: Pin>) -> Self { Self { future, - waker: None, + paused: AtomicBool::new(false), } } - #[inline(always)] fn poll(&mut self, cx: &mut Context) -> Poll<()> { self.future.as_mut().poll(cx) } + + fn is_paused(&self) -> bool { + self.paused.load(Ordering::Acquire) + } + + fn set_paused(&self, paused: bool) { + self.paused.store(paused, Ordering::Release) + } } +fn create_waker(task_id: usize, task_queue: Arc>) -> Waker { + let data = Box::new(TaskWaker { + task_id, + task_queue, + }); + let raw_waker = RawWaker::new(Box::into_raw(data) as *const (), &VTABLE); + unsafe { Waker::from_raw(raw_waker) } +} + +#[derive(Clone)] struct TaskWaker { - id: usize, - task_queue: Arc, + task_id: usize, + task_queue: Arc>, } impl TaskWaker { - #[inline(always)] - fn new(id: usize, task_queue: Arc) -> Self { - Self { id, task_queue } - } - - #[inline(always)] fn wake(&self) { - self.task_queue.queue.push(self.id); - } - - fn into_raw_waker(waker: &TaskWaker) -> RawWaker { - let ptr = waker as *const TaskWaker; - RawWaker::new(ptr.cast(), &VTABLE) + self.task_queue.push(self.task_id); } } const VTABLE: RawWakerVTable = RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw); unsafe fn clone_raw(ptr: *const ()) -> RawWaker { - let waker = &*(ptr as *const TaskWaker); - TaskWaker::into_raw_waker(waker) + let task_waker = Box::from_raw(ptr as *mut TaskWaker); + let raw_waker = RawWaker::new(Box::into_raw(task_waker.clone()) as *const (), &VTABLE); + raw_waker } unsafe fn wake_raw(ptr: *const ()) { - let waker = &*(ptr as *const TaskWaker); - waker.wake(); + let task_waker = Box::from_raw(ptr as *mut TaskWaker); + task_waker.wake(); } unsafe fn wake_by_ref_raw(ptr: *const ()) { - let waker = &*(ptr as *const TaskWaker); - waker.wake(); + let task_waker = &*(ptr as *const TaskWaker); + task_waker.wake(); } -unsafe fn drop_raw(_: *const ()) {} - -struct TaskQueue { - queue: SegQueue, - next_task: usize, - free_tasks: SegQueue, -} - -impl TaskQueue { - fn new() -> Self { - Self { - queue: SegQueue::new(), - next_task: 0, - free_tasks: SegQueue::new(), - } - } - - #[inline(always)] - fn batch_pop(&self, output: &mut [usize], len: &mut usize) { - *len = 0; - while let Some(id) = self.queue.pop() { - output[*len] = id; - *len += 1; - if *len == output.len() { - break; - } - } - } - - #[inline(always)] - fn is_empty(&self) -> bool { - self.queue.is_empty() - } +unsafe fn drop_raw(ptr: *const ()) { + drop(Box::from_raw(ptr as *mut TaskWaker)); } diff --git a/repbuild/src/dev.rs b/repbuild/src/dev.rs index 48f90e07..2f0a95aa 100644 --- a/repbuild/src/dev.rs +++ b/repbuild/src/dev.rs @@ -83,7 +83,8 @@ impl Package { &path, Options { fmt: true, - in_house_regalloc: true, + resolver: Some(hblang::ABLEOS_PATH_RESOLVER), + ..Default::default() }, out, @@ -99,7 +100,7 @@ impl Package { hblang::run_compiler( &path, Options { - in_house_regalloc: true, + resolver: Some(hblang::ABLEOS_PATH_RESOLVER), ..Default::default() }, out, @@ -111,8 +112,9 @@ impl Package { hblang::run_compiler( &path, Options { + resolver: Some(hblang::ABLEOS_PATH_RESOLVER), dump_asm: true, - in_house_regalloc: true, + ..Default::default() }, out, diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index 5a80bf49..d361cbc1 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -460,6 +460,10 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> { // "-serial", "stdio", "-m", "2G", "-smp", "1", + "-audiodev", + "pa,id=speaker", + "-machine", + "pcspk-audiodev=speaker", "-parallel", "none", "-monitor", "none", "-machine", accel, @@ -485,7 +489,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> { #[rustfmt::skip] com.args([ "-M", "virt", - "-cpu", "neoverse-n2", + "-cpu", "max", "-device", "ramfb", "-device", "qemu-xhci", "-device", "usb-kbd", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a0db7f55..b37e5aaf 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,7 @@ [toolchain] # old toolchain # channel = "nightly-2024-07-27" -channel = "nightly-2024-11-20" +# last stable +# channel = "nightly-2024-11-20" +channel = "nightly" components = ["rust-src", "llvm-tools"] diff --git a/sysdata/libraries/horizon_api/src/lib.hb b/sysdata/libraries/horizon_api/src/lib.hb index 112bbac3..bae1ba61 100644 --- a/sysdata/libraries/horizon_api/src/lib.hb +++ b/sysdata/libraries/horizon_api/src/lib.hb @@ -26,12 +26,6 @@ create_window := fn(channel: int): ^render.Surface { if windowing_system_buffer == 0 { return @as(^render.Surface, idk) } else { - // ! bad able, stop using string messages :ragey: - // msg := "\{01}\0" - // msg_length := 2 - - // @as(void, @eca(3, windowing_system_buffer, msg, msg_length)) - x := 0 loop if x > 1000 break else x += 1 diff --git a/sysdata/libraries/horizon_api/src/widgets/label.hb b/sysdata/libraries/horizon_api/src/widgets/label.hb index 5d1fb195..ce7e030a 100644 --- a/sysdata/libraries/horizon_api/src/widgets/label.hb +++ b/sysdata/libraries/horizon_api/src/widgets/label.hb @@ -14,14 +14,27 @@ Label := struct { text_length: uint, bg: Color, fg: Color, -} -set_label_text := fn(label: Label, text: ^u8): void { - text_length := string.length(text) + new_label := fn(text: ^u8): Self { + text_surface := render.new_surface(1024, 20) + text_length := string.length(text) + label := Self.(3, true, text_surface, text, text_length, render.black, render.white) + return label + } - label.is_dirty = true - label.text = text - label.text_length = text_length + set_label_text := fn(self: Self, text: ^u8): void { + text_length := string.length(text) + + self.is_dirty = true + self.text = text + self.text_length = text_length + } + + $set_color := fn(self: Self, bg: Color, fg: Color): void { + self.bg = bg + self.fg = fg + self.is_dirty = true + } } render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void { @@ -30,17 +43,4 @@ render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: V render.put_text(label.surface, font, .(0, 0), label.fg, label.text) } render.put_surface(surface, label.surface, pos, false) -} - -new_label := fn(text: ^u8): Label { - text_surface := render.new_surface(1024, 20) - text_length := string.length(text) - label := Label.(3, true, text_surface, text, text_length, render.black, render.white) - return label -} - -$set_color := fn(label: Label, bg: Color, fg: Color): void { - label.bg = bg - label.fg = fg - label.is_dirty = true } \ No newline at end of file diff --git a/sysdata/libraries/stn/src/alloc/alloc_return.hb b/sysdata/libraries/stn/src/alloc/alloc_return.hb new file mode 100644 index 00000000..bdc61f51 --- /dev/null +++ b/sysdata/libraries/stn/src/alloc/alloc_return.hb @@ -0,0 +1,4 @@ +AllocReturn := struct { + byte_count: uint, + ptr: ?^u8, +} \ No newline at end of file diff --git a/sysdata/libraries/stn/src/alloc/block_alloc.hb b/sysdata/libraries/stn/src/alloc/block_alloc.hb new file mode 100644 index 00000000..7cca6062 --- /dev/null +++ b/sysdata/libraries/stn/src/alloc/block_alloc.hb @@ -0,0 +1,90 @@ +.{log, panic, memory} := @use("../lib.hb") +alloc_return := @use("alloc_return.hb") + +/* the block size is 64 bytes, 64 blocks of 64 bytes. + this will very quickly lead to exhaustion of free blocks. +*/ +BlockAlloc := struct { + // hi + state: uint, + ptr: ?^u8, + + $init := fn(): Self { + alloc_page_ptr := memory.request_page(1) + state := 0xFFFFFFFFFFFFFFFF + return .(state, alloc_page_ptr) + } + + alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn { + offset := 0 + state_2 := 0 + loop { + xyz := self.state & 1 + abc := if xyz == 1 { + true + } else { + false + } + // check if the `offset` bit is 1, if it is move to the next offset + if abc { + offset += 1 + return .(0, null) + } else { + log.info("Already Allocated\0") + } + + // else { + // // self it to 1 and return the ptr to the allocation + // self.state |= a + // // return ptr + offset * 64 + // if self.ptr != null { + // return .(64, self.ptr + offset * 64) + // } else { + // // panic.panic("Allocator is not inited.\0") + // // return .(0, null) + // } + // } + // there are only 64 blocks + if offset >= 64 { + return .(0, null) + } + } + } + + dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void { + // size := size_of(alloc_type)*count + size := 64 + // get the size alligned to the nearest block + // rounded_size := nearest_block_size_rounded_up(size) + rounded_size := 64 + + state_bit_start := { + // Do math here to figure out what starting ptr corresponds to what bit + 3 + } + + offset := 0 + + loop { + if rounded_size > 0 { + // set state_bit_start+offset to 0 + + // at the end move to the next one + offset += 1 + } else { + break + } + + rounded_size -= 64 + } + return void + } + + $deinit := fn(self: Self): void { + self.state = 0 + self.ptr = null + } +} + +// request a kernel page +// ptr := memory.alloc(1) \ No newline at end of file diff --git a/sysdata/libraries/stn/src/alloc/fake_alloc.hb b/sysdata/libraries/stn/src/alloc/fake_alloc.hb new file mode 100644 index 00000000..82c422ac --- /dev/null +++ b/sysdata/libraries/stn/src/alloc/fake_alloc.hb @@ -0,0 +1,19 @@ +alloc_return := @use("alloc_return.hb") + +FakeAlloc := struct { + $init := fn(): Self { + return .() + } + + $alloc := fn(self: Self, alloc_type: type, count: uint): alloc_return.AllocReturn { + return .(0, null) + } + + $dealloc := fn(self: Self, ptr: ^u8, alloc_type: type, count: uint): void { + return void + } + // Nothing to clean up here + $deinit := fn(self: Self): void { + return void + } +} \ No newline at end of file diff --git a/sysdata/libraries/stn/src/alloc/lib.hb b/sysdata/libraries/stn/src/alloc/lib.hb new file mode 100644 index 00000000..f80a3619 --- /dev/null +++ b/sysdata/libraries/stn/src/alloc/lib.hb @@ -0,0 +1,2 @@ +.{BlockAlloc} := @use("block_alloc.hb"); +.{FakeAlloc} := @use("fake_alloc.hb") \ No newline at end of file diff --git a/sysdata/libraries/stn/src/alloc/main.hb b/sysdata/libraries/stn/src/alloc/main.hb new file mode 100644 index 00000000..138d53c4 --- /dev/null +++ b/sysdata/libraries/stn/src/alloc/main.hb @@ -0,0 +1,25 @@ +allocators := @use("alloc/alloc.hb") + +AStruct := struct { + a_field: u8, +} + +main := fn():void{ + alloc := allocators.FakeAlloc.init() + astruct := alloc.alloc(AStruct, 2) + if astruct.ptr != null{ + panic("FakeAlloc actually allocated.") + } + alloc.dealloc(astruct_ptr, AStruct, 2) + alloc.deinit() + + balloc := allocators.BlockAlloc.init() + bstruct_ptr := balloc.alloc(AStruct, 2) + if bstruct_ptr == null { + panic("BlockAlloc actually didn't allocate.") + } + balloc.dealloc(bstruct_ptr, AStruct, 2) + balloc.deinit() + + +} diff --git a/sysdata/libraries/stn/src/buffer.hb b/sysdata/libraries/stn/src/buffer.hb index 17f5a3f3..495f53a2 100644 --- a/sysdata/libraries/stn/src/buffer.hb +++ b/sysdata/libraries/stn/src/buffer.hb @@ -1,5 +1,9 @@ string := @use("string.hb") +$await := fn(buffer_id: uint): void { + return @eca(7, buffer_id) +} + $recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void { return @eca(4, buffer_id, memory_map_location, @sizeof(Expr)) } diff --git a/sysdata/libraries/stn/src/hash/foldhash.hb b/sysdata/libraries/stn/src/hash/foldhash.hb new file mode 100644 index 00000000..2aa9e1b4 --- /dev/null +++ b/sysdata/libraries/stn/src/hash/foldhash.hb @@ -0,0 +1,189 @@ +/* +* This code is an implementation of the FoldHash algorithm from https://github.com/orlp/foldhash, +* originally written by Orson Peters under the zlib license. +* +* Changes to the original code were made to meet the simplicity requirements of this implementation. +* Behaviour aims to be equivalent but not identical to the original code. +* +* Copyright (c) 2024 Orson Peters +* +* This software is provided 'as-is', without any express or implied warranty. In +* no event will the authors be held liable for any damages arising from the use of +* this software. +* +* Permission is granted to anyone to use this software for any purpose, including +* commercial applications, and to alter it and redistribute it freely, subject to +* the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim +* that you wrote the original software. If you use this software in a product, +* an acknowledgment in the product documentation would be appreciated but is +* not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be +* misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +*/; + +.{math, random} := @use("../lib.hb") + +$ARBITRARY0 := 0x243F6A8885A308D3 +$ARBITRARY1 := 0x13198A2E03707344 +$ARBITRARY2 := 0xA4093822299F31D0 +$ARBITRARY3 := 0x82EFA98EC4E6C89 +$ARBITRARY4 := 0x452821E638D01377 +$ARBITRARY5 := 0xBE5466CF34E90C6C +$ARBITRARY6 := 0xC0AC29B7C97C50DD +$ARBITRARY7 := 0x3F84D5B5B5470917 +$ARBITRARY8 := 0x9216D5D98979FB1B +$ARBITRARY9 := 0xD1310BA698DFB5AC +$FIXED_GLOBAL_SEED := [uint].(ARBITRARY4, ARBITRARY5, ARBITRARY6, ARBITRARY7) + +global_seed := 0 + +u128 := packed struct {a: uint, b: uint} + +$folded_multiply := fn(x: uint, y: uint): uint { + lx := @as(u32, @intcast(x)) + ly := @as(u32, @intcast(y)) + hx := x >> 32 + hy := y >> 32 + afull := lx * hy + bfull := hx * ly + return afull ^ (bfull << 32 | bfull >> 32) +} + +hash_bytes_medium := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, fold_seed: uint): uint { + lo := bytes + end := bytes + len + hi := end - 16 + + loop if lo >= hi break else { + a := *@as(^uint, @bitcast(lo)) + b := *@as(^uint, @bitcast(lo + 8)) + c := *@as(^uint, @bitcast(hi)) + d := *@as(^uint, @bitcast(hi + 8)) + s0 = folded_multiply(a ^ s0, c ^ fold_seed) + s1 = folded_multiply(b ^ s1, d ^ fold_seed) + hi -= 16 + lo += 16 + } + return s0 ^ s1 +} + +hash_bytes_long := fn(bytes: ^u8, len: uint, s0: uint, s1: uint, s2: uint, s3: uint, fold_seed: uint): uint { + $chunk_size := 64 + chunks := len / chunk_size + remainder := len % chunk_size + + ptr := bytes + i := 0 + loop if i >= chunks break else { + a := *@as(^uint, @bitcast(ptr)) + b := *@as(^uint, @bitcast(ptr + 8)) + c := *@as(^uint, @bitcast(ptr + 16)) + d := *@as(^uint, @bitcast(ptr + 24)) + e := *@as(^uint, @bitcast(ptr + 32)) + f := *@as(^uint, @bitcast(ptr + 40)) + g := *@as(^uint, @bitcast(ptr + 48)) + h := *@as(^uint, @bitcast(ptr + 56)) + + s0 = folded_multiply(a ^ s0, e ^ fold_seed) + s1 = folded_multiply(b ^ s1, f ^ fold_seed) + s2 = folded_multiply(c ^ s2, g ^ fold_seed) + s3 = folded_multiply(d ^ s3, h ^ fold_seed) + + ptr += chunk_size + i += 1 + } + + s0 ^= s2 + s1 ^= s3 + + if remainder > 0 { + remainder_start := bytes + len - math.max(uint, remainder, 16) + return hash_bytes_medium(remainder_start, math.max(uint, remainder, 16), s0, s1, fold_seed) + } + + return s0 ^ s1 +} + +FoldHasher := struct { + accumulator: uint, + original_seed: uint, + sponge: u128, + sponge_len: u8, + fold_seed: uint, + expand_seed: uint, + expand_seed2: uint, + expand_seed3: uint, + + $new := fn(seed: uint): Self { + return .( + seed, + seed, + .(0, 0), + 0, + FIXED_GLOBAL_SEED[0], + FIXED_GLOBAL_SEED[1], + FIXED_GLOBAL_SEED[2], + FIXED_GLOBAL_SEED[3], + ) + } + + default := fn(): Self { + if global_seed == 0 { + // ! consider this "secure enough" for now + global_seed = random.any(uint) + } + return Self.new(global_seed) + } + + write := fn(self: ^Self, bytes: ^u8, len: uint): void { + s0 := self.accumulator + s1 := self.expand_seed + if len <= 16 { + if len >= 8 { + s0 ^= *@bitcast(bytes) + s1 ^= *@bitcast(bytes + len - 8) + } else if len >= 4 { + s0 ^= *@as(^u32, @bitcast(bytes)) + s1 ^= *@as(^u32, @bitcast(bytes + len - 4)) + } else if len > 0 { + lo := *bytes + mid := *(bytes + len / 2) + hi := *(bytes + len - 1) + s0 ^= lo + s1 ^= @as(uint, hi) << 8 | mid + } + self.accumulator = folded_multiply(s0, s1) + } else if len < 256 { + self.accumulator = hash_bytes_medium(bytes, len, s0, s1, self.fold_seed) + } else { + self.accumulator = hash_bytes_long( + bytes, + len, + s0, + s1, + self.expand_seed2, + self.expand_seed3, + self.fold_seed, + ) + } + } + + finish := fn(self: ^Self): uint { + if self.sponge_len > 0 { + return folded_multiply(self.sponge.b ^ self.accumulator, self.sponge.a ^ self.fold_seed) + } else { + return self.accumulator + } + } + + reset := fn(self: ^Self): void { + self.accumulator = self.original_seed + self.sponge = .(0, 0) + self.sponge_len = 0 + } +} \ No newline at end of file diff --git a/sysdata/libraries/stn/src/hash/lib.hb b/sysdata/libraries/stn/src/hash/lib.hb new file mode 100644 index 00000000..da97bfd7 --- /dev/null +++ b/sysdata/libraries/stn/src/hash/lib.hb @@ -0,0 +1,2 @@ +//! NON CRYPTOGRAPHIC HASHER +foldhash := @use("foldhash.hb") \ No newline at end of file diff --git a/sysdata/libraries/stn/src/lib.hb b/sysdata/libraries/stn/src/lib.hb index 961037cb..93919178 100644 --- a/sysdata/libraries/stn/src/lib.hb +++ b/sysdata/libraries/stn/src/lib.hb @@ -1,4 +1,6 @@ acs := @use("acs.hb") +allocators := @use("alloc/lib.hb") +hashers := @use("hash/lib.hb") string := @use("string.hb") log := @use("log.hb") memory := @use("memory.hb") @@ -8,6 +10,7 @@ random := @use("random.hb") file := @use("file_io.hb") dt := @use("dt.hb") process := @use("process.hb") +sleep := @use("sleep.hb") panic := fn(message: ?^u8): never { log.error("Error: Panic Called, Message:\0") diff --git a/sysdata/libraries/stn/src/sleep.hb b/sysdata/libraries/stn/src/sleep.hb index d3232675..5aeaf148 100644 --- a/sysdata/libraries/stn/src/sleep.hb +++ b/sysdata/libraries/stn/src/sleep.hb @@ -3,4 +3,5 @@ subscribe_to_interrupt := fn(interrupt_number: u8): bool { } // Pauses execution until the interrupt occures sleep_until_interrupt := fn(interrupt_number: u8): void { + @eca(6, interrupt_number) } \ No newline at end of file diff --git a/sysdata/libraries/sunset_proto/src/lib.hb b/sysdata/libraries/sunset_proto/src/lib.hb index f75dfb28..9be50d85 100644 --- a/sysdata/libraries/sunset_proto/src/lib.hb +++ b/sysdata/libraries/sunset_proto/src/lib.hb @@ -1,4 +1,4 @@ -.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb"); +.{math: .{Vec2}, buffer, memory} := @use("stn"); .{Surface} := @use("../../render/src/lib.hb") $BUFFER_SERVER := "sunset_server\0" @@ -48,6 +48,8 @@ await_channel := fn(): Channel { await_message := fn($Expr: type, buffer_id: uint): Message(Expr) { response := @as(?Message(Expr), null) loop { + // awaiting here causes flickering... idk why + buffer.await(buffer_id) buffer.recv(?Message(Expr), buffer_id, &response) if response != null { return @as(Message(Expr), response) @@ -58,9 +60,11 @@ await_message := fn($Expr: type, buffer_id: uint): Message(Expr) { await_header := fn(buffer_id: uint): MessageHeader { response := @as(?MessageHeader, null) loop { + // awaiting here causes flickering... idk why + buffer.await(buffer_id) buffer.recv(?MessageHeader, buffer_id, &response) if response != null { - return @as(?MessageHeader, response) + return @as(MessageHeader, response) } } } diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb index 4850ce69..4dd16d9c 100644 --- a/sysdata/libraries/sunset_proto/src/server.hb +++ b/sysdata/libraries/sunset_proto/src/server.hb @@ -1,6 +1,6 @@ -.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb"); -.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("../../render/src/lib.hb"); -.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb") +.{math, log, string, random, buffer, memory} := @use("stn"); +.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("lib:render"); +.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("lib:sunset_proto") WindowServer := struct { window_count: uint, diff --git a/sysdata/programs/dt_buffer_test/README.md b/sysdata/programs/dt_buffer_test/README.md deleted file mode 100644 index c01a7c5e..00000000 --- a/sysdata/programs/dt_buffer_test/README.md +++ /dev/null @@ -1 +0,0 @@ -# dt_buffer_test \ No newline at end of file diff --git a/sysdata/programs/dt_buffer_test/src/main.hb b/sysdata/programs/dt_buffer_test/src/main.hb deleted file mode 100644 index 7d37f6ad..00000000 --- a/sysdata/programs/dt_buffer_test/src/main.hb +++ /dev/null @@ -1,13 +0,0 @@ -.{dt} := @use("../../../libraries/stn/src/lib.hb") - -main := fn(): void { - dt.get(void, "framebuffer/fb0/width\0") - dt.get(void, "cpu/cpu0/architecture\0") - - // Checking if the first detected serial port is memory mapped or port mapped - // 0 -> memory mapped - // 1 -> port mapped - dt.get(void, "serial_ports/sp0/mapping\0") - - return -} \ No newline at end of file diff --git a/sysdata/programs/pcspkr/README.md b/sysdata/programs/pcspkr/README.md new file mode 100644 index 00000000..5a5f4b95 --- /dev/null +++ b/sysdata/programs/pcspkr/README.md @@ -0,0 +1 @@ +# pcspkr \ No newline at end of file diff --git a/sysdata/programs/processes/meta.toml b/sysdata/programs/pcspkr/meta.toml similarity index 74% rename from sysdata/programs/processes/meta.toml rename to sysdata/programs/pcspkr/meta.toml index 86a48694..d71a5f20 100644 --- a/sysdata/programs/processes/meta.toml +++ b/sysdata/programs/pcspkr/meta.toml @@ -1,6 +1,6 @@ [package] -name = "processes" -authors = ["koniifer"] +name = "pcspkr" +authors = [""] [dependants.libraries] diff --git a/sysdata/programs/pcspkr/src/main.hb b/sysdata/programs/pcspkr/src/main.hb new file mode 100644 index 00000000..5c5055cb --- /dev/null +++ b/sysdata/programs/pcspkr/src/main.hb @@ -0,0 +1,45 @@ +stn := @use("../../../libraries/stn/src/lib.hb"); +.{memory, buffer, log, string, math} := stn; +.{inb, outb} := memory + +$PIT_CLOCK := 1193180 + +play_sound := fn(frequency: u32): void { + div := 0 + + div = PIT_CLOCK / frequency + memory.outb(0x43, 0xB6) + memory.outb(0x42, @intcast(div)) + memory.outb(0x42, @intcast(div >> 8)) + + tmp := inb(0x61) + if tmp != (tmp | 3) { + outb(0x61, tmp | 3) + } +} + +no_sound := fn(): void { + tmp := memory.inb(0x61) & 0xFC + + memory.outb(0x61, tmp) +} + +beep := fn(): void { + play_sound(1000) + idx := 0 + loop { + if idx >= 1000000 { + idx += 1 + } else { + break + } + } + + no_sound() +} + +main := fn(): int { + no_sound() + beep() + return 0 +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 77cb04c0..ab66cfa8 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1 +1 @@ -.{example: main} := @use("./examples/text.hb") \ No newline at end of file +.{example: main} := @use("./examples/orbit.hb") \ No newline at end of file diff --git a/sysdata/programs/sdoom/README.md b/sysdata/programs/sdoom/README.md new file mode 100644 index 00000000..e752f1fa --- /dev/null +++ b/sysdata/programs/sdoom/README.md @@ -0,0 +1,4 @@ +# sdoom +SDoom stands for simple doom. + +This is not a full implementation of doom and is instead a doom style renderer. \ No newline at end of file diff --git a/sysdata/programs/dt_buffer_test/meta.toml b/sysdata/programs/sdoom/meta.toml similarity index 73% rename from sysdata/programs/dt_buffer_test/meta.toml rename to sysdata/programs/sdoom/meta.toml index f25002e9..b6e9cbde 100644 --- a/sysdata/programs/dt_buffer_test/meta.toml +++ b/sysdata/programs/sdoom/meta.toml @@ -1,6 +1,6 @@ [package] -name = "dt_buffer_test" -authors = ["able"] +name = "sdoom" +authors = [""] [dependants.libraries] diff --git a/sysdata/programs/sdoom/src/main.hb b/sysdata/programs/sdoom/src/main.hb new file mode 100644 index 00000000..22aebc7b --- /dev/null +++ b/sysdata/programs/sdoom/src/main.hb @@ -0,0 +1,53 @@ +sunset := @use("../../../libraries/sunset_proto/src/lib.hb") +render := @use("../../../libraries/render/src/lib.hb") + +stn := @use("../../../libraries/stn/src/lib.hb"); +.{log} := stn; +.{Vec2} := stn.math + +Player := struct { + x: i8, + y: i8, + + $new := fn(x: i8, y: i8): Self { + return Self.(x, y) + } +} + +GameState := struct { + player: Player, + + $new := fn(): Self { + p := Player.new(0, 0) + return Self.(p) + } +} + +main := fn(): void { + sunset.client.find_server() + + window := sunset.client.new(.(.(600, 400), .(200, 200), "SDoom\0")) + + if window == null { + log.error("got no window\0") + return + } + + game_state := GameState.new() + + loop { + render.clear(window.surface, render.black) + width := 100 + idx := 1 + + loop { + if idx >= width { + break + } + render.put_vline(window.surface, idx, 10, 100, render.white) + idx += 1 + } + + _ = sunset.client.send_frame(window) + } +} \ No newline at end of file diff --git a/sysdata/programs/sdoom/src/player.hb b/sysdata/programs/sdoom/src/player.hb new file mode 100644 index 00000000..e69de29b diff --git a/sysdata/programs/serial_driver_test/src/main.hb b/sysdata/programs/serial_driver_test/src/main.hb deleted file mode 100644 index 19ad6c15..00000000 --- a/sysdata/programs/serial_driver_test/src/main.hb +++ /dev/null @@ -1,20 +0,0 @@ -.{string, buffer} := @use("../../../libraries/stn/src/lib.hb") - -log_info := fn(): void { - a := buffer.search("XNumber\0") - if a == 0 { - } else { - msg := "XABC\0" - // inline is broked - // msg_length := @inline(string.length, msg) - msg_length := 5 - @as(void, @eca(3, a, msg, msg_length)) - } - - return -} - -main := fn(): int { - log_info() - return 0 -} \ No newline at end of file diff --git a/sysdata/programs/sunset_client_2/src/main.hb b/sysdata/programs/sunset_client_2/src/main.hb index 3fcf1c1a..2e547596 100644 --- a/sysdata/programs/sunset_client_2/src/main.hb +++ b/sysdata/programs/sunset_client_2/src/main.hb @@ -13,7 +13,7 @@ main := fn(): void { return } - window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0")) + window := sunset.client.new(.(.(400, 100), .(400, 240), "Sunset!\0")) if window == null { log.error("got no window\0") diff --git a/sysdata/programs/sunset_server/src/main.hb b/sysdata/programs/sunset_server/src/main.hb index 43295868..9f438d74 100644 --- a/sysdata/programs/sunset_server/src/main.hb +++ b/sysdata/programs/sunset_server/src/main.hb @@ -3,7 +3,7 @@ render := @use("../../../libraries/render/src/lib.hb") intouch := @use("../../../libraries/intouch/src/lib.hb") horizon_api := @use("../../../libraries/horizon_api/src/lib.hb"); -.{new_label, render_label_to_surface, set_label_text, set_color} := horizon_api.widgets.label +.{set_color, render_label_to_surface, Label} := horizon_api.widgets.label stn := @use("../../../libraries/stn/src/lib.hb"); .{Vec2} := stn.math @@ -13,6 +13,9 @@ img := @embed("../../../assets/wallpaper.qoi") main := fn(): int { sunset.server.start() + defer { + stn.log.info("Sunset Server Exit\0") + } screen := render.init(true) render.clear(screen, render.black) @@ -28,8 +31,8 @@ main := fn(): int { mouse_x := 100 mouse_y := 100 - text_label := new_label("Hi\0") - set_color(text_label, sunset.server.DECO_COLOUR, render.black) + text_label := Label.new_label("Hi\0") + text_label.set_color(sunset.server.DECO_COLOUR, render.black) loop { mouse_event := intouch.recieve_mouse_event() @@ -59,13 +62,13 @@ main := fn(): int { } if mouse_event.left { - set_label_text(text_label, "LEFT CLICK\0") + text_label.set_label_text("LEFT CLICK\0") } if mouse_event.middle { - set_label_text(text_label, "MIDDLE CLICK\0") + text_label.set_label_text("MIDDLE CLICK\0") } if mouse_event.right { - set_label_text(text_label, "RIGHT CLICK\0") + text_label.set_label_text("RIGHT CLICK\0") } } { @@ -88,8 +91,8 @@ main := fn(): int { // Mouse cursor { - render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR_DARKER) - render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR) + render.put_filled_circle(screen, .(mouse_x, mouse_y), 10, sunset.server.DECO_COLOUR_DARKER) + render.put_circle(screen, .(mouse_x, mouse_y), 10, sunset.server.DECO_COLOUR) } render.sync(screen) diff --git a/sysdata/programs/serial_driver_test/meta.toml b/sysdata/programs/test/meta.toml similarity index 72% rename from sysdata/programs/serial_driver_test/meta.toml rename to sysdata/programs/test/meta.toml index f8f995c9..93c3dd77 100644 --- a/sysdata/programs/serial_driver_test/meta.toml +++ b/sysdata/programs/test/meta.toml @@ -1,6 +1,6 @@ [package] -name = "serial_driver_test" -authors = ["able"] +name = "test" +authors = ["koniifer", "able"] [dependants.libraries] diff --git a/sysdata/programs/test/src/main.hb b/sysdata/programs/test/src/main.hb new file mode 100644 index 00000000..debec4e0 --- /dev/null +++ b/sysdata/programs/test/src/main.hb @@ -0,0 +1,7 @@ +stn := @use("./tests/stn/lib.hb") +serial_driver := @use("./tests/serial_driver.hb") + +main := fn(): uint { + // return serial_driver.test() + return stn.sleep.test() +} \ No newline at end of file diff --git a/sysdata/programs/test/src/tests/serial_driver.hb b/sysdata/programs/test/src/tests/serial_driver.hb new file mode 100644 index 00000000..8e27b11d --- /dev/null +++ b/sysdata/programs/test/src/tests/serial_driver.hb @@ -0,0 +1,18 @@ +.{string, buffer} := @use("../../../../libraries/stn/src/lib.hb") + +log_info := fn(): void { + a := buffer.search("XNumber\0") + if a == 0 { + } else { + msg := "XABC\0" + msg_length := string.length(msg) + @eca(3, a, msg, msg_length) + } + + return +} + +test := fn(): uint { + log_info() + return 0 +} \ No newline at end of file diff --git a/sysdata/programs/test/src/tests/stn/allocators.hb b/sysdata/programs/test/src/tests/stn/allocators.hb new file mode 100644 index 00000000..8b194b7f --- /dev/null +++ b/sysdata/programs/test/src/tests/stn/allocators.hb @@ -0,0 +1,30 @@ +stn := @use("../../../../../libraries/stn/src/lib.hb"); +.{allocators, panic, log} := stn + +AStruct := struct { + a_field: u8, +} + +test := fn(): uint { + // alloc := allocators.FakeAlloc.init() + // astruct := alloc.alloc(AStruct, 2) + // if astruct.ptr != null{ + // panic.panic("FakeAlloc actually allocated.") + // } + // alloc.dealloc(&astruct.ptr, AStruct, 2) + // alloc.deinit() + + balloc := allocators.BlockAlloc.init() + // defer { + // balloc.deinit() + // } + bstruct := balloc.alloc(AStruct, 2) + // if bstruct.ptr == null { + // log.info("Hi\0") + // // panic.panic("BlockAlloc actually didn't allocate.") + // } else { + // log.info("Allocator functioned.\0") + // } + // balloc.dealloc(bstruct_ptr, AStruct, 2) + return 0 +} \ No newline at end of file diff --git a/sysdata/programs/processes/src/hello_world_and_spin.hb b/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hb similarity index 100% rename from sysdata/programs/processes/src/hello_world_and_spin.hb rename to sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hb diff --git a/sysdata/programs/processes/src/hello_world_and_spin.hbf b/sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hbf similarity index 100% rename from sysdata/programs/processes/src/hello_world_and_spin.hbf rename to sysdata/programs/test/src/tests/stn/assets/hello_world_and_spin.hbf diff --git a/sysdata/programs/test/src/tests/stn/dt.hb b/sysdata/programs/test/src/tests/stn/dt.hb new file mode 100644 index 00000000..e331f33b --- /dev/null +++ b/sysdata/programs/test/src/tests/stn/dt.hb @@ -0,0 +1,18 @@ +.{dt, memory, string, log} := @use("../../../../../libraries/stn/src/lib.hb") + +test := fn(): uint { + buffer := memory.request_page(1) + + log.info(string.display_int(dt.get(int, "framebuffer/fb0/width\0"), buffer, 10)) + string.clear(buffer) + + log.info(string.display_int(dt.get(int, "cpu/cpu0/architecture\0"), buffer, 10)) + string.clear(buffer) + + // 0 -> memory mapped + // 1 -> port mapped + + log.info(string.display_int(dt.get(int, "serial_ports/sp0/mapping\0"), buffer, 10)) + + return 0 +} \ No newline at end of file diff --git a/sysdata/programs/test/src/tests/stn/hashers.hb b/sysdata/programs/test/src/tests/stn/hashers.hb new file mode 100644 index 00000000..a1052d6e --- /dev/null +++ b/sysdata/programs/test/src/tests/stn/hashers.hb @@ -0,0 +1,32 @@ +.{hashers, log, memory, string} := @use("../../../../../libraries/stn/src/lib.hb") + +test := fn(): uint { + buffer := memory.request_page(1) + target := "abcdefghijklmnop\0" + strings := [^u8].("abcdefshijklmnop\0", "abcdefghijklnnop\0", "abcdefshijklmnop\0", "abcdefghijklmnop\0", "abcdefghijflmnop\0", "dbcdefghijklmnop\0", "abcdefghijklmnop\0") + len := @sizeof(@TypeOf(strings)) / @sizeof(^u8) + strlen := string.length(target) + + // hasher := hashers.foldhash.FoldHasher.new(1) + hasher := hashers.foldhash.FoldHasher.default() + hasher.write(target, strlen) + correct := hasher.finish() + + log.warn("target:\0") + log.warn(target) + + i := 0 + loop if i == len break else { + defer i += 1 + hasher.reset() + hasher.write(strings[i], strlen) + d := hasher.finish() + if d == correct { + log.warn("match found\0") + } + log.info(strings[i]) + log.debug(string.display_int(@bitcast(d), buffer, 16)) + string.clear(buffer) + } + return 0 +} \ No newline at end of file diff --git a/sysdata/programs/test/src/tests/stn/lib.hb b/sysdata/programs/test/src/tests/stn/lib.hb new file mode 100644 index 00000000..da08b779 --- /dev/null +++ b/sysdata/programs/test/src/tests/stn/lib.hb @@ -0,0 +1,5 @@ +hashers := @use("./hashers.hb") +allocators := @use("./allocators.hb") +sleep := @use("./sleep.hb") +dt := @use("./dt.hb") +process := @use("./process.hb") \ No newline at end of file diff --git a/sysdata/programs/processes/src/main.hb b/sysdata/programs/test/src/tests/stn/process.hb similarity index 61% rename from sysdata/programs/processes/src/main.hb rename to sysdata/programs/test/src/tests/stn/process.hb index 06b4ade8..493e36a7 100644 --- a/sysdata/programs/processes/src/main.hb +++ b/sysdata/programs/test/src/tests/stn/process.hb @@ -1,8 +1,8 @@ -.{process, log, string, memory} := @use("../../../libraries/stn/src/lib.hb") +.{process, log, string, memory} := @use("../../../../../libraries/stn/src/lib.hb") -exe := @embed("./hello_world_and_spin.hbf") +exe := @embed("./assets/hello_world_and_spin.hbf") -main := fn(): void { +test := fn(): uint { buf := "\0\0\0\0\0\0\0" loop { log.info( @@ -16,4 +16,5 @@ main := fn(): void { i := 0 loop if i == 1000000 break else i += 1 } + return 0 } \ No newline at end of file diff --git a/sysdata/programs/test/src/tests/stn/sleep.hb b/sysdata/programs/test/src/tests/stn/sleep.hb new file mode 100644 index 00000000..9eaeb31d --- /dev/null +++ b/sysdata/programs/test/src/tests/stn/sleep.hb @@ -0,0 +1,8 @@ +.{sleep, log} := @use("../../../../../libraries/stn/src/lib.hb") + +test := fn(): uint { + log.info("BEFORE\0") + sleep.sleep_until_interrupt(32) + log.info("AFTER\0") + return 0 +} \ No newline at end of file