1
0
Fork 0
forked from AbleOS/ableos

Compare commits

...

6 commits

Author SHA1 Message Date
peony 15c978f90f Merge remote-tracking branch 'ableos/master' 2024-10-14 22:06:05 +02:00
koniifer 1eee33ce8b fix icky pointer misalignment
move dt_api to stn for ease of use
do away with now redundant strobe example (colour example is basically strobe now)
2024-10-14 18:54:53 +01:00
Able 6fa1c829fd Horizon work 2024-10-13 22:34:33 -05:00
koniifer 820c3e459b optimisations 2024-10-14 01:31:23 +01:00
koniifer 3af28f1666 use able image 2024-10-13 23:41:17 +01:00
koniifer 96c2bd5cd5 bitmap image support & better mem opts
restructure render lib
add peony's render api additions and example
add image example
fix some dubious bugs i had made in unused code in mem_serve.rs
remove tetris stub (now in peony's fork)
update hblang
2024-10-13 23:38:43 +01:00
29 changed files with 412 additions and 262 deletions

6
Cargo.lock generated
View file

@ -350,12 +350,12 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc2e0cc5b36f84f9d5bb82b6f48e6b29869746d5" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc2e0cc5b36f84f9d5bb82b6f48e6b29869746d5" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
dependencies = [ dependencies = [
"hashbrown 0.15.0", "hashbrown 0.15.0",
"hbbytecode", "hbbytecode",
@ -367,7 +367,7 @@ dependencies = [
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#dc2e0cc5b36f84f9d5bb82b6f48e6b29869746d5" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]

View file

@ -97,7 +97,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 +110,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 {
@ -173,7 +175,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 {

View file

@ -24,6 +24,75 @@ fn alloc_page(vm: &mut Vm, _mem_addr: u64, _length: usize) -> Result<(), MemoryS
Ok(()) Ok(())
} }
#[inline(always)]
unsafe fn memcpy(mut dest: *mut u8, mut src: *const u8, mut count: usize) {
if count < 16 {
src.copy_to_nonoverlapping(dest, count);
return;
}
// let dest_misalignment = dest as usize & 7;
// if dest_misalignment != 0 {
// let align_bytes = 8 - dest_misalignment;
// src.copy_to_nonoverlapping(dest, align_bytes);
// dest = dest.add(align_bytes);
// src = src.add(align_bytes);
// count -= align_bytes;
// }
while count >= 8 {
if (src as usize) & 7 == 0 && (dest as usize) & 7 == 0 {
*(dest as *mut u64) = *(src as *const u64);
} else {
src.copy_to_nonoverlapping(dest, 8);
}
dest = dest.add(8);
src = src.add(8);
count -= 8;
}
if count > 0 {
src.copy_to_nonoverlapping(dest, count);
}
}
#[inline(always)]
unsafe fn memset(mut dest: *mut u8, src: *const u8, count: usize, size: usize) {
let mut remaining = count * size;
if remaining < 16 {
src.copy_to_nonoverlapping(dest, remaining);
return;
}
let mut buffer = [0u8; 64];
let mut buffer_size = size;
src.copy_to_nonoverlapping(buffer.as_mut_ptr(), size);
while buffer_size * 2 <= 64 {
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 remaining >= 8 {
if (dest as usize) & 7 == 0 {
*(dest as *mut u64) = *buffer_ptr;
} else {
buffer.as_ptr().copy_to_nonoverlapping(dest, 8);
}
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 +101,37 @@ 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_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!("Allocating {} pages @ {:x}", page_count, mptr); log::debug!("Allocating {} pages @ {:x}", page_count, mptr);
let ptr = unsafe { let ptr = alloc(Layout::from_size_align_unchecked(
alloc(Layout::from_size_align_unchecked( page_count as usize * 4096,
page_count as usize * 4096, 4096,
4096, ));
))
};
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, 4096),
) )
} },
}
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 +148,25 @@ 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 = u64::from_le_bytes(msg_vec[1..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;
memcpy(dest, src, count);
},
5 => unsafe {
let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize;
let size = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as usize;
let src =
u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *const u8;
let dest = u64::from_le_bytes(msg_vec[25..33].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);
} }

View file

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

2
known_bugs.md Normal file
View 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

View file

@ -395,12 +395,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
"-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",
]); ]);
} }

View file

@ -1 +0,0 @@
# dt_api

View file

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

View file

@ -3,12 +3,16 @@ stn := @use("../../stn/src/lib.hb");
input := @use("../../intouch/src/lib.hb") input := @use("../../intouch/src/lib.hb")
widgets := @use("widgets.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): WindowID {
// 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
@ -16,10 +20,12 @@ create_window := fn(channel: int): void {
windowing_system_buffer := buffer.search("XHorizon\0") windowing_system_buffer := buffer.search("XHorizon\0")
if windowing_system_buffer == 0 { if windowing_system_buffer == 0 {
return return VoidWindowID
} else { } else {
msg := "\{01}\0" msg := "\{01}\0"
msg_length := 2 msg_length := 2
return @eca(3, windowing_system_buffer, msg, msg_length)
@as(void, @eca(3, windowing_system_buffer, msg, msg_length))
return WindowID.(1, 0)
} }
} }

View file

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

View file

@ -7,7 +7,7 @@ ApplicationInfo := struct {
pNext: ^int, 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,
} }

View file

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

View file

@ -0,0 +1,51 @@
.{Color} := @use("./lib.hb");
.{memory, log} := @use("../../stn/src/lib.hb")
Image := struct {
buf: ^Color,
width: i32,
height: i32,
}
BitmapFileHeader := packed struct {
img_type: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
from_bmp := fn(bmp: ^u8): Image {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return @as(Image, idk)
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
return .(@bitcast(bmp), @bitcast(info_header.width), @bitcast(info_header.height))
}

View file

@ -1,5 +1,6 @@
svga := @use("svga.hb") svga := @use("svga.hb")
software := @use("software.hb") software := @use("software.hb")
image := @use("image.hb")
// default mode // default mode
mode := software mode := software
@ -8,23 +9,24 @@ init := mode.init
doublebuffer := mode.doublebuffer doublebuffer := mode.doublebuffer
// Colours // Colours
Color := mode.Color Color := packed struct {b: u8, g: u8, r: u8, a: u8}
white := mode.white Image := image.Image
black := mode.black white := Color.(255, 255, 255, 255)
gray := mode.gray black := Color.(0, 0, 0, 255)
red := mode.red gray := Color.(127, 127, 127, 255)
green := mode.green red := Color.(0, 0, 205, 255)
yellow := mode.yellow green := Color.(0, 205, 0, 255)
blue := mode.blue yellow := Color.(0, 205, 205, 255)
magenta := mode.magenta blue := Color.(205, 0, 0, 255)
cyan := mode.cyan magenta := Color.(205, 0, 205, 255)
light_gray := mode.light_gray cyan := Color.(205, 205, 0, 255)
light_red := mode.light_red light_gray := Color.(229, 229, 229, 255)
light_green := mode.light_green light_red := Color.(0, 0, 255, 255)
light_yellow := mode.light_yellow light_green := Color.(0, 255, 0, 255)
light_blue := mode.light_blue light_yellow := Color.(0, 255, 255, 255)
light_magenta := mode.light_magenta light_blue := Color.(255, 0, 0, 255)
light_cyan := mode.light_cyan light_magenta := Color.(255, 0, 255, 255)
light_cyan := Color.(255, 255, 0, 255)
// Drawing // Drawing
put_pixel := mode.put_pixel put_pixel := mode.put_pixel
@ -35,7 +37,11 @@ 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_image := mode.put_image
// 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 width := mode.width
@ -44,10 +50,4 @@ dimensions := mode.dimensions
set_height := mode.set_height set_height := mode.set_height
set_width := mode.set_width set_width := mode.set_width
set_dimensions := mode.set_dimensions set_dimensions := mode.set_dimensions
sync := mode.sync sync := mode.sync
// Trash Image
Image := struct {
start: ^Color,
end: ^Color,
}

View file

@ -1,62 +1,31 @@
.{math, memory} := @use("../../stn/src/lib.hb"); .{math, memory, dt} := @use("../../stn/src/lib.hb");
.{dt_get} := @use("../../dt_api/src/lib.hb"); .{Color, Image} := @use("lib.hb");
.{Image} := @use("lib.hb");
.{Vec2} := math .{Vec2} := math
Color := struct {b: u8, g: u8, r: u8, a: u8}
white := Color.(255, 255, 255, 255)
black := Color.(0, 0, 0, 255)
gray := Color.(127, 127, 127, 255)
red := Color.(0, 0, 205, 255)
green := Color.(0, 205, 0, 255)
yellow := Color.(0, 205, 205, 255)
blue := Color.(205, 0, 0, 255)
magenta := Color.(205, 0, 205, 255)
cyan := Color.(205, 205, 0, 255)
light_gray := Color.(229, 229, 229, 255)
light_red := Color.(0, 0, 255, 255)
light_green := Color.(0, 255, 0, 255)
light_yellow := Color.(0, 255, 255, 255)
light_blue := Color.(255, 0, 0, 255)
light_magenta := Color.(255, 0, 255, 255)
light_cyan := Color.(255, 255, 0, 255)
// might not work for some resolutions, but needs to be comptime because...
copy_pixels := 0xC000 >> 2
ctx := @as(Context, idk) ctx := @as(Context, idk)
// some of these are redudant holdovers from fb_driver
// will keep them for future work if necessary
Context := struct { Context := struct {
fb: ^Color, fb: ^Color,
bb: ^Color, bb: ^Color,
buf: ^Color, buf: ^Color,
width: int, width: int,
height: int, height: int,
partitions: int,
pixels: int, pixels: int,
bb_pages: int,
double_buffer: bool, double_buffer: bool,
} }
init := fn(): void { init := fn(): void {
width := dt_get("framebuffer/fb0/width\0") width := dt.get(int, "framebuffer/fb0/width\0")
height := dt_get("framebuffer/fb0/height\0") height := dt.get(int, "framebuffer/fb0/height\0")
pixels := width * height pixels := width * height
bytes := pixels << 2 back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
partitions := pixels / copy_pixels
pages := 1 + bytes >> 12
back_buffer := create_back_buffer(pages)
ctx = Context.{ ctx = Context.{
fb: dt_get("framebuffer/fb0/ptr\0"), fb: dt.get(^Color, "framebuffer/fb0/ptr\0"),
bb: back_buffer, bb: back_buffer,
buf: back_buffer, buf: back_buffer,
width, width,
height, height,
partitions,
pixels, pixels,
bb_pages: pages,
double_buffer: true, double_buffer: true,
} }
return return
@ -72,60 +41,12 @@ doublebuffer := fn(enable: bool): void {
return return
} }
create_back_buffer := fn(pages: int): ^Color {
if pages <= 0xFF {
return @bitcast(@inline(memory.request_page, pages))
}
ptr := @inline(memory.request_page, 255)
remaining := pages - 0xFF
loop if remaining <= 0 break else {
if remaining < 0xFF {
memory.request_page(remaining)
} else {
memory.request_page(0xFF)
}
remaining -= 0xFF
}
return @bitcast(ptr)
}
clear := fn(color: Color): void { clear := fn(color: Color): void {
cursor := ctx.buf return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels))
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 { sync := fn(): void {
if ctx.double_buffer { return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels))
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 { width := fn(): int {
@ -149,55 +70,31 @@ put_pixel := fn(pos: Vec2(int), color: Color): void {
} }
put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
x := pos.x start_idx := @inline(screenidx, pos.x, pos.y)
y := pos.y end_idx := @inline(screenidx, pos.x, pos.y + tr.y)
end := pos + tr
loop if x == end.x break else { loop if start_idx >= end_idx break else {
loop if y == end.y break else { @inline(memory.set, Color, &color, ctx.buf + start_idx, @bitcast(tr.x))
*(ctx.buf + @inline(screenidx, x, y)) = color start_idx += ctx.width
y += 1
}
x += 1
y = pos.y
} }
return return
} }
put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
x := pos.x start_idx := @inline(screenidx, pos.x, pos.y)
y := pos.y end_idx := @inline(screenidx, pos.x, pos.y + tr.y)
end := pos + tr right_start_idx := @inline(screenidx, pos.x + tr.x, pos.y)
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 { loop if start_idx > end_idx break else {
step := Vec2(int).(1, 1) *(ctx.buf + start_idx) = color;
if size.x < 0 { *(ctx.buf + right_start_idx) = color
step.x = -1 start_idx += ctx.width
} right_start_idx += ctx.width
if size.y < 0 {
step.y = size.y / size.x
} }
start_y := pos.y @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y), @bitcast(tr.x + 1))
target := pos + size @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
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
} }
@ -315,6 +212,78 @@ set_dimensions := fn(new: Vec2(int)): void {
return return
} }
put_img := fn(img: Image, pos: Vec2(int)): void { put_image := fn(image: Image, pos: Vec2(int)): void {
// y := 0
// loop if y == image.height break else {
// @inline(memory.copy, Color, image.buf + y * image.width, ctx.buf + @inline(screenidx, pos.x, pos.y + image.height - y), @intcast(image.width))
// y += 1
// }
// return
start_idx := @inline(screenidx, pos.x, pos.y)
end_idx := @inline(screenidx, pos.x, pos.y + image.height)
cursor := image.width * image.height
loop if start_idx >= end_idx break else {
@inline(memory.copy, Color, image.buf + cursor, ctx.buf + start_idx, @intcast(image.width))
start_idx += ctx.width
cursor -= image.width
}
return
}
// peony-made
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)
@inline(put_vline, pos.x, pos.y, start_y, color1)
pos += step
}
return
}
// peony-made
put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
if y1 < y0 {
tmp := y0
y0 = y1
y1 = tmp
}
y := y0
loop if y == y1 break else {
*(ctx.buf + @inline(screenidx, x, y)) = color
y += 1
}
return
}
// peony-made
put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
if x1 < x0 {
tmp := x0
x0 = x1
x1 = tmp
}
x := x0
loop if x == x1 break else {
*(ctx.buf + @inline(screenidx, x, y)) = color
x += 1
}
return return
} }

