Litrally almost functional PS/2 driver. #19

Open
peony wants to merge 32 commits from peony/ableos:master into master
39 changed files with 697 additions and 461 deletions
Showing only changes of commit b795aced8e - Show all commits

10
Cargo.lock generated
View file

@ -82,9 +82,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
dependencies = [
"shlex",
]
@ -228,12 +228,12 @@ dependencies = [
[[package]]
name = "hbbytecode"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7058efe75c7ad245db80986e77a97d426b9be8a4"
[[package]]
name = "hblang"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7058efe75c7ad245db80986e77a97d426b9be8a4"
dependencies = [
"hashbrown 0.15.1",
"hbbytecode",
@ -245,7 +245,7 @@ dependencies = [
[[package]]
name = "hbvm"
version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#7058efe75c7ad245db80986e77a97d426b9be8a4"
dependencies = [
"hbbytecode",
]

View file

@ -11,6 +11,7 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
#[repr(u8)]
#[derive(Debug)]
enum Interrupt {
Timer = 32,
ApicErr = u8::MAX - 1,
@ -66,11 +67,20 @@ extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
}
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
interrupt(Interrupt::ApicErr);
panic!("Internal APIC error");
}
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
interrupt(Interrupt::Spurious);
unsafe {
LAPIC.end_of_interrupt();
}
}
fn interrupt(interrupt_type: Interrupt){
log::info!("Interrupt type {:?}", interrupt_type);
panic!()
}

View file

@ -111,7 +111,7 @@ unsafe extern "C" fn oops() -> ! {
unsafe extern "C" fn start() -> ! {
logging::init();
crate::logger::init().expect("failed to set logger");
log::info!("Initialising AKern {}", crate::VERSION);
log::debug!("Initialising AKern {}", crate::VERSION);
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
memory::init_pt(VirtAddr::new(
@ -190,7 +190,7 @@ unsafe extern "C" fn start() -> ! {
// TODO: Add in rdseed and rdrand as sources for randomness
let _rand = xml::XMLElement::new("Random");
log::trace!("Getting boot modules");
log::debug!("Getting boot modules");
let bm = MOD_REQ.get_response().get();
let mut bootmodules = alloc::vec::Vec::new();
@ -228,7 +228,7 @@ unsafe extern "C" fn start() -> ! {
break;
}
}
log::info!("Boot module count: {:?}", bootmodules.len());
log::debug!("Boot module count: {:?}", bootmodules.len());
assert_eq!(bm.module_count, bootmodules.len() as u64);
}

View file

@ -69,7 +69,7 @@ pub fn check_device(bus: u8, device: u8) -> Option<PciDeviceInfo> {
}
let (reg2, addr) = unsafe { pci_config_read_2(bus, device, 0, 0x8) };
log::info!("pci device-({}) addr {} is {}", device, addr, reg2);
log::debug!("pci device-({}) addr {} is {}", device, addr, reg2);
let class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
let pci_class = PciFullClass::from_u16(class);
let header_type = get_header_type(bus, device, 0);

View file

@ -58,10 +58,10 @@ pub fn handler(vm: &mut Vm) {
true => IpcBuffer::new(true, length),
},
);
info!("Buffer ID: {}", buff_id);
vm.registers[1] = hbvm::value::Value(buff_id);
}
2 => {
log::error!("Oops, deleting buffers is not implemented.")
// Delete buffer
}
3 => {
@ -182,7 +182,7 @@ pub fn handler(vm: &mut Vm) {
} else {
unsafe {
let ptr = map_ptr as *mut u8;
ptr.copy_from(msg.as_ptr(), msg.len());
ptr.copy_from_nonoverlapping(msg.as_ptr(), msg.len());
}
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);

View file

@ -9,7 +9,20 @@ use log::Record;
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
let msg_vec = block_read(mem_addr, length);
let log_level = msg_vec[0];
use log::Level::*;
let log_level = match msg_vec[0] {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
if log_level > log::max_level() {
return Ok(());
}
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
@ -20,18 +33,6 @@ pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(),
match core::str::from_utf8(&str) {
Ok(strr) => {
use log::Level::*;
let log_level = match log_level {
0 | 48 => Error,
1 | 49 => Warn,
2 | 50 => Info,
3 | 51 => Debug,
4 | 52 => Trace,
_ => {
return Err(LogError::InvalidLogFormat);
}
};
log::logger().log(
&Record::builder()
.args(format_args!("{}", strr))

View file

@ -25,42 +25,16 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
}
#[inline(always)]
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
const BLOCK_SIZE: usize = 64;
let mut remaining = count * size;
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
let total_size = count * size;
src.copy_to_nonoverlapping(dest, size);
if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
let mut copied = size;
let mut buffer = [0u8; BLOCK_SIZE];
let mut buffer_size = size;
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
buffer
.as_mut_ptr()
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
buffer_size *= 2;
}
let buffer_ptr = buffer.as_ptr() as *const u64;
while (dest as usize) & 7 != 0 && remaining >= 8 {
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
dest = dest.add(1);
remaining -= 1;
}
while core::intrinsics::likely(remaining >= 8) {
*(dest as *mut u64) = *buffer_ptr;
dest = dest.add(8);
remaining -= 8;
}
if remaining > 0 {
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
while copied < total_size {
let copy_size = copied.min(total_size - copied);
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
copied += copy_size;
}
}

View file

@ -71,7 +71,18 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
let cmd = module.cmd.trim_matches('"');
let cmd_len = cmd.len() as u64;
log::info!("Spawning {} with arguments \"{}\"", module.path, cmd);
log::info!(
"Starting {}",
module
.path
.split('/')
.last()
.unwrap()
.split('.')
.next()
.unwrap()
);
log::debug!("Spawning {} with arguments \"{}\"", module.path, cmd);
// decode AbleOS Executable format
let header = &module.bytes[0..46];
@ -92,7 +103,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
let code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
let end = (code_length + data_length) as usize;
log::info!("{code_length} + {data_length} = {end}");
log::debug!("{code_length} + {data_length} = {end}");
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
if cmd_len > 0 {

View file

@ -1,5 +1,6 @@
#![allow(unused)]
use std::{
collections::HashMap,
fmt::format,
fs::{read_to_string, File},
io::{BufWriter, Write},
@ -13,6 +14,7 @@ pub struct Package {
name: String,
binaries: Vec<String>,
build_cmd: String,
args: HashMap<String, String>,
}
impl Package {
@ -46,26 +48,32 @@ impl Package {
let mut binaries = vec![];
for (count, (name, table)) in bin_table.into_iter().enumerate() {
// if count != 0 {
binaries.push(name.clone());
// }
}
let build_table = data.get("build").unwrap();
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
build_cmd.remove(0);
// build_cmd.pop();
let mut args: HashMap<String, String> = match build_table.get("args") {
None => HashMap::new(),
Some(v) => v
.as_table()
.unwrap()
.into_iter()
.map(|(k, v)| (k.clone(), v.to_string()))
.collect::<HashMap<String, String>>(),
};
Self {
name,
binaries,
build_cmd,
args,
}
}
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
let path = format!("sysdata/programs/{}/{}", self.name, file);
// compile here
@ -73,6 +81,7 @@ impl Package {
&path,
Options {
fmt: true,
in_house_regalloc: true,
..Default::default()
},
out,
@ -87,6 +96,7 @@ impl Package {
hblang::run_compiler(
&path,
Options {
in_house_regalloc: true,
..Default::default()
},
out,
@ -98,6 +108,7 @@ impl Package {
&path,
Options {
dump_asm: true,
in_house_regalloc: true,
..Default::default()
},
out,

View file

@ -1,13 +1,9 @@
keycodes := @use("keycodes.hb");
.{KeyCode} := keycodes
KeyEvent := struct {
// 0 if down
// 1 if up
up: u8,
// 0 if not just triggered
// 1 if just triggered
just_triggered: u8,
KeyEvent := packed struct {
up: bool,
just_triggered: bool,
key: KeyCode,
}

View file

@ -6,6 +6,17 @@ events := @use("events.hb");
.{KeyEvent, MouseEvent} := events
recieve_key_event := fn(): ?KeyEvent {
kevent := KeyEvent.(false, false, 0)
buf_id := buffer.search("PS/2 Keyboard\0")
// Read out of the Keyboard buffer here
buffer.recv(KeyEvent, buf_id, &kevent)
if kevent.just_triggered {
return kevent
}
return null
}
@ -15,7 +26,7 @@ recieve_mouse_event := fn(): ?MouseEvent {
buf_id := buffer.search("PS/2 Mouse\0")
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, @bitcast(&mevent))
buffer.recv(MouseEvent, buf_id, &mevent)
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
return mevent

View file

@ -1,7 +1,4 @@
# Images
- General over image format
- Support formats:
- PNG
- Animation
# API

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
.{log} := @use("../../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
magic: u16,
@ -41,7 +41,7 @@ from := fn(bmp: ^u8): ?Surface {
return null
}
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height)
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height, info_header.width * info_header.height)
rhs := new_surface(info_header.width, info_header.height)
put_surface(rhs, lhs, .(0, 0), true)

View file

@ -1,5 +1,5 @@
.{Color, Surface, new_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
.{log} := @use("../../../stn/src/lib.hb")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
@ -13,7 +13,7 @@ $QOI_OP_RUN := 0xC0
$QOI_OP_RGB := 0xFE
$QOI_OP_RGBA := 0xFF
$QOI_MASK_2 := 0xC0
QOI_COLOR_HASH := fn(c: Color): u8 {
$QOI_COLOR_HASH := fn(c: Color): u8 {
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
}
$QOI_MAGIC := 0x716F6966
@ -89,7 +89,7 @@ from := fn(qoi: ^u8): ?Surface {
run = b1 & 0x3F
}
index[@inline(QOI_COLOR_HASH, px)] = px
index[QOI_COLOR_HASH(px)] = px
};
*(surface.buf + px_pos) = px

View file

@ -10,19 +10,21 @@ Surface := struct {
buf: ^Color,
width: uint,
height: uint,
size: uint,
}
new_surface := fn(width: uint, height: uint): Surface {
return .(
@inline(memory.alloc, Color, width * height),
memory.alloc(Color, width * height),
width,
height,
width * height,
)
}
clone_surface := fn(surface: ^Surface): Surface {
new := new_surface(surface.width, surface.height)
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
memory.copy(Color, surface.buf, new.buf, @intcast(surface.size))
return new
}
@ -33,42 +35,38 @@ init := fn(doublebuffer: bool): Surface {
if doublebuffer {
return new_surface(width, height)
} else {
return .(framebuffer, width, height)
return .(framebuffer, width, height, width * height)
}
}
clear := fn(surface: Surface, color: Color): void {
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
$clear := fn(surface: Surface, color: Color): void {
memory.set(Color, &color, surface.buf, surface.width * surface.height)
}
sync := fn(surface: Surface): void {
if surface.buf == framebuffer {
return
}
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
$sync := fn(surface: Surface): void {
memory.copy(Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
}
index := fn(surface: Surface, x: uint, y: uint): uint {
$index := fn(surface: Surface, x: uint, y: uint): uint {
return x + surface.width * y
}
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + @inline(index, surface, x, y)
$indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
return surface.buf + index(surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
*@inline(indexptr, surface, pos.x, pos.y) = color
return
$put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
return *indexptr(surface, pos.x, pos.y) = color
}
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
top_start_idx := indexptr(surface, pos.x, pos.y)
bottom_start_idx := indexptr(surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else {
@inline(memory.set, Color, &color, top_start_idx, tr.x)
@inline(memory.set, Color, &color, bottom_start_idx, tr.x)
memory.set(Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, bottom_start_idx, tr.x)
top_start_idx += surface.width
bottom_start_idx -= surface.width
@ -76,16 +74,16 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color:
}
if rows_to_fill == 1 {
@inline(memory.set, Color, &color, top_start_idx, tr.x)
memory.set(Color, &color, top_start_idx, tr.x)
}
return
}
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
start_idx := indexptr(surface, pos.x, pos.y)
end_idx := indexptr(surface, pos.x, pos.y + tr.y)
right_start_idx := indexptr(surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else {
*start_idx = color;
@ -94,8 +92,8 @@ put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color):
right_start_idx += surface.width
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
memory.set(Color, &color, indexptr(surface, pos.x, pos.y), @bitcast(tr.x + 1))
memory.set(Color, &color, indexptr(surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return
}
@ -112,7 +110,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
y := p0.y
x := p0.x
loop if x == p1.x break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
if D > 0 {
y += yi
D += 2 * (dy - dx)
@ -136,7 +134,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Col
x := p0.x
y := p0.y
loop if y == p1.y break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
if D > 0 {
x += xi
D += 2 * (dx - dy)
@ -169,8 +167,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
src_top_cursor := top.buf
src_bottom_cursor := top.buf + top.width * (top.height - 1)
dst_top_idx := @inline(indexptr, surface, pos.x, pos.y)
dst_bottom_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
dst_top_idx := indexptr(surface, pos.x, pos.y)
dst_bottom_idx := indexptr(surface, pos.x, pos.y + top.height - 1)
dst_increment := surface.width
@ -184,8 +182,8 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
rows_to_copy := top.height
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
@inline(memory.copy, Color, src_bottom_cursor, dst_bottom_idx, top.width)
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
memory.copy(Color, src_bottom_cursor, dst_bottom_idx, top.width)
dst_top_idx += dst_increment
dst_bottom_idx -= dst_increment
@ -195,7 +193,7 @@ put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool)
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
memory.copy(Color, src_top_cursor, dst_top_idx, top.width)
}
return
@ -233,7 +231,7 @@ put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): vo
y := y0
loop if y == y1 break else {
*@inline(indexptr, surface, x, y) = color
*indexptr(surface, x, y) = color
y += 1
}
@ -247,7 +245,8 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
x0 = x1
x1 = tmp
}
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
// x0 = math.min(x0, x1)
memory.set(Color, &color, indexptr(surface, x0, y), @bitcast(x1 - x0 - 1))
return
}
@ -255,29 +254,29 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - @as(int, @intcast(2 * radius));
*@inline(indexptr, surface, pos.x + radius, pos.y) = color;
*@inline(indexptr, surface, pos.x - radius, pos.y) = color;
*@inline(indexptr, surface, pos.x, pos.y + radius) = color;
*@inline(indexptr, surface, pos.x, pos.y - radius) = color
error := @as(int, 3) - @intcast(2 * radius);
*indexptr(surface, pos.x + radius, pos.y) = color;
*indexptr(surface, pos.x - radius, pos.y) = color;
*indexptr(surface, pos.x, pos.y + radius) = color;
*indexptr(surface, pos.x, pos.y - radius) = color
loop if y < x break else {
x += 1
if error > 0 {
y -= 1
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
};
*@inline(indexptr, surface, pos.x + x, pos.y + y) = color;
*@inline(indexptr, surface, pos.x + y, pos.y + x) = color;
*@inline(indexptr, surface, pos.x - x, pos.y + y) = color;
*@inline(indexptr, surface, pos.x - y, pos.y + x) = color;
*@inline(indexptr, surface, pos.x + x, pos.y - y) = color;
*@inline(indexptr, surface, pos.x + y, pos.y - x) = color;
*@inline(indexptr, surface, pos.x - x, pos.y - y) = color;
*@inline(indexptr, surface, pos.x - y, pos.y - x) = color
*indexptr(surface, pos.x + x, pos.y + y) = color;
*indexptr(surface, pos.x + y, pos.y + x) = color;
*indexptr(surface, pos.x - x, pos.y + y) = color;
*indexptr(surface, pos.x - y, pos.y + x) = color;
*indexptr(surface, pos.x + x, pos.y - y) = color;
*indexptr(surface, pos.x + y, pos.y - x) = color;
*indexptr(surface, pos.x - x, pos.y - y) = color;
*indexptr(surface, pos.x - y, pos.y - x) = color
}
return
@ -286,24 +285,24 @@ put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color):
put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
x := 0
y := radius
error := @as(int, 3) - @as(int, @intcast(2 * radius))
@inline(put_hline, surface, pos.y - x, pos.x - radius, pos.x + radius, color);
*@inline(indexptr, surface, pos.x, pos.y + radius) = color;
*@inline(indexptr, surface, pos.x, pos.y - radius) = color
error := @as(int, 3) - @intcast(2 * radius)
put_hline(surface, pos.y - x, pos.x - radius, pos.x + radius, color);
*indexptr(surface, pos.x, pos.y + radius) = color;
*indexptr(surface, pos.x, pos.y - radius) = color
loop if y < x break else {
x += 1
if error > 0 {
@inline(put_hline, surface, pos.y + y, pos.x - x, pos.x + x, color)
@inline(put_hline, surface, pos.y - y, pos.x - x, pos.x + x, color)
put_hline(surface, pos.y + y, pos.x - x, pos.x + x, color)
put_hline(surface, pos.y - y, pos.x - x, pos.x + x, color)
y -= 1
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
}
@inline(put_hline, surface, pos.y + x, pos.x - y, pos.x + y, color)
@inline(put_hline, surface, pos.y - x, pos.x - y, pos.x + y, color)
put_hline(surface, pos.y + x, pos.x - y, pos.x + y, color)
put_hline(surface, pos.y - x, pos.x - y, pos.x + y, color)
}
return
@ -312,24 +311,24 @@ put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color:
put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
x := 0
y := radius
error := @as(int, 3) - @as(int, @intcast(2 * radius))
@inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y), @inline(indexptr, surface, pos.x - y, pos.y), 2 * y);
*@inline(indexptr, surface, pos.x, pos.y + y) = *@inline(indexptr, source, source_pos.x, source_pos.y + y);
*@inline(indexptr, surface, pos.x, pos.y - y) = *@inline(indexptr, source, source_pos.x, source_pos.y - y)
error := @as(int, 3) - @intcast(2 * radius)
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y), indexptr(surface, pos.x - y, pos.y), 2 * y);
*indexptr(surface, pos.x, pos.y + y) = *indexptr(source, source_pos.x, source_pos.y + y);
*indexptr(surface, pos.x, pos.y - y) = *indexptr(source, source_pos.x, source_pos.y - y)
loop if y < x break else {
x += 1
if error > 0 {
@inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - x, source_pos.y + y), @inline(indexptr, surface, pos.x - x, pos.y + y), 2 * x)
@inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - x, source_pos.y - y), @inline(indexptr, surface, pos.x - x, pos.y - y), 2 * x)
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y + y), indexptr(surface, pos.x - x, pos.y + y), 2 * x)
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y - y), indexptr(surface, pos.x - x, pos.y - y), 2 * x)
y -= 1
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
error += 4 * (@intcast(x) - @intcast(y)) + 10
} else {
error += 4 * @intcast(x) + 6
}
@inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y + x), @inline(indexptr, surface, pos.x - y, pos.y + x), 2 * y)
@inline(memory.copy, Color, @inline(indexptr, source, source_pos.x - y, source_pos.y - x), @inline(indexptr, surface, pos.x - y, pos.y - x), 2 * y)
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y + x), indexptr(surface, pos.x - y, pos.y + x), 2 * y)
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y - x), indexptr(surface, pos.x - y, pos.y - x), 2 * y)
}
return
@ -364,7 +363,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
str += 1
continue
}
glyph_data = @inline(get_glyph, font, *str)
glyph_data = get_glyph(font, *str)
} else {
if *str < UNC_TABLE_SIZE {
glyph_index := *(font.unicode + *str)
@ -436,7 +435,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
cursor.y += next_line_y
}
dest := @inline(indexptr, surface, cursor.x, cursor.y)
dest := indexptr(surface, cursor.x, cursor.y)
rows := font.height
loop if rows == 0 break else {

View file

@ -74,16 +74,16 @@ font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
return font
}
get_glyph := fn(font: Font, index: u8): ^u8 {
$get_glyph := fn(font: Font, index: u8): ^u8 {
return font.data + @as(uint, index) * font.bytes_per_glyph
}
UNC_TABLE_SIZE := 1 << 16
$UNC_TABLE_SIZE := 1 << 16
init_unicode := fn(font: ^Font): void {
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
@inline(memory.set, u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
memory.set(u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
table := font.data + font.num_glyphs * font.bytes_per_glyph
curr_glyph := @as(u16, 0)
@ -121,8 +121,6 @@ init_unicode := fn(font: ^Font): void {
next_byte := *table
if (next_byte & 0xC0) != 0x80 {
valid = false
}
if valid == false {
break
}
unicode = unicode << 6 | next_byte & 0x3F

View file

@ -1,18 +1,18 @@
string := @use("string.hb")
recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^u8): void {
$recv := fn($Expr: type, buffer_id: uint, memory_map_location: ^Expr): void {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
}
write := fn($Expr: type, msg: ^Expr, buffer_id: uint): void {
$write := fn($Expr: type, buffer_id: uint, msg: ^Expr): void {
return @eca(3, buffer_id, msg, @sizeof(Expr))
}
recv_length := fn(buffer_id: uint, memory_map_location: ^u8, length: uint): void {
$recv_length := fn(length: uint, memory_map_location: ^u8, buffer_id: uint): void {
return @eca(4, buffer_id, memory_map_location, length)
}
write_length := fn(msg: ^u8, buffer_id: uint, length: uint): void {
$write_length := fn(length: uint, msg: ^u8, buffer_id: uint): void {
return @eca(3, buffer_id, msg, length)
}
@ -22,6 +22,14 @@ create := fn(msg: ^u8): uint {
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}
$create_nameless := fn(): uint {
return @eca(1, 0)
}
$delete_buffer := fn(buffer_id: uint): void {
return @eca(2, buffer_id)
}
search := fn(msg: ^u8): uint {
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
}

View file

@ -1,29 +1,14 @@
abs := fn($Expr: type, x: Expr): Expr {
mask := x >> @bitcast(@sizeof(Expr) - 1)
return (x ^ mask) - mask
$abs := fn($Expr: type, x: Expr): Expr {
return (x ^ x >> @sizeof(Expr) - 1) - (x >> @sizeof(Expr) - 1)
}
min := fn($Expr: type, a: Expr, b: Expr): Expr {
c := a - b
return b + (c & c >> @bitcast(@sizeof(Expr) - 1))
$min := fn($Expr: type, a: Expr, b: Expr): Expr {
return b + (a - b & a - b >> @sizeof(Expr) - 1)
}
max := fn($Expr: type, a: Expr, b: Expr): Expr {
c := a - b
return a - (c & c >> @bitcast(@sizeof(Expr) - 1))
$max := fn($Expr: type, a: Expr, b: Expr): Expr {
return a - (a - b & a - b >> @sizeof(Expr) - 1)
}
signum := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
} else if x < @as(Expr, @intcast(0)) {
return -1
} else {
return 0
}
}
signincl := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
}
return -1
$sign := fn($Expr: type, x: Expr): i8 {
return @bitcast(x > 0) - @bitcast(x < 0)
}
Vec2 := fn($Expr: type): type {

View file

@ -1,32 +1,26 @@
PAGE_SIZE := 4096
MAX_ALLOC := 0xFF
MAX_FREE := 0xFF
$PAGE_SIZE := 4096
$MAX_ALLOC := 0xFF
$MAX_FREE := 0xFF
is_uninit := fn($Expr: type, ptr: ^Expr): bool {
i := 0
loop if *(@as(^u8, @bitcast(ptr)) + i) != 0 return false else if i + 1 == @sizeof(Expr) return true else i += 1
}
uninit := fn($Expr: type): Expr {
empty := @as(Expr, idk)
@inline(set, u8, &0, @bitcast(&empty), @sizeof(Expr))
return empty
$uninit := fn($Expr: type): ?Expr {
return null
}
dangling := fn($Expr: type): ^Expr {
return @bitcast(@alignof(Expr))
}
calc_pages := fn($Expr: type, num: uint): uint {
$calc_pages := fn($Expr: type, num: uint): uint {
return 1 + @sizeof(Expr) * num / PAGE_SIZE
}
// ! will be replaced, don't get attached
alloc := fn($Expr: type, num: uint): ^Expr {
pages := @inline(calc_pages, Expr, num)
pages := calc_pages(Expr, num)
if pages <= MAX_ALLOC {
return @bitcast(request_page(@intcast(pages)))
}
ptr := request_page(0xFF)
ptr := request_page(MAX_ALLOC)
remaining := pages - MAX_ALLOC
loop if remaining < MAX_ALLOC break else {
_ = request_page(@intcast(MAX_ALLOC))
@ -37,46 +31,46 @@ alloc := fn($Expr: type, num: uint): ^Expr {
}
// ! stub
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
$free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
return
}
RqPageMsg := packed struct {a: u8, count: u8}
request_page := fn(count: u8): ^u8 {
$request_page := fn(count: u8): ^u8 {
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
}
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
release_page := fn(ptr: ^u8, count: u8): void {
$release_page := fn(ptr: ^u8, count: u8): void {
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
}
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
outb := fn(addr: u16, value: u8): void {
$outb := fn(addr: u16, value: u8): void {
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
}
InbMsg := packed struct {a: u8, b: u8, addr: u16}
inb := fn(addr: u16): u8 {
$inb := fn(addr: u16): u8 {
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
}
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
outl := fn(addr: u16, value: u32): void {
$outl := fn(addr: u16, value: u32): void {
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
}
InlMsg := packed struct {a: u8, b: u8, addr: u16}
inl := fn(addr: u16): u32 {
$inl := fn(addr: u16): u32 {
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
}
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
$copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
$set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
}

View file

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

View file

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

View file

@ -4,118 +4,60 @@ length := fn(ptr: ^u8): uint {
}
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
is_negative := num < 0
if is_negative num = -num
ptr := p
negative := num < 0
if negative {
num = -num
}
if radix == 2 {
*ptr = 48
ptr += 1;
*ptr = 98
ptr += 1
} else if radix == 16 {
*ptr = 48
ptr += 1;
*ptr = 120
ptr += 1
} else if radix == 8 {
*ptr = 48
ptr += 1;
*ptr = 111
ptr += 1
}
digits_start := ptr
if num == 0 {
*ptr = 48
ptr += 1
} else {
loop if num == 0 break else {
digit := num % @bitcast(radix)
if digit < 10 {
*ptr = @intcast(digit) + 48
} else {
*ptr = @intcast(digit) + 55
}
ptr += 1
num /= @bitcast(radix)
}
*ptr = 0x30;
*(ptr + 1) = 0
return p
}
if negative {
*ptr = 45
loop if num == 0 break else {
remainder := num % @bitcast(radix)
num /= @bitcast(radix);
*ptr = @intcast(remainder + 0x30)
if remainder > 9 {
*ptr = @intcast(remainder - 10 + 0x41)
}
ptr += 1
};
}
*ptr = 0
@inline(reverse, digits_start)
if is_negative {
*ptr = 0x2D
ptr += 1
}
// ! it gets broked when you do this ??
// *ptr = 0
@inline(reverse, p)
return p
}
reverse := fn(s: ^u8): void {
i := 0
j := @inline(length, s) - 1
j := s + @inline(length, s) - 1
temp := @as(u8, 0)
loop if i >= j break else {
temp = *(s + i);
*(s + i) = *(s + j);
*(s + j) = temp
i += 1
loop if s < j {
temp = *s;
*s = *j;
*j = temp
s += 1
j -= 1
}
return
} else return
}
equals := fn(lhs: ^u8, rhs: ^u8): bool {
if lhs == rhs {
return true
}
i := 0
loop if *(lhs + i) != *(rhs + i) {
loop if *lhs != *rhs {
return false
} else if *lhs == 0 {
return true
} else {
i += 1
lhs += 1
rhs += 1
}
}
contains := fn(haystack: ^u8, needle: ^u8): bool {
haystack_len := @inline(length, haystack)
needle_len := @inline(length, needle)
if needle_len == 0 {
return true
}
if haystack_len < needle_len {
return false
}
max_start := haystack_len - needle_len
pos := 0
loop if pos > max_start break else {
is_match := true
offset := 0
loop if offset >= needle_len break else {
if *(haystack + pos + offset) != *(needle + offset) {
is_match = false
}
if is_match == false {
break
}
offset += 1
}
if is_match {
return true
}
pos += 1
}
return false
}

View file

@ -1,62 +1,63 @@
.{math: .{Vec2}, buffer, log, memory} := @use("../../stn/src/lib.hb");
.{Surface, new_surface} := @use("../../render/src/lib.hb");
.{WindowWrapper, WindowID, WindowProps, WindowMessage, message, BUFFER} := @use("./lib.hb")
.{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
.{new_surface, Color} := @use("../../render/src/lib.hb")
buffer_id := @as(?uint, null)
// ! in the future this should be safely handled
channel := Channel.(0, 0)
new_window := fn(props: WindowProps): ?WindowWrapper {
if buffer_id == null {
log.error("client: (request_new) buffer id is null. did you init the client?\0")
return null
}
buf := memory.uninit(?WindowWrapper)
buffer.write(WindowMessage, &.(message.new, 0, @sizeof(WindowProps), @bitcast(&props), @bitcast(&buf)), @unwrap(buffer_id))
loop if memory.is_uninit(?WindowWrapper, &buf) == false break else {
}
// loop until i write a better socket
i := 0
loop if i >= 1000 break else i += 1
return buf
find_server := fn(): void {
log.info("client: locating server\0")
channel2 := await_channel()
channel.server = channel2.server
channel.client = channel2.client
log.info("client: server located\0")
}
update_window_props := fn(wrapper: WindowWrapper): ?WindowProps {
log.error("todo: sunset_proto/src/client/update_window_props.hb\0")
if buffer_id == null {
log.error("client: (request_update_properties) buffer id is null. did you init the client?\0")
new := fn(props: WindowProps): ?Window {
send_header(message.syn, channel.server)
response := await_message(Channel, channel.client)
if response.header.kind != message.ack {
return null
}
// TODO: buffer.write(WINDOWING_BUFFER, update properties) request
return null
log.info("client: recv ack\0")
send_message(WindowProps, message.props, props, response.body.server)
windowdata := await_message(WindowData, response.body.client)
if windowdata.header.kind != message.ack {
return null
}
log.info("client: recv windowdata\0")
surface := new_surface(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y)
return .(windowdata.body, surface)
}
request_shutdown := fn(): ?bool {
if buffer_id == null {
log.error("client: (request_shutdown) buffer id is null. did you init the client?\0")
return null
}
buf := memory.uninit(?u8)
buffer.write(WindowMessage, &.(message.shutdown, 0, 0, memory.dangling(u8), @bitcast(&buf)), @unwrap(buffer_id))
loop if memory.is_uninit(?u8, &buf) == false break else {
}
// loop until i write a better socket
i := 0
loop if i >= 1000 break else i += 1
// had to do ?u8 here, ?bool didnt work
if buf == null | @unwrap(buf) != 255 {
quit := fn(client: Window): void {
send_header(message.quit, client.data.channel.server)
}
connected := fn(client: Window): bool {
return true
}
shutdown_server := fn(client: Window): bool {
return false
}
update_props := fn(client: Window): bool {
return false
}
update_permissions := fn(client: Window): bool {
return false
}
send_frame := fn(client: Window): bool {
send_header(message.frame_ready, client.data.channel.server)
response := await_message(uint, client.data.channel.client)
if response.header.kind != message.ack {
return false
} else {
return true
}
}
init := fn(): void {
log.info("client: waiting for server\0")
id := 0
loop if id != 0 {
buffer_id = id
log.info("client: done waiting\0")
return
} else {
id = buffer.search(BUFFER)
}
// ! FOR NOW, server will ALWAYS be local,
// ! so we can send pointer to surface.
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
return true
}

View file

@ -1,36 +1,97 @@
.{math: .{Vec2}} := @use("../../stn/src/lib.hb");
.{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb");
.{Surface} := @use("../../render/src/lib.hb")
$BUFFER := "sunset\0"
$BUFFER_SERVER := "sunset_server\0"
$BUFFER_CLIENT := "sunset_client\0"
Channel := packed struct {
client: uint,
server: uint,
}
client := @use("./client.hb")
server := @use("./server.hb")
message := @use("./message.hb")
permissions := @use("./permissions.hb")
WindowID := uint
MessageKind := uint
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg)))
}
WindowMessage := packed struct {
$send_header := fn(kind: MessageKind, buffer_id: uint): void {
buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind)))
}
$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
buffer.recv(?Message(Expr), buffer_id, &response)
return response
}
$recv_header := fn(buffer_id: uint): ?MessageHeader {
response := @as(?MessageHeader, null)
buffer.recv(?MessageHeader, buffer_id, &response)
return response
}
await_channel := fn(): Channel {
channel := Channel.(0, 0)
loop if channel.server != 0 break else {
channel.server = buffer.search(BUFFER_SERVER)
}
loop if channel.client != 0 break else {
channel.client = buffer.search(BUFFER_CLIENT)
}
return channel
}
await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
response := @as(?Message(Expr), null)
loop {
buffer.recv(?Message(Expr), buffer_id, &response)
if response != null {
return @as(Message(Expr), response)
}
}
}
await_header := fn(buffer_id: uint): MessageHeader {
response := @as(?MessageHeader, null)
loop {
buffer.recv(?MessageHeader, buffer_id, &response)
if response != null {
return @as(?MessageHeader, response)
}
}
}
MessageKind := u8
MessageHeader := packed struct {
kind: MessageKind,
id: WindowID,
length: uint,
data_ptr: ^u8,
// need to replace this with a buffer id
callback: ^u8,
}
Message := fn($Expr: type): type {
return packed struct {
header: MessageHeader,
body: Expr,
}
}
WindowProps := struct {
position: Vec2(uint),
dimensions: Vec2(uint),
// ! replace with owned string type later
title: ^u8,
}
WindowWrapper := struct {
id: WindowID,
WindowData := struct {
props: WindowProps,
channel: Channel,
permissions: uint,
}
Window := struct {
data: WindowData,
surface: Surface,
props: WindowProps,
}

View file

@ -1,4 +1,8 @@
$new := 0
$destroy := 1
$update_props := 2
$shutdown := 3
// ! all values in this file are subject to change.
$syn := 1
$ack := 2
$refused := 3
$quit := 4
$props := 5
$shutdown := 6
$frame_ready := 7

View file

@ -0,0 +1,5 @@
$none := 0b0
$exclusive_framebuffer := 0b1
$shutdown := 0b100
$default := none

View file

@ -1,34 +1,135 @@
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
.{Surface, new_surface} := @use("../../render/src/lib.hb");
.{WindowWrapper, WindowID, WindowProps, WindowMessage, BUFFER} := @use("./lib.hb")
.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text, clear, white, black} := @use("../../render/src/lib.hb");
.{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb")
WindowServer := struct {window_count: uint, buffer_id: uint}
server := @as(?WindowServer, null)
new_window_id := fn(): WindowID {
return random.any(uint)
WindowServer := struct {
window_count: uint,
channel: Channel,
// ! replace this with a collection when we get an allocator
windows: [?Window; 10],
font: text.Font,
}
init := fn(): bool {
log.info("server: starting server\0")
server = .(0, buffer.create(BUFFER))
// ! in the future this should be safely handled
server := @as(WindowServer, idk)
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
start := fn(): void {
font := text.font_from_psf2(@bitcast(&psf), false)
if font == null {
log.error("server: failed to load asset\0")
return
}
server = .(
0,
.{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)},
.(null, null, null, null, null, null, null, null, null, null),
@as(text.Font, font),
)
log.info("server: started server\0")
}
incoming := fn(): bool {
msg := recv_header(server.channel.server)
if msg == null {
return true
}
if msg.kind == message.syn {
log.info("server: recv syn\0")
channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
send_message(Channel, message.ack, channel, server.channel.client)
props := await_message(WindowProps, channel.server)
if props.header.kind != message.props {
return true
}
log.info("server: recv props\0")
// ! do inspection of requested props here
data := WindowData.(props.body, channel, permissions.default)
send_message(WindowData, message.ack, data, channel.client)
surface := new_window_decorations(data.props.dimensions)
// decorations
{
title := data.props.title
title_length := string.length(title)
deco_length := title_length * 10
// draw the window tab bar
put_filled_rect(surface, .(0, 0), .(data.props.dimensions.x + DECO_WIDTH + deco_length, DECO_HEIGHT_TOP), DECO_COLOUR)
// Draw the window tab
put_filled_rect(surface, .(0, 0), .(deco_length, DECO_HEIGHT_TOP - 1), DECO_COLOUR_DARKER)
// Draw the outside box
put_rect(surface, .(0, 0), data.props.dimensions + .(DECO_WIDTH - 1, DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM - 1), DECO_COLOUR)
put_text(surface, server.font, .(2, 1), .(0, 0, 0, 255), data.props.title)
}
server.windows[server.window_count] = .(data, surface)
server.window_count += 1
}
return true
}
recieve := fn(): ?WindowMessage {
if server == null {
log.error("server: (request_new) server is null. did you init the client?\0")
return null
}
buf := memory.uninit(WindowMessage)
buffer.recv(WindowMessage, @unwrap(server).buffer_id, @bitcast(&buf))
if memory.is_uninit(WindowMessage, &buf) {
return null
}
return buf
$DECO_WIDTH := 2
$DECO_HEIGHT_TOP := 20
$DECO_HEIGHT_BOTTOM := 1
$DECO_COLOUR := Color.(100, 200, 255, 255)
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
return new_surface(
dimensions.x + DECO_WIDTH,
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
)
}
should_shutdown := fn(): bool {
return false
// ! compositor code. this currently disallows tearing.
collect_frames := fn(): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
header := recv_header(window.data.channel.server)
if header == null {
i += 1
continue
}
if header.kind != message.frame_ready {
i += 1
continue
}
send_header(message.ack, window.data.channel.client)
ptr := await_message(^Color, window.data.channel.server)
if ptr.header.kind != message.ack {
return
}
put_surface(
window.surface,
Surface.(
ptr.body,
window.data.props.dimensions.x,
window.data.props.dimensions.y,
window.data.props.dimensions.x * window.data.props.dimensions.y,
),
.(DECO_WIDTH / 2, DECO_HEIGHT_TOP),
false,
)
i += 1
}
}
render_clients := fn(screen: Surface): void {
i := 0
loop if i == 10 break else {
window := server.windows[i]
if window == null {
i += 1
continue
}
put_surface(screen, window.surface, window.data.props.position, false)
i += 1
}
}

View file

@ -56,23 +56,13 @@ main := fn(): int {
loop {
// Clear the screen
render.clear(screen, render.black)
render.put_surface(screen, wallpaper, .(0, 0), false)
// TODO: Read the window buffer here
{
// buffer.recv([u8; 4096], win_buff, mem_buf)
// // for some reason this null check causes the compiler to spin forever
// if *mem_buf == 0 {
// log.info("No messages\0")
// } else {
// log.info("Handle Messages\0")
// }
}
// get input events from drivers via intouch
// key_event := intouch.recieve_key_event();
// log.info("before mouse event check\0");
if false {
// Scroll bar :ThumbsUp:
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
@ -82,6 +72,12 @@ main := fn(): int {
render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
}
{
// osu dots
render.put_rect(screen, .(400, 100), .(100, 100), render.red)
render.put_rect(screen, .(100, 100 + 300), .(100, 100), render.red)
}
{
pos := Vec2(uint).(1, screen.height - 21)
render_label_to_surface(screen, text_label, font, pos)
@ -91,12 +87,20 @@ main := fn(): int {
// Screen border
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
// get input events from drivers via intouch
if false {
key_event := intouch.recieve_key_event()
if key_event != null {
log.info("Key event \0")
}
}
{
mouse_event := intouch.recieve_mouse_event()
//
if mouse_event != null {
// log.warn("Mouse event recieved\0")
// log.warn("Mouse event received\0")
change_x := @as(i16, mouse_event.x_change)
change_x = change_x << 8
@ -133,13 +137,9 @@ main := fn(): int {
}
}
// render mouse
lum := render.indexptr(screen, mouse_x, mouse_y)
if lum.r / 3 + lum.g / 3 + lum.b / 3 < 128 {
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
} else {
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
}
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
// Send events to focused window
}

View file

@ -1,4 +1,8 @@
.{memory, log, buffer} := @use("../../../libraries/stn/src/lib.hb")
stn := @use("../../../libraries/stn/src/lib.hb");
.{memory, log, buffer} := stn
intouch := @use("../../../libraries/intouch/src/lib.hb");
.{KeyEvent} := intouch
send_byte := fn(byte: u8): u8 {
memory.outb(96, byte)
@ -6,23 +10,31 @@ send_byte := fn(byte: u8): u8 {
}
main := fn(): int {
buf := buffer.create("XKeyboard\0")
buf := buffer.create("PS/2 Keyboard\0")
_ = send_byte(238)
log.info("PS/2 Driver Loaded\0")
if send_byte(238) == 238 {
log.info("PS/2 Keyboard Echoed\0")
}
if send_byte(244) == 250 {
log.info("Enabled scanning\0")
}
prev_input := 250
loop {
loop if (memory.inb(0x64) & 0x20) == 0x20 break
input := memory.inb(96)
if input == prev_input {
continue
}
prev_input = input
buffer.write(u8, &input, buf)
kevent := KeyEvent.(false, true, input)
buffer.write(KeyEvent, buf, &kevent)
}
return 0
}

View file

@ -145,7 +145,7 @@ main := fn(): int {
event.x_change = x_change
event.y_change = y_change
buffer.write(MouseEvent, &event, mouse_buffer)
buffer.write(MouseEvent, mouse_buffer, &event)
}
return 0

View file

@ -10,12 +10,12 @@ example := fn(): void {
color := render.light_cyan
n := @as(u8, 1)
loop {
// ! dead code elimination bug
render.clear(screen, color)
render.sync(screen)
if (color.b & 255) == 255 | (color.b & 255) == 0 {
if color.b == 255 | color.b == 0 {
n = -n
}
color.b += n
}
return
}

View file

@ -46,7 +46,7 @@ example := fn(): void {
bottom := buf + msg_len
@inline(memory.copy, u8, msg, buf, msg_len)
memory.copy(u8, msg, buf, msg_len)
cursor := bottom
draw_window(window, font, buf, cursor)

View file

@ -1 +1 @@
.{example: main} := @use("./examples/orbit.hb")
.{example: main} := @use("./examples/text.hb")

View file

@ -1,24 +1,29 @@
.{log, string} := @use("../../../libraries/stn/src/lib.hb")
.{log} := @use("../../../libraries/stn/src/lib.hb")
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
bmp := @embed("../../../assets/mini.bmp")
main := fn(): void {
sunset.client.init()
log.info("client: request new window\0")
window := sunset.client.new_window(.(.(100, 100), .(150, 150), "Hello, World!\0"))
if window == null {
log.error("Could not create window\0")
sunset.client.find_server()
image := render.image.bmp.from(@bitcast(&bmp))
if image == null {
log.error("got no image\0")
return
}
log.info("client: window created. title:\0")
log.info(window.props.title)
window.props.position = .(500, 500)
props := @unwrap(sunset.client.update_window_props(window))
if props.position.x != window.props.position.x {
log.error("client: we did not update props\0")
window := sunset.client.new(.(.(100, 100), .(200, 200), "Hello,\0"))
if window == null {
log.error("got no window\0")
return
}
log.info("client: sending shutdown request\0")
shutdown := sunset.client.request_shutdown()
if shutdown == null {
log.error("client: didnt shutdown the server\0")
x := 0
loop {
render.clear(window.surface, render.black)
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
_ = sunset.client.send_frame(window)
x += 1
}
}

View file

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

View file

@ -0,0 +1,29 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
bmp := @embed("../../../assets/able.bmp")
main := fn(): void {
sunset.client.find_server()
image := render.image.bmp.from(@bitcast(&bmp))
if image == null {
log.error("got no image\0")
return
}
window := sunset.client.new(.(.(400, 300), .(400, 240), "Sunset!\0"))
if window == null {
log.error("got no window\0")
return
}
x := 0
loop {
render.clear(window.surface, render.black)
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 40), false)
_ = sunset.client.send_frame(window)
x += 1
}
}

View file

@ -1,36 +1,98 @@
.{log} := @use("../../../libraries/stn/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb");
.{server, message, WindowWrapper, WindowProps} := @use("../../../libraries/sunset_proto/src/lib.hb")
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
render := @use("../../../libraries/render/src/lib.hb")
intouch := @use("../../../libraries/intouch/src/lib.hb")
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{new_label, render_label_to_surface, set_label_text} := horizon_api.widgets.label
stn := @use("../../../libraries/stn/src/lib.hb");
.{Vec2} := stn.math
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
img := @embed("../../../assets/wallpaper.qoi")
main := fn(): void {
screen := render.init(false)
font := render.text.font_from_psf2(@bitcast(&psf), false)
if font == null {
return
main := fn(): int {
sunset.server.start()
screen := render.init(true)
render.clear(screen, render.black)
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
wallpaper := render.image.from(@bitcast(&img))
if wallpaper == null {
// stn.panic("Wallpaper not loaded\0")
return 1
}
if server.init() == false {
log.error("Failed to create server\0")
return
}
loop if server.should_shutdown() break else {
recv := server.recieve()
if recv == null {
continue
} else if recv.kind == message.new {
props := *@as(^WindowProps, @bitcast(recv.data_ptr));
*@as(^?WindowWrapper, @bitcast(recv.callback)) = WindowWrapper.(0, props)
render.put_rect(screen, props.position, props.dimensions, render.white)
render.put_text(screen, font, props.position + .(1, 1), render.white, props.title)
render.put_hline(screen, props.position.y + font.height + 2, props.position.x, props.position.x + props.dimensions.x, render.white)
log.info("server: made a new window\0")
} else if recv.kind == message.shutdown {
*@as(^?u8, @bitcast(recv.callback)) = 255
break
mouse_x := 100
mouse_y := 100
text_label := new_label("Hi\0")
loop {
mouse_event := intouch.recieve_mouse_event()
if mouse_event != null {
change_x := @as(i16, mouse_event.x_change)
change_x = change_x << 8
change_x = change_x >> 8
mouse_x += change_x
if mouse_x < 0 {
mouse_x = 0
}
if mouse_x >= screen.width - 20 {
mouse_x = @intcast(screen.width - 21)
}
change_y := @as(i16, mouse_event.y_change)
change_y = change_y << 8
change_y = change_y >> 8
if mouse_y < 0 {
mouse_y = 0
}
if mouse_y >= screen.height - 20 {
mouse_y = @intcast(screen.height - 21)
}
mouse_y -= change_y
if mouse_event.left {
set_label_text(text_label, "LEFT CLICK\0")
}
if mouse_event.middle {
set_label_text(text_label, "MIDDLE CLICK\0")
}
if mouse_event.right {
set_label_text(text_label, "RIGHT CLICK\0")
}
}
{
render.clear(screen, render.black)
render.put_surface(screen, wallpaper, .(0, 0), false)
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), sunset.server.DECO_COLOUR)
}
if sunset.server.incoming() {
sunset.server.collect_frames()
sunset.server.render_clients(screen)
}
{
pos := Vec2(uint).(1, screen.height - 21)
render_label_to_surface(screen, text_label, font, pos)
render.put_rect(screen, .(0, screen.height - 21), .(screen.width - 1, 20), sunset.server.DECO_COLOUR)
}
// Mouse cursor
{
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR_DARKER)
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), sunset.server.DECO_COLOUR)
}
render.sync(screen)
}
render.put_text(screen, font, .(0, 0), render.white, "Shutdown triggered\0")
log.info("Server shutdown\0")
return 0
}

View file

@ -28,8 +28,8 @@ resolution = "1024x768x24"
# [boot.limine.ableos.modules.horizon]
# path = "boot:///horizon.hbf"
# [boot.limine.ableos.modules.ps2_mouse_driver]
# path = "boot:///ps2_mouse_driver.hbf"
[boot.limine.ableos.modules.ps2_mouse_driver]
path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_keyboard_driver]
# path = "boot:///ps2_keyboard_driver.hbf"

View file

@ -19,12 +19,14 @@
@morshy
Simple Userland Allocator
@funky
Kernel Testing Framework (A rust framework for testing the kernel)
@unassigned
FileIO (Fat32)
DiskIO (Undecided Disk type)
Proper Memory Protection
Channels (Two buffers bundled together to form two way communication)
Kernel Testing Framework (A rust framework for testing the kernel)
Userland Testing Framework (An hblang framework for testing the userspace)
PCI/E (Honestly I have no fucking clue whats going on with PCI or why userland cant properly read it)
Kernel Reimpl (Do not you dare think about this yet its only here as an option to show goals)