Litrally amlmost functional PS/2 driver. #19
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -82,9 +82,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
|
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
@ -228,12 +228,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbbytecode"
|
name = "hbbytecode"
|
||||||
version = "0.1.0"
|
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]]
|
[[package]]
|
||||||
name = "hblang"
|
name = "hblang"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"hashbrown 0.15.1",
|
"hashbrown 0.15.1",
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
|
@ -245,7 +245,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbvm"
|
name = "hbvm"
|
||||||
version = "0.1.0"
|
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 = [
|
dependencies = [
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,6 +11,7 @@ static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||||
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Debug)]
|
||||||
enum Interrupt {
|
enum Interrupt {
|
||||||
Timer = 32,
|
Timer = 32,
|
||||||
ApicErr = u8::MAX - 1,
|
ApicErr = u8::MAX - 1,
|
||||||
|
@ -66,11 +67,20 @@ extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
||||||
|
interrupt(Interrupt::ApicErr);
|
||||||
|
|
||||||
panic!("Internal APIC error");
|
panic!("Internal APIC error");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
||||||
|
interrupt(Interrupt::Spurious);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
LAPIC.end_of_interrupt();
|
LAPIC.end_of_interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn interrupt(interrupt_type: Interrupt){
|
||||||
|
log::info!("Interrupt type {:?}", interrupt_type);
|
||||||
|
panic!()
|
||||||
|
}
|
|
@ -111,7 +111,7 @@ unsafe extern "C" fn oops() -> ! {
|
||||||
unsafe extern "C" fn start() -> ! {
|
unsafe extern "C" fn start() -> ! {
|
||||||
logging::init();
|
logging::init();
|
||||||
crate::logger::init().expect("failed to set logger");
|
crate::logger::init().expect("failed to set logger");
|
||||||
log::info!("Initialising AKern {}", crate::VERSION);
|
log::debug!("Initialising AKern {}", crate::VERSION);
|
||||||
|
|
||||||
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
|
static HDHM_REQ: HhdmRequest = HhdmRequest::new(0);
|
||||||
memory::init_pt(VirtAddr::new(
|
memory::init_pt(VirtAddr::new(
|
||||||
|
@ -190,7 +190,7 @@ unsafe extern "C" fn start() -> ! {
|
||||||
// TODO: Add in rdseed and rdrand as sources for randomness
|
// TODO: Add in rdseed and rdrand as sources for randomness
|
||||||
let _rand = xml::XMLElement::new("Random");
|
let _rand = xml::XMLElement::new("Random");
|
||||||
|
|
||||||
log::trace!("Getting boot modules");
|
log::debug!("Getting boot modules");
|
||||||
let bm = MOD_REQ.get_response().get();
|
let bm = MOD_REQ.get_response().get();
|
||||||
|
|
||||||
let mut bootmodules = alloc::vec::Vec::new();
|
let mut bootmodules = alloc::vec::Vec::new();
|
||||||
|
@ -228,7 +228,7 @@ unsafe extern "C" fn start() -> ! {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log::info!("Boot module count: {:?}", bootmodules.len());
|
log::debug!("Boot module count: {:?}", bootmodules.len());
|
||||||
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
assert_eq!(bm.module_count, bootmodules.len() as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) };
|
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 class = ((reg2 >> 16) & 0x0000_FFFF) as u16;
|
||||||
let pci_class = PciFullClass::from_u16(class);
|
let pci_class = PciFullClass::from_u16(class);
|
||||||
let header_type = get_header_type(bus, device, 0);
|
let header_type = get_header_type(bus, device, 0);
|
||||||
|
|
|
@ -58,10 +58,10 @@ pub fn handler(vm: &mut Vm) {
|
||||||
true => IpcBuffer::new(true, length),
|
true => IpcBuffer::new(true, length),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
info!("Buffer ID: {}", buff_id);
|
|
||||||
vm.registers[1] = hbvm::value::Value(buff_id);
|
vm.registers[1] = hbvm::value::Value(buff_id);
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
|
log::error!("Oops, deleting buffers is not implemented.")
|
||||||
// Delete buffer
|
// Delete buffer
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
|
@ -182,7 +182,7 @@ pub fn handler(vm: &mut Vm) {
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = map_ptr as *mut u8;
|
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);
|
debug!("Recieve {:?} from Buffer({})", msg, buffer_id);
|
||||||
|
|
|
@ -9,7 +9,20 @@ use log::Record;
|
||||||
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
|
|
||||||
let log_level = msg_vec[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 strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
|
||||||
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
|
let 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) {
|
match core::str::from_utf8(&str) {
|
||||||
Ok(strr) => {
|
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(
|
log::logger().log(
|
||||||
&Record::builder()
|
&Record::builder()
|
||||||
.args(format_args!("{}", strr))
|
.args(format_args!("{}", strr))
|
||||||
|
|
|
@ -25,42 +25,16 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
unsafe fn memset(dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
||||||
const BLOCK_SIZE: usize = 64;
|
let total_size = count * size;
|
||||||
let mut remaining = count * size;
|
src.copy_to_nonoverlapping(dest, size);
|
||||||
|
|
||||||
if remaining < 16 {
|
let mut copied = size;
|
||||||
src.copy_to_nonoverlapping(dest, remaining);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buffer = [0u8; BLOCK_SIZE];
|
while copied < total_size {
|
||||||
let mut buffer_size = size;
|
let copy_size = copied.min(total_size - copied);
|
||||||
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
|
dest.add(copied).copy_from_nonoverlapping(dest, copy_size);
|
||||||
|
copied += copy_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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,18 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
|
||||||
let cmd = module.cmd.trim_matches('"');
|
let cmd = module.cmd.trim_matches('"');
|
||||||
let cmd_len = cmd.len() as u64;
|
let cmd_len = cmd.len() as u64;
|
||||||
|
|
||||||
log::info!("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
|
// decode AbleOS Executable format
|
||||||
let header = &module.bytes[0..46];
|
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 code_length = u64::from_le_bytes(header[7..15].try_into().unwrap());
|
||||||
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
|
let data_length = u64::from_le_bytes(header[15..23].try_into().unwrap());
|
||||||
let end = (code_length + data_length) as usize;
|
let end = (code_length + data_length) as usize;
|
||||||
log::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));
|
let mut thr = ExecThread::new(&module.bytes[offset..end], Address::new(0));
|
||||||
if cmd_len > 0 {
|
if cmd_len > 0 {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
fmt::format,
|
fmt::format,
|
||||||
fs::{read_to_string, File},
|
fs::{read_to_string, File},
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
|
@ -13,6 +14,7 @@ pub struct Package {
|
||||||
name: String,
|
name: String,
|
||||||
binaries: Vec<String>,
|
binaries: Vec<String>,
|
||||||
build_cmd: String,
|
build_cmd: String,
|
||||||
|
args: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
|
@ -46,26 +48,32 @@ impl Package {
|
||||||
let mut binaries = vec![];
|
let mut binaries = vec![];
|
||||||
|
|
||||||
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
||||||
// if count != 0 {
|
|
||||||
binaries.push(name.clone());
|
binaries.push(name.clone());
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
let build_table = data.get("build").unwrap();
|
let build_table = data.get("build").unwrap();
|
||||||
|
|
||||||
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
|
let mut build_cmd: String = build_table.get("command").unwrap().as_str().unwrap().into();
|
||||||
build_cmd.remove(0);
|
build_cmd.remove(0);
|
||||||
// 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 {
|
Self {
|
||||||
name,
|
name,
|
||||||
binaries,
|
binaries,
|
||||||
build_cmd,
|
build_cmd,
|
||||||
|
args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
|
pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
|
||||||
if self.binaries.contains(&"hblang".to_string()) {
|
if self.binaries.contains(&"hblang".to_string()) {
|
||||||
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
|
let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
|
||||||
|
|
||||||
let path = format!("sysdata/programs/{}/{}", self.name, file);
|
let path = format!("sysdata/programs/{}/{}", self.name, file);
|
||||||
// compile here
|
// compile here
|
||||||
|
|
||||||
|
@ -73,6 +81,7 @@ impl Package {
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
fmt: true,
|
fmt: true,
|
||||||
|
in_house_regalloc: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
out,
|
out,
|
||||||
|
@ -87,6 +96,7 @@ impl Package {
|
||||||
hblang::run_compiler(
|
hblang::run_compiler(
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
|
in_house_regalloc: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
out,
|
out,
|
||||||
|
@ -98,6 +108,7 @@ impl Package {
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
dump_asm: true,
|
dump_asm: true,
|
||||||
|
in_house_regalloc: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
out,
|
out,
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
keycodes := @use("keycodes.hb");
|
keycodes := @use("keycodes.hb");
|
||||||
.{KeyCode} := keycodes
|
.{KeyCode} := keycodes
|
||||||
|
|
||||||
KeyEvent := struct {
|
KeyEvent := packed struct {
|
||||||
// 0 if down
|
up: bool,
|
||||||
// 1 if up
|
just_triggered: bool,
|
||||||
up: u8,
|
|
||||||
// 0 if not just triggered
|
|
||||||
// 1 if just triggered
|
|
||||||
just_triggered: u8,
|
|
||||||
key: KeyCode,
|
key: KeyCode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,17 @@ events := @use("events.hb");
|
||||||
.{KeyEvent, MouseEvent} := events
|
.{KeyEvent, MouseEvent} := events
|
||||||
|
|
||||||
recieve_key_event := fn(): ?KeyEvent {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +26,7 @@ recieve_mouse_event := fn(): ?MouseEvent {
|
||||||
buf_id := buffer.search("PS/2 Mouse\0")
|
buf_id := buffer.search("PS/2 Mouse\0")
|
||||||
|
|
||||||
// Read out of the Mouse buffer here
|
// 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 {
|
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
|
||||||
return mevent
|
return mevent
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
# Images
|
# Images
|
||||||
- General over image format
|
|
||||||
- Support formats:
|
|
||||||
- PNG
|
|
||||||
- Animation
|
- Animation
|
||||||
|
|
||||||
# API
|
# API
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
|
.{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 {
|
BitmapFileHeader := packed struct {
|
||||||
magic: u16,
|
magic: u16,
|
||||||
|
@ -41,7 +41,7 @@ from := fn(bmp: ^u8): ?Surface {
|
||||||
return null
|
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)
|
rhs := new_surface(info_header.width, info_header.height)
|
||||||
put_surface(rhs, lhs, .(0, 0), true)
|
put_surface(rhs, lhs, .(0, 0), true)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
.{Color, Surface, new_surface} := @use("../lib.hb");
|
.{Color, Surface, new_surface} := @use("../lib.hb");
|
||||||
.{log, memory} := @use("../../../stn/src/lib.hb")
|
.{log} := @use("../../../stn/src/lib.hb")
|
||||||
|
|
||||||
/* source:
|
/* source:
|
||||||
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
||||||
|
@ -13,7 +13,7 @@ $QOI_OP_RUN := 0xC0
|
||||||
$QOI_OP_RGB := 0xFE
|
$QOI_OP_RGB := 0xFE
|
||||||
$QOI_OP_RGBA := 0xFF
|
$QOI_OP_RGBA := 0xFF
|
||||||
$QOI_MASK_2 := 0xC0
|
$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
|
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
|
||||||
}
|
}
|
||||||
$QOI_MAGIC := 0x716F6966
|
$QOI_MAGIC := 0x716F6966
|
||||||
|
@ -89,7 +89,7 @@ from := fn(qoi: ^u8): ?Surface {
|
||||||
run = b1 & 0x3F
|
run = b1 & 0x3F
|
||||||
}
|
}
|
||||||
|
|
||||||
index[@inline(QOI_COLOR_HASH, px)] = px
|
index[QOI_COLOR_HASH(px)] = px
|
||||||
};
|
};
|
||||||
|
|
||||||
*(surface.buf + px_pos) = px
|
*(surface.buf + px_pos) = px
|
||||||
|
|
|
@ -10,19 +10,21 @@ Surface := struct {
|
||||||
buf: ^Color,
|
buf: ^Color,
|
||||||
width: uint,
|
width: uint,
|
||||||
height: uint,
|
height: uint,
|
||||||
|
size: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_surface := fn(width: uint, height: uint): Surface {
|
new_surface := fn(width: uint, height: uint): Surface {
|
||||||
return .(
|
return .(
|
||||||
@inline(memory.alloc, Color, width * height),
|
memory.alloc(Color, width * height),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
width * height,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
clone_surface := fn(surface: ^Surface): Surface {
|
clone_surface := fn(surface: ^Surface): Surface {
|
||||||
new := new_surface(surface.width, surface.height)
|
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
|
return new
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,42 +35,38 @@ init := fn(doublebuffer: bool): Surface {
|
||||||
if doublebuffer {
|
if doublebuffer {
|
||||||
return new_surface(width, height)
|
return new_surface(width, height)
|
||||||
} else {
|
} else {
|
||||||
return .(framebuffer, width, height)
|
return .(framebuffer, width, height, width * height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear := fn(surface: Surface, color: Color): void {
|
$clear := fn(surface: Surface, color: Color): void {
|
||||||
return @inline(memory.set, Color, &color, surface.buf, surface.width * surface.height)
|
memory.set(Color, &color, surface.buf, surface.width * surface.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
sync := fn(surface: Surface): void {
|
$sync := fn(surface: Surface): void {
|
||||||
if surface.buf == framebuffer {
|
memory.copy(Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
|
||||||
return
|
|
||||||
}
|
|
||||||
return @inline(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
|
return x + surface.width * y
|
||||||
}
|
}
|
||||||
|
|
||||||
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
|
$indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
|
||||||
return surface.buf + @inline(index, surface, x, y)
|
return surface.buf + index(surface, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
|
$put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
|
||||||
*@inline(indexptr, surface, pos.x, pos.y) = color
|
return *indexptr(surface, pos.x, pos.y) = color
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
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)
|
top_start_idx := indexptr(surface, pos.x, pos.y)
|
||||||
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
|
bottom_start_idx := indexptr(surface, pos.x, pos.y + tr.y - 1)
|
||||||
rows_to_fill := tr.y
|
rows_to_fill := tr.y
|
||||||
|
|
||||||
loop if rows_to_fill <= 1 break else {
|
loop if rows_to_fill <= 1 break else {
|
||||||
@inline(memory.set, Color, &color, top_start_idx, tr.x)
|
memory.set(Color, &color, top_start_idx, tr.x)
|
||||||
@inline(memory.set, Color, &color, bottom_start_idx, tr.x)
|
memory.set(Color, &color, bottom_start_idx, tr.x)
|
||||||
|
|
||||||
top_start_idx += surface.width
|
top_start_idx += surface.width
|
||||||
bottom_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 {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
||||||
start_idx := @inline(indexptr, surface, pos.x, pos.y)
|
start_idx := indexptr(surface, pos.x, pos.y)
|
||||||
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
|
end_idx := indexptr(surface, pos.x, pos.y + tr.y)
|
||||||
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
|
right_start_idx := indexptr(surface, pos.x + tr.x, pos.y)
|
||||||
|
|
||||||
loop if start_idx > end_idx break else {
|
loop if start_idx > end_idx break else {
|
||||||
*start_idx = color;
|
*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
|
right_start_idx += surface.width
|
||||||
}
|
}
|
||||||
|
|
||||||
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
|
memory.set(Color, &color, 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 + tr.y), @bitcast(tr.x + 1))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -112,7 +110,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Colo
|
||||||
y := p0.y
|
y := p0.y
|
||||||
x := p0.x
|
x := p0.x
|
||||||
loop if x == p1.x break else {
|
loop if x == p1.x break else {
|
||||||
*@inline(indexptr, surface, x, y) = color
|
*indexptr(surface, x, y) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
y += yi
|
y += yi
|
||||||
D += 2 * (dy - dx)
|
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
|
x := p0.x
|
||||||
y := p0.y
|
y := p0.y
|
||||||
loop if y == p1.y break else {
|
loop if y == p1.y break else {
|
||||||
*@inline(indexptr, surface, x, y) = color
|
*indexptr(surface, x, y) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
x += xi
|
x += xi
|
||||||
D += 2 * (dx - dy)
|
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_top_cursor := top.buf
|
||||||
src_bottom_cursor := top.buf + top.width * (top.height - 1)
|
src_bottom_cursor := top.buf + top.width * (top.height - 1)
|
||||||
|
|
||||||
dst_top_idx := @inline(indexptr, surface, pos.x, pos.y)
|
dst_top_idx := indexptr(surface, pos.x, pos.y)
|
||||||
dst_bottom_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
|
dst_bottom_idx := indexptr(surface, pos.x, pos.y + top.height - 1)
|
||||||
|
|
||||||
dst_increment := surface.width
|
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
|
rows_to_copy := top.height
|
||||||
|
|
||||||
loop if rows_to_copy <= 1 break else {
|
loop if rows_to_copy <= 1 break else {
|
||||||
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
|
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_bottom_cursor, dst_bottom_idx, top.width)
|
||||||
|
|
||||||
dst_top_idx += dst_increment
|
dst_top_idx += dst_increment
|
||||||
dst_bottom_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 {
|
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
|
return
|
||||||
|
@ -233,7 +231,7 @@ put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): vo
|
||||||
y := y0
|
y := y0
|
||||||
|
|
||||||
loop if y == y1 break else {
|
loop if y == y1 break else {
|
||||||
*@inline(indexptr, surface, x, y) = color
|
*indexptr(surface, x, y) = color
|
||||||
y += 1
|
y += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +245,8 @@ put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): vo
|
||||||
x0 = x1
|
x0 = x1
|
||||||
x1 = tmp
|
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
|
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 {
|
put_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
||||||
x := 0
|
x := 0
|
||||||
y := radius
|
y := radius
|
||||||
error := @as(int, 3) - @as(int, @intcast(2 * radius));
|
error := @as(int, 3) - @intcast(2 * radius);
|
||||||
*@inline(indexptr, surface, pos.x + radius, pos.y) = color;
|
*indexptr(surface, pos.x + radius, pos.y) = color;
|
||||||
*@inline(indexptr, surface, pos.x - radius, pos.y) = color;
|
*indexptr(surface, pos.x - radius, pos.y) = color;
|
||||||
*@inline(indexptr, surface, pos.x, pos.y + radius) = color;
|
*indexptr(surface, pos.x, pos.y + radius) = color;
|
||||||
*@inline(indexptr, surface, pos.x, pos.y - radius) = color
|
*indexptr(surface, pos.x, pos.y - radius) = color
|
||||||
|
|
||||||
loop if y < x break else {
|
loop if y < x break else {
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
if error > 0 {
|
if error > 0 {
|
||||||
y -= 1
|
y -= 1
|
||||||
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
|
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||||
} else {
|
} else {
|
||||||
error += 4 * @intcast(x) + 6
|
error += 4 * @intcast(x) + 6
|
||||||
};
|
};
|
||||||
*@inline(indexptr, surface, pos.x + x, pos.y + y) = color;
|
*indexptr(surface, pos.x + x, pos.y + y) = color;
|
||||||
*@inline(indexptr, surface, pos.x + y, pos.y + x) = color;
|
*indexptr(surface, pos.x + y, pos.y + x) = color;
|
||||||
*@inline(indexptr, surface, pos.x - x, pos.y + y) = color;
|
*indexptr(surface, pos.x - x, pos.y + y) = color;
|
||||||
*@inline(indexptr, surface, pos.x - y, pos.y + x) = color;
|
*indexptr(surface, pos.x - y, pos.y + x) = color;
|
||||||
*@inline(indexptr, surface, pos.x + x, pos.y - y) = color;
|
*indexptr(surface, pos.x + x, pos.y - y) = color;
|
||||||
*@inline(indexptr, surface, pos.x + y, pos.y - x) = color;
|
*indexptr(surface, pos.x + y, pos.y - x) = color;
|
||||||
*@inline(indexptr, surface, pos.x - x, pos.y - y) = color;
|
*indexptr(surface, pos.x - x, pos.y - y) = color;
|
||||||
*@inline(indexptr, surface, pos.x - y, pos.y - x) = color
|
*indexptr(surface, pos.x - y, pos.y - x) = color
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
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 {
|
put_filled_circle := fn(surface: Surface, pos: Vec2(uint), radius: uint, color: Color): void {
|
||||||
x := 0
|
x := 0
|
||||||
y := radius
|
y := radius
|
||||||
error := @as(int, 3) - @as(int, @intcast(2 * radius))
|
error := @as(int, 3) - @intcast(2 * radius)
|
||||||
@inline(put_hline, surface, pos.y - x, pos.x - radius, pos.x + radius, color);
|
put_hline(surface, pos.y - x, pos.x - radius, pos.x + radius, color);
|
||||||
*@inline(indexptr, surface, pos.x, pos.y + radius) = color;
|
*indexptr(surface, pos.x, pos.y + radius) = color;
|
||||||
*@inline(indexptr, surface, pos.x, pos.y - radius) = color
|
*indexptr(surface, pos.x, pos.y - radius) = color
|
||||||
|
|
||||||
loop if y < x break else {
|
loop if y < x break else {
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
if error > 0 {
|
if error > 0 {
|
||||||
@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)
|
||||||
@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)
|
||||||
y -= 1
|
y -= 1
|
||||||
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
|
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||||
} else {
|
} else {
|
||||||
error += 4 * @intcast(x) + 6
|
error += 4 * @intcast(x) + 6
|
||||||
}
|
}
|
||||||
@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)
|
||||||
@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)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
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 {
|
put_textured_circle := fn(surface: Surface, source: Surface, source_pos: Vec2(uint), pos: Vec2(uint), radius: uint): void {
|
||||||
x := 0
|
x := 0
|
||||||
y := radius
|
y := radius
|
||||||
error := @as(int, 3) - @as(int, @intcast(2 * radius))
|
error := @as(int, 3) - @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);
|
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y), 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);
|
*indexptr(surface, pos.x, pos.y + y) = *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)
|
*indexptr(surface, pos.x, pos.y - y) = *indexptr(source, source_pos.x, source_pos.y - y)
|
||||||
|
|
||||||
loop if y < x break else {
|
loop if y < x break else {
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
if error > 0 {
|
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)
|
memory.copy(Color, indexptr(source, source_pos.x - x, source_pos.y + y), 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)
|
||||||
y -= 1
|
y -= 1
|
||||||
error += 4 * (@as(int, @intcast(x)) - @as(int, @intcast(y))) + 10
|
error += 4 * (@intcast(x) - @intcast(y)) + 10
|
||||||
} else {
|
} else {
|
||||||
error += 4 * @intcast(x) + 6
|
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)
|
memory.copy(Color, indexptr(source, source_pos.x - y, source_pos.y + x), 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -364,7 +363,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
|
||||||
str += 1
|
str += 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
glyph_data = @inline(get_glyph, font, *str)
|
glyph_data = get_glyph(font, *str)
|
||||||
} else {
|
} else {
|
||||||
if *str < UNC_TABLE_SIZE {
|
if *str < UNC_TABLE_SIZE {
|
||||||
glyph_index := *(font.unicode + *str)
|
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
|
cursor.y += next_line_y
|
||||||
}
|
}
|
||||||
|
|
||||||
dest := @inline(indexptr, surface, cursor.x, cursor.y)
|
dest := indexptr(surface, cursor.x, cursor.y)
|
||||||
rows := font.height
|
rows := font.height
|
||||||
|
|
||||||
loop if rows == 0 break else {
|
loop if rows == 0 break else {
|
||||||
|
|
|
@ -74,16 +74,16 @@ font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
|
||||||
return 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
|
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 {
|
init_unicode := fn(font: ^Font): void {
|
||||||
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
|
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
|
table := font.data + font.num_glyphs * font.bytes_per_glyph
|
||||||
curr_glyph := @as(u16, 0)
|
curr_glyph := @as(u16, 0)
|
||||||
|
@ -121,8 +121,6 @@ init_unicode := fn(font: ^Font): void {
|
||||||
next_byte := *table
|
next_byte := *table
|
||||||
if (next_byte & 0xC0) != 0x80 {
|
if (next_byte & 0xC0) != 0x80 {
|
||||||
valid = false
|
valid = false
|
||||||
}
|
|
||||||
if valid == false {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
unicode = unicode << 6 | next_byte & 0x3F
|
unicode = unicode << 6 | next_byte & 0x3F
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
string := @use("string.hb")
|
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))
|
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))
|
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)
|
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)
|
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))
|
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 {
|
search := fn(msg: ^u8): uint {
|
||||||
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
||||||
}
|
}
|
|
@ -1,29 +1,14 @@
|
||||||
abs := fn($Expr: type, x: Expr): Expr {
|
$abs := fn($Expr: type, x: Expr): Expr {
|
||||||
mask := x >> @bitcast(@sizeof(Expr) - 1)
|
return (x ^ x >> @sizeof(Expr) - 1) - (x >> @sizeof(Expr) - 1)
|
||||||
return (x ^ mask) - mask
|
|
||||||
}
|
}
|
||||||
min := fn($Expr: type, a: Expr, b: Expr): Expr {
|
$min := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||||
c := a - b
|
return b + (a - b & a - b >> @sizeof(Expr) - 1)
|
||||||
return b + (c & c >> @bitcast(@sizeof(Expr) - 1))
|
|
||||||
}
|
}
|
||||||
max := fn($Expr: type, a: Expr, b: Expr): Expr {
|
$max := fn($Expr: type, a: Expr, b: Expr): Expr {
|
||||||
c := a - b
|
return a - (a - b & a - b >> @sizeof(Expr) - 1)
|
||||||
return a - (c & c >> @bitcast(@sizeof(Expr) - 1))
|
|
||||||
}
|
}
|
||||||
signum := fn($Expr: type, x: Expr): int {
|
$sign := fn($Expr: type, x: Expr): i8 {
|
||||||
if x > @as(Expr, @intcast(0)) {
|
return @bitcast(x > 0) - @bitcast(x < 0)
|
||||||
return 1
|
|
||||||
} else if x < @as(Expr, @intcast(0)) {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
signincl := fn($Expr: type, x: Expr): int {
|
|
||||||
if x > @as(Expr, @intcast(0)) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2 := fn($Expr: type): type {
|
Vec2 := fn($Expr: type): type {
|
||||||
|
|
|
@ -1,32 +1,26 @@
|
||||||
PAGE_SIZE := 4096
|
$PAGE_SIZE := 4096
|
||||||
MAX_ALLOC := 0xFF
|
$MAX_ALLOC := 0xFF
|
||||||
MAX_FREE := 0xFF
|
$MAX_FREE := 0xFF
|
||||||
|
|
||||||
is_uninit := fn($Expr: type, ptr: ^Expr): bool {
|
$uninit := fn($Expr: type): ?Expr {
|
||||||
i := 0
|
return null
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dangling := fn($Expr: type): ^Expr {
|
dangling := fn($Expr: type): ^Expr {
|
||||||
return @bitcast(@alignof(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
|
return 1 + @sizeof(Expr) * num / PAGE_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ! will be replaced, don't get attached
|
||||||
alloc := fn($Expr: type, num: uint): ^Expr {
|
alloc := fn($Expr: type, num: uint): ^Expr {
|
||||||
pages := @inline(calc_pages, Expr, num)
|
pages := calc_pages(Expr, num)
|
||||||
if pages <= MAX_ALLOC {
|
if pages <= MAX_ALLOC {
|
||||||
return @bitcast(request_page(@intcast(pages)))
|
return @bitcast(request_page(@intcast(pages)))
|
||||||
}
|
}
|
||||||
ptr := request_page(0xFF)
|
ptr := request_page(MAX_ALLOC)
|
||||||
remaining := pages - MAX_ALLOC
|
remaining := pages - MAX_ALLOC
|
||||||
loop if remaining < MAX_ALLOC break else {
|
loop if remaining < MAX_ALLOC break else {
|
||||||
_ = request_page(@intcast(MAX_ALLOC))
|
_ = request_page(@intcast(MAX_ALLOC))
|
||||||
|
@ -37,46 +31,46 @@ alloc := fn($Expr: type, num: uint): ^Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! stub
|
// ! stub
|
||||||
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
$free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
RqPageMsg := packed struct {a: u8, count: u8}
|
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))
|
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
|
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))
|
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
|
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))
|
return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
InbMsg := packed struct {a: u8, b: u8, addr: u16}
|
InbMsg := packed struct {a: u8, b: u8, addr: u16}
|
||||||
inb := fn(addr: u16): u8 {
|
$inb := fn(addr: u16): u8 {
|
||||||
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
|
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
|
||||||
outl := fn(addr: u16, value: u32): void {
|
$outl := fn(addr: u16, value: u32): void {
|
||||||
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
InlMsg := packed struct {a: u8, b: u8, addr: u16}
|
InlMsg := packed struct {a: u8, b: u8, addr: u16}
|
||||||
inl := fn(addr: u16): u32 {
|
$inl := fn(addr: u16): u32 {
|
||||||
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
|
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))
|
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}
|
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))
|
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
|
||||||
}
|
}
|
|
@ -3,5 +3,5 @@ any := fn($Expr: type): Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
range := fn($Expr: type, min: Expr, max: Expr): 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
|
||||||
}
|
}
|
6
sysdata/libraries/stn/src/sleep.hb
Normal file
6
sysdata/libraries/stn/src/sleep.hb
Normal 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 {
|
||||||
|
}
|
|
@ -4,118 +4,60 @@ length := fn(ptr: ^u8): uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
|
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
|
||||||
|
is_negative := num < 0
|
||||||
|
if is_negative num = -num
|
||||||
|
|
||||||
ptr := p
|
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 {
|
if num == 0 {
|
||||||
*ptr = 48
|
*ptr = 0x30;
|
||||||
ptr += 1
|
*(ptr + 1) = 0
|
||||||
} else {
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
loop if num == 0 break else {
|
loop if num == 0 break else {
|
||||||
digit := num % @bitcast(radix)
|
remainder := num % @bitcast(radix)
|
||||||
if digit < 10 {
|
num /= @bitcast(radix);
|
||||||
*ptr = @intcast(digit) + 48
|
*ptr = @intcast(remainder + 0x30)
|
||||||
} else {
|
if remainder > 9 {
|
||||||
*ptr = @intcast(digit) + 55
|
*ptr = @intcast(remainder - 10 + 0x41)
|
||||||
}
|
}
|
||||||
ptr += 1
|
ptr += 1
|
||||||
num /= @bitcast(radix)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if negative {
|
if is_negative {
|
||||||
*ptr = 45
|
*ptr = 0x2D
|
||||||
ptr += 1
|
ptr += 1
|
||||||
};
|
}
|
||||||
|
// ! it gets broked when you do this ??
|
||||||
*ptr = 0
|
// *ptr = 0
|
||||||
|
|
||||||
@inline(reverse, digits_start)
|
|
||||||
|
|
||||||
|
@inline(reverse, p)
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse := fn(s: ^u8): void {
|
reverse := fn(s: ^u8): void {
|
||||||
i := 0
|
j := s + @inline(length, s) - 1
|
||||||
j := @inline(length, s) - 1
|
|
||||||
temp := @as(u8, 0)
|
temp := @as(u8, 0)
|
||||||
loop if i >= j break else {
|
loop if s < j {
|
||||||
temp = *(s + i);
|
temp = *s;
|
||||||
*(s + i) = *(s + j);
|
*s = *j;
|
||||||
*(s + j) = temp
|
*j = temp
|
||||||
i += 1
|
s += 1
|
||||||
j -= 1
|
j -= 1
|
||||||
}
|
} else return
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
equals := fn(lhs: ^u8, rhs: ^u8): bool {
|
equals := fn(lhs: ^u8, rhs: ^u8): bool {
|
||||||
if lhs == rhs {
|
if lhs == rhs {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
i := 0
|
loop if *lhs != *rhs {
|
||||||
loop if *(lhs + i) != *(rhs + i) {
|
|
||||||
return false
|
return false
|
||||||
} else if *lhs == 0 {
|
} else if *lhs == 0 {
|
||||||
return true
|
return true
|
||||||
} else {
|
} 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
|
|
||||||
}
|
|
|
@ -1,62 +1,63 @@
|
||||||
.{math: .{Vec2}, buffer, log, memory} := @use("../../stn/src/lib.hb");
|
.{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
|
||||||
.{Surface, new_surface} := @use("../../render/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");
|
||||||
.{WindowWrapper, WindowID, WindowProps, WindowMessage, message, BUFFER} := @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 {
|
find_server := fn(): void {
|
||||||
if buffer_id == null {
|
log.info("client: locating server\0")
|
||||||
log.error("client: (request_new) buffer id is null. did you init the client?\0")
|
channel2 := await_channel()
|
||||||
return null
|
channel.server = channel2.server
|
||||||
}
|
channel.client = channel2.client
|
||||||
buf := memory.uninit(?WindowWrapper)
|
log.info("client: server located\0")
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_window_props := fn(wrapper: WindowWrapper): ?WindowProps {
|
new := fn(props: WindowProps): ?Window {
|
||||||
log.error("todo: sunset_proto/src/client/update_window_props.hb\0")
|
send_header(message.syn, channel.server)
|
||||||
if buffer_id == null {
|
response := await_message(Channel, channel.client)
|
||||||
log.error("client: (request_update_properties) buffer id is null. did you init the client?\0")
|
if response.header.kind != message.ack {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// TODO: buffer.write(WINDOWING_BUFFER, update properties) request
|
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
|
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 {
|
quit := fn(client: Window): void {
|
||||||
if buffer_id == null {
|
send_header(message.quit, client.data.channel.server)
|
||||||
log.error("client: (request_shutdown) buffer id is null. did you init the client?\0")
|
}
|
||||||
return null
|
|
||||||
}
|
connected := fn(client: Window): bool {
|
||||||
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 {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init := fn(): void {
|
shutdown_server := fn(client: Window): bool {
|
||||||
log.info("client: waiting for server\0")
|
return false
|
||||||
id := 0
|
}
|
||||||
loop if id != 0 {
|
|
||||||
buffer_id = id
|
update_props := fn(client: Window): bool {
|
||||||
log.info("client: done waiting\0")
|
return false
|
||||||
return
|
}
|
||||||
} else {
|
|
||||||
id = buffer.search(BUFFER)
|
update_permissions := fn(client: Window): bool {
|
||||||
}
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
send_frame := fn(client: Window): bool {
|
||||||
|
send_header(message.frame_ready, client.data.channel.server)
|
||||||
|
response := await_message(uint, client.data.channel.client)
|
||||||
|
if response.header.kind != message.ack {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// ! FOR NOW, server will ALWAYS be local,
|
||||||
|
// ! so we can send pointer to surface.
|
||||||
|
send_message(^Color, message.ack, client.surface.buf, client.data.channel.server)
|
||||||
|
return true
|
||||||
}
|
}
|
|
@ -1,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")
|
.{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")
|
client := @use("./client.hb")
|
||||||
server := @use("./server.hb")
|
server := @use("./server.hb")
|
||||||
message := @use("./message.hb")
|
message := @use("./message.hb")
|
||||||
|
permissions := @use("./permissions.hb")
|
||||||
|
|
||||||
WindowID := uint
|
$send_message := fn($Expr: type, kind: MessageKind, msg: Expr, buffer_id: uint): void {
|
||||||
MessageKind := uint
|
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,
|
kind: MessageKind,
|
||||||
id: WindowID,
|
}
|
||||||
length: uint,
|
|
||||||
data_ptr: ^u8,
|
Message := fn($Expr: type): type {
|
||||||
// need to replace this with a buffer id
|
return packed struct {
|
||||||
callback: ^u8,
|
header: MessageHeader,
|
||||||
|
body: Expr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowProps := struct {
|
WindowProps := struct {
|
||||||
position: Vec2(uint),
|
position: Vec2(uint),
|
||||||
dimensions: Vec2(uint),
|
dimensions: Vec2(uint),
|
||||||
|
// ! replace with owned string type later
|
||||||
title: ^u8,
|
title: ^u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowWrapper := struct {
|
WindowData := struct {
|
||||||
id: WindowID,
|
|
||||||
props: WindowProps,
|
props: WindowProps,
|
||||||
|
channel: Channel,
|
||||||
|
permissions: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
Window := struct {
|
Window := struct {
|
||||||
|
data: WindowData,
|
||||||
surface: Surface,
|
surface: Surface,
|
||||||
props: WindowProps,
|
|
||||||
}
|
}
|
|
@ -1,4 +1,8 @@
|
||||||
$new := 0
|
// ! all values in this file are subject to change.
|
||||||
$destroy := 1
|
$syn := 1
|
||||||
$update_props := 2
|
$ack := 2
|
||||||
$shutdown := 3
|
$refused := 3
|
||||||
|
$quit := 4
|
||||||
|
$props := 5
|
||||||
|
$shutdown := 6
|
||||||
|
$frame_ready := 7
|
5
sysdata/libraries/sunset_proto/src/permissions.hb
Normal file
5
sysdata/libraries/sunset_proto/src/permissions.hb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
$none := 0b0
|
||||||
|
$exclusive_framebuffer := 0b1
|
||||||
|
$shutdown := 0b100
|
||||||
|
|
||||||
|
$default := none
|
|
@ -1,34 +1,135 @@
|
||||||
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
|
.{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
|
||||||
.{Surface, new_surface} := @use("../../render/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");
|
||||||
.{WindowWrapper, WindowID, WindowProps, WindowMessage, BUFFER} := @use("./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}
|
WindowServer := struct {
|
||||||
|
window_count: uint,
|
||||||
server := @as(?WindowServer, null)
|
channel: Channel,
|
||||||
|
// ! replace this with a collection when we get an allocator
|
||||||
new_window_id := fn(): WindowID {
|
windows: [?Window; 10],
|
||||||
return random.any(uint)
|
font: text.Font,
|
||||||
}
|
}
|
||||||
|
|
||||||
init := fn(): bool {
|
// ! in the future this should be safely handled
|
||||||
log.info("server: starting server\0")
|
server := @as(WindowServer, idk)
|
||||||
server = .(0, buffer.create(BUFFER))
|
|
||||||
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
recieve := fn(): ?WindowMessage {
|
$DECO_WIDTH := 2
|
||||||
if server == null {
|
$DECO_HEIGHT_TOP := 20
|
||||||
log.error("server: (request_new) server is null. did you init the client?\0")
|
$DECO_HEIGHT_BOTTOM := 1
|
||||||
return null
|
$DECO_COLOUR := Color.(100, 200, 255, 255)
|
||||||
}
|
$DECO_COLOUR_DARKER := Color.(89, 57, 89, 255)
|
||||||
buf := memory.uninit(WindowMessage)
|
|
||||||
buffer.recv(WindowMessage, @unwrap(server).buffer_id, @bitcast(&buf))
|
new_window_decorations := fn(dimensions: math.Vec2(uint)): Surface {
|
||||||
if memory.is_uninit(WindowMessage, &buf) {
|
return new_surface(
|
||||||
return null
|
dimensions.x + DECO_WIDTH,
|
||||||
}
|
dimensions.y + DECO_HEIGHT_TOP + DECO_HEIGHT_BOTTOM,
|
||||||
return buf
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
should_shutdown := fn(): bool {
|
// ! compositor code. this currently disallows tearing.
|
||||||
return false
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -56,23 +56,13 @@ main := fn(): int {
|
||||||
loop {
|
loop {
|
||||||
// Clear the screen
|
// Clear the screen
|
||||||
render.clear(screen, render.black)
|
render.clear(screen, render.black)
|
||||||
|
|
||||||
render.put_surface(screen, wallpaper, .(0, 0), false)
|
render.put_surface(screen, wallpaper, .(0, 0), false)
|
||||||
|
|
||||||
// TODO: Read the window buffer here
|
// 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 {
|
if false {
|
||||||
// Scroll bar :ThumbsUp:
|
// Scroll bar :ThumbsUp:
|
||||||
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
|
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)
|
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)
|
pos := Vec2(uint).(1, screen.height - 21)
|
||||||
render_label_to_surface(screen, text_label, font, pos)
|
render_label_to_surface(screen, text_label, font, pos)
|
||||||
|
@ -91,12 +87,20 @@ main := fn(): int {
|
||||||
// Screen border
|
// Screen border
|
||||||
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
|
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
|
||||||
|
|
||||||
|
// get input events from drivers via intouch
|
||||||
|
if false {
|
||||||
|
key_event := intouch.recieve_key_event()
|
||||||
|
if key_event != null {
|
||||||
|
log.info("Key event \0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
mouse_event := intouch.recieve_mouse_event()
|
mouse_event := intouch.recieve_mouse_event()
|
||||||
//
|
//
|
||||||
|
|
||||||
if mouse_event != null {
|
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 := @as(i16, mouse_event.x_change)
|
||||||
change_x = change_x << 8
|
change_x = change_x << 8
|
||||||
|
@ -133,13 +137,9 @@ main := fn(): int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// render mouse
|
render.put_filled_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.black)
|
||||||
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)
|
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)
|
|
||||||
}
|
|
||||||
// Send events to focused window
|
// Send events to focused window
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
send_byte := fn(byte: u8): u8 {
|
||||||
memory.outb(96, byte)
|
memory.outb(96, byte)
|
||||||
|
@ -6,23 +10,31 @@ send_byte := fn(byte: u8): u8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
buf := buffer.create("XKeyboard\0")
|
buf := buffer.create("PS/2 Keyboard\0")
|
||||||
_ = send_byte(238)
|
_ = send_byte(238)
|
||||||
log.info("PS/2 Driver Loaded\0")
|
log.info("PS/2 Driver Loaded\0")
|
||||||
|
|
||||||
if send_byte(238) == 238 {
|
if send_byte(238) == 238 {
|
||||||
log.info("PS/2 Keyboard Echoed\0")
|
log.info("PS/2 Keyboard Echoed\0")
|
||||||
}
|
}
|
||||||
|
|
||||||
if send_byte(244) == 250 {
|
if send_byte(244) == 250 {
|
||||||
log.info("Enabled scanning\0")
|
log.info("Enabled scanning\0")
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_input := 250
|
prev_input := 250
|
||||||
loop {
|
loop {
|
||||||
|
loop if (memory.inb(0x64) & 0x20) == 0x20 break
|
||||||
|
|
||||||
input := memory.inb(96)
|
input := memory.inb(96)
|
||||||
|
|
||||||
if input == prev_input {
|
if input == prev_input {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
prev_input = input
|
prev_input = input
|
||||||
buffer.write(u8, &input, buf)
|
kevent := KeyEvent.(false, true, input)
|
||||||
|
|
||||||
|
buffer.write(KeyEvent, buf, &kevent)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
|
@ -145,7 +145,7 @@ main := fn(): int {
|
||||||
event.x_change = x_change
|
event.x_change = x_change
|
||||||
event.y_change = y_change
|
event.y_change = y_change
|
||||||
|
|
||||||
buffer.write(MouseEvent, &event, mouse_buffer)
|
buffer.write(MouseEvent, mouse_buffer, &event)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -10,12 +10,12 @@ example := fn(): void {
|
||||||
color := render.light_cyan
|
color := render.light_cyan
|
||||||
n := @as(u8, 1)
|
n := @as(u8, 1)
|
||||||
loop {
|
loop {
|
||||||
|
// ! dead code elimination bug
|
||||||
render.clear(screen, color)
|
render.clear(screen, color)
|
||||||
render.sync(screen)
|
render.sync(screen)
|
||||||
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
if color.b == 255 | color.b == 0 {
|
||||||
n = -n
|
n = -n
|
||||||
}
|
}
|
||||||
color.b += n
|
color.b += n
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
|
@ -46,7 +46,7 @@ example := fn(): void {
|
||||||
|
|
||||||
bottom := buf + msg_len
|
bottom := buf + msg_len
|
||||||
|
|
||||||
@inline(memory.copy, u8, msg, buf, msg_len)
|
memory.copy(u8, msg, buf, msg_len)
|
||||||
cursor := bottom
|
cursor := bottom
|
||||||
|
|
||||||
draw_window(window, font, buf, cursor)
|
draw_window(window, font, buf, cursor)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
.{example: main} := @use("./examples/orbit.hb")
|
.{example: main} := @use("./examples/text.hb")
|
|
@ -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")
|
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
|
||||||
|
render := @use("../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
|
bmp := @embed("../../../assets/mini.bmp")
|
||||||
|
|
||||||
main := fn(): void {
|
main := fn(): void {
|
||||||
sunset.client.init()
|
sunset.client.find_server()
|
||||||
log.info("client: request new window\0")
|
|
||||||
window := sunset.client.new_window(.(.(100, 100), .(150, 150), "Hello, World!\0"))
|
image := render.image.bmp.from(@bitcast(&bmp))
|
||||||
if window == null {
|
if image == null {
|
||||||
log.error("Could not create window\0")
|
log.error("got no image\0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.info("client: window created. title:\0")
|
|
||||||
log.info(window.props.title)
|
window := sunset.client.new(.(.(100, 100), .(200, 200), "Hello,\0"))
|
||||||
window.props.position = .(500, 500)
|
|
||||||
props := @unwrap(sunset.client.update_window_props(window))
|
if window == null {
|
||||||
if props.position.x != window.props.position.x {
|
log.error("got no window\0")
|
||||||
log.error("client: we did not update props\0")
|
return
|
||||||
}
|
}
|
||||||
log.info("client: sending shutdown request\0")
|
x := 0
|
||||||
shutdown := sunset.client.request_shutdown()
|
loop {
|
||||||
if shutdown == null {
|
render.clear(window.surface, render.black)
|
||||||
log.error("client: didnt shutdown the server\0")
|
render.put_surface(window.surface, image, .(image.width + x % window.data.props.dimensions.x, 20), false)
|
||||||
|
_ = sunset.client.send_frame(window)
|
||||||
|
x += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
11
sysdata/programs/sunset_client_2/meta.toml
Normal file
11
sysdata/programs/sunset_client_2/meta.toml
Normal 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"
|
29
sysdata/programs/sunset_client_2/src/main.hb
Normal file
29
sysdata/programs/sunset_client_2/src/main.hb
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,36 +1,98 @@
|
||||||
.{log} := @use("../../../libraries/stn/src/lib.hb")
|
sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
|
||||||
render := @use("../../../libraries/render/src/lib.hb");
|
render := @use("../../../libraries/render/src/lib.hb")
|
||||||
.{server, message, WindowWrapper, WindowProps} := @use("../../../libraries/sunset_proto/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")
|
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
|
||||||
|
img := @embed("../../../assets/wallpaper.qoi")
|
||||||
|
|
||||||
main := fn(): void {
|
main := fn(): int {
|
||||||
screen := render.init(false)
|
sunset.server.start()
|
||||||
font := render.text.font_from_psf2(@bitcast(&psf), false)
|
|
||||||
if font == null {
|
screen := render.init(true)
|
||||||
return
|
render.clear(screen, render.black)
|
||||||
}
|
|
||||||
if server.init() == false {
|
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
|
||||||
log.error("Failed to create server\0")
|
|
||||||
return
|
wallpaper := render.image.from(@bitcast(&img))
|
||||||
}
|
if wallpaper == null {
|
||||||
loop if server.should_shutdown() break else {
|
// stn.panic("Wallpaper not loaded\0")
|
||||||
recv := server.recieve()
|
return 1
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render.put_text(screen, font, .(0, 0), render.white, "Shutdown triggered\0")
|
mouse_x := 100
|
||||||
log.info("Server shutdown\0")
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
|
@ -28,8 +28,8 @@ resolution = "1024x768x24"
|
||||||
# [boot.limine.ableos.modules.horizon]
|
# [boot.limine.ableos.modules.horizon]
|
||||||
# path = "boot:///horizon.hbf"
|
# path = "boot:///horizon.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.ps2_mouse_driver]
|
[boot.limine.ableos.modules.ps2_mouse_driver]
|
||||||
# path = "boot:///ps2_mouse_driver.hbf"
|
path = "boot:///ps2_mouse_driver.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
||||||
# path = "boot:///ps2_keyboard_driver.hbf"
|
# path = "boot:///ps2_keyboard_driver.hbf"
|
||||||
|
|
4
todo.md
4
todo.md
|
@ -19,12 +19,14 @@
|
||||||
@morshy
|
@morshy
|
||||||
Simple Userland Allocator
|
Simple Userland Allocator
|
||||||
|
|
||||||
|
@funky
|
||||||
|
Kernel Testing Framework (A rust framework for testing the kernel)
|
||||||
|
|
||||||
@unassigned
|
@unassigned
|
||||||
FileIO (Fat32)
|
FileIO (Fat32)
|
||||||
DiskIO (Undecided Disk type)
|
DiskIO (Undecided Disk type)
|
||||||
Proper Memory Protection
|
Proper Memory Protection
|
||||||
Channels (Two buffers bundled together to form two way communication)
|
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)
|
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)
|
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)
|
Kernel Reimpl (Do not you dare think about this yet its only here as an option to show goals)
|
||||||
|
|
Loading…
Reference in a new issue