View file

@ -1,23 +1,5 @@
.{Vec2, Image} := @use("lib.hb") .{Vec2} := @use("../../stn/src/lib.hb").math;
// .{pci, memory, string, log} := @use("../../stn/src/lib.hb"); .{Image, Color} := @use("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 { clear := fn(color: Color): void {
return return
@ -79,6 +61,18 @@ init := fn(): void {
return return
} }
put_img := fn(img: Image, pos: Vec2(int)): void { put_image := fn(img: Image, pos: Vec2(int)): void {
return
}
put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
return
}
put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
return
}
put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
return return
} }

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

View file

@ -1,9 +1,9 @@
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")
buffer := @use("buffer.hb") 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")

View file

@ -1,3 +1,24 @@
PAGE_SIZE := 4096
MAX_ALLOC := 0xFF
alloc := fn($Expr: type, bytes: int): ^Expr {
pages := (1 + bytes) / PAGE_SIZE
if pages <= MAX_ALLOC {
return @bitcast(@inline(request_page, pages))
}
ptr := @inline(request_page, 0xFF)
remaining := pages - MAX_ALLOC
loop if remaining <= 0 break else {
if remaining < MAX_ALLOC {
request_page(remaining)
} else {
request_page(MAX_ALLOC)
}
remaining -= MAX_ALLOC
}
return @bitcast(ptr)
}
request_page := fn(page_count: u8): ^u8 { request_page := fn(page_count: u8): ^u8 {
msg := "\{00}\{01}xxxxxxxx\0" msg := "\{00}\{01}xxxxxxxx\0"
msg_page_count := msg + 1; msg_page_count := msg + 1;
@ -36,4 +57,14 @@ outl := fn(addr: u16, value: u32): void {
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: uint, src: uint, dest: ^u8}
copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg))
}
SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8}
set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg))
} }

