Complete revert to mainline, I think?
This commit is contained in:
commit
b5b122f451
|
@ -1,3 +1,3 @@
|
||||||
[alias]
|
[alias]
|
||||||
repbuild = "run --manifest-path ./repbuild/Cargo.toml -r --"
|
repbuild = "run --manifest-path ./repbuild/Cargo.toml -- "
|
||||||
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
dev = "run --manifest-path ./dev/Cargo.toml -r --"
|
||||||
|
|
1040
Cargo.lock
generated
1040
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -138,8 +138,8 @@ fn build(name: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_program(name: String) {}
|
pub fn build_program(_name: String) {}
|
||||||
pub fn build_library(name: String) {}
|
pub fn build_library(_name: String) {}
|
||||||
|
|
||||||
fn help() {
|
fn help() {
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -4,9 +4,3 @@ build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
target = "./targets/x86_64-ableos.json"
|
target = "./targets/x86_64-ableos.json"
|
||||||
|
|
||||||
# [target.'cfg(target_arch = "x86_64")']
|
|
||||||
# rustflags = [
|
|
||||||
# "-C",
|
|
||||||
#"target-feature=+sse4.1,+avx,+aes,+fma,+popcnt,+bmi2,+avx2,+lzcnt,+xsave",
|
|
||||||
# ]
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ uart_16550 = { version = "0.3", features = ["nightly"] }
|
||||||
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
xml.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
versioning.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
# able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland"
|
||||||
hashbrown = { version = "0.14", features = ["nightly"] }
|
hashbrown = { version = "0.15", features = ["nightly"] }
|
||||||
limine = "0.1"
|
limine = "0.1"
|
||||||
|
|
||||||
[dependencies.crossbeam-queue]
|
[dependencies.crossbeam-queue]
|
||||||
|
@ -24,10 +24,6 @@ version = "0.3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["alloc", "nightly"]
|
features = ["alloc", "nightly"]
|
||||||
|
|
||||||
# [dependencies.clparse]
|
|
||||||
# git = "https://git.ablecorp.us/ableos/ableos_userland"
|
|
||||||
# default-features = false
|
|
||||||
|
|
||||||
[dependencies.derive_more]
|
[dependencies.derive_more]
|
||||||
version = "1"
|
version = "1"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -3,7 +3,7 @@ pub static SERIAL_CONSOLE: Mutex<SerialConsole> = Mutex::new(SerialConsole {
|
||||||
uart: 0x09000000 as *mut u8,
|
uart: 0x09000000 as *mut u8,
|
||||||
});
|
});
|
||||||
|
|
||||||
struct SerialConsole {
|
pub struct SerialConsole {
|
||||||
uart: *mut u8,
|
uart: *mut u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ const INITIAL_KERNEL_HEAP_SIZE: *const () = _initial_kernel_heap_size as _;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[naked]
|
#[naked]
|
||||||
|
#[cfg(not(target_feature = "avx2"))]
|
||||||
unsafe extern "C" fn _kernel_start() -> ! {
|
unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
// Initialise SSE, then jump to kernel entrypoint
|
// Initialise SSE, then jump to kernel entrypoint
|
||||||
core::arch::asm!(
|
core::arch::asm!(
|
||||||
|
@ -49,58 +50,59 @@ unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[no_mangle]
|
#[no_mangle]
|
||||||
// #[naked]
|
#[naked]
|
||||||
// unsafe extern "C" fn _kernel_start() -> ! {
|
#[cfg(target_feature = "avx2")]
|
||||||
// core::arch::asm!(
|
unsafe extern "C" fn _kernel_start() -> ! {
|
||||||
// // Enable protected mode and configure control registers
|
core::arch::asm!(
|
||||||
// "mov rax, cr0",
|
// Enable protected mode and configure control registers
|
||||||
// "and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
|
"mov rax, cr0",
|
||||||
// "or ax, 0x2", // Set CR0.MP (bit 1) for coprocessor monitoring
|
"and ax, 0xFFFB", // Clear CR0.EM (bit 2) for coprocessor emulation
|
||||||
// "mov cr0, rax",
|
"or ax, 0x2", // Set CR0.MP (bit 1) for coprocessor monitoring
|
||||||
|
"mov cr0, rax",
|
||||||
|
|
||||||
// "mov rax, cr4",
|
"mov rax, cr4",
|
||||||
// "or ax, (1 << 9) | (1 << 10)", // Set CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10)
|
"or ax, (1 << 9) | (1 << 10)", // Set CR4.OSFXSR (bit 9) and CR4.OSXMMEXCPT (bit 10)
|
||||||
// "mov cr4, rax",
|
"mov cr4, rax",
|
||||||
|
|
||||||
// // Enable OSXSAVE (required for AVX, AVX2, and XSAVE)
|
// Enable OSXSAVE (required for AVX, AVX2, and XSAVE)
|
||||||
// "mov rax, cr4",
|
"mov rax, cr4",
|
||||||
// "or eax, 1 << 18", // Set CR4.OSXSAVE (bit 18)
|
"or eax, 1 << 18", // Set CR4.OSXSAVE (bit 18)
|
||||||
// "mov cr4, rax",
|
"mov cr4, rax",
|
||||||
|
|
||||||
// // Enable AVX and AVX2 state saving
|
// Enable AVX and AVX2 state saving
|
||||||
// "xor rcx, rcx",
|
"xor rcx, rcx",
|
||||||
// "xgetbv",
|
"xgetbv",
|
||||||
// "or eax, 7", // Enable SSE, AVX, and AVX2 state saving
|
"or eax, 7", // Enable SSE, AVX, and AVX2 state saving
|
||||||
// "xsetbv",
|
"xsetbv",
|
||||||
|
|
||||||
// // Check for AVX and XSAVE support
|
// Check for AVX and XSAVE support
|
||||||
// "mov eax, 1",
|
"mov eax, 1",
|
||||||
// "cpuid",
|
"cpuid",
|
||||||
// "and ecx, 0x18000000",
|
"and ecx, 0x18000000",
|
||||||
// "cmp ecx, 0x18000000",
|
"cmp ecx, 0x18000000",
|
||||||
// "jne {1}", // Jump if AVX/OSXSAVE is not supported
|
"jne {1}", // Jump if AVX/OSXSAVE is not supported
|
||||||
|
|
||||||
// // Check for BMI2 and AVX2 support
|
// Check for BMI2 and AVX2 support
|
||||||
// "mov eax, 7",
|
"mov eax, 7",
|
||||||
// "xor ecx, ecx",
|
"xor ecx, ecx",
|
||||||
// "cpuid",
|
"cpuid",
|
||||||
// "and ebx, (1 << 8) | (1 << 5)", // Check BMI2 (bit 8) and AVX2 (bit 5)
|
"and ebx, (1 << 8) | (1 << 5)", // Check BMI2 (bit 8) and AVX2 (bit 5)
|
||||||
// "cmp ebx, (1 << 8) | (1 << 5)", // Compare to ensure both are supported
|
"cmp ebx, (1 << 8) | (1 << 5)", // Compare to ensure both are supported
|
||||||
|
|
||||||
// // Check for LZCNT and POPCNT support
|
// Check for LZCNT and POPCNT support
|
||||||
// "mov eax, 1",
|
"mov eax, 1",
|
||||||
// "cpuid",
|
"cpuid",
|
||||||
// "and ecx, (1 << 5) | (1 << 23)", // Check LZCNT (bit 5) and POPCNT (bit 23)
|
"and ecx, (1 << 5) | (1 << 23)", // Check LZCNT (bit 5) and POPCNT (bit 23)
|
||||||
// "cmp ecx, (1 << 5) | (1 << 23)", // Compare to ensure both are supported
|
"cmp ecx, (1 << 5) | (1 << 23)", // Compare to ensure both are supported
|
||||||
|
|
||||||
// // Jump to the kernel entry point
|
// Jump to the kernel entry point
|
||||||
// "jmp {0}",
|
"jmp {0}",
|
||||||
// sym start,
|
sym start,
|
||||||
// sym oops,
|
sym oops,
|
||||||
// options(noreturn),
|
options(noreturn),
|
||||||
// )
|
)
|
||||||
// }
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn oops() -> ! {
|
unsafe extern "C" fn oops() -> ! {
|
||||||
panic!("your cpu is ancient >:(")
|
panic!("your cpu is ancient >:(")
|
||||||
|
@ -249,6 +251,7 @@ unsafe extern "C" fn start() -> ! {
|
||||||
/// Spin loop
|
/// Spin loop
|
||||||
pub fn spin_loop() -> ! {
|
pub fn spin_loop() -> ! {
|
||||||
loop {
|
loop {
|
||||||
|
core::hint::spin_loop();
|
||||||
x86_64::instructions::hlt()
|
x86_64::instructions::hlt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,6 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn handler(vm: &mut Vm) {
|
pub fn handler(vm: &mut Vm) {
|
||||||
let ecall_number = vm.registers[2].cast::<u64>();
|
let ecall_number = vm.registers[2].cast::<u64>();
|
||||||
// log::info!("eca called :pensive:");
|
|
||||||
// debug!("Ecall number {:?}", ecall_number);
|
|
||||||
//info!("Register dump: {:?}", vm.registers);
|
|
||||||
|
|
||||||
match ecall_number {
|
match ecall_number {
|
||||||
0 => {
|
0 => {
|
||||||
|
@ -97,7 +94,8 @@ pub fn handler(vm: &mut Vm) {
|
||||||
match msg_type {
|
match msg_type {
|
||||||
0 => unsafe {
|
0 => unsafe {
|
||||||
let size = msg_vec[1];
|
let size = msg_vec[1];
|
||||||
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
let addr =
|
||||||
|
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
||||||
let value = match size {
|
let value = match size {
|
||||||
0 => x86_in::<u8>(addr) as u64,
|
0 => x86_in::<u8>(addr) as u64,
|
||||||
1 => x86_in::<u16>(addr) as u64,
|
1 => x86_in::<u16>(addr) as u64,
|
||||||
|
@ -109,7 +107,8 @@ pub fn handler(vm: &mut Vm) {
|
||||||
},
|
},
|
||||||
1 => unsafe {
|
1 => unsafe {
|
||||||
let size = msg_vec[1];
|
let size = msg_vec[1];
|
||||||
let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap());
|
let addr =
|
||||||
|
u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked());
|
||||||
// info!("Setting address {}", addr);
|
// info!("Setting address {}", addr);
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
|
@ -132,9 +131,13 @@ pub fn handler(vm: &mut Vm) {
|
||||||
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
3 => unimplemented!("TODO: implement whatever buffer 3 does for no x86_64"),
|
||||||
// source of rng
|
// source of rng
|
||||||
4 => {
|
4 => {
|
||||||
// limit to last 32 bits
|
let block = block_read(mem_addr, length);
|
||||||
vm.registers[1] =
|
block.chunks_mut(8.min(length)).for_each(|chunk| {
|
||||||
hbvm::value::Value(crate::arch::hardware_random_u64() & 0xFFFFFFFF);
|
chunk.clone_from_slice(
|
||||||
|
&crate::arch::hardware_random_u64().to_le_bytes()[..chunk.len()],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
vm.registers[1] = hbvm::value::Value(mem_addr);
|
||||||
}
|
}
|
||||||
5 => match dt_msg_handler(vm, mem_addr, length) {
|
5 => match dt_msg_handler(vm, mem_addr, length) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
@ -173,7 +176,7 @@ pub fn handler(vm: &mut Vm) {
|
||||||
Ok(msg) => msg,
|
Ok(msg) => msg,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
if msg.len() > max_length.try_into().unwrap() {
|
if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } {
|
||||||
info!("{}", max_length);
|
info!("{}", max_length);
|
||||||
error!("Message is too long to map in.");
|
error!("Message is too long to map in.");
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,15 +208,3 @@ pub enum LogError {
|
||||||
NoMessages,
|
NoMessages,
|
||||||
InvalidLogFormat,
|
InvalidLogFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
// use {alloc::vec, log::Record};
|
|
||||||
// fn memory_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
|
||||||
// let mut val = alloc::vec::Vec::new();
|
|
||||||
// for _ in 0..4096 {
|
|
||||||
// val.push(0);
|
|
||||||
// }
|
|
||||||
// info!("Block address: {:?}", val.as_ptr());
|
|
||||||
// vm.registers[1] = hbvm::value::Value(val.as_ptr() as u64);
|
|
||||||
// vm.registers[2] = hbvm::value::Value(4096);
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
|
|
|
@ -9,12 +9,16 @@ use log::Record;
|
||||||
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
pub fn log_msg_handler(_vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), LogError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
|
|
||||||
let log_level = msg_vec.last().unwrap();
|
let log_level = msg_vec[0];
|
||||||
|
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
|
||||||
|
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
|
||||||
|
|
||||||
|
let str = block_read(strptr, strlen);
|
||||||
|
|
||||||
let file_name = "None";
|
let file_name = "None";
|
||||||
let line_number = 0;
|
let line_number = 0;
|
||||||
|
|
||||||
match core::str::from_utf8(&msg_vec[..msg_vec.len()]) {
|
match core::str::from_utf8(&str) {
|
||||||
Ok(strr) => {
|
Ok(strr) => {
|
||||||
use log::Level::*;
|
use log::Level::*;
|
||||||
let log_level = match log_level {
|
let log_level = match log_level {
|
||||||
|
|
|
@ -17,13 +17,54 @@ pub enum MemoryQuotaType {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryServiceError> {
|
||||||
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 4096)) };
|
let ptr = unsafe { alloc(Layout::from_size_align_unchecked(4096, 8)) };
|
||||||
info!("Block address: {:?}", ptr);
|
info!("Block address: {:?}", ptr);
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||||
vm.registers[2] = hbvm::value::Value(4096);
|
vm.registers[2] = hbvm::value::Value(4096);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
|
||||||
|
const BLOCK_SIZE: usize = 64;
|
||||||
|
let mut remaining = count * size;
|
||||||
|
|
||||||
|
if remaining < 16 {
|
||||||
|
src.copy_to_nonoverlapping(dest, remaining);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = [0u8; BLOCK_SIZE];
|
||||||
|
let mut buffer_size = size;
|
||||||
|
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
|
||||||
|
|
||||||
|
while core::intrinsics::likely(buffer_size * 2 <= BLOCK_SIZE) {
|
||||||
|
buffer
|
||||||
|
.as_mut_ptr()
|
||||||
|
.copy_to_nonoverlapping(buffer.as_mut_ptr().add(buffer_size), buffer_size);
|
||||||
|
buffer_size *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
let buffer_ptr = buffer.as_ptr() as *const u64;
|
||||||
|
|
||||||
|
while (dest as usize) & 7 != 0 && remaining >= 8 {
|
||||||
|
buffer.as_ptr().copy_to_nonoverlapping(dest, 1);
|
||||||
|
dest = dest.add(1);
|
||||||
|
remaining -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while core::intrinsics::likely(remaining >= 8) {
|
||||||
|
*(dest as *mut u64) = *buffer_ptr;
|
||||||
|
dest = dest.add(8);
|
||||||
|
remaining -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if remaining > 0 {
|
||||||
|
buffer.as_ptr().copy_to_nonoverlapping(dest, remaining);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn memory_msg_handler(
|
pub fn memory_msg_handler(
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
mem_addr: u64,
|
mem_addr: u64,
|
||||||
|
@ -32,40 +73,35 @@ pub fn memory_msg_handler(
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let msg_type = msg_vec[0];
|
let msg_type = msg_vec[0];
|
||||||
match msg_type {
|
match msg_type {
|
||||||
0 => {
|
0 => unsafe {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[1];
|
||||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
|
||||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
|
||||||
|
|
||||||
log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
|
let ptr = alloc(Layout::from_size_align_unchecked(
|
||||||
|
|
||||||
let ptr = unsafe {
|
|
||||||
alloc(Layout::from_size_align_unchecked(
|
|
||||||
page_count as usize * 4096,
|
page_count as usize * 4096,
|
||||||
4096,
|
8,
|
||||||
))
|
));
|
||||||
};
|
|
||||||
|
log::debug!("Allocating {} pages @ {:x}", page_count, ptr as u64);
|
||||||
|
|
||||||
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
vm.registers[1] = hbvm::value::Value(ptr as u64);
|
||||||
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
log::debug!("Kernel ptr: {:x}", ptr as u64);
|
||||||
}
|
},
|
||||||
|
|
||||||
1 => {
|
1 => unsafe {
|
||||||
let page_count = msg_vec[1];
|
let page_count = msg_vec[1];
|
||||||
|
|
||||||
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap();
|
||||||
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
let mptr: u64 = u64::from_le_bytes(mptr_raw);
|
||||||
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
log::debug!("Deallocating {} pages @ {:x}", page_count, mptr);
|
||||||
unsafe {
|
|
||||||
dealloc(
|
dealloc(
|
||||||
mptr as *mut u8,
|
mptr as *mut u8,
|
||||||
Layout::from_size_align_unchecked(page_count as usize * 4096, 4096),
|
Layout::from_size_align_unchecked(page_count as usize * 4096, 8),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
}
|
|
||||||
2 => {
|
2 => {
|
||||||
use MemoryQuotaType::*;
|
use MemoryQuotaType::*;
|
||||||
let quota_type = match msg_vec[0] {
|
let quota_type = match msg_vec[1] {
|
||||||
0 => NoQuota,
|
0 => NoQuota,
|
||||||
1 => SoftQuota,
|
1 => SoftQuota,
|
||||||
2 => HardQuota,
|
2 => HardQuota,
|
||||||
|
@ -82,10 +118,24 @@ pub fn memory_msg_handler(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let page_count = msg_vec[0];
|
let page_count = msg_vec[1];
|
||||||
log::debug!(" {} pages", page_count);
|
log::debug!(" {} pages", page_count);
|
||||||
}
|
}
|
||||||
|
4 => unsafe {
|
||||||
|
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
|
||||||
|
let src = u64::from_le_bytes(msg_vec[5..13].try_into().unwrap_unchecked()) as *const u8;
|
||||||
|
let dest = u64::from_le_bytes(msg_vec[13..21].try_into().unwrap_unchecked()) as *mut u8;
|
||||||
|
|
||||||
|
src.copy_to_nonoverlapping(dest, count);
|
||||||
|
},
|
||||||
|
5 => unsafe {
|
||||||
|
let count = u32::from_le_bytes(msg_vec[1..5].try_into().unwrap_unchecked()) as usize;
|
||||||
|
let size = u32::from_le_bytes(msg_vec[5..9].try_into().unwrap_unchecked()) as usize;
|
||||||
|
let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8;
|
||||||
|
let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
|
||||||
|
|
||||||
|
memset(dest, src, count, size);
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
log::debug!("Unknown memory service message type: {}", msg_type);
|
log::debug!("Unknown memory service message type: {}", msg_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,21 +22,19 @@ pub enum ServiceError {
|
||||||
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
pub fn sds_msg_handler(vm: &mut Vm, mem_addr: u64, length: usize) -> Result<(), ServiceError> {
|
||||||
let msg_vec = block_read(mem_addr, length);
|
let msg_vec = block_read(mem_addr, length);
|
||||||
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
let sds_event_type: ServiceEventType = msg_vec[0].into();
|
||||||
|
let strptr = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap());
|
||||||
// info!("Length {}", msg_vec.len());
|
let strlen = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap()) as usize;
|
||||||
|
let string_vec = block_read(strptr, strlen);
|
||||||
|
let string = core::str::from_utf8(string_vec).expect("Our bytes should be valid utf8");
|
||||||
|
|
||||||
use ServiceEventType::*;
|
use ServiceEventType::*;
|
||||||
match sds_event_type {
|
match sds_event_type {
|
||||||
CreateService => {
|
CreateService => {
|
||||||
let string =
|
|
||||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
|
||||||
let ret = sds_create_service(string);
|
let ret = sds_create_service(string);
|
||||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||||
}
|
}
|
||||||
DeleteService => todo!(),
|
DeleteService => todo!(),
|
||||||
SearchServices => {
|
SearchServices => {
|
||||||
let string =
|
|
||||||
core::str::from_utf8(&msg_vec[1..]).expect("Our bytes should be valid utf8");
|
|
||||||
let ret = sds_search_service(string);
|
let ret = sds_search_service(string);
|
||||||
vm.registers[1] = hbvm::value::Value(ret as u64);
|
vm.registers[1] = hbvm::value::Value(ret as u64);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ impl hbvm::mem::Memory for Memory {
|
||||||
target: *mut u8,
|
target: *mut u8,
|
||||||
count: usize,
|
count: usize,
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
) -> Result<(), hbvm::mem::LoadError> {
|
||||||
// if addr.get() % 4096 == 0 {}
|
|
||||||
core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count);
|
core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl HandlePageFault for PageFaultHandler {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
const fn stack_layout() -> Layout {
|
const fn stack_layout() -> Layout {
|
||||||
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) }
|
unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 8) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
slice_split_once,
|
slice_split_once,
|
||||||
exclusive_wrapper,
|
exclusive_wrapper,
|
||||||
new_uninit,
|
new_uninit,
|
||||||
|
core_intrinsics,
|
||||||
abi_x86_interrupt,
|
abi_x86_interrupt,
|
||||||
alloc_error_handler,
|
alloc_error_handler,
|
||||||
ptr_sub_ptr,
|
ptr_sub_ptr,
|
||||||
|
@ -14,8 +15,7 @@
|
||||||
pointer_is_aligned_to
|
pointer_is_aligned_to
|
||||||
)]
|
)]
|
||||||
#![test_runner(crate::test_runner)]
|
#![test_runner(crate::test_runner)]
|
||||||
#![cfg_attr(not(debug_assertions), allow(unused, deprecated))]
|
#![allow(dead_code, internal_features)]
|
||||||
#![allow(dead_code)]
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
mod allocator;
|
mod allocator;
|
||||||
|
|
|
@ -36,7 +36,19 @@ impl log::Log for Logger {
|
||||||
Level::Debug => "25",
|
Level::Debug => "25",
|
||||||
Level::Trace => "103",
|
Level::Trace => "103",
|
||||||
};
|
};
|
||||||
let module = record.module_path().unwrap_or_default();
|
let module = record
|
||||||
|
.module_path()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.rsplit_once(':')
|
||||||
|
.unwrap_or_default()
|
||||||
|
.1;
|
||||||
|
if module == "" {
|
||||||
|
crate::arch::log(format_args!(
|
||||||
|
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
|
||||||
|
record.args(),
|
||||||
|
))
|
||||||
|
.expect("write to serial console");
|
||||||
|
} else {
|
||||||
let line = record.line().unwrap_or_default();
|
let line = record.line().unwrap_or_default();
|
||||||
crate::arch::log(format_args!(
|
crate::arch::log(format_args!(
|
||||||
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
|
||||||
|
@ -44,6 +56,7 @@ impl log::Log for Logger {
|
||||||
))
|
))
|
||||||
.expect("write to serial console");
|
.expect("write to serial console");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
2
known_bugs.md
Normal file
2
known_bugs.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# i did not know where to put this
|
||||||
|
- memcpy / memset cause crash on debug builds due to ptr misalignment that is not present on release builds
|
|
@ -6,26 +6,15 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
str-reader = "0.1"
|
str-reader = "0.1"
|
||||||
derive_more = { version = "1", default-features = false, features = [
|
derive_more = { version = "1", default-features = false, features = [
|
||||||
"add",
|
|
||||||
"add_assign",
|
|
||||||
"constructor",
|
|
||||||
"display",
|
"display",
|
||||||
"from",
|
|
||||||
"into",
|
|
||||||
"mul",
|
|
||||||
"mul_assign",
|
|
||||||
"not",
|
|
||||||
"sum",
|
|
||||||
] }
|
] }
|
||||||
error-stack = "0.5"
|
error-stack = "0.5"
|
||||||
fatfs = "0.3"
|
fatfs = { version = "0.3", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
# hbasm.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
|
||||||
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
raw-cpuid = "11"
|
raw-cpuid = "11"
|
||||||
|
ureq = { version = "2", default-features = false, features = ["tls"] }
|
||||||
[dependencies.reqwest]
|
|
||||||
version = "0.12"
|
|
||||||
default-features = false
|
|
||||||
features = ["rustls-tls", "blocking"]
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ impl Package {
|
||||||
|
|
||||||
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
for (count, (name, table)) in bin_table.into_iter().enumerate() {
|
||||||
// if count != 0 {
|
// if count != 0 {
|
||||||
println!("{}", name);
|
|
||||||
binaries.push(name.clone());
|
binaries.push(name.clone());
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
@ -63,40 +62,49 @@ impl Package {
|
||||||
build_cmd,
|
build_cmd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn build(&self) {
|
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);
|
||||||
let mut bytes = Vec::new();
|
|
||||||
// compile here
|
// compile here
|
||||||
|
|
||||||
let _ = hblang::run_compiler(
|
hblang::run_compiler(
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
fmt: true,
|
fmt: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
&mut bytes,
|
out,
|
||||||
);
|
)?;
|
||||||
let _ = hblang::run_compiler(&path, Default::default(), &mut bytes);
|
|
||||||
|
|
||||||
match std::fs::create_dir("target/programs") {
|
match std::fs::create_dir("target/programs") {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||||
Err(e) => panic!("{}", e),
|
Err(e) => panic!("{}", e),
|
||||||
}
|
}
|
||||||
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
|
|
||||||
bytes.clear();
|
hblang::run_compiler(
|
||||||
let _ = hblang::run_compiler(
|
&path,
|
||||||
|
Options {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
out,
|
||||||
|
)?;
|
||||||
|
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
|
||||||
|
out.clear();
|
||||||
|
|
||||||
|
hblang::run_compiler(
|
||||||
&path,
|
&path,
|
||||||
Options {
|
Options {
|
||||||
dump_asm: true,
|
dump_asm: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
&mut bytes,
|
out,
|
||||||
);
|
)?;
|
||||||
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap();
|
std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
|
||||||
}
|
out.clear();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
// #![allow(unused)]
|
|
||||||
|
|
||||||
mod dev;
|
mod dev;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
core::fmt::Write as _,
|
||||||
derive_more::Display,
|
derive_more::Display,
|
||||||
dev::Package,
|
dev::Package,
|
||||||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||||
std::{
|
std::{
|
||||||
// fmt::Display,
|
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
@ -38,6 +36,8 @@ fn main() -> Result<(), Error> {
|
||||||
target = Target::Riscv64Virt;
|
target = Target::Riscv64Virt;
|
||||||
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
} else if arg == "arm64" || arg == "aarch64" || arg == "aarch64-virt" {
|
||||||
target = Target::Aarch64;
|
target = Target::Aarch64;
|
||||||
|
} else if arg == "avx2" {
|
||||||
|
target = Target::X86_64Avx2;
|
||||||
} else {
|
} else {
|
||||||
return Err(report!(Error::InvalidSubCom));
|
return Err(report!(Error::InvalidSubCom));
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,8 @@ fn main() -> Result<(), Error> {
|
||||||
target = Target::Aarch64;
|
target = Target::Aarch64;
|
||||||
} else if arg == "--noaccel" {
|
} else if arg == "--noaccel" {
|
||||||
do_accel = false;
|
do_accel = false;
|
||||||
|
} else if arg == "avx2" {
|
||||||
|
target = Target::X86_64Avx2;
|
||||||
} else {
|
} else {
|
||||||
return Err(report!(Error::InvalidSubCom));
|
return Err(report!(Error::InvalidSubCom));
|
||||||
}
|
}
|
||||||
|
@ -80,7 +82,7 @@ fn main() -> Result<(), Error> {
|
||||||
" -r / --release: build in release mode\n",
|
" -r / --release: build in release mode\n",
|
||||||
" -d / --debuginfo: build with debug info\n",
|
" -d / --debuginfo: build with debug info\n",
|
||||||
" --noaccel: run without acceleration (e.g, no kvm)\n",
|
" --noaccel: run without acceleration (e.g, no kvm)\n",
|
||||||
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt ]: sets target"
|
"[ rv64 / riscv64 / riscv64-virt / aarch64 / arm64 / aarch64-virt / avx2 ]: sets target"
|
||||||
),);
|
),);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -203,7 +205,12 @@ TERM_BACKDROP={}
|
||||||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||||
// let mut real_modules = modules.clone();
|
// let mut real_modules = modules.clone();
|
||||||
|
|
||||||
modules.into_iter().for_each(|(_, value)| {
|
let mut errors = String::new();
|
||||||
|
let mut out = Vec::new();
|
||||||
|
|
||||||
|
modules
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, value)| -> Result<(), io::Error> {
|
||||||
if value.is_table() {
|
if value.is_table() {
|
||||||
let path = get_path_without_boot_prefix(
|
let path = get_path_without_boot_prefix(
|
||||||
value.get("path").expect("You must have `path` as a value"),
|
value.get("path").expect("You must have `path` as a value"),
|
||||||
|
@ -215,9 +222,26 @@ TERM_BACKDROP={}
|
||||||
let p = Package::load_from_file(
|
let p = Package::load_from_file(
|
||||||
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
format!("sysdata/programs/{}/meta.toml", path).to_owned(),
|
||||||
);
|
);
|
||||||
p.build();
|
match p.build(&mut out) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(_) => {
|
||||||
|
writeln!(errors, "========= while compiling {} =========", path)
|
||||||
|
.unwrap();
|
||||||
|
errors.push_str(core::str::from_utf8(&out).expect("no"));
|
||||||
|
out.clear();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.for_each(drop);
|
||||||
|
|
||||||
|
if !errors.is_empty() {
|
||||||
|
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
|
||||||
|
std::eprint!("{errors}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
modules.into_iter().for_each(|(_key, value)| {
|
modules.into_iter().for_each(|(_key, value)| {
|
||||||
if value.is_table() {
|
if value.is_table() {
|
||||||
let path = value.get("path").expect("You must have `path` as a value");
|
let path = value.get("path").expect("You must have `path` as a value");
|
||||||
|
@ -304,6 +328,9 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
if target == Target::Aarch64 {
|
if target == Target::Aarch64 {
|
||||||
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
||||||
}
|
}
|
||||||
|
if target == Target::X86_64Avx2 {
|
||||||
|
com.args(["--target", "targets/x86_64_v3-ableos.json"]);
|
||||||
|
}
|
||||||
|
|
||||||
match com.status() {
|
match com.status() {
|
||||||
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
||||||
|
@ -317,6 +344,10 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
path.push_str("_x86-64");
|
path.push_str("_x86-64");
|
||||||
"target/x86_64-ableos"
|
"target/x86_64-ableos"
|
||||||
}
|
}
|
||||||
|
Target::X86_64Avx2 => {
|
||||||
|
path.push_str("_x86-64");
|
||||||
|
"target/x86_64_v3-ableos"
|
||||||
|
}
|
||||||
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
||||||
Target::Aarch64 => {
|
Target::Aarch64 => {
|
||||||
path.push_str("_aarch64");
|
path.push_str("_aarch64");
|
||||||
|
@ -341,7 +372,7 @@ fn build(release: bool, target: Target, debuginfo: bool) -> Result<(), Error> {
|
||||||
|
|
||||||
fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
||||||
let target_str = match target {
|
let target_str = match target {
|
||||||
Target::X86_64 => "qemu-system-x86_64",
|
Target::X86_64 | Target::X86_64Avx2 => "qemu-system-x86_64",
|
||||||
Target::Riscv64Virt => "qemu-system-riscv64",
|
Target::Riscv64Virt => "qemu-system-riscv64",
|
||||||
Target::Aarch64 => "qemu-system-aarch64",
|
Target::Aarch64 => "qemu-system-aarch64",
|
||||||
};
|
};
|
||||||
|
@ -384,23 +415,19 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match target {
|
match target {
|
||||||
Target::X86_64 => {
|
Target::X86_64 | Target::X86_64Avx2 => {
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
com.args([
|
com.args([
|
||||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||||
"-drive", "file=target/disk.img,format=raw",
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
"-device", "vmware-svga",
|
"-device", "vmware-svga",
|
||||||
|
// "-serial", "stdio",
|
||||||
"-m", "2G",
|
"-m", "2G",
|
||||||
"-smp", "1",
|
"-smp", "1",
|
||||||
"-parallel", "none",
|
"-parallel", "none",
|
||||||
"-monitor", "none",
|
"-monitor", "none",
|
||||||
"-machine", accel,
|
"-machine", accel,
|
||||||
"-cpu",
|
"-cpu", "max",
|
||||||
if accel != "accel=tcg" {
|
|
||||||
"host"
|
|
||||||
} else {
|
|
||||||
"Broadwell-v4"
|
|
||||||
},
|
|
||||||
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
"-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -445,7 +472,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
|
||||||
|
|
||||||
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||||
let (ovmf_url, ovmf_path) = match target {
|
let (ovmf_url, ovmf_path) = match target {
|
||||||
Target::X86_64 => (
|
Target::X86_64 | Target::X86_64Avx2 => (
|
||||||
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
|
"https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd",
|
||||||
"target/RELEASEX64_OVMF.fd",
|
"target/RELEASEX64_OVMF.fd",
|
||||||
),
|
),
|
||||||
|
@ -467,12 +494,12 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
||||||
Ok(_) => return Ok(ovmf_path.to_owned()),
|
Ok(_) => return Ok(ovmf_path.to_owned()),
|
||||||
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
||||||
};
|
};
|
||||||
let mut bytes = reqwest::blocking::get(ovmf_url)
|
let req = ureq::get(ovmf_url)
|
||||||
|
.call()
|
||||||
.map_err(Report::from)
|
.map_err(Report::from)
|
||||||
.change_context(OvmfFetchError::Fetch)?;
|
.change_context(OvmfFetchError::Fetch)?;
|
||||||
|
|
||||||
bytes
|
std::io::copy(&mut req.into_reader(), &mut file)
|
||||||
.copy_to(&mut file)
|
|
||||||
.map_err(Report::from)
|
.map_err(Report::from)
|
||||||
.change_context(OvmfFetchError::Io)?;
|
.change_context(OvmfFetchError::Io)?;
|
||||||
|
|
||||||
|
@ -494,6 +521,7 @@ impl Context for OvmfFetchError {}
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
enum Target {
|
enum Target {
|
||||||
X86_64,
|
X86_64,
|
||||||
|
X86_64Avx2,
|
||||||
Riscv64Virt,
|
Riscv64Virt,
|
||||||
Aarch64,
|
Aarch64,
|
||||||
}
|
}
|
||||||
|
|
BIN
sysdata/assets/able.bmp
Normal file
BIN
sysdata/assets/able.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
sysdata/assets/consolefonts/tamsyn/10x20b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/10x20b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/10x20r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/10x20r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/5x9b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/5x9b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/5x9r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/5x9r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/6x12b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/6x12b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/6x12r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/6x12r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x13b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x13b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x13r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x13r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x14b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x14b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/7x14r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/7x14r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x15b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x15b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x15r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x15r.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x16b.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x16b.psf
Normal file
Binary file not shown.
BIN
sysdata/assets/consolefonts/tamsyn/8x16r.psf
Normal file
BIN
sysdata/assets/consolefonts/tamsyn/8x16r.psf
Normal file
Binary file not shown.
10
sysdata/assets/consolefonts/tamsyn/LICENSE
Normal file
10
sysdata/assets/consolefonts/tamsyn/LICENSE
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Tamsyn font is free. You are hereby granted permission to use, copy, modify,
|
||||||
|
and distribute it as you see fit.
|
||||||
|
|
||||||
|
Tamsyn font is provided "as is" without any express or implied warranty.
|
||||||
|
|
||||||
|
The author makes no representations about the suitability of this font for
|
||||||
|
a particular purpose.
|
||||||
|
|
||||||
|
In no event will the author be held liable for damages arising from the use
|
||||||
|
of this font.
|
BIN
sysdata/assets/mini.bmp
Normal file
BIN
sysdata/assets/mini.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
sysdata/assets/mini.qoi
Normal file
BIN
sysdata/assets/mini.qoi
Normal file
Binary file not shown.
BIN
sysdata/assets/wallpaper.qoi
Normal file
BIN
sysdata/assets/wallpaper.qoi
Normal file
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
# dt_api
|
|
|
@ -1,6 +0,0 @@
|
||||||
.{string} := @use("../../stn/src/lib.hb")
|
|
||||||
|
|
||||||
dt_get := fn(query: ^u8): int {
|
|
||||||
length := string.length(query)
|
|
||||||
return @eca(3, 5, query, length)
|
|
||||||
}
|
|
4
sysdata/libraries/horizon_api/examples/horizontal.lui
Normal file
4
sysdata/libraries/horizon_api/examples/horizontal.lui
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
(horizontal
|
||||||
|
spacing : 10
|
||||||
|
(label "hi")
|
||||||
|
(label "goodbye"))
|
1
sysdata/libraries/horizon_api/examples/label.lui
Normal file
1
sysdata/libraries/horizon_api/examples/label.lui
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(label "hello")
|
3
sysdata/libraries/horizon_api/examples/vertical.lui
Normal file
3
sysdata/libraries/horizon_api/examples/vertical.lui
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
(vertical
|
||||||
|
(label "hello")
|
||||||
|
(label "hello" color:red))
|
|
@ -1,25 +1,49 @@
|
||||||
stn := @use("../../stn/src/lib.hb");
|
stn := @use("../../stn/src/lib.hb");
|
||||||
.{string, memory, buffer} := stn
|
.{string, memory, buffer, log} := stn
|
||||||
|
|
||||||
|
render := @use("../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
input := @use("../../intouch/src/lib.hb")
|
input := @use("../../intouch/src/lib.hb")
|
||||||
|
|
||||||
|
widgets := @use("widgets/widgets.hb")
|
||||||
|
ui := @use("ui.hb")
|
||||||
|
|
||||||
WindowID := struct {
|
WindowID := struct {
|
||||||
host_id: int,
|
host_id: int,
|
||||||
window_id: int,
|
window_id: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
create_window := fn(channel: int): void {
|
VoidWindowID := WindowID.(0, 0)
|
||||||
|
|
||||||
|
create_window := fn(channel: int): ^render.Surface {
|
||||||
// get the horizon buffer
|
// get the horizon buffer
|
||||||
// request a new window and provide the callback buffer
|
// request a new window and provide the callback buffer
|
||||||
// wait to recieve a message
|
// wait to recieve a message
|
||||||
|
|
||||||
windowing_system_buffer := buffer.search("XHorizon\0")
|
windowing_system_buffer := buffer.search("XHorizon\0")
|
||||||
|
mem_buf := memory.request_page(1)
|
||||||
|
|
||||||
if windowing_system_buffer == 0 {
|
if windowing_system_buffer == 0 {
|
||||||
return
|
return @as(^render.Surface, idk)
|
||||||
} else {
|
} else {
|
||||||
msg := "\{01}\0"
|
// ! bad able, stop using string messages :ragey:
|
||||||
msg_length := 2
|
// msg := "\{01}\0"
|
||||||
return @eca(3, windowing_system_buffer, msg, msg_length)
|
// msg_length := 2
|
||||||
|
|
||||||
|
// @as(void, @eca(3, windowing_system_buffer, msg, msg_length))
|
||||||
|
|
||||||
|
x := 0
|
||||||
|
loop if x > 1000 break else x += 1
|
||||||
|
|
||||||
|
ret := buffer.recv([u8; 4096], windowing_system_buffer, mem_buf)
|
||||||
|
if ret == null {
|
||||||
|
log.info("No messages\0")
|
||||||
|
}
|
||||||
|
|
||||||
|
if *mem_buf == 0 {
|
||||||
|
log.info("No messages\0")
|
||||||
|
}
|
||||||
|
|
||||||
|
return @as(^render.Surface, idk)
|
||||||
}
|
}
|
||||||
}
|
}
|
47
sysdata/libraries/horizon_api/src/ui.hb
Normal file
47
sysdata/libraries/horizon_api/src/ui.hb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||||
|
.{string, log} := stn;
|
||||||
|
.{Vec2} := stn.math
|
||||||
|
|
||||||
|
render := @use("../../../libraries/render/src/lib.hb");
|
||||||
|
.{Surface} := render;
|
||||||
|
.{Font} := render.text
|
||||||
|
|
||||||
|
UI := struct {raw: ^u8, raw_length: uint, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
|
||||||
|
// children: ^^u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
render_ui := fn(surface: Surface, ui: UI): void {
|
||||||
|
if ui.is_dirty {
|
||||||
|
render.clear(ui.surface, render.black)
|
||||||
|
ui.is_dirty = false
|
||||||
|
}
|
||||||
|
pos := Vec2(uint).(0, 0)
|
||||||
|
render.put_surface(surface, ui.surface, pos, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
sexpr_parser := fn(sexpr: ^u8): UI {
|
||||||
|
cursor := sexpr
|
||||||
|
paren_balance := 0
|
||||||
|
loop {
|
||||||
|
if *cursor == 0 {
|
||||||
|
if paren_balance != 0 {
|
||||||
|
log.error("Unbalanced Parens\0")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
} else if *cursor == 40 {
|
||||||
|
log.info("Open paren\0")
|
||||||
|
paren_balance += 1
|
||||||
|
} else if *cursor == 41 {
|
||||||
|
log.info("Closed paren\0")
|
||||||
|
paren_balance -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
length := string.length(sexpr)
|
||||||
|
|
||||||
|
ui_surface := render.new_surface(100, 100)
|
||||||
|
|
||||||
|
return UI.(sexpr, length, true, ui_surface)
|
||||||
|
}
|
13
sysdata/libraries/horizon_api/src/widgets/image.hb
Normal file
13
sysdata/libraries/horizon_api/src/widgets/image.hb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb");
|
||||||
|
.{Surface} := render
|
||||||
|
|
||||||
|
Image := struct {
|
||||||
|
magic: uint,
|
||||||
|
is_dirty: bool,
|
||||||
|
surface: Surface,
|
||||||
|
}
|
||||||
|
|
||||||
|
image_from_surface := fn(surface: Surface): Image {
|
||||||
|
img := Image.(4, true, surface)
|
||||||
|
return img
|
||||||
|
}
|
38
sysdata/libraries/horizon_api/src/widgets/label.hb
Normal file
38
sysdata/libraries/horizon_api/src/widgets/label.hb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
stn := @use("../../../../libraries/stn/src/lib.hb");
|
||||||
|
.{string, log} := stn;
|
||||||
|
.{Vec2} := stn.math
|
||||||
|
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb");
|
||||||
|
.{Surface} := render;
|
||||||
|
.{Font} := render.text
|
||||||
|
|
||||||
|
Label := struct {
|
||||||
|
magic: uint,
|
||||||
|
is_dirty: bool,
|
||||||
|
surface: Surface,
|
||||||
|
text: ^u8,
|
||||||
|
text_length: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
set_label_text := fn(label: Label, text: ^u8): void {
|
||||||
|
text_length := string.length(text)
|
||||||
|
|
||||||
|
label.is_dirty = true
|
||||||
|
label.text = text
|
||||||
|
label.text_length = text_length
|
||||||
|
}
|
||||||
|
|
||||||
|
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
|
||||||
|
if label.is_dirty {
|
||||||
|
render.clear(label.surface, render.black)
|
||||||
|
render.put_text(label.surface, font, .(0, 0), render.white, label.text)
|
||||||
|
}
|
||||||
|
render.put_surface(surface, label.surface, pos, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
new_label := fn(text: ^u8): Label {
|
||||||
|
text_surface := render.new_surface(1024, 20)
|
||||||
|
text_length := string.length(text)
|
||||||
|
label := Label.(3, true, text_surface, text, text_length)
|
||||||
|
return label
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
NoWidget := 0
|
||||||
|
|
||||||
|
VerticalWidgetType := 1
|
||||||
|
HorizontalWidgetType := 2
|
||||||
|
|
||||||
|
LabelWidgetType := 3
|
||||||
|
ImageWidgetType := 4
|
36
sysdata/libraries/horizon_api/src/widgets/widgets.hb
Normal file
36
sysdata/libraries/horizon_api/src/widgets/widgets.hb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Widget types
|
||||||
|
|
||||||
|
// End types
|
||||||
|
stn := @use("../../../../libraries/stn/src/lib.hb");
|
||||||
|
.{string, log} := stn;
|
||||||
|
.{Vec2} := stn.math
|
||||||
|
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb");
|
||||||
|
.{Surface} := render;
|
||||||
|
.{Font} := render.text
|
||||||
|
|
||||||
|
widget_types := @use("widget_types.hb")
|
||||||
|
label := @use("label.hb")
|
||||||
|
image := @use("image.hb")
|
||||||
|
|
||||||
|
Size := struct {
|
||||||
|
min_width: int,
|
||||||
|
max_width: int,
|
||||||
|
min_height: int,
|
||||||
|
max_height: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
Vertical := packed struct {
|
||||||
|
magic: uint,
|
||||||
|
// array of children, idk
|
||||||
|
// use a vec or linked list or whatever
|
||||||
|
|
||||||
|
children: ^^u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
Horizontal := packed struct {
|
||||||
|
magic: uint,
|
||||||
|
// array of children, idk
|
||||||
|
// use a vec or linked list or whatever
|
||||||
|
children: ^^u8,
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ ApplicationInfo := struct {
|
||||||
pNext: ^int,
|
pNext: ^int,
|
||||||
application_name: ^u8,
|
application_name: ^u8,
|
||||||
application_version: int,
|
application_version: int,
|
||||||
engine_name: int,
|
engine_name: ^u8,
|
||||||
engine_version: int,
|
engine_version: int,
|
||||||
api_version: int,
|
api_version: int,
|
||||||
}
|
}
|
||||||
|
|
22
sysdata/libraries/intouch/src/events.hb
Normal file
22
sysdata/libraries/intouch/src/events.hb
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
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,
|
||||||
|
key: KeyCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseEvent := packed struct {
|
||||||
|
x_change: i8,
|
||||||
|
y_change: i8,
|
||||||
|
left: bool,
|
||||||
|
middle: bool,
|
||||||
|
right: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
GamepadEvent := struct {}
|
|
@ -1,67 +1,121 @@
|
||||||
|
/*
|
||||||
|
Originally I was modelling this after the following(1). I have since changed my mind.
|
||||||
|
I am now modelling it as I see fit. This is likely not the final version.
|
||||||
|
|
||||||
|
1) https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
||||||
|
*/
|
||||||
|
|
||||||
KeyCode := u32
|
KeyCode := u32
|
||||||
|
|
||||||
// https://www.libsdl.org/release/SDL-1.2.15/include/SDL_keysym.h
|
// Typically this is not a keycode you will ever recieve.
|
||||||
Backspace := KeyCode.(8)
|
None := KeyCode.(0)
|
||||||
Tab := KeyCode.(9)
|
|
||||||
Clear := KeyCode.(12)
|
|
||||||
Return := KeyCode.(13)
|
|
||||||
Pause := KeyCode.(19)
|
|
||||||
Escape := KeyCode.(27)
|
|
||||||
Space := KeyCode.(32)
|
|
||||||
|
|
||||||
A := KeyCode.(97)
|
Escape := KeyCode.(1)
|
||||||
/*
|
/* Alphabet keycodes */
|
||||||
ETC
|
|
||||||
*/
|
|
||||||
Z := KeyCode.(122)
|
|
||||||
|
|
||||||
Delete := KeyCode.(127)
|
A := KeyCode.(2)
|
||||||
|
B := KeyCode.(3)
|
||||||
|
C := KeyCode.(4)
|
||||||
|
D := KeyCode.(5)
|
||||||
|
E := KeyCode.(6)
|
||||||
|
F := KeyCode.(7)
|
||||||
|
G := KeyCode.(8)
|
||||||
|
H := KeyCode.(9)
|
||||||
|
I := KeyCode.(10)
|
||||||
|
J := KeyCode.(11)
|
||||||
|
K := KeyCode.(12)
|
||||||
|
L := KeyCode.(13)
|
||||||
|
M := KeyCode.(14)
|
||||||
|
N := KeyCode.(15)
|
||||||
|
O := KeyCode.(16)
|
||||||
|
P := KeyCode.(17)
|
||||||
|
Q := KeyCode.(18)
|
||||||
|
R := KeyCode.(19)
|
||||||
|
S := KeyCode.(20)
|
||||||
|
T := KeyCode.(21)
|
||||||
|
U := KeyCode.(22)
|
||||||
|
V := KeyCode.(23)
|
||||||
|
W := KeyCode.(24)
|
||||||
|
X := KeyCode.(25)
|
||||||
|
Y := KeyCode.(26)
|
||||||
|
Z := KeyCode.(27)
|
||||||
|
|
||||||
/*
|
/* Numeric keycodes*/
|
||||||
ETC
|
|
||||||
*/
|
|
||||||
|
|
||||||
KeypadNumber0 := KeyCode.(256)
|
Number0 := KeyCode.(28)
|
||||||
KeypadNumber1 := KeyCode.(257)
|
Number1 := KeyCode.(29)
|
||||||
KeypadNumber2 := KeyCode.(258)
|
Number2 := KeyCode.(30)
|
||||||
KeypadNumber3 := KeyCode.(259)
|
Number3 := KeyCode.(31)
|
||||||
KeypadNumber4 := KeyCode.(260)
|
Number4 := KeyCode.(32)
|
||||||
KeypadNumber5 := KeyCode.(261)
|
Number5 := KeyCode.(33)
|
||||||
KeypadNumber6 := KeyCode.(262)
|
Number6 := KeyCode.(34)
|
||||||
KeypadNumber7 := KeyCode.(263)
|
Number7 := KeyCode.(35)
|
||||||
KeypadNumber8 := KeyCode.(264)
|
Number8 := KeyCode.(36)
|
||||||
KeypadNumber9 := KeyCode.(265)
|
Number9 := KeyCode.(37)
|
||||||
|
|
||||||
KeypadPeriod := KeyCode.(266)
|
KeypadNumber0 := KeyCode.(38)
|
||||||
KeypadDivide := KeyCode.(267)
|
KeypadNumber1 := KeyCode.(39)
|
||||||
KeypadMultiply := KeyCode.(268)
|
KeypadNumber2 := KeyCode.(40)
|
||||||
KeypadMinus := KeyCode.(269)
|
KeypadNumber3 := KeyCode.(41)
|
||||||
KeypadPlus := KeyCode.(270)
|
KeypadNumber4 := KeyCode.(42)
|
||||||
KeypadEnter := KeyCode.(271)
|
KeypadNumber5 := KeyCode.(43)
|
||||||
KeypadEquals := KeyCode.(272)
|
KeypadNumber6 := KeyCode.(44)
|
||||||
|
KeypadNumber7 := KeyCode.(45)
|
||||||
|
KeypadNumber8 := KeyCode.(46)
|
||||||
|
KeypadNumber9 := KeyCode.(47)
|
||||||
|
|
||||||
NumLock := KeyCode.(300)
|
KeypadPeriod := KeyCode.(48)
|
||||||
CapsLock := KeyCode.(301)
|
KeypadDivide := KeyCode.(49)
|
||||||
ScrollLock := KeyCode.(302)
|
KeypadMultiply := KeyCode.(50)
|
||||||
|
KeypadMinus := KeyCode.(51)
|
||||||
|
KeypadPlus := KeyCode.(52)
|
||||||
|
KeypadEnter := KeyCode.(53)
|
||||||
|
KeypadEquals := KeyCode.(54)
|
||||||
|
|
||||||
RightShift := KeyCode.(303)
|
Delete := KeyCode.(55)
|
||||||
LeftShift := KeyCode.(304)
|
/* Locking Keys */
|
||||||
|
NumLock := KeyCode.(56)
|
||||||
RightControl := KeyCode.(305)
|
CapsLock := KeyCode.(57)
|
||||||
LeftControl := KeyCode.(306)
|
ScrollLock := KeyCode.(58)
|
||||||
RightAlt := KeyCode.(307)
|
|
||||||
LeftAlt := KeyCode.(308)
|
|
||||||
RightMeta := KeyCode.(309)
|
|
||||||
LeftMeta := KeyCode.(310)
|
|
||||||
|
|
||||||
/* Left "Windows" key */
|
|
||||||
LeftSuper := KeyCode.(311)
|
|
||||||
|
|
||||||
/* Right "Windows" key */
|
|
||||||
RightSuper := KeyCode.(312)
|
|
||||||
|
|
||||||
/* "Alt Gr" key */
|
/* "Alt Gr" key */
|
||||||
Mode := KeyCode.(313)
|
Mode := KeyCode.(59)
|
||||||
|
|
||||||
/* Multi-key compose key */
|
/* Multi-key compose key */
|
||||||
Compose := KeyCode.(314)
|
Compose := KeyCode.(60)
|
||||||
|
|
||||||
|
LeftAlt := KeyCode.(61)
|
||||||
|
LeftControl := KeyCode.(62)
|
||||||
|
LeftMeta := KeyCode.(63)
|
||||||
|
LeftShift := KeyCode.(64)
|
||||||
|
/* Left "Windows" key */
|
||||||
|
LeftSuper := KeyCode.(65)
|
||||||
|
|
||||||
|
RightAlt := KeyCode.(66)
|
||||||
|
RightControl := KeyCode.(67)
|
||||||
|
RightMeta := KeyCode.(68)
|
||||||
|
RightShift := KeyCode.(69)
|
||||||
|
/* Right "Windows" key */
|
||||||
|
RightSuper := KeyCode.(70)
|
||||||
|
|
||||||
|
/*
|
||||||
|
This block of any triggers on any press of any of the keys.
|
||||||
|
Typically this is the event to care about.
|
||||||
|
*/
|
||||||
|
AnyNumber0 := KeyCode.(71)
|
||||||
|
AnyNumber1 := KeyCode.(72)
|
||||||
|
AnyNumber2 := KeyCode.(73)
|
||||||
|
AnyNumber3 := KeyCode.(74)
|
||||||
|
AnyNumber4 := KeyCode.(75)
|
||||||
|
AnyNumber5 := KeyCode.(76)
|
||||||
|
AnyNumber6 := KeyCode.(77)
|
||||||
|
AnyNumber7 := KeyCode.(78)
|
||||||
|
AnyNumber8 := KeyCode.(79)
|
||||||
|
AnyNumber9 := KeyCode.(80)
|
||||||
|
|
||||||
|
AnyAlt := KeyCode.(81)
|
||||||
|
AnyControl := KeyCode.(82)
|
||||||
|
AnyMeta := KeyCode.(83)
|
||||||
|
AnyShift := KeyCode.(84)
|
||||||
|
/* Any "Windows" key */
|
||||||
|
AnySuper := KeyCode.(85)
|
|
@ -1,22 +1,25 @@
|
||||||
keycodes := @use("keycodes.hb");
|
stn := @use("../../stn/src/lib.hb");
|
||||||
.{KeyCode} := keycodes
|
.{log, buffer, memory} := stn
|
||||||
|
keycodes := @use("keycodes.hb")
|
||||||
|
|
||||||
MouseEvent := struct {
|
events := @use("events.hb");
|
||||||
x_change: u8,
|
.{KeyEvent, MouseEvent} := events
|
||||||
y_change: u8,
|
|
||||||
left: u8,
|
recieve_key_event := fn(): ?KeyEvent {
|
||||||
middle: u8,
|
return null
|
||||||
right: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyEvent := struct {
|
recieve_mouse_event := fn(): ?MouseEvent {
|
||||||
// 0 if down
|
mevent := MouseEvent.(0, 0, false, false, false)
|
||||||
// 1 if up
|
|
||||||
up: u8,
|
buf_id := buffer.search("PS/2 Mouse\0")
|
||||||
// 0 if not just triggered
|
|
||||||
// 1 if just triggered
|
// Read out of the Mouse buffer here
|
||||||
just_triggered: u8,
|
buffer.recv(MouseEvent, buf_id, @bitcast(&mevent))
|
||||||
key: KeyCode,
|
|
||||||
|
if mevent.x_change != 0 | mevent.y_change != 0 | mevent.left | mevent.middle | mevent.right {
|
||||||
|
return mevent
|
||||||
}
|
}
|
||||||
|
|
||||||
GamepadEvent := struct {}
|
return null
|
||||||
|
}
|
30
sysdata/libraries/render/TODO.md
Normal file
30
sysdata/libraries/render/TODO.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Images
|
||||||
|
- General over image format
|
||||||
|
- Support formats:
|
||||||
|
- PNG
|
||||||
|
- Animation
|
||||||
|
|
||||||
|
# API
|
||||||
|
- Colour operations:
|
||||||
|
- Alpha Composite
|
||||||
|
- Invert
|
||||||
|
- Surface Operations:
|
||||||
|
- FlipH
|
||||||
|
- Resize
|
||||||
|
- Wrap the colour operations
|
||||||
|
- Tile
|
||||||
|
- Gradient overlay
|
||||||
|
- Draw operations:
|
||||||
|
- Curve raster algorithm
|
||||||
|
- VGA font fast blit
|
||||||
|
- Polygon
|
||||||
|
- Rounded rects
|
||||||
|
|
||||||
|
# Backend
|
||||||
|
- SVGA Driver
|
||||||
|
- Support whatever vulkan stuff able is cooking
|
||||||
|
|
||||||
|
# Bits and bobs on the table
|
||||||
|
- Funny 3D Renderer
|
||||||
|
- stn.memory.swap & kernel message
|
||||||
|
- Make memory.{copy, set} smart
|
49
sysdata/libraries/render/src/image/bmp.hb
Normal file
49
sysdata/libraries/render/src/image/bmp.hb
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
|
||||||
|
.{log, memory} := @use("../../../stn/src/lib.hb")
|
||||||
|
|
||||||
|
BitmapFileHeader := packed struct {
|
||||||
|
magic: u16,
|
||||||
|
size: u32,
|
||||||
|
reserved_1: u16,
|
||||||
|
reserved_2: u16,
|
||||||
|
offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapInfoHeader := packed struct {
|
||||||
|
size: u32,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
planes: u16,
|
||||||
|
bits: u16,
|
||||||
|
compression: u32,
|
||||||
|
image_size: u32,
|
||||||
|
x_resolution: i32,
|
||||||
|
y_resolution: i32,
|
||||||
|
n_colours: u32,
|
||||||
|
important_colours: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
BitmapColorHeader := packed struct {
|
||||||
|
red_mask: u32,
|
||||||
|
green_mask: u32,
|
||||||
|
blue_mask: u32,
|
||||||
|
alpha_mask: u32,
|
||||||
|
color_space_type: u32,
|
||||||
|
unused: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
from := fn(bmp: ^u8): ?Surface {
|
||||||
|
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
|
||||||
|
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
|
||||||
|
|
||||||
|
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
|
||||||
|
log.error("Invalid BMP image.\0")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
lhs := Surface.(@bitcast(bmp + file_header.offset), info_header.width, info_header.height)
|
||||||
|
rhs := new_surface(info_header.width, info_header.height)
|
||||||
|
put_surface(rhs, lhs, .(0, 0), true)
|
||||||
|
|
||||||
|
return rhs
|
||||||
|
}
|
31
sysdata/libraries/render/src/image/lib.hb
Normal file
31
sysdata/libraries/render/src/image/lib.hb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
.{log} := @use("../../../stn/src/lib.hb");
|
||||||
|
.{Surface} := @use("../lib.hb")
|
||||||
|
bmp := @use("bmp.hb")
|
||||||
|
qoi := @use("qoi.hb")
|
||||||
|
$BMP := 0x4D42
|
||||||
|
$QOI := 0x66696F71
|
||||||
|
|
||||||
|
get_format := fn(file: ^u8): ?uint {
|
||||||
|
if *@as(^u16, @bitcast(file)) == BMP {
|
||||||
|
return BMP
|
||||||
|
} else if *@as(^u32, @bitcast(file)) == QOI {
|
||||||
|
return QOI
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from := fn(file: ^u8): ?Surface {
|
||||||
|
format := get_format(file)
|
||||||
|
|
||||||
|
if format == null {
|
||||||
|
log.error("Could not detect image format.\0")
|
||||||
|
return null
|
||||||
|
} else if format == BMP {
|
||||||
|
return bmp.from(file)
|
||||||
|
} else if format == QOI {
|
||||||
|
return qoi.from(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
101
sysdata/libraries/render/src/image/qoi.hb
Normal file
101
sysdata/libraries/render/src/image/qoi.hb
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
.{Color, Surface, new_surface} := @use("../lib.hb");
|
||||||
|
.{log, memory} := @use("../../../stn/src/lib.hb")
|
||||||
|
|
||||||
|
/* source:
|
||||||
|
https://github.com/phoboslab/qoi/blob/master/qoi.h */
|
||||||
|
|
||||||
|
$QOI_SRGB := 0
|
||||||
|
$QOI_LINEAR := 1
|
||||||
|
$QOI_OP_INDEX := 0x0
|
||||||
|
$QOI_OP_DIFF := 0x40
|
||||||
|
$QOI_OP_LUMA := 0x80
|
||||||
|
$QOI_OP_RUN := 0xC0
|
||||||
|
$QOI_OP_RGB := 0xFE
|
||||||
|
$QOI_OP_RGBA := 0xFF
|
||||||
|
$QOI_MASK_2 := 0xC0
|
||||||
|
QOI_COLOR_HASH := fn(c: Color): u8 {
|
||||||
|
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
|
||||||
|
}
|
||||||
|
$QOI_MAGIC := 0x716F6966
|
||||||
|
$QOI_PIXELS_MAX := 400000000
|
||||||
|
|
||||||
|
QuiteOkayHeader := packed struct {
|
||||||
|
magic: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
channels: u8,
|
||||||
|
colorspace: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
be_to_le := fn(big: u32): u32 {
|
||||||
|
return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24
|
||||||
|
}
|
||||||
|
|
||||||
|
from := fn(qoi: ^u8): ?Surface {
|
||||||
|
header := @as(^QuiteOkayHeader, @bitcast(qoi))
|
||||||
|
|
||||||
|
qoi += @sizeof(QuiteOkayHeader)
|
||||||
|
|
||||||
|
width := be_to_le(header.width)
|
||||||
|
height := be_to_le(header.height)
|
||||||
|
|
||||||
|
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
|
||||||
|
log.error("Invalid QOI image.\0")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
surface := new_surface(width, height)
|
||||||
|
index := @as([Color; 64], idk)
|
||||||
|
|
||||||
|
run := 0
|
||||||
|
px := Color.(0, 0, 0, 255)
|
||||||
|
px_pos := 0
|
||||||
|
|
||||||
|
total_pixels := width * height
|
||||||
|
|
||||||
|
loop if px_pos >= total_pixels break else {
|
||||||
|
if run > 0 {
|
||||||
|
run -= 1
|
||||||
|
} else {
|
||||||
|
b1 := *qoi
|
||||||
|
qoi += 1
|
||||||
|
|
||||||
|
if b1 == QOI_OP_RGB {
|
||||||
|
px.r = *qoi
|
||||||
|
px.g = *(qoi + 1)
|
||||||
|
px.b = *(qoi + 2)
|
||||||
|
qoi += 3
|
||||||
|
} else if b1 == QOI_OP_RGBA {
|
||||||
|
px.r = *qoi
|
||||||
|
px.g = *(qoi + 1)
|
||||||
|
px.b = *(qoi + 2)
|
||||||
|
px.a = *(qoi + 3)
|
||||||
|
qoi += 4
|
||||||
|
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
|
||||||
|
px = index[b1 & 0x3F]
|
||||||
|
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
|
||||||
|
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
|
||||||
|
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
|
||||||
|
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
|
||||||
|
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
|
||||||
|
b2 := *qoi
|
||||||
|
vg := (b1 & 0x3F) - 32
|
||||||
|
|
||||||
|
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
|
||||||
|
px.g = px.g + vg & 0xFF
|
||||||
|
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
|
||||||
|
qoi += 1
|
||||||
|
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
|
||||||
|
run = b1 & 0x3F
|
||||||
|
}
|
||||||
|
|
||||||
|
index[@inline(QOI_COLOR_HASH, px)] = px
|
||||||
|
};
|
||||||
|
|
||||||
|
*(surface.buf + px_pos) = px
|
||||||
|
|
||||||
|
px_pos += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface
|
||||||
|
}
|
|
@ -1,30 +1,38 @@
|
||||||
svga := @use("svga.hb")
|
|
||||||
software := @use("software.hb")
|
software := @use("software.hb")
|
||||||
|
image := @use("image/lib.hb")
|
||||||
|
text := @use("text.hb")
|
||||||
|
|
||||||
// default mode
|
// default mode
|
||||||
mode := software
|
mode := software
|
||||||
|
|
||||||
init := mode.init
|
init := mode.init
|
||||||
doublebuffer := mode.doublebuffer
|
doublebuffer := mode.doublebuffer
|
||||||
|
Surface := mode.Surface
|
||||||
|
new_surface := mode.new_surface
|
||||||
|
surface_from_ptr := mode.surface_from_ptr
|
||||||
|
clone_surface := mode.clone_surface
|
||||||
|
free_surface := mode.free_surface
|
||||||
|
index := mode.index
|
||||||
|
indexptr := mode.indexptr
|
||||||
|
|
||||||
// Colours
|
// Colours
|
||||||
Color := mode.Color
|
Color := packed struct {b: u8, g: u8, r: u8, a: u8}
|
||||||
white := mode.white
|
$white := Color.(255, 255, 255, 255)
|
||||||
black := mode.black
|
$black := Color.(0, 0, 0, 255)
|
||||||
gray := mode.gray
|
$gray := Color.(127, 127, 127, 255)
|
||||||
red := mode.red
|
$red := Color.(0, 0, 205, 255)
|
||||||
green := mode.green
|
$green := Color.(0, 205, 0, 255)
|
||||||
yellow := mode.yellow
|
$yellow := Color.(0, 205, 205, 255)
|
||||||
blue := mode.blue
|
$blue := Color.(205, 0, 0, 255)
|
||||||
magenta := mode.magenta
|
$magenta := Color.(205, 0, 205, 255)
|
||||||
cyan := mode.cyan
|
$cyan := Color.(205, 205, 0, 255)
|
||||||
light_gray := mode.light_gray
|
$light_gray := Color.(229, 229, 229, 255)
|
||||||
light_red := mode.light_red
|
$light_red := Color.(0, 0, 255, 255)
|
||||||
light_green := mode.light_green
|
$light_green := Color.(0, 255, 0, 255)
|
||||||
light_yellow := mode.light_yellow
|
$light_yellow := Color.(0, 255, 255, 255)
|
||||||
light_blue := mode.light_blue
|
$light_blue := Color.(255, 0, 0, 255)
|
||||||
light_magenta := mode.light_magenta
|
$light_magenta := Color.(255, 0, 255, 255)
|
||||||
light_cyan := mode.light_cyan
|
$light_cyan := Color.(255, 255, 0, 255)
|
||||||
|
|
||||||
// Drawing
|
// Drawing
|
||||||
put_pixel := mode.put_pixel
|
put_pixel := mode.put_pixel
|
||||||
|
@ -35,19 +43,12 @@ put_line := mode.put_line
|
||||||
put_vline := mode.put_vline
|
put_vline := mode.put_vline
|
||||||
put_hline := mode.put_hline
|
put_hline := mode.put_hline
|
||||||
clear := mode.clear
|
clear := mode.clear
|
||||||
put_img := mode.put_img
|
put_surface := mode.put_surface
|
||||||
|
put_text := mode.put_text
|
||||||
|
// thanks peony for these three!
|
||||||
|
put_trirect := mode.put_trirect
|
||||||
|
put_vline := mode.put_vline
|
||||||
|
put_hline := mode.put_hline
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
width := mode.width
|
|
||||||
height := mode.height
|
|
||||||
dimensions := mode.dimensions
|
|
||||||
set_height := mode.set_height
|
|
||||||
set_width := mode.set_width
|
|
||||||
set_dimensions := mode.set_dimensions
|
|
||||||
sync := mode.sync
|
sync := mode.sync
|
||||||
|
|
||||||
// Trash Image
|
|
||||||
Image := struct {
|
|
||||||
start: ^Color,
|
|
||||||
end: ^Color,
|
|
||||||
}
|
|
|
@ -1,220 +1,118 @@
|
||||||
.{math, memory} := @use("../../stn/src/lib.hb");
|
.{math, memory, dt} := @use("../../stn/src/lib.hb");
|
||||||
.{dt_get} := @use("../../dt_api/src/lib.hb");
|
.{Color, text} := @use("lib.hb");
|
||||||
.{Image} := @use("lib.hb");
|
.{get_glyph, get_glyph_unicode, Font, UNC_TABLE_SIZE} := text;
|
||||||
.{Vec2} := math
|
.{Vec2} := math
|
||||||
|
|
||||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
// safety: don't use before init() or you will get a memory access violation
|
||||||
white := Color.(255, 255, 255, 255)
|
framebuffer := memory.dangling(Color)
|
||||||
black := Color.(0, 0, 0, 255)
|
|
||||||
gray := Color.(127, 127, 127, 255)
|
|
||||||
red := Color.(0, 0, 205, 255)
|
|
||||||
green := Color.(0, 205, 0, 255)
|
|
||||||
yellow := Color.(0, 205, 205, 255)
|
|
||||||
blue := Color.(205, 0, 0, 255)
|
|
||||||
magenta := Color.(205, 0, 205, 255)
|
|
||||||
cyan := Color.(205, 205, 0, 255)
|
|
||||||
light_gray := Color.(229, 229, 229, 255)
|
|
||||||
light_red := Color.(0, 0, 255, 255)
|
|
||||||
light_green := Color.(0, 255, 0, 255)
|
|
||||||
light_yellow := Color.(0, 255, 255, 255)
|
|
||||||
light_blue := Color.(255, 0, 0, 255)
|
|
||||||
light_magenta := Color.(255, 0, 255, 255)
|
|
||||||
light_cyan := Color.(255, 255, 0, 255)
|
|
||||||
|
|
||||||
// might not work for some resolutions, but needs to be comptime because...
|
Surface := struct {
|
||||||
copy_pixels := 0xC000 >> 2
|
|
||||||
|
|
||||||
ctx := @as(Context, idk)
|
|
||||||
|
|
||||||
// some of these are redudant holdovers from fb_driver
|
|
||||||
// will keep them for future work if necessary
|
|
||||||
Context := struct {
|
|
||||||
fb: ^Color,
|
|
||||||
bb: ^Color,
|
|
||||||
buf: ^Color,
|
buf: ^Color,
|
||||||
width: int,
|
width: uint,
|
||||||
height: int,
|
height: uint,
|
||||||
partitions: int,
|
|
||||||
pixels: int,
|
|
||||||
bb_pages: int,
|
|
||||||
double_buffer: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init := fn(): void {
|
new_surface := fn(width: uint, height: uint): Surface {
|
||||||
width := dt_get("framebuffer/fb0/width\0")
|
return .(
|
||||||
height := dt_get("framebuffer/fb0/height\0")
|
@inline(memory.alloc, Color, width * height),
|
||||||
pixels := width * height
|
|
||||||
bytes := pixels << 2
|
|
||||||
partitions := pixels / copy_pixels
|
|
||||||
pages := 1 + bytes >> 12
|
|
||||||
back_buffer := create_back_buffer(pages)
|
|
||||||
ctx = Context.{
|
|
||||||
fb: dt_get("framebuffer/fb0/ptr\0"),
|
|
||||||
bb: back_buffer,
|
|
||||||
buf: back_buffer,
|
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
partitions,
|
)
|
||||||
pixels,
|
|
||||||
bb_pages: pages,
|
|
||||||
double_buffer: true,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doublebuffer := fn(enable: bool): void {
|
clone_surface := fn(surface: ^Surface): Surface {
|
||||||
if enable {
|
new := new_surface(surface.width, surface.height)
|
||||||
ctx.buf = ctx.bb
|
@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
|
||||||
|
return new
|
||||||
|
}
|
||||||
|
|
||||||
|
init := fn(doublebuffer: bool): Surface {
|
||||||
|
framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
|
||||||
|
width := dt.get(uint, "framebuffer/fb0/width\0")
|
||||||
|
height := dt.get(uint, "framebuffer/fb0/height\0")
|
||||||
|
if doublebuffer {
|
||||||
|
return new_surface(width, height)
|
||||||
} else {
|
} else {
|
||||||
ctx.buf = ctx.fb
|
return .(framebuffer, width, height)
|
||||||
}
|
}
|
||||||
ctx.double_buffer = enable
|
}
|
||||||
|
|
||||||
|
clear := fn(surface: Surface, color: Color): void {
|
||||||
|
return @inline(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))
|
||||||
|
}
|
||||||
|
|
||||||
|
index := fn(surface: Surface, x: uint, y: uint): uint {
|
||||||
|
return x + surface.width * y
|
||||||
|
}
|
||||||
|
|
||||||
|
indexptr := fn(surface: Surface, x: uint, y: uint): ^Color {
|
||||||
|
return surface.buf + @inline(index, surface, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
put_pixel := fn(surface: Surface, pos: Vec2(uint), color: Color): void {
|
||||||
|
*@inline(indexptr, surface, pos.x, pos.y) = color
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
create_back_buffer := fn(pages: int): ^Color {
|
put_filled_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
||||||
if pages <= 0xFF {
|
top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
|
||||||
return @bitcast(@inline(memory.request_page, pages))
|
bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
|
||||||
}
|
rows_to_fill := tr.y
|
||||||
ptr := @inline(memory.request_page, 255)
|
|
||||||
remaining := pages - 0xFF
|
loop if rows_to_fill <= 1 break else {
|
||||||
loop if remaining <= 0 break else {
|
@inline(memory.set, Color, &color, top_start_idx, tr.x)
|
||||||
if remaining < 0xFF {
|
@inline(memory.set, Color, &color, bottom_start_idx, tr.x)
|
||||||
memory.request_page(remaining)
|
|
||||||
} else {
|
top_start_idx += surface.width
|
||||||
memory.request_page(0xFF)
|
bottom_start_idx -= surface.width
|
||||||
}
|
rows_to_fill -= 2
|
||||||
remaining -= 0xFF
|
|
||||||
}
|
|
||||||
return @bitcast(ptr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear := fn(color: Color): void {
|
if rows_to_fill == 1 {
|
||||||
cursor := ctx.buf
|
@inline(memory.set, Color, &color, top_start_idx, tr.x)
|
||||||
boundary := cursor + 512
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*cursor = color
|
|
||||||
cursor += 1
|
|
||||||
}
|
|
||||||
boundary += 512 * 7
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(ctx.buf))
|
|
||||||
cursor += 512
|
|
||||||
}
|
|
||||||
boundary += copy_pixels - 4096
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(ctx.buf))
|
|
||||||
cursor += 4096
|
|
||||||
}
|
|
||||||
boundary += (ctx.partitions - 1) * copy_pixels
|
|
||||||
loop if cursor == boundary break else {
|
|
||||||
*@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(ctx.buf))
|
|
||||||
cursor += @sizeof([u8; copy_pixels])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sync := fn(): void {
|
|
||||||
if ctx.double_buffer {
|
|
||||||
bb := ctx.buf
|
|
||||||
fb := ctx.fb
|
|
||||||
boundary := bb + ctx.pixels
|
|
||||||
loop if bb >= boundary break else {
|
|
||||||
*@as(^[Color; copy_pixels], @bitcast(fb)) = *@as(^[Color; copy_pixels], @bitcast(bb))
|
|
||||||
bb += copy_pixels
|
|
||||||
fb += copy_pixels
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
width := fn(): int {
|
|
||||||
return ctx.width
|
|
||||||
}
|
|
||||||
|
|
||||||
height := fn(): int {
|
|
||||||
return ctx.height
|
|
||||||
}
|
|
||||||
|
|
||||||
screenidx := fn(x: int, y: int): int {
|
|
||||||
/*if x < 0 || y < 0 || x >= ctx.width || y >= ctx.height {
|
|
||||||
return -1
|
|
||||||
}*/
|
|
||||||
return x + ctx.width * y
|
|
||||||
}
|
|
||||||
|
|
||||||
put_pixel := fn(pos: Vec2(int), color: Color): void {
|
|
||||||
*(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
|
||||||
x := pos.x
|
|
||||||
y := pos.y
|
|
||||||
end := pos + tr
|
|
||||||
loop if x == end.x break else {
|
|
||||||
loop if y == end.y break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
x += 1
|
|
||||||
y = pos.y
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
|
||||||
x := pos.x
|
|
||||||
y := pos.y
|
|
||||||
end := pos + tr
|
|
||||||
loop if y == end.y break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
|
||||||
*(ctx.buf + @inline(screenidx, x + tr.x, y)) = color
|
|
||||||
y += 1
|
|
||||||
}
|
|
||||||
y = pos.y
|
|
||||||
loop if x == end.x break else {
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color;
|
|
||||||
*(ctx.buf + @inline(screenidx, x, y + tr.y)) = color
|
|
||||||
x += 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
|
|
||||||
step := Vec2(int).(1, 1)
|
|
||||||
if size.x < 0 {
|
|
||||||
step.x = -1
|
|
||||||
}
|
|
||||||
if size.y < 0 {
|
|
||||||
step.y = size.y / size.x
|
|
||||||
}
|
|
||||||
|
|
||||||
start_y := pos.y
|
|
||||||
target := pos + size
|
|
||||||
|
|
||||||
loop if pos.x == target.x break else {
|
|
||||||
put_vline(pos.x, pos.y, target.y, color0)
|
|
||||||
put_vline(pos.x, pos.y, start_y, color1)
|
|
||||||
pos += step
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
put_rect := fn(surface: Surface, pos: Vec2(uint), tr: Vec2(uint), color: Color): void {
|
||||||
dx := p1.x - p0.x
|
start_idx := @inline(indexptr, surface, pos.x, pos.y)
|
||||||
dy := p1.y - p0.y
|
end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
|
||||||
|
right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
|
||||||
|
|
||||||
|
loop if start_idx > end_idx break else {
|
||||||
|
*start_idx = color;
|
||||||
|
*right_start_idx = color
|
||||||
|
start_idx += surface.width
|
||||||
|
right_start_idx += surface.width
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
|
||||||
|
@inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
put_line_low := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
||||||
|
dx := @as(int, @bitcast(p1.x - p0.x))
|
||||||
|
dy := @as(int, @bitcast(p1.y - p0.y))
|
||||||
yi := 1
|
yi := 1
|
||||||
if dy < 0 {
|
if dy < 0 {
|
||||||
yi = -1
|
yi = -1
|
||||||
dy = -dy
|
dy = -dy
|
||||||
}
|
}
|
||||||
D := 2 * dy - dx
|
D := @as(int, 2) * dy - dx
|
||||||
y := p0.y
|
y := p0.y
|
||||||
x := p0.x
|
x := p0.x
|
||||||
loop if x == p1.x break else {
|
loop if x == p1.x break else {
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
*@inline(indexptr, surface, x, y) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
y += yi
|
y += yi
|
||||||
D += 2 * (dy - dx)
|
D += 2 * (dy - dx)
|
||||||
|
@ -226,19 +124,19 @@ put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
put_line_high := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
||||||
dx := p1.x - p0.x
|
dx := @as(int, @bitcast(p1.x - p0.x))
|
||||||
dy := p1.y - p0.y
|
dy := @as(int, @bitcast(p1.y - p0.y))
|
||||||
xi := 1
|
xi := 1
|
||||||
if dy < 0 {
|
if dy < 0 {
|
||||||
xi = -1
|
xi = -1
|
||||||
dx = -dx
|
dx = -dx
|
||||||
}
|
}
|
||||||
D := 2 * dx - dy
|
D := @as(int, 2) * dx - dy
|
||||||
x := p0.x
|
x := p0.x
|
||||||
y := p0.y
|
y := p0.y
|
||||||
loop if y == p1.y break else {
|
loop if y == p1.y break else {
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
*@inline(indexptr, surface, x, y) = color
|
||||||
if D > 0 {
|
if D > 0 {
|
||||||
x += xi
|
x += xi
|
||||||
D += 2 * (dx - dy)
|
D += 2 * (dx - dy)
|
||||||
|
@ -250,24 +148,83 @@ put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_line := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
put_line := fn(surface: Surface, p0: Vec2(uint), p1: Vec2(uint), color: Color): void {
|
||||||
if math.abs(int, p1.y - p0.y) < math.abs(int, p1.x - p0.x) {
|
if math.abs(uint, p1.y - p0.y) < math.abs(uint, p1.x - p0.x) {
|
||||||
if p0.x > p1.x {
|
if p0.x > p1.x {
|
||||||
@inline(put_line_low, p1, p0, color)
|
@inline(put_line_low, surface, p1, p0, color)
|
||||||
} else {
|
} else {
|
||||||
@inline(put_line_low, p0, p1, color)
|
@inline(put_line_low, surface, p0, p1, color)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if p0.y > p1.y {
|
if p0.y > p1.y {
|
||||||
@inline(put_line_high, p1, p0, color)
|
@inline(put_line_high, surface, p1, p0, color)
|
||||||
} else {
|
} else {
|
||||||
@inline(put_line_high, p0, p1, color)
|
@inline(put_line_high, surface, p0, p1, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
|
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(uint), flip_v: bool): void {
|
||||||
|
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_increment := surface.width
|
||||||
|
|
||||||
|
if flip_v {
|
||||||
|
dst_increment = -dst_increment
|
||||||
|
tmp := dst_top_idx
|
||||||
|
dst_top_idx = dst_bottom_idx
|
||||||
|
dst_bottom_idx = tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
rows_to_copy := top.height
|
||||||
|
|
||||||
|
loop if rows_to_copy <= 1 break else {
|
||||||
|
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
|
||||||
|
@inline(memory.copy, Color, src_bottom_cursor, dst_bottom_idx, top.width)
|
||||||
|
|
||||||
|
dst_top_idx += dst_increment
|
||||||
|
dst_bottom_idx -= dst_increment
|
||||||
|
src_top_cursor += top.width
|
||||||
|
src_bottom_cursor -= top.width
|
||||||
|
rows_to_copy -= 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if rows_to_copy == 1 {
|
||||||
|
@inline(memory.copy, Color, src_top_cursor, dst_top_idx, top.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// peony-made
|
||||||
|
put_trirect := fn(surface: Surface, pos: Vec2(uint), size: Vec2(int), color0: Color, color1: Color): void {
|
||||||
|
step := Vec2(int).(1, 1)
|
||||||
|
if size.x < 0 {
|
||||||
|
step.x = -1
|
||||||
|
}
|
||||||
|
if size.y < 0 {
|
||||||
|
step.y /= @bitcast(size.x)
|
||||||
|
}
|
||||||
|
|
||||||
|
start_y := pos.y
|
||||||
|
target := pos + @bitcast(size)
|
||||||
|
|
||||||
|
loop if pos.x == target.x break else {
|
||||||
|
@inline(put_vline, surface, pos.x, pos.y, target.y, color0)
|
||||||
|
@inline(put_vline, surface, pos.x, pos.y, start_y, color1)
|
||||||
|
pos += @bitcast(step)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// peony-made
|
||||||
|
put_vline := fn(surface: Surface, x: uint, y0: uint, y1: uint, color: Color): void {
|
||||||
if y1 < y0 {
|
if y1 < y0 {
|
||||||
tmp := y0
|
tmp := y0
|
||||||
y0 = y1
|
y0 = y1
|
||||||
|
@ -276,45 +233,157 @@ put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
|
||||||
y := y0
|
y := y0
|
||||||
|
|
||||||
loop if y == y1 break else {
|
loop if y == y1 break else {
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
*@inline(indexptr, surface, x, y) = color
|
||||||
y += 1
|
y += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
|
// peony-made
|
||||||
|
put_hline := fn(surface: Surface, y: uint, x0: uint, x1: uint, color: Color): void {
|
||||||
if x1 < x0 {
|
if x1 < x0 {
|
||||||
tmp := x0
|
tmp := x0
|
||||||
x0 = x1
|
x0 = x1
|
||||||
x1 = tmp
|
x1 = tmp
|
||||||
}
|
}
|
||||||
x := x0
|
@inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
|
||||||
|
|
||||||
loop if x == x1 break else {
|
return
|
||||||
*(ctx.buf + @inline(screenidx, x, y)) = color
|
}
|
||||||
x += 1
|
utf8_len_table := [u8].(0, 0, 2, 3)
|
||||||
|
|
||||||
|
put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str: ^u8): void {
|
||||||
|
cursor := Vec2(uint).(pos.x, pos.y)
|
||||||
|
|
||||||
|
max_y := surface.height - font.height
|
||||||
|
next_line_y := font.height + font.line_gap
|
||||||
|
char_advance := font.width + font.char_gap
|
||||||
|
surface_width := surface.width
|
||||||
|
|
||||||
|
loop if *str == 0 break else {
|
||||||
|
if cursor.y > max_y break
|
||||||
|
|
||||||
|
glyph_data := @as(^u8, idk)
|
||||||
|
code_point := @as(uint, 0)
|
||||||
|
|
||||||
|
if (*str & 0x80) == 0 {
|
||||||
|
if *str == 10 {
|
||||||
|
cursor.x = pos.x
|
||||||
|
cursor.y += next_line_y
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if font.unicode == null {
|
||||||
|
if *str > font.num_glyphs {
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
glyph_data = @inline(get_glyph, font, *str)
|
||||||
|
} else {
|
||||||
|
if *str < UNC_TABLE_SIZE {
|
||||||
|
glyph_index := *(font.unicode + *str)
|
||||||
|
if glyph_index == 0xFFFF {
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
glyph_data = font.data + glyph_index * font.bytes_per_glyph
|
||||||
|
} else {
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str += 1
|
||||||
|
} else if font.unicode != null {
|
||||||
|
first_byte := *str
|
||||||
|
num_bytes := @as(uint, 0)
|
||||||
|
|
||||||
|
num_bytes = utf8_len_table[first_byte >> 5 & 0x3]
|
||||||
|
|
||||||
|
if num_bytes == 0 {
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
code_point = first_byte & (0x7F >> num_bytes | 0x1F)
|
||||||
|
|
||||||
|
valid_sequence := true
|
||||||
|
bytes_processed := 1
|
||||||
|
|
||||||
|
loop if bytes_processed >= num_bytes break else {
|
||||||
|
str += 1
|
||||||
|
if *str == 0 | (*str & 0xC0) != 0x80 {
|
||||||
|
valid_sequence = false
|
||||||
|
}
|
||||||
|
if valid_sequence == false {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
code_point = code_point << 6 | *str & 0x3F
|
||||||
|
bytes_processed += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if valid_sequence == false {
|
||||||
|
str += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
str += 1
|
||||||
|
|
||||||
|
if code_point == 10 {
|
||||||
|
cursor.x = pos.x
|
||||||
|
cursor.y += next_line_y
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if code_point >= UNC_TABLE_SIZE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
glyph_index := *(font.unicode + code_point)
|
||||||
|
if glyph_index == 0xFFFF {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
glyph_data = font.data + glyph_index * font.bytes_per_glyph
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursor.x + font.width >= surface_width {
|
||||||
|
cursor.x = pos.x
|
||||||
|
cursor.y += next_line_y
|
||||||
|
}
|
||||||
|
|
||||||
|
dest := @inline(indexptr, surface, cursor.x, cursor.y)
|
||||||
|
rows := font.height
|
||||||
|
|
||||||
|
loop if rows == 0 break else {
|
||||||
|
byte := *glyph_data
|
||||||
|
pixel_dest := dest
|
||||||
|
mask := @as(u8, 0x80)
|
||||||
|
bits := font.width
|
||||||
|
|
||||||
|
loop if bits == 0 break else {
|
||||||
|
if (byte & mask) != 0 {
|
||||||
|
*pixel_dest = color
|
||||||
|
}
|
||||||
|
pixel_dest += 1
|
||||||
|
mask >>= 1
|
||||||
|
if mask == 0 & bits > 0 {
|
||||||
|
glyph_data += 1
|
||||||
|
byte = *glyph_data
|
||||||
|
mask = 0x80
|
||||||
|
}
|
||||||
|
bits -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if mask != 0x80 {
|
||||||
|
glyph_data += 1
|
||||||
|
}
|
||||||
|
dest += surface_width
|
||||||
|
rows -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.x += char_advance
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
set_height := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_width := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dimensions := fn(): Vec2(int) {
|
|
||||||
return .(ctx.width, ctx.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dimensions := fn(new: Vec2(int)): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_img := fn(img: Image, pos: Vec2(int)): void {
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
.{Vec2, Image} := @use("lib.hb")
|
|
||||||
// .{pci, memory, string, log} := @use("../../stn/src/lib.hb");
|
|
||||||
|
|
||||||
Color := struct {b: u8, g: u8, r: u8, a: u8}
|
|
||||||
white := Color.(255, 255, 255, 255)
|
|
||||||
black := Color.(0, 0, 0, 255)
|
|
||||||
gray := Color.(127, 127, 127, 255)
|
|
||||||
red := Color.(0, 0, 205, 255)
|
|
||||||
green := Color.(0, 205, 0, 255)
|
|
||||||
yellow := Color.(0, 205, 205, 255)
|
|
||||||
blue := Color.(205, 0, 0, 255)
|
|
||||||
magenta := Color.(205, 0, 205, 255)
|
|
||||||
cyan := Color.(205, 205, 0, 255)
|
|
||||||
light_gray := Color.(229, 229, 229, 255)
|
|
||||||
light_red := Color.(0, 0, 255, 255)
|
|
||||||
light_green := Color.(0, 255, 0, 255)
|
|
||||||
light_yellow := Color.(0, 255, 255, 255)
|
|
||||||
light_blue := Color.(255, 0, 0, 255)
|
|
||||||
light_magenta := Color.(255, 0, 255, 255)
|
|
||||||
light_cyan := Color.(255, 255, 0, 255)
|
|
||||||
|
|
||||||
clear := fn(color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
width := fn(): int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
height := fn(): int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
dimensions := fn(): Vec2(int) {
|
|
||||||
return .(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
put_pixel := fn(position: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// do not use, use line() instead
|
|
||||||
put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_line := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_height := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_width := fn(new: int): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dimensions := fn(new: Vec2(int)): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sync := fn(): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
init := fn(): void {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
put_img := fn(img: Image, pos: Vec2(int)): void {
|
|
||||||
return
|
|
||||||
}
|
|
162
sysdata/libraries/render/src/text.hb
Normal file
162
sysdata/libraries/render/src/text.hb
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
.{log, memory} := @use("../../stn/src/lib.hb")
|
||||||
|
|
||||||
|
PSF1Header := packed struct {
|
||||||
|
magic: u16,
|
||||||
|
font_mode: u8,
|
||||||
|
character_size: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
PSF2Header := packed struct {
|
||||||
|
magic: u32,
|
||||||
|
version: u32,
|
||||||
|
header_size: u32,
|
||||||
|
flags: u32,
|
||||||
|
num_glyph: u32,
|
||||||
|
bytes_per_glyph: u32,
|
||||||
|
height: u32,
|
||||||
|
width: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
Font := struct {
|
||||||
|
data: ^u8,
|
||||||
|
width: uint,
|
||||||
|
height: uint,
|
||||||
|
num_glyphs: uint,
|
||||||
|
bytes_per_glyph: uint,
|
||||||
|
line_gap: uint,
|
||||||
|
char_gap: uint,
|
||||||
|
unicode: ?^u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
font_from_psf1 := fn(psf: ^u8): ?Font {
|
||||||
|
header := @as(^PSF1Header, @bitcast(psf))
|
||||||
|
if header.magic != 0x436 {
|
||||||
|
log.error("failed to load psf font: not a psf1 font, idiot\0")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
psf += @sizeof(PSF1Header)
|
||||||
|
|
||||||
|
return .(
|
||||||
|
psf,
|
||||||
|
8,
|
||||||
|
header.character_size,
|
||||||
|
256,
|
||||||
|
header.character_size,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
|
||||||
|
header := @as(^PSF2Header, @bitcast(psf))
|
||||||
|
if header.magic != 0x864AB572 {
|
||||||
|
log.error("failed to load psf font: not a psf2 font, idiot\0")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
psf += header.header_size
|
||||||
|
|
||||||
|
font := Font.(
|
||||||
|
psf,
|
||||||
|
header.width,
|
||||||
|
header.height,
|
||||||
|
header.num_glyph,
|
||||||
|
header.bytes_per_glyph,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
if (header.flags & 1) != 0 & unicode {
|
||||||
|
init_unicode(&font)
|
||||||
|
}
|
||||||
|
return font
|
||||||
|
}
|
||||||
|
|
||||||
|
get_glyph := fn(font: Font, index: u8): ^u8 {
|
||||||
|
return font.data + @as(uint, index) * font.bytes_per_glyph
|
||||||
|
}
|
||||||
|
|
||||||
|
UNC_TABLE_SIZE := 1 << 16
|
||||||
|
|
||||||
|
init_unicode := fn(font: ^Font): void {
|
||||||
|
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
|
||||||
|
|
||||||
|
@inline(memory.set, u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
|
||||||
|
|
||||||
|
table := font.data + font.num_glyphs * font.bytes_per_glyph
|
||||||
|
curr_glyph := @as(u16, 0)
|
||||||
|
|
||||||
|
loop if curr_glyph >= font.num_glyphs break else {
|
||||||
|
loop {
|
||||||
|
byte := *table
|
||||||
|
table += 1
|
||||||
|
|
||||||
|
if byte == 0xFF break
|
||||||
|
if byte == 0xFE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
unicode := @as(uint, 0)
|
||||||
|
bytes_to_read := @as(uint, 1)
|
||||||
|
|
||||||
|
if (byte & 0x80) == 0 {
|
||||||
|
unicode = byte
|
||||||
|
} else if (byte & 0xE0) == 0xC0 {
|
||||||
|
unicode = byte & 0x1F
|
||||||
|
bytes_to_read = 2
|
||||||
|
} else if (byte & 0xF0) == 0xE0 {
|
||||||
|
unicode = byte & 0xF
|
||||||
|
bytes_to_read = 3
|
||||||
|
} else if (byte & 0xF8) == 0xF0 {
|
||||||
|
unicode = byte & 0x7
|
||||||
|
bytes_to_read = 4
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
valid := true
|
||||||
|
loop if bytes_to_read <= 1 break else {
|
||||||
|
next_byte := *table
|
||||||
|
if (next_byte & 0xC0) != 0x80 {
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
|
if valid == false {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
unicode = unicode << 6 | next_byte & 0x3F
|
||||||
|
table += 1
|
||||||
|
bytes_to_read -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if valid == false continue
|
||||||
|
|
||||||
|
if bytes_to_read == 4 {
|
||||||
|
if unicode < 0x10000 | unicode > 0x10FFFF continue
|
||||||
|
|
||||||
|
if unicode <= 0xFFFF {
|
||||||
|
if unicode < UNC_TABLE_SIZE {
|
||||||
|
*(@unwrap(font.unicode) + unicode) = curr_glyph
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unicode -= 0x10000
|
||||||
|
high_surrogate := 0xD800 | unicode >> 10 & 0x3FF
|
||||||
|
low_surrogate := 0xDC00 | unicode & 0x3FF
|
||||||
|
|
||||||
|
if high_surrogate < UNC_TABLE_SIZE {
|
||||||
|
*(@unwrap(font.unicode) + high_surrogate) = curr_glyph
|
||||||
|
}
|
||||||
|
if low_surrogate < UNC_TABLE_SIZE {
|
||||||
|
*(@unwrap(font.unicode) + low_surrogate) = curr_glyph
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if unicode < UNC_TABLE_SIZE {
|
||||||
|
*(@unwrap(font.unicode) + unicode) = curr_glyph
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr_glyph += 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +1,27 @@
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
|
|
||||||
recv := fn(buffer_id: int, memory_map_location: ^u8, length: int): ^u8 {
|
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): void {
|
||||||
|
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
write := fn($Expr: type, msg: ^Expr, buffer_id: int): void {
|
||||||
|
return @eca(3, buffer_id, msg, @sizeof(Expr))
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_length := fn(buffer_id: int, memory_map_location: ^u8, length: int): void {
|
||||||
return @eca(4, buffer_id, memory_map_location, length)
|
return @eca(4, buffer_id, memory_map_location, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
write := fn(msg: ^u8, buffer_id: int, length: int): void {
|
write_length := fn(msg: ^u8, buffer_id: int, length: int): void {
|
||||||
return @eca(3, buffer_id, msg, length)
|
return @eca(3, buffer_id, msg, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferMsg := packed struct {operation: u8, msg: ^u8, msg_len: uint}
|
||||||
|
|
||||||
create := fn(msg: ^u8): int {
|
create := fn(msg: ^u8): int {
|
||||||
msg_length := @inline(string.length, msg);
|
return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
||||||
*msg = 0
|
|
||||||
return @eca(3, 0, msg, msg_length)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
search := fn(msg: ^u8): int {
|
search := fn(msg: ^u8): int {
|
||||||
msg_length := @inline(string.length, msg);
|
return @eca(3, 0, BufferMsg.(3, msg, @inline(string.length, msg)), @sizeof(BufferMsg))
|
||||||
*msg = 3
|
|
||||||
|
|
||||||
return @eca(3, 0, msg, msg_length)
|
|
||||||
}
|
}
|
5
sysdata/libraries/stn/src/dt.hb
Normal file
5
sysdata/libraries/stn/src/dt.hb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.{string} := @use("../../stn/src/lib.hb")
|
||||||
|
|
||||||
|
get := fn($Expr: type, query: ^u8): Expr {
|
||||||
|
return @eca(3, 5, query, @inline(string.length, query))
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
acs := @use("acs.hb")
|
acs := @use("acs.hb")
|
||||||
|
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
log := @use("log.hb")
|
log := @use("log.hb")
|
||||||
memory := @use("memory.hb")
|
memory := @use("memory.hb")
|
||||||
|
@ -7,3 +6,14 @@ buffer := @use("buffer.hb")
|
||||||
math := @use("math.hb")
|
math := @use("math.hb")
|
||||||
random := @use("random.hb")
|
random := @use("random.hb")
|
||||||
file := @use("file_io.hb")
|
file := @use("file_io.hb")
|
||||||
|
dt := @use("dt.hb")
|
||||||
|
|
||||||
|
panic := fn(message: ?^u8): never {
|
||||||
|
log.error("Error: Panic Called, Message:\0")
|
||||||
|
if message == null {
|
||||||
|
log.error("None\0")
|
||||||
|
} else {
|
||||||
|
log.error(message)
|
||||||
|
}
|
||||||
|
die
|
||||||
|
}
|
|
@ -1,15 +1,13 @@
|
||||||
string := @use("string.hb")
|
string := @use("string.hb")
|
||||||
buffer := @use("buffer.hb")
|
|
||||||
|
|
||||||
log := fn(message: ^u8, level: u8): void {
|
LogMsg := packed struct {level: u8, string: ^u8, strlen: uint}
|
||||||
message_length := @inline(string.length, message);
|
|
||||||
*(message + message_length) = level
|
|
||||||
|
|
||||||
return @eca(3, 1, message, message_length + 1)
|
log := fn(level: u8, message: ^u8): void {
|
||||||
|
return @eca(3, 1, LogMsg.(level, message, @inline(string.length, message)), @sizeof(LogMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
error := fn(message: ^u8): void return log(message, 0)
|
error := fn(message: ^u8): void return @inline(log, 0, message)
|
||||||
warn := fn(message: ^u8): void return log(message, 1)
|
warn := fn(message: ^u8): void return @inline(log, 1, message)
|
||||||
info := fn(message: ^u8): void return log(message, 2)
|
info := fn(message: ^u8): void return @inline(log, 2, message)
|
||||||
debug := fn(message: ^u8): void return log(message, 3)
|
debug := fn(message: ^u8): void return @inline(log, 3, message)
|
||||||
trace := fn(message: ^u8): void return log(message, 4)
|
trace := fn(message: ^u8): void return @inline(log, 4, message)
|
File diff suppressed because one or more lines are too long
|
@ -1,39 +1,71 @@
|
||||||
request_page := fn(page_count: u8): ^u8 {
|
PAGE_SIZE := 4096
|
||||||
msg := "\{00}\{01}xxxxxxxx\0"
|
MAX_ALLOC := 0xFF
|
||||||
msg_page_count := msg + 1;
|
MAX_FREE := 0xFF
|
||||||
*msg_page_count = page_count
|
|
||||||
return @eca(3, 2, msg, 12)
|
dangling := fn($Expr: type): ^Expr {
|
||||||
|
return @bitcast(@alignof(Expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
release_page := fn(ptr: ^u8, page_count: u8): void {
|
calc_pages := fn($Expr: type, num: uint): uint {
|
||||||
msg := "\{01}\{00}xxxxxxxx\0"
|
return 1 + @sizeof(Expr) * num / PAGE_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
msg_page_count := msg + 1;
|
alloc := fn($Expr: type, num: uint): ^Expr {
|
||||||
*msg_page_count = page_count
|
pages := @inline(calc_pages, Expr, num)
|
||||||
|
if pages <= MAX_ALLOC {
|
||||||
|
return @bitcast(request_page(@intcast(pages)))
|
||||||
|
}
|
||||||
|
ptr := request_page(0xFF)
|
||||||
|
remaining := pages - MAX_ALLOC
|
||||||
|
loop if remaining < MAX_ALLOC break else {
|
||||||
|
_ = request_page(@intcast(MAX_ALLOC))
|
||||||
|
remaining -= MAX_ALLOC
|
||||||
|
}
|
||||||
|
_ = request_page(@intcast(remaining))
|
||||||
|
return @bitcast(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
msg_ptr := @as(^^u8, @bitcast(msg + 2));
|
// ! stub
|
||||||
*msg_ptr = ptr
|
free := fn($Expr: type, ptr: ^Expr, num: uint, nullify: bool): void {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return @eca(3, 2, msg, 12)
|
RqPageMsg := packed struct {a: u8, count: u8}
|
||||||
|
request_page := fn(count: u8): ^u8 {
|
||||||
|
return @eca(3, 2, &RqPageMsg.(0, count), @sizeof(RqPageMsg))
|
||||||
|
}
|
||||||
|
|
||||||
|
RlPageMsg := packed struct {a: u8, count: u8, ptr: ^u8}
|
||||||
|
release_page := fn(ptr: ^u8, count: u8): void {
|
||||||
|
return @eca(3, 2, &RlPageMsg.(1, count, ptr), @sizeof(RlPageMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
|
OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8}
|
||||||
InbMsg := packed struct {a: u8, b: u8, addr: u16}
|
|
||||||
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
|
|
||||||
InlMsg := packed struct {a: u8, b: u8, addr: u16}
|
|
||||||
|
|
||||||
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}
|
||||||
inb := fn(addr: u16): u8 {
|
inb := fn(addr: u16): u8 {
|
||||||
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32}
|
||||||
outl := fn(addr: u16, value: u32): void {
|
outl := fn(addr: u16, value: u32): void {
|
||||||
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InlMsg := packed struct {a: u8, b: u8, addr: u16}
|
||||||
inl := fn(addr: u16): u32 {
|
inl := fn(addr: u16): u32 {
|
||||||
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CopyMsg := packed struct {a: u8, count: u32, src: ^u8, dest: ^u8}
|
||||||
|
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
||||||
|
return @eca(3, 2, &CopyMsg.(4, @intcast(count * @sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMsg := packed struct {a: u8, count: u32, size: u32, src: ^u8, dest: ^u8}
|
||||||
|
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
|
||||||
|
return @eca(3, 2, &SetMsg.(5, @intcast(count), @intcast(@sizeof(Expr)), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
any := fn($Expr: type): Expr {
|
any := fn($Expr: type): Expr {
|
||||||
return @intcast(@eca(3, 4))
|
return *@eca(3, 4, &@as(Expr, idk), @sizeof(Expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
range := fn($Expr: type, min: Expr, max: Expr): Expr {
|
range := fn($Expr: type, min: Expr, max: Expr): Expr {
|
||||||
return @eca(3, 4) % (max - min + 1) + min
|
return @inline(any, Expr) % (max - min) + @intcast(1) + min
|
||||||
}
|
}
|
|
@ -1,42 +1,64 @@
|
||||||
length := fn(ptr: ^u8): int {
|
length := fn(ptr: ^u8): uint {
|
||||||
len := 0
|
len := 0
|
||||||
loop if *(ptr + len) == 0 break else len += 1
|
loop if *(ptr + len) == 0 return len else len += 1
|
||||||
return len
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WTFFF is wrong with display_int
|
display_int := fn(num: int, p: ^u8, radix: uint): ^u8 {
|
||||||
display_int := fn(num: int, p: ^u8): ^u8 {
|
|
||||||
ptr := p
|
ptr := p
|
||||||
negative := num < 0
|
negative := num < 0
|
||||||
if negative {
|
if negative {
|
||||||
num = -num
|
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 = 48
|
||||||
ptr += 1
|
ptr += 1
|
||||||
} else {
|
} else {
|
||||||
loop if num == 0 break else {
|
loop if num == 0 break else {
|
||||||
*ptr = num % 10 + 48
|
digit := num % @bitcast(radix)
|
||||||
|
if digit < 10 {
|
||||||
|
*ptr = @intcast(digit) + 48
|
||||||
|
} else {
|
||||||
|
*ptr = @intcast(digit) + 55
|
||||||
|
}
|
||||||
ptr += 1
|
ptr += 1
|
||||||
num /= 10
|
num /= @bitcast(radix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if negative {
|
if negative {
|
||||||
*ptr = 45
|
*ptr = 45
|
||||||
ptr += 1
|
ptr += 1
|
||||||
};
|
};
|
||||||
|
|
||||||
*ptr = 0
|
*ptr = 0
|
||||||
@inline(reverse, p)
|
|
||||||
|
@inline(reverse, digits_start)
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse := fn(s: ^u8): void {
|
reverse := fn(s: ^u8): void {
|
||||||
//reverse a string, don't remove digits
|
|
||||||
len := 0
|
|
||||||
loop if *(s + len) == 0 break else len += 1
|
|
||||||
i := 0
|
i := 0
|
||||||
j := len - 1
|
j := @inline(length, s) - 1
|
||||||
temp := 0
|
temp := @as(u8, 0)
|
||||||
loop if i >= j break else {
|
loop if i >= j break else {
|
||||||
temp = *(s + i);
|
temp = *(s + i);
|
||||||
*(s + i) = *(s + j);
|
*(s + i) = *(s + j);
|
||||||
|
@ -46,3 +68,54 @@ reverse := fn(s: ^u8): void {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
equals := fn(lhs: ^u8, rhs: ^u8): bool {
|
||||||
|
if lhs == rhs {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
loop if *(lhs + i) != *(rhs + i) {
|
||||||
|
return false
|
||||||
|
} else if *lhs == 0 {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
i += 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,14 +1,13 @@
|
||||||
dt_api := @use("../../../libraries/dt_api/src/lib.hb");
|
.{dt} := @use("../../../libraries/stn/src/lib.hb")
|
||||||
.{dt_get} := dt_api
|
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): void {
|
||||||
dt_api.dt_get("framebuffer/fb0/width\0")
|
dt.get(void, "framebuffer/fb0/width\0")
|
||||||
dt_api.dt_get("cpu/cpu0/architecture\0")
|
dt.get(void, "cpu/cpu0/architecture\0")
|
||||||
|
|
||||||
// Checking if the first detected serial port is memory mapped or port mapped
|
// Checking if the first detected serial port is memory mapped or port mapped
|
||||||
// 0 -> memory mapped
|
// 0 -> memory mapped
|
||||||
// 1 -> port mapped
|
// 1 -> port mapped
|
||||||
dt_get("serial_ports/sp0/mapping\0")
|
dt.get(void, "serial_ports/sp0/mapping\0")
|
||||||
|
|
||||||
return 0
|
return
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
READ_ONLY := 0x1
|
READ_ONLY := @as(u32, 0x1)
|
||||||
HIDDEN := 0x2
|
HIDDEN := @as(u32, 0x2)
|
||||||
SYSTEM := 0x4
|
SYSTEM := @as(u32, 0x4)
|
||||||
VOLUME_ID := 0x8
|
VOLUME_ID := @as(u32, 0x8)
|
||||||
DIRECTORY := 0x10
|
DIRECTORY := @as(u32, 0x10)
|
||||||
ARCHIVE := 0x20
|
ARCHIVE := @as(u32, 0x20)
|
||||||
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID
|
LFN := READ_ONLY | HIDDEN | SYSTEM | VOLUME_ID
|
|
@ -9,8 +9,7 @@ OemIdent := struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
new_oem_ident := fn(major: int, minor: int): OemIdent {
|
new_oem_ident := fn(major: int, minor: int): OemIdent {
|
||||||
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
|
return .(.(0, 0, 0, 0, 0, 0, 0, 0), .(0, 0, 0, 0, 0, 0, 0, 0))
|
||||||
return OemIdent.(ver, ver)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BiosParameterBlock := struct {
|
BiosParameterBlock := struct {
|
||||||
|
@ -38,9 +37,7 @@ bpb_sanity_check := fn(bpb: BiosParameterBlock): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
new_bpb := fn(): BiosParameterBlock {
|
new_bpb := fn(): BiosParameterBlock {
|
||||||
oem := new_oem_ident(0, 0)
|
return .(VALID_JUMP_BYTES, new_oem_ident(0, 0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
|
||||||
return BiosParameterBlock.(VALID_JUMP_BYTES, oem, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
sector_count := fn(bpb: BiosParameterBlock): u32 {
|
||||||
|
@ -63,7 +60,7 @@ VolumeName := [u8; 11]
|
||||||
|
|
||||||
SystemIdentifierString := [u8; 8]
|
SystemIdentifierString := [u8; 8]
|
||||||
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
VALID_SYSTEM_IDENTIFIER_STRING := [u8].(46, 41, 54, 33, 32, 20, 20, 20)
|
||||||
BOOTABLE_PARTITION_SIGNATURE := 0xAA55
|
BOOTABLE_PARTITION_SIGNATURE := @as(u32, 0xAA55)
|
||||||
|
|
||||||
BootCode := [u8; 420]
|
BootCode := [u8; 420]
|
||||||
|
|
||||||
|
@ -100,9 +97,10 @@ ebr_sanity_check := fn(ebr: ExtendedBootRecord): int {
|
||||||
log.warn("EBR-Signature sanity check failed\0")
|
log.warn("EBR-Signature sanity check failed\0")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
|
// ! comparison between [u8] is not supported in hblang
|
||||||
log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
// if ebr.system_identifier_string != VALID_SYSTEM_IDENTIFIER_STRING {
|
||||||
}
|
// log.warn("EBR-Signature-Identifier-String sanity check failed\0")
|
||||||
|
// }
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,8 +129,8 @@ new_ebr := fn(): ExtendedBootRecord {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALID_LEAD_FS_INFO := 0x41615252
|
VALID_LEAD_FS_INFO := @as(u32, 0x41615252)
|
||||||
VALID_TRAIL_FS_INFO := 0xAA550000
|
VALID_TRAIL_FS_INFO := @as(u32, 0xAA550000)
|
||||||
|
|
||||||
FSInfo := struct {
|
FSInfo := struct {
|
||||||
// Must be 0x41615252 to indicate a valid FSInfo structure
|
// Must be 0x41615252 to indicate a valid FSInfo structure
|
||||||
|
@ -145,7 +143,7 @@ FSInfo := struct {
|
||||||
trail_signature: u32,
|
trail_signature: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fs_info_sanity_check := fn(fs_info: FSInfo): int {
|
fs_info_sanity_check := fn(fs_info: FSInfo): uint {
|
||||||
ret := 0
|
ret := 0
|
||||||
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
|
if fs_info.lead_signature != VALID_LEAD_FS_INFO {
|
||||||
ret &= 1
|
ret &= 1
|
||||||
|
|
|
@ -16,7 +16,7 @@ FAT12 := 1
|
||||||
FAT16 := 2
|
FAT16 := 2
|
||||||
FAT32 := 3
|
FAT32 := 3
|
||||||
|
|
||||||
calculate_fat_type := fn(sector_size: int, total_clusters: int): int {
|
calculate_fat_type := fn(sector_size: uint, total_clusters: uint): uint {
|
||||||
if sector_size == 0 {
|
if sector_size == 0 {
|
||||||
return ExFAT
|
return ExFAT
|
||||||
} else if total_clusters < 4085 {
|
} else if total_clusters < 4085 {
|
||||||
|
|
|
@ -1,11 +1,152 @@
|
||||||
stn := @use("../../../libraries/stn/src/lib.hb");
|
stn := @use("../../../libraries/stn/src/lib.hb");
|
||||||
.{string, memory, buffer} := stn
|
.{string, memory, buffer, random, log} := stn;
|
||||||
|
.{Vec2} := stn.math
|
||||||
|
|
||||||
horizon_api := @use("../../../libraries/horizon_api/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;
|
||||||
|
.{sexpr_parser, render_ui} := horizon_api.ui
|
||||||
|
|
||||||
|
render := @use("../../../libraries/render/src/lib.hb");
|
||||||
|
.{Surface} := render;
|
||||||
|
.{Font} := render.text
|
||||||
|
|
||||||
|
intouch := @use("../../../libraries/intouch/src/lib.hb")
|
||||||
|
|
||||||
|
Window := struct {
|
||||||
|
// TODO: Replace this with widgets
|
||||||
|
implicit_framebuffer: render.Surface,
|
||||||
|
width: int,
|
||||||
|
height: int,
|
||||||
|
x: int,
|
||||||
|
y: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
|
||||||
|
img := @embed("../../../assets/wallpaper.qoi")
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
a := buffer.create("XHorizon\0")
|
win_buff := buffer.create("XHorizon\0")
|
||||||
|
|
||||||
|
screen := render.init(true)
|
||||||
|
|
||||||
|
// Clear the screen to black.
|
||||||
|
render.clear(screen, render.black)
|
||||||
|
|
||||||
|
wallpaper := render.image.from(@bitcast(&img))
|
||||||
|
if wallpaper == null {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
window := render.new_surface(screen.width / 3, screen.height / 3)
|
||||||
|
|
||||||
|
mem_buf := memory.request_page(1)
|
||||||
|
color := random.any(render.Color)
|
||||||
|
side := window.width / 8
|
||||||
|
|
||||||
|
// really we should null check but it is a bit broked
|
||||||
|
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
|
||||||
|
|
||||||
|
mouse_x := @as(i16, 0)
|
||||||
|
mouse_y := @as(i16, 0)
|
||||||
|
text_label := new_label("Hi\0")
|
||||||
|
|
||||||
|
// widgets := "()\0"
|
||||||
|
// ui := sexpr_parser(widgets)
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
// Clear the screen
|
||||||
|
render.clear(screen, render.black)
|
||||||
|
render.put_surface(screen, wallpaper, .(0, 0), false)
|
||||||
|
|
||||||
|
// TODO: Read the window buffer here
|
||||||
|
{
|
||||||
|
// ret := buffer.recv([u8; 4096], win_buff, mem_buf)
|
||||||
|
// for some reason this null check causes the compiler to spin forever
|
||||||
|
// if ret == null {
|
||||||
|
// 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)
|
||||||
|
render.put_filled_rect(screen, .(110, 100), .(20, 10), render.white)
|
||||||
|
|
||||||
|
render.put_rect(screen, .(90, 110), .(10, 100), render.white)
|
||||||
|
render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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), render.white)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Screen border
|
||||||
|
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
|
||||||
|
|
||||||
|
{
|
||||||
|
mouse_event := intouch.recieve_mouse_event()
|
||||||
|
//
|
||||||
|
|
||||||
|
if mouse_event != null {
|
||||||
|
// log.warn("Mouse event recieved\0")
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
}
|
||||||
|
// Send events to focused window
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Get windows out of a collection and iter through
|
||||||
|
|
||||||
|
// Sync the screen
|
||||||
|
render.sync(screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -7,12 +7,16 @@ horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
|
||||||
ignim := @use("../../../libraries/ignim/src/lib.hb");
|
ignim := @use("../../../libraries/ignim/src/lib.hb");
|
||||||
.{errors} := ignim
|
.{errors} := ignim
|
||||||
|
|
||||||
|
psf := @embed("../../../consolefonts/tamsyn/10x20r.psf")
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
windowing_system_buffer := buffer.create("XHorizon\0")
|
x := 0
|
||||||
|
// loop if x > 10000 break else x += 1
|
||||||
|
|
||||||
|
windowing_system_buffer := buffer.search("XHorizon\0")
|
||||||
// TODO: get WindowID
|
// TODO: get WindowID
|
||||||
create_window(windowing_system_buffer)
|
wid := create_window(windowing_system_buffer)
|
||||||
|
if false {
|
||||||
program_name := "Horizon Testing Program\0"
|
program_name := "Horizon Testing Program\0"
|
||||||
program_version := ignim.version.make_version(0, 1, 0)
|
program_version := ignim.version.make_version(0, 1, 0)
|
||||||
engine_name := "None\0"
|
engine_name := "None\0"
|
||||||
|
@ -25,11 +29,14 @@ main := fn(): int {
|
||||||
|
|
||||||
instance := ignim.instance.void_instance()
|
instance := ignim.instance.void_instance()
|
||||||
|
|
||||||
// TODO: recursively follow this https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
|
// // TODO: recursively follow this https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Instance
|
||||||
ret := ignim.instance.create_instance(&create_info, 0, &instance)
|
ret := ignim.instance.create_instance(&create_info, 0, &instance)
|
||||||
if ret == errors.IncompatibleDriver {
|
if ret == errors.IncompatibleDriver {
|
||||||
log.error("Driver Incompatible with Vulkan\0")
|
log.error("Driver Incompatible with Vulkan\0")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: get window from the window system and draw to the surface
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ps2_driver"
|
name = "ps2_keyboard_driver"
|
||||||
authors = ["Talha Qamar"]
|
authors = ["Talha Qamar"]
|
||||||
|
|
||||||
[dependants.libraries]
|
[dependants.libraries]
|
|
@ -1,4 +1,4 @@
|
||||||
.{memory, log, string, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
.{memory, log, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||||
|
|
||||||
send_byte := fn(byte: u8): u8 {
|
send_byte := fn(byte: u8): u8 {
|
||||||
memory.outb(96, byte)
|
memory.outb(96, byte)
|
||||||
|
@ -7,7 +7,7 @@ send_byte := fn(byte: u8): u8 {
|
||||||
|
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
buf := buffer.create("XKeyboard\0")
|
buf := buffer.create("XKeyboard\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")
|
||||||
|
@ -15,7 +15,6 @@ main := fn(): int {
|
||||||
if send_byte(244) == 250 {
|
if send_byte(244) == 250 {
|
||||||
log.info("Enabled scanning\0")
|
log.info("Enabled scanning\0")
|
||||||
}
|
}
|
||||||
ptr := memory.request_page(1)
|
|
||||||
prev_input := 250
|
prev_input := 250
|
||||||
loop {
|
loop {
|
||||||
input := memory.inb(96)
|
input := memory.inb(96)
|
||||||
|
@ -23,7 +22,7 @@ main := fn(): int {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
prev_input = input
|
prev_input = input
|
||||||
buffer.write(&input, buf, 1)
|
buffer.write(u8, &input, buf)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
2
sysdata/programs/ps2_mouse_driver/README.md
Normal file
2
sysdata/programs/ps2_mouse_driver/README.md
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# ps2_mouse_driver
|
||||||
|
A small PS/2 mouse driver. This driver pushes changes to the input service in ableOS.
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tests"
|
name = "ps2_mouse_driver"
|
||||||
authors = ["able"]
|
authors = ["able", "peony"]
|
||||||
|
|
||||||
[dependants.libraries]
|
[dependants.libraries]
|
||||||
|
|
152
sysdata/programs/ps2_mouse_driver/src/main.hb
Normal file
152
sysdata/programs/ps2_mouse_driver/src/main.hb
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
.{memory, buffer, log, string, math} := @use("../../../libraries/stn/src/lib.hb")
|
||||||
|
Vec2 := math.Vec2
|
||||||
|
|
||||||
|
intouch := @use("../../../libraries/intouch/src/lib.hb");
|
||||||
|
.{MouseEvent} := intouch.events
|
||||||
|
|
||||||
|
i9 := packed struct {sign: bool, value: u8}
|
||||||
|
Button := struct {id: u8}
|
||||||
|
$LeftButton := Button.(1)
|
||||||
|
$RightButton := Button.(2)
|
||||||
|
$MiddleButton := Button.(4)
|
||||||
|
$Button4 := Button.(8)
|
||||||
|
$Button5 := Button.(16)
|
||||||
|
|
||||||
|
send_byte := fn(target: u8, data: u8): void {
|
||||||
|
loop if (memory.inb(0x64) & 2) == 0 break
|
||||||
|
memory.outb(target, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_mouse := fn(): void {
|
||||||
|
@inline(send_byte, 0x64, 0xD4)
|
||||||
|
@inline(send_byte, 0x60, 0xFF)
|
||||||
|
loop if memory.inb(0x60) == 0xAA {
|
||||||
|
log.info("Self check passed.\0")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send_command_byte := fn(byte: u8): void {
|
||||||
|
@inline(send_byte, 0x64, 0xD4)
|
||||||
|
@inline(send_byte, 0x60, byte)
|
||||||
|
loop if memory.inb(0x60) == 0xFA {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_defaults := fn(): void @inline(send_command_byte, 0xF6)
|
||||||
|
disable_streaming := fn(): void @inline(send_command_byte, 0xF5)
|
||||||
|
enable_streaming := fn(): void @inline(send_command_byte, 0xF4)
|
||||||
|
|
||||||
|
set_remote_mode := fn(): void @inline(send_command_byte, 0xF0)
|
||||||
|
set_warp_mode := fn(): void @inline(send_command_byte, 0xEE)
|
||||||
|
reset_warp_mode := fn(): void @inline(send_command_byte, 0xEC)
|
||||||
|
set_stream_mode := fn(): void @inline(send_command_byte, 0xEA)
|
||||||
|
|
||||||
|
set_non_linear_scaling := fn(): void @inline(send_command_byte, 0xE7)
|
||||||
|
set_linear_scaling := fn(): void @inline(send_command_byte, 0xE6)
|
||||||
|
|
||||||
|
resend_packet := fn(): void @inline(send_command_byte, 0xFE)
|
||||||
|
|
||||||
|
SampleRate := struct {value: u8}
|
||||||
|
$sr10 := SampleRate.(10)
|
||||||
|
$sr20 := SampleRate.(20)
|
||||||
|
$sr40 := SampleRate.(40)
|
||||||
|
$sr60 := SampleRate.(60)
|
||||||
|
$sr80 := SampleRate.(80)
|
||||||
|
$sr100 := SampleRate.(100)
|
||||||
|
$sr200 := SampleRate.(200)
|
||||||
|
|
||||||
|
set_sample_rate := fn(sample_rate: SampleRate): void {
|
||||||
|
@inline(send_command_byte, 0xE6)
|
||||||
|
@inline(send_command_byte, sample_rate.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
Resolution := struct {value: u8}
|
||||||
|
$res_1count_per_mm := Resolution.(0)
|
||||||
|
$res_2count_per_mm := Resolution.(1)
|
||||||
|
$res_4count_per_mm := Resolution.(2)
|
||||||
|
$res_8count_per_mm := Resolution.(3)
|
||||||
|
|
||||||
|
set_resolution := fn(resolution: Resolution): void {
|
||||||
|
@inline(send_command_byte, 0xE6)
|
||||||
|
@inline(send_command_byte, resolution.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
set_up_mouse := fn(): void {
|
||||||
|
@inline(reset_mouse)
|
||||||
|
@inline(set_resolution, res_8count_per_mm)
|
||||||
|
@inline(enable_streaming)
|
||||||
|
}
|
||||||
|
|
||||||
|
button_states := @as(u8, 0)
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
mouse_buffer := buffer.create("PS/2 Mouse\0")
|
||||||
|
format_page := memory.alloc(u8, 1024)
|
||||||
|
|
||||||
|
send_byte(0x64, 0xA8)
|
||||||
|
log.info("Aux mouse device enabled.\0")
|
||||||
|
|
||||||
|
set_up_mouse()
|
||||||
|
|
||||||
|
set_resolution(res_8count_per_mm)
|
||||||
|
|
||||||
|
x := @as(u8, 0)
|
||||||
|
y := @as(u8, 0)
|
||||||
|
|
||||||
|
loop {
|
||||||
|
loop if (memory.inb(0x64) & 0x20) == 0x20 break
|
||||||
|
|
||||||
|
status := memory.inb(0x60)
|
||||||
|
|
||||||
|
if status == 0xAA {
|
||||||
|
loop if memory.inb(0x60) == 0 break
|
||||||
|
log.info("Mouse plugged in!\0")
|
||||||
|
set_up_mouse()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
event := MouseEvent.(0, 0, false, false, false)
|
||||||
|
|
||||||
|
changes := button_states ^ status & 7
|
||||||
|
|
||||||
|
if (changes & LeftButton.id) != 0 | (status & LeftButton.id) != 0 {
|
||||||
|
event.left = true
|
||||||
|
} else {
|
||||||
|
event.left = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes & MiddleButton.id) != 0 | (status & MiddleButton.id) != 0 {
|
||||||
|
event.middle = true
|
||||||
|
} else {
|
||||||
|
event.middle = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes & RightButton.id) != 0 | (status & RightButton.id) != 0 {
|
||||||
|
event.right = true
|
||||||
|
} else {
|
||||||
|
event.right = false
|
||||||
|
}
|
||||||
|
|
||||||
|
button_states ^= changes
|
||||||
|
|
||||||
|
dx := i9.(false, 0)
|
||||||
|
dy := i9.(false, 0)
|
||||||
|
|
||||||
|
dx.value = memory.inb(0x60)
|
||||||
|
dx.sign = (status & 0x10) > 0
|
||||||
|
|
||||||
|
dy.value = memory.inb(0x60)
|
||||||
|
dy.sign = (status & 0x20) != 0
|
||||||
|
|
||||||
|
y_change := @as(i8, @bitcast(dy.value))
|
||||||
|
x_change := @as(i8, @bitcast(dx.value))
|
||||||
|
|
||||||
|
event.x_change = x_change
|
||||||
|
event.y_change = y_change
|
||||||
|
|
||||||
|
buffer.write(MouseEvent, &event, mouse_buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -4,16 +4,16 @@ render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
the impostor travels left and loops around the screen */
|
the impostor travels left and loops around the screen */
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(true)
|
||||||
x := 0
|
x := 0
|
||||||
loop {
|
loop {
|
||||||
render.put_rect(.(200 - x, 80), .(430, 380), render.red)
|
render.put_rect(screen, .(200 - x, 80), .(430, 380), render.red)
|
||||||
render.put_rect(.(630 - x, 120), .(120, 300), render.red)
|
render.put_rect(screen, .(630 - x, 120), .(120, 300), render.red)
|
||||||
render.put_rect(.(200 - x, 460), .(160, 270), render.red)
|
render.put_rect(screen, .(200 - x, 460), .(160, 270), render.red)
|
||||||
render.put_rect(.(470 - x, 460), .(160, 270), render.red)
|
render.put_rect(screen, .(470 - x, 460), .(160, 270), render.red)
|
||||||
render.put_rect(.(140 - x, 140), .(340, 250), render.cyan)
|
render.put_rect(screen, .(140 - x, 140), .(340, 250), render.cyan)
|
||||||
render.sync()
|
render.sync(screen)
|
||||||
render.clear(render.black)
|
render.clear(screen, render.black)
|
||||||
x += 1
|
x += 1
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -6,12 +6,12 @@ render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
note that this may happen too fast for you to notice... */
|
note that this may happen too fast for you to notice... */
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(true)
|
||||||
color := render.light_cyan
|
color := render.light_cyan
|
||||||
n := @as(u8, 1)
|
n := @as(u8, 1)
|
||||||
loop {
|
loop {
|
||||||
render.clear(color)
|
render.clear(screen, color)
|
||||||
render.sync()
|
render.sync(screen)
|
||||||
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
if (color.b & 255) == 255 | (color.b & 255) == 0 {
|
||||||
n = -n
|
n = -n
|
||||||
}
|
}
|
||||||
|
|
26
sysdata/programs/render_example/src/examples/image.hb
Normal file
26
sysdata/programs/render_example/src/examples/image.hb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
.{log, math, string} := @use("../../../../libraries/stn/src/lib.hb")
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
|
/* expected result:
|
||||||
|
a cute qoi image and a cute bmp image */
|
||||||
|
|
||||||
|
example := fn(): void {
|
||||||
|
screen := render.init(true)
|
||||||
|
image_qoi := render.image.from(@bitcast(&@embed("../../../../assets/mini.qoi")))
|
||||||
|
image_bmp := render.image.from(@bitcast(&@embed("../../../../assets/mini.bmp")))
|
||||||
|
|
||||||
|
if image_qoi == null | image_bmp == null {
|
||||||
|
log.error("failed to load images for whatever reason\0")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t := 0.0
|
||||||
|
loop {
|
||||||
|
render.clear(screen, render.black)
|
||||||
|
render.put_surface(screen, image_bmp, .(@bitcast(@fti(math.cos(t) * 100.0)) + (screen.width - image_bmp.width * 3) / 2, (screen.height - image_bmp.height) / 2), false)
|
||||||
|
render.put_surface(screen, image_qoi, .((screen.width + image_qoi.width) / 2, @bitcast(@fti(math.sin(t) * 100.0)) + (screen.height - image_qoi.height) / 2), false)
|
||||||
|
render.sync(screen)
|
||||||
|
t += 0.02
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -6,18 +6,16 @@ render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
created on a blue background */
|
created on a blue background */
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(true)
|
||||||
render.clear(.(100, 50, 0, 255))
|
render.clear(screen, .(100, 50, 0, 255))
|
||||||
width := render.width()
|
p0 := Vec2(uint).(0, 0)
|
||||||
height := render.height()
|
p1 := Vec2(uint).(0, screen.height)
|
||||||
p0 := Vec2(int).(0, 0)
|
loop if p0.y >= screen.height break else {
|
||||||
p1 := Vec2(int).(0, height)
|
render.put_line(screen, p0, p1, .(255, 180, 100, 255))
|
||||||
loop if p0.y >= height break else {
|
render.put_line(screen, .(screen.width, screen.height) - p0, .(screen.width, screen.height) - p1, .(255, 180, 100, 255))
|
||||||
render.put_line(p0, p1, .(255, 180, 100, 255))
|
p0.y += screen.height >> 6
|
||||||
render.put_line(.(width, height) - p0, .(width, height) - p1, .(255, 180, 100, 255))
|
p1.x += screen.width >> 6
|
||||||
p0.y += height >> 6
|
|
||||||
p1.x += width >> 6
|
|
||||||
}
|
}
|
||||||
render.sync()
|
render.sync(screen)
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -2,16 +2,15 @@
|
||||||
render := @use("../../../../libraries/render/src/lib.hb")
|
render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(false)
|
||||||
render.doublebuffer(false)
|
render.clear(screen, render.black)
|
||||||
render.clear(render.black)
|
|
||||||
loop {
|
loop {
|
||||||
x := random.range(int, 0, 1024)
|
x := random.range(uint, 0, screen.width)
|
||||||
y := random.range(int, 0, 768)
|
y := random.range(uint, 0, screen.height)
|
||||||
r := random.range(int, 0, 255)
|
r := random.range(u8, 0, 255)
|
||||||
g := random.range(int, 0, 75)
|
g := random.range(u8, 0, 75)
|
||||||
b := random.range(int, 0, 155)
|
b := random.range(u8, 0, 155)
|
||||||
render.put_pixel(.(x, y), .(b, g, r, 255))
|
render.put_pixel(screen, .(x, y), .(b, g, r, 255))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -6,27 +6,26 @@ render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
a square that changes colour bounces around the screen */
|
a square that changes colour bounces around the screen */
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(true)
|
||||||
vel := Vec2(int).(1, 1)
|
vel := Vec2(int).(1, 1)
|
||||||
pos := Vec2(int).(100, 100)
|
side := screen.width / 8
|
||||||
width := render.width()
|
pos := Vec2(uint).((screen.width - side) / 2, (screen.height - side) / 2)
|
||||||
height := render.height()
|
color := random.any(render.Color)
|
||||||
color := @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
|
|
||||||
loop {
|
loop {
|
||||||
render.put_filled_rect(pos, .(100, 100), color)
|
render.put_filled_rect(screen, pos, .(side, side), color)
|
||||||
render.sync()
|
render.sync(screen)
|
||||||
render.clear(render.black)
|
render.clear(screen, render.black)
|
||||||
|
|
||||||
if pos.x == 0 | pos.x == width - 100 {
|
if pos.x == 0 | pos.x == screen.width - side {
|
||||||
vel.x = -vel.x
|
vel.x = -vel.x
|
||||||
color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
|
color = random.any(render.Color)
|
||||||
}
|
}
|
||||||
if pos.y == 0 | pos.y == height - 100 {
|
if pos.y == 0 | pos.y == screen.height - side {
|
||||||
vel.y = -vel.y
|
vel.y = -vel.y
|
||||||
color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
|
color = random.any(render.Color)
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += vel
|
pos += @bitcast(vel)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
render := @use("../../../../libraries/render/src/lib.hb")
|
|
||||||
|
|
||||||
/* expected result: (EPILEPSY WARNING)
|
|
||||||
the screen rapidly flashes red then black */
|
|
||||||
|
|
||||||
example := fn(): void {
|
|
||||||
render.init()
|
|
||||||
loop {
|
|
||||||
render.clear(render.red)
|
|
||||||
render.sync()
|
|
||||||
render.clear(render.yellow)
|
|
||||||
render.sync()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
55
sysdata/programs/render_example/src/examples/surface.hb
Normal file
55
sysdata/programs/render_example/src/examples/surface.hb
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math;
|
||||||
|
.{random} := @use("../../../../libraries/stn/src/lib.hb")
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
|
/* expected result:
|
||||||
|
bouncing gradient square inside coloured bouncing box inside black screen */
|
||||||
|
|
||||||
|
example := fn(): void {
|
||||||
|
screen := render.init(true)
|
||||||
|
|
||||||
|
image := render.new_surface(screen.width / 3, screen.height / 3)
|
||||||
|
vel := Vec2(int).(-1, -1)
|
||||||
|
pos := Vec2(uint).(100, 100)
|
||||||
|
side := image.width / 8
|
||||||
|
vel_inner := Vec2(int).(1, 1)
|
||||||
|
pos_inner := Vec2(uint).((image.width - side) / 2, (image.height - side) / 2)
|
||||||
|
color := random.any(render.Color)
|
||||||
|
target_color := random.any(render.Color)
|
||||||
|
loop {
|
||||||
|
render.clear(screen, render.black)
|
||||||
|
render.put_filled_rect(image, pos_inner, .(side, side), color)
|
||||||
|
render.put_rect(image, pos_inner, .(side, side), render.black)
|
||||||
|
render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), color)
|
||||||
|
|
||||||
|
render.put_surface(screen, image, pos, false)
|
||||||
|
render.put_rect(image, pos_inner, .(side, side), color)
|
||||||
|
render.sync(screen)
|
||||||
|
|
||||||
|
if pos_inner.x == 0 | pos_inner.x == image.width - side {
|
||||||
|
vel_inner.x = -vel_inner.x
|
||||||
|
target_color = random.any(render.Color)
|
||||||
|
}
|
||||||
|
if pos_inner.y == 0 | pos_inner.y == image.height - side {
|
||||||
|
vel_inner.y = -vel_inner.y
|
||||||
|
target_color = random.any(render.Color)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos.x == 0 | pos.x == screen.width - image.width {
|
||||||
|
vel.x = -vel.x
|
||||||
|
}
|
||||||
|
if pos.y == 0 | pos.y == screen.height - image.height {
|
||||||
|
vel.y = -vel.y
|
||||||
|
}
|
||||||
|
|
||||||
|
color += .(
|
||||||
|
@bitcast(color.b < target_color.b) - @bitcast(color.b > target_color.b),
|
||||||
|
@bitcast(color.g < target_color.g) - @bitcast(color.g > target_color.g),
|
||||||
|
@bitcast(color.r < target_color.r) - @bitcast(color.r > target_color.r),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
pos += @bitcast(vel)
|
||||||
|
pos_inner += @bitcast(vel_inner)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
render := @use("../../../../libraries/render/src/lib.hb")
|
|
||||||
|
|
||||||
render.mode = render.svga
|
|
||||||
|
|
||||||
example := fn(): void {
|
|
||||||
render.init()
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -7,12 +7,12 @@ Vec2 := math.Vec2
|
||||||
with a "target" randomly apperaing in one of them and a "seeker" "catching" it */
|
with a "target" randomly apperaing in one of them and a "seeker" "catching" it */
|
||||||
|
|
||||||
example := fn(): void {
|
example := fn(): void {
|
||||||
render.init()
|
screen := render.init(true)
|
||||||
|
|
||||||
width := render.width()
|
width := screen.width
|
||||||
height := render.height()
|
height := screen.height
|
||||||
cell_size := 0
|
cell_size := 0
|
||||||
range := Vec2(int).(0, 0)
|
range := Vec2(uint).(0, 0)
|
||||||
if width > height {
|
if width > height {
|
||||||
cell_size = width / 40
|
cell_size = width / 40
|
||||||
range = .(39, height / cell_size - 1)
|
range = .(39, height / cell_size - 1)
|
||||||
|
@ -24,41 +24,41 @@ example := fn(): void {
|
||||||
height -= 1
|
height -= 1
|
||||||
|
|
||||||
scroll := 0
|
scroll := 0
|
||||||
target := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y))
|
target := Vec2(uint).(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
|
||||||
|
|
||||||
halfcell := cell_size / 2
|
halfcell := cell_size / 2
|
||||||
octcell := cell_size / 8
|
octcell := cell_size / 8
|
||||||
sevenoctcell := cell_size - octcell
|
sevenoctcell := cell_size - octcell
|
||||||
|
|
||||||
seeker := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y))
|
seeker := Vec2(uint).(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
render.clear(render.black)
|
render.clear(screen, render.black)
|
||||||
|
|
||||||
target_pixel_coord := target * .(cell_size, cell_size) + .(scroll, scroll)
|
target_pixel_coord := target * .(@bitcast(cell_size), @bitcast(cell_size)) + .(scroll, scroll)
|
||||||
render.put_trirect(target_pixel_coord, .(cell_size, cell_size), render.red, render.light_red)
|
render.put_trirect(screen, target_pixel_coord, .(@bitcast(cell_size), @bitcast(cell_size)), render.red, render.light_red)
|
||||||
|
|
||||||
render.put_hline(target_pixel_coord.y + halfcell, target_pixel_coord.x - octcell, target_pixel_coord.x - sevenoctcell, render.light_red)
|
render.put_hline(screen, target_pixel_coord.y + halfcell, target_pixel_coord.x - octcell, target_pixel_coord.x - sevenoctcell, render.light_red)
|
||||||
render.put_hline(target_pixel_coord.y + halfcell, target_pixel_coord.x + cell_size + octcell, target_pixel_coord.x + cell_size + sevenoctcell, render.light_red)
|
render.put_hline(screen, target_pixel_coord.y + halfcell, target_pixel_coord.x + cell_size + octcell, target_pixel_coord.x + cell_size + sevenoctcell, render.light_red)
|
||||||
render.put_vline(target_pixel_coord.x + halfcell, target_pixel_coord.y - octcell, target_pixel_coord.y - sevenoctcell, render.light_red)
|
render.put_vline(screen, target_pixel_coord.x + halfcell, target_pixel_coord.y - octcell, target_pixel_coord.y - sevenoctcell, render.light_red)
|
||||||
render.put_vline(target_pixel_coord.x + halfcell, target_pixel_coord.y + cell_size + octcell, target_pixel_coord.y + cell_size + sevenoctcell, render.light_red)
|
render.put_vline(screen, target_pixel_coord.x + halfcell, target_pixel_coord.y + cell_size + octcell, target_pixel_coord.y + cell_size + sevenoctcell, render.light_red)
|
||||||
|
|
||||||
x := scroll
|
x := scroll
|
||||||
loop if x > width break else {
|
loop if x > width break else {
|
||||||
render.put_vline(x, 0, height, .(0, 127, 0, 127))
|
render.put_vline(screen, x, 0, height, .(0, 127, 0, 127))
|
||||||
x += cell_size
|
x += cell_size
|
||||||
}
|
}
|
||||||
|
|
||||||
y := scroll
|
y := scroll
|
||||||
loop if y > height break else {
|
loop if y > height break else {
|
||||||
render.put_hline(y, 0, width, .(0, 127, 0, 127))
|
render.put_hline(screen, y, 0, width, .(0, 127, 0, 127))
|
||||||
y += cell_size
|
y += cell_size
|
||||||
}
|
}
|
||||||
|
|
||||||
render.put_hline(seeker.y * cell_size + halfcell + scroll, 0, width, render.light_green)
|
render.put_hline(screen, seeker.y * cell_size + halfcell + scroll, 0, width, render.blue)
|
||||||
render.put_vline(seeker.x * cell_size + halfcell + scroll, 0, height, render.light_green)
|
render.put_vline(screen, seeker.x * cell_size + halfcell + scroll, 0, height, render.blue)
|
||||||
|
|
||||||
render.sync()
|
render.sync(screen)
|
||||||
|
|
||||||
if seeker.x < target.x {
|
if seeker.x < target.x {
|
||||||
seeker.x += 1
|
seeker.x += 1
|
||||||
|
@ -69,7 +69,7 @@ example := fn(): void {
|
||||||
} else if seeker.y > target.y {
|
} else if seeker.y > target.y {
|
||||||
seeker.y -= 1
|
seeker.y -= 1
|
||||||
} else {
|
} else {
|
||||||
target = .(random.range(int, 0, range.x), random.range(int, 0, range.y))
|
target = .(random.range(uint, 0, range.x), random.range(uint, 0, range.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
scroll += 1
|
scroll += 1
|
||||||
|
|
243
sysdata/programs/render_example/src/examples/text.hb
Normal file
243
sysdata/programs/render_example/src/examples/text.hb
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
.{memory, log, string, math} := @use("../../../../libraries/stn/src/lib.hb")
|
||||||
|
render := @use("../../../../libraries/render/src/lib.hb")
|
||||||
|
|
||||||
|
/* expected result: pretty decent notepad app
|
||||||
|
slightly jank
|
||||||
|
-----------------
|
||||||
|
features:
|
||||||
|
- basic keys
|
||||||
|
- holding support with DAS
|
||||||
|
- visible cursor
|
||||||
|
- l+r arrow key support
|
||||||
|
- proper insertion and deletion
|
||||||
|
- shift key support
|
||||||
|
*/
|
||||||
|
|
||||||
|
psf := @embed("../../../../assets/consolefonts/tamsyn/10x20r.psf")
|
||||||
|
img := @embed("../../../../assets/wallpaper.qoi")
|
||||||
|
|
||||||
|
is_shift_pressed := false
|
||||||
|
is_ctrl_pressed := false
|
||||||
|
is_extended := false
|
||||||
|
$initial_delay := 50
|
||||||
|
$repeat_delay := 7
|
||||||
|
$left_arrow := 0x4B
|
||||||
|
$right_arrow := 0x4D
|
||||||
|
$up_arrow := 0x48
|
||||||
|
$down_arrow := 0x50
|
||||||
|
|
||||||
|
example := fn(): void {
|
||||||
|
screen := render.init(true)
|
||||||
|
window := render.new_surface(600, 300)
|
||||||
|
font := render.text.font_from_psf2(@bitcast(&psf), false)
|
||||||
|
wallpaper := render.image.from(@bitcast(&img))
|
||||||
|
|
||||||
|
if font == null {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if wallpaper == null {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "sticky note:\n\0"
|
||||||
|
msg_len := string.length(msg)
|
||||||
|
|
||||||
|
buf := memory.alloc(u8, 4096)
|
||||||
|
|
||||||
|
bottom := buf + msg_len
|
||||||
|
|
||||||
|
@inline(memory.copy, u8, msg, buf, msg_len)
|
||||||
|
cursor := bottom
|
||||||
|
|
||||||
|
draw_window(window, font, buf, cursor)
|
||||||
|
draw_screen(screen, window, wallpaper)
|
||||||
|
|
||||||
|
memory.outb(96, 238)
|
||||||
|
memory.outb(96, 238)
|
||||||
|
memory.outb(96, 244)
|
||||||
|
|
||||||
|
prev_input := @as(u8, 0xFF)
|
||||||
|
current_key := @as(u8, 0)
|
||||||
|
holding_timer := 0
|
||||||
|
|
||||||
|
loop {
|
||||||
|
input := memory.inb(96)
|
||||||
|
if input != prev_input {
|
||||||
|
if input == 0xE0 {
|
||||||
|
is_extended = true
|
||||||
|
} else {
|
||||||
|
if (input & 0x80) != 0 {
|
||||||
|
if (input & 0x7F) == current_key {
|
||||||
|
current_key = 0
|
||||||
|
holding_timer = 0
|
||||||
|
} else if input == 0xAA | input == 0xB6 {
|
||||||
|
is_shift_pressed = false
|
||||||
|
} else if input == 0x9D {
|
||||||
|
is_ctrl_pressed = false
|
||||||
|
}
|
||||||
|
is_extended = false
|
||||||
|
} else {
|
||||||
|
if is_extended {
|
||||||
|
current_key = input
|
||||||
|
holding_timer = 1
|
||||||
|
cursor = handle_extended_key(input, cursor, bottom, font)
|
||||||
|
} else {
|
||||||
|
if input == 0x2A | input == 0x36 {
|
||||||
|
is_shift_pressed = true
|
||||||
|
} else if input == 0x1D {
|
||||||
|
is_ctrl_pressed = true
|
||||||
|
} else {
|
||||||
|
current_key = input
|
||||||
|
holding_timer = 1
|
||||||
|
cursor = handle_char(map_keys(current_key), cursor, bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_input = input
|
||||||
|
}
|
||||||
|
|
||||||
|
if current_key != 0 & holding_timer > 0 {
|
||||||
|
holding_timer += 1
|
||||||
|
|
||||||
|
if holding_timer >= initial_delay {
|
||||||
|
if is_extended {
|
||||||
|
cursor = handle_extended_key(current_key, cursor, bottom, font)
|
||||||
|
} else {
|
||||||
|
cursor = handle_char(map_keys(current_key), cursor, bottom)
|
||||||
|
}
|
||||||
|
holding_timer = initial_delay - repeat_delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_window(window, font, buf, cursor)
|
||||||
|
draw_screen(screen, window, wallpaper)
|
||||||
|
|
||||||
|
if holding_timer > 0 & current_key != 0 {
|
||||||
|
if (memory.inb(96) & 0x80) != 0 {
|
||||||
|
current_key = 0
|
||||||
|
holding_timer = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_extended_key := fn(scancode: u8, cursor: ^u8, bottom: ^u8, font: render.text.Font): ^u8 {
|
||||||
|
if scancode == left_arrow {
|
||||||
|
if cursor > bottom {
|
||||||
|
return cursor - 1
|
||||||
|
}
|
||||||
|
} else if scancode == right_arrow {
|
||||||
|
if *cursor != 0 {
|
||||||
|
return cursor + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
padding := 3 * @sizeof(render.Color)
|
||||||
|
|
||||||
|
draw_window := fn(window: render.Surface, font: render.text.Font, buf: ^u8, cursor: ^u8): void {
|
||||||
|
render.clear(window, .(0x88, 0xF4, 0xFC, 0x0))
|
||||||
|
line := font.height + padding - 1
|
||||||
|
render.put_rect(window, .(0, 0), .(window.width - 1, window.height - 1), render.black)
|
||||||
|
|
||||||
|
loop if line >= window.height break else {
|
||||||
|
render.put_hline(window, line, padding, window.width - padding, render.yellow)
|
||||||
|
line += font.height
|
||||||
|
}
|
||||||
|
|
||||||
|
render.put_text(window, font, .(padding, padding), render.black, buf)
|
||||||
|
|
||||||
|
cursor_offset := cursor - buf
|
||||||
|
|
||||||
|
y_pos := padding
|
||||||
|
x_pos := padding
|
||||||
|
i := 0
|
||||||
|
|
||||||
|
loop if i >= cursor_offset break else {
|
||||||
|
if *(buf + i) == 10 {
|
||||||
|
y_pos += font.height + font.line_gap
|
||||||
|
x_pos = padding
|
||||||
|
} else {
|
||||||
|
if x_pos + font.width >= window.width - padding {
|
||||||
|
y_pos += font.height + font.line_gap
|
||||||
|
x_pos = padding - font.width
|
||||||
|
}
|
||||||
|
x_pos += font.width
|
||||||
|
}
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
render.put_rect(window, .(x_pos, y_pos), .(1, font.height - 1), render.black)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_screen := fn(screen: render.Surface, window: render.Surface, wallpaper: render.Surface): void {
|
||||||
|
render.put_surface(screen, wallpaper, .(0, 0), false)
|
||||||
|
render.put_surface(screen, window, .(100, 100), false)
|
||||||
|
render.sync(screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_char := fn(char: u8, cursor: ^u8, bottom: ^u8): ^u8 {
|
||||||
|
if char == 0 {
|
||||||
|
return cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_ctrl_pressed & char == 48 {
|
||||||
|
cursor = bottom
|
||||||
|
} else if char != 0x8 {
|
||||||
|
end := cursor
|
||||||
|
loop if *end == 0 break else {
|
||||||
|
end += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursor < end {
|
||||||
|
src := end
|
||||||
|
dst := end + 1
|
||||||
|
loop if src < cursor break else {
|
||||||
|
*dst = *src
|
||||||
|
dst -= 1
|
||||||
|
src -= 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*cursor = char
|
||||||
|
return cursor + 1
|
||||||
|
} else if char == 0xA {
|
||||||
|
*cursor = 32
|
||||||
|
cursor += 1;
|
||||||
|
*cursor = 92
|
||||||
|
return cursor + 1
|
||||||
|
} else if cursor > bottom {
|
||||||
|
if cursor == bottom {
|
||||||
|
return cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
end := cursor
|
||||||
|
loop if *end == 0 break else {
|
||||||
|
end += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if cursor < end {
|
||||||
|
src := cursor
|
||||||
|
dst := cursor - 1
|
||||||
|
loop if src > end break else {
|
||||||
|
*dst = *src
|
||||||
|
dst += 1
|
||||||
|
src += 1
|
||||||
|
}
|
||||||
|
return cursor - 1
|
||||||
|
} else {
|
||||||
|
cursor -= 1;
|
||||||
|
*cursor = 32
|
||||||
|
return cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cursor
|
||||||
|
}
|
||||||
|
map_keys := fn(scancode: u8): u8 {
|
||||||
|
if is_shift_pressed {
|
||||||
|
return ps2_table[scancode + 0x40]
|
||||||
|
}
|
||||||
|
return ps2_table[scancode]
|
||||||
|
}
|
||||||
|
ps2_table := [u8].(0x0, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x8, 0x9, 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0xA, 0x0, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x0, 0x5C, 0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x0, 0x2A, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x8, 0x9, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0xA, 0x0, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x0, 0x7C, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
|
@ -1,6 +1 @@
|
||||||
.{example} := @use("./examples/tactical_screen.hb")
|
.{example: main} := @use("./examples/text.hb")
|
||||||
|
|
||||||
main := fn(): void {
|
|
||||||
@inline(example)
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
.{memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
||||||
|
|
||||||
serial_print := fn(ptr: ^u8): void {
|
serial_print := fn(ptr: ^u8): void {
|
||||||
letter := 0
|
letter := @as(u8, 0)
|
||||||
loop if *ptr == 0 break else {
|
loop if *ptr == 0 break else {
|
||||||
letter = *ptr
|
letter = *ptr
|
||||||
memory.outb(0xF803, letter)
|
memory.outb(0xF803, letter)
|
||||||
|
@ -25,7 +25,7 @@ main := fn(): int {
|
||||||
mem := memory.request_page(1)
|
mem := memory.request_page(1)
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
ptr := @eca(4, a, mem, 0x1000)
|
ptr := @as(^u8, @eca(4, a, mem, 0x1000))
|
||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
serial_println("No message\0")
|
serial_println("No message\0")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,10 @@ log_info := fn(): void {
|
||||||
if a == 0 {
|
if a == 0 {
|
||||||
} else {
|
} else {
|
||||||
msg := "XABC\0"
|
msg := "XABC\0"
|
||||||
msg_length := @inline(string.length, msg)
|
// inline is broked
|
||||||
@eca(3, a, msg, msg_length)
|
// msg_length := @inline(string.length, msg)
|
||||||
|
msg_length := 5
|
||||||
|
@as(void, @eca(3, a, msg, msg_length))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,9 +2,7 @@ stn := @use("../../../libraries/stn/src/lib.hb");
|
||||||
.{string, memory, buffer, log} := stn
|
.{string, memory, buffer, log} := stn
|
||||||
|
|
||||||
pci := @use("../../../libraries/pci/src/lib.hb");
|
pci := @use("../../../libraries/pci/src/lib.hb");
|
||||||
.{PCIAddress, get_ids, config_read32} := pci;
|
.{PCIAddress, get_ids, config_read32} := pci
|
||||||
|
|
||||||
.{dt_get} := @use("../../../libraries/dt_api/src/lib.hb")
|
|
||||||
|
|
||||||
reg := @use("./reg.hb")
|
reg := @use("./reg.hb")
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
.{log, string, memory, buffer} := @use("../../../libraries/stn/src/lib.hb")
|
|
||||||
|
|
||||||
service_search := fn(): void {
|
|
||||||
a := "\{01}\0"
|
|
||||||
@eca(3, 0, a, 2)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
main := fn(): int {
|
|
||||||
//service_search()
|
|
||||||
return 0
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tetris"
|
|
||||||
authors = ["peony"]
|
|
||||||
|
|
||||||
[dependants.libraries]
|
|
||||||
|
|
||||||
[dependants.binaries]
|
|
||||||
hblang.version = "1.0.0"
|
|
||||||
|
|
||||||
[build]
|
|
||||||
command = "hblang src/main.hb"
|
|
|
@ -3,11 +3,12 @@
|
||||||
default_entry = 1
|
default_entry = 1
|
||||||
timeout = 0
|
timeout = 0
|
||||||
verbose = false
|
verbose = false
|
||||||
interface_resolution = "1600x900x24"
|
# interface_resolution = "1920x1080x24"
|
||||||
# interface_resolution = "640x480x32"
|
interface_resolution = "1024x768x24"
|
||||||
|
# interface_resolution = "640x480x24"
|
||||||
# Terminal related settings
|
# Terminal related settings
|
||||||
term_wallpaper = "boot:///background.bmp"
|
# term_wallpaper = "boot:///background.bmp"
|
||||||
# term_wallpaper = "boot:///empty-background.bmp"
|
term_wallpaper = "boot:///empty-background.bmp"
|
||||||
term_background = "008080"
|
term_background = "008080"
|
||||||
|
|
||||||
[boot.limine.ableos]
|
[boot.limine.ableos]
|
||||||
|
@ -15,46 +16,20 @@ comment = "Default AbleOS boot entry."
|
||||||
protocol = "limine"
|
protocol = "limine"
|
||||||
kernel_path = "boot:///kernel_${ARCH}"
|
kernel_path = "boot:///kernel_${ARCH}"
|
||||||
kernel_cmdline = ""
|
kernel_cmdline = ""
|
||||||
# resolution = "640x480x32"
|
# resolution = "1920x1080x24"
|
||||||
resolution = "1600x900x24"
|
resolution = "1024x768x24"
|
||||||
|
# resolution = "640x480x24"
|
||||||
|
|
||||||
[boot.limine.ableos.modules]
|
[boot.limine.ableos.modules]
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.tests]
|
# [boot.limine.ableos.modules.render_example]
|
||||||
# path = "boot:///tests.hbf"
|
# path = "boot:///render_example.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.serial_driver]
|
[boot.limine.ableos.modules.horizon]
|
||||||
# path = "boot:///serial_driver.hbf"
|
path = "boot:///horizon.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.diskio_driver]
|
[boot.limine.ableos.modules.ps2_mouse_driver]
|
||||||
# path = "boot:///diskio_driver.hbf"
|
path = "boot:///ps2_mouse_driver.hbf"
|
||||||
|
|
||||||
[boot.limine.ableos.modules.render_example]
|
# [boot.limine.ableos.modules.ps2_keyboard_driver]
|
||||||
path = "boot:///render_example.hbf"
|
# path = "boot:///ps2_keyboard_driver.hbf"
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.serial_driver_test]
|
|
||||||
# path = "boot:///serial_driver_test.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.horizon]
|
|
||||||
# path = "boot:///horizon.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.horizon_testing_program]
|
|
||||||
# path = "boot:///horizon_testing_program.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.dt_buffer_test]
|
|
||||||
# path = "boot:///dt_buffer_test.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.svga_driver]
|
|
||||||
# path = "boot:///svga_driver.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.ps2_driver]
|
|
||||||
# path = "boot:///ps2_driver.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.filesystem_fat32]
|
|
||||||
# path = "boot:///filesystem_fat32.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.pumpkin_print]
|
|
||||||
# path = "boot:///pumpkin_print.hbf"
|
|
||||||
|
|
||||||
# [boot.limine.ableos.modules.tetris]
|
|
||||||
# path = "boot:///tetris.hbf"
|
|
||||||
|
|
Loading…
Reference in a new issue