View file

@ -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(): int {
dt_api.dt_get("framebuffer/fb0/width\0") dt.get(int, "framebuffer/fb0/width\0")
dt_api.dt_get("cpu/cpu0/architecture\0") dt.get(int, "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(int, "serial_ports/sp0/mapping\0")
return 0 return 0
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View file

@ -0,0 +1,31 @@
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math
render := @use("../../../../libraries/render/src/lib.hb")
/* expected result:
a cute image bounces around the screen */
bmp := @embed("./able.bmp")
example := fn(): void {
render.init()
image := render.image.from_bmp(@bitcast(&bmp))
vel := Vec2(int).(1, 1)
pos := Vec2(int).(100, 100)
width := render.width()
height := render.height()
loop {
render.put_image(image, pos)
render.sync()
render.clear(render.black)
if pos.x == 0 | pos.x == width - image.width {
vel.x = -vel.x
}
if pos.y == 0 | pos.y == height - image.height {
vel.y = -vel.y
}
pos += vel
}
return
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View file

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

View file

@ -1,4 +1,4 @@
.{example} := @use("./examples/tactical_screen.hb") .{example} := @use("./examples/image.hb")
main := fn(): void { main := fn(): void {
@inline(example) @inline(example)

View file

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

View file

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

View file

@ -25,4 +25,4 @@ main := fn(): void {
} }
} }
return return
} }

View file

@ -6,8 +6,8 @@ verbose = false
interface_resolution = "1600x900x24" interface_resolution = "1600x900x24"
# interface_resolution = "640x480x32" # interface_resolution = "640x480x32"
# 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]
@ -35,11 +35,11 @@ path = "boot:///render_example.hbf"
# [boot.limine.ableos.modules.serial_driver_test] # [boot.limine.ableos.modules.serial_driver_test]
# path = "boot:///serial_driver_test.hbf" # path = "boot:///serial_driver_test.hbf"
# [boot.limine.ableos.modules.horizon] [boot.limine.ableos.modules.horizon]
# path = "boot:///horizon.hbf" path = "boot:///horizon.hbf"
# [boot.limine.ableos.modules.horizon_testing_program] [boot.limine.ableos.modules.horizon_testing_program]
# path = "boot:///horizon_testing_program.hbf" path = "boot:///horizon_testing_program.hbf"
# [boot.limine.ableos.modules.dt_buffer_test] # [boot.limine.ableos.modules.dt_buffer_test]
# path = "boot:///dt_buffer_test.hbf" # path = "boot:///dt_buffer_test.hbf"