From 96c2bd5cd550fb224bd9c1f6bbd3aee90f17775f Mon Sep 17 00:00:00 2001
From: koniifer <aurlex1@gmail.com>
Date: Sun, 13 Oct 2024 23:38:43 +0100
Subject: [PATCH] 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

---
 Cargo.lock                                    |   6 +-
 kernel/src/holeybytes/ecah.rs                 |   8 +-
 .../holeybytes/kernel_services/mem_serve.rs   |  65 ++++--
 kernel/src/holeybytes/mem.rs                  |   1 -
 repbuild/src/main.rs                          |   7 +-
 sysdata/libraries/dt_api/src/lib.hb           |   2 +-
 sysdata/libraries/render/src/image.hb         |  51 +++++
 sysdata/libraries/render/src/lib.hb           |  50 ++---
 sysdata/libraries/render/src/software.hb      | 185 ++++++++----------
 sysdata/libraries/render/src/svga.hb          |  36 ++--
 sysdata/libraries/stn/src/memory.hb           |  31 +++
 .../render_example/src/examples/image.hb      |  31 +++
 .../render_example/src/examples/mini.bmp      | Bin 0 -> 102454 bytes
 .../src/examples/tactical_screen.hb           |  83 ++++++++
 sysdata/programs/render_example/src/main.hb   |   2 +-
 sysdata/programs/tetris/meta.toml             |  11 --
 sysdata/programs/tetris/src/main.hb           |  15 --
 17 files changed, 373 insertions(+), 211 deletions(-)
 create mode 100644 sysdata/libraries/render/src/image.hb
 create mode 100644 sysdata/programs/render_example/src/examples/image.hb
 create mode 100644 sysdata/programs/render_example/src/examples/mini.bmp
 create mode 100644 sysdata/programs/render_example/src/examples/tactical_screen.hb
 delete mode 100644 sysdata/programs/tetris/meta.toml
 delete mode 100644 sysdata/programs/tetris/src/main.hb

diff --git a/Cargo.lock b/Cargo.lock
index bfd0b3e..25cd7bf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -350,12 +350,12 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
 [[package]]
 name = "hbbytecode"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
 
 [[package]]
 name = "hblang"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
 dependencies = [
  "hashbrown 0.15.0",
  "hbbytecode",
@@ -367,7 +367,7 @@ dependencies = [
 [[package]]
 name = "hbvm"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
 dependencies = [
  "hbbytecode",
 ]
diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs
index 8d67692..0d077d3 100644
--- a/kernel/src/holeybytes/ecah.rs
+++ b/kernel/src/holeybytes/ecah.rs
@@ -97,7 +97,8 @@ pub fn handler(vm: &mut Vm) {
                     match msg_type {
                         0 => unsafe {
                             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 {
                                 0 => x86_in::<u8>(addr) as u64,
                                 1 => x86_in::<u16>(addr) as u64,
@@ -109,7 +110,8 @@ pub fn handler(vm: &mut Vm) {
                         },
                         1 => unsafe {
                             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);
 
                             match size {
@@ -173,7 +175,7 @@ pub fn handler(vm: &mut Vm) {
                 Ok(msg) => msg,
                 Err(_) => return,
             };
-            if msg.len() > max_length.try_into().unwrap() {
+            if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } {
                 info!("{}", max_length);
                 error!("Message is too long to map in.");
             } else {
diff --git a/kernel/src/holeybytes/kernel_services/mem_serve.rs b/kernel/src/holeybytes/kernel_services/mem_serve.rs
index 935ca9b..e99a1aa 100644
--- a/kernel/src/holeybytes/kernel_services/mem_serve.rs
+++ b/kernel/src/holeybytes/kernel_services/mem_serve.rs
@@ -32,40 +32,37 @@ pub fn memory_msg_handler(
     let msg_vec = block_read(mem_addr, length);
     let msg_type = msg_vec[0];
     match msg_type {
-        0 => {
+        0 => unsafe {
             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 = unsafe {
-                alloc(Layout::from_size_align_unchecked(
-                    page_count as usize * 4096,
-                    4096,
-                ))
-            };
+            let ptr = alloc(Layout::from_size_align_unchecked(
+                page_count as usize * 4096,
+                4096,
+            ));
 
             vm.registers[1] = hbvm::value::Value(ptr as u64);
             log::debug!("Kernel ptr: {:x}", ptr as u64);
-        }
+        },
 
-        1 => {
+        1 => unsafe {
             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!("Deallocating {} pages @ {:x}", page_count, mptr);
-            unsafe {
-                dealloc(
-                    mptr as *mut u8,
-                    Layout::from_size_align_unchecked(page_count as usize * 4096, 4096),
-                )
-            }
-        }
+
+            dealloc(
+                mptr as *mut u8,
+                Layout::from_size_align_unchecked(page_count as usize * 4096, 4096),
+            )
+        },
         2 => {
             use MemoryQuotaType::*;
-            let quota_type = match msg_vec[0] {
+            let quota_type = match msg_vec[1] {
                 0 => NoQuota,
                 1 => SoftQuota,
                 2 => HardQuota,
@@ -82,10 +79,42 @@ pub fn memory_msg_handler(
             )
         }
         3 => {
-            let page_count = msg_vec[0];
+            let page_count = msg_vec[1];
             log::debug!(" {} pages", page_count);
         }
+        // memcpy
+        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;
+            src.copy_to(dest, count);
+        },
+        // memset
+        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 dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8;
+            let src = u64::from_le_bytes(msg_vec[25..33].try_into().unwrap_unchecked()) as *mut u8;
 
+            let total_size = count * size;
+
+            if total_size > 32 {
+                core::ptr::copy(src, dest, size);
+                let pattern = core::slice::from_raw_parts(dest, size);
+                let mut offset = size;
+
+                while offset < total_size {
+                    let remaining = total_size - offset;
+                    let copy_size = remaining.min(offset);
+                    core::ptr::copy_nonoverlapping(pattern.as_ptr(), dest.add(offset), copy_size);
+                    offset += copy_size;
+                }
+            } else {
+                for i in 0..total_size {
+                    *dest.add(i) = *src.add(i % size);
+                }
+            }
+        },
         _ => {
             log::debug!("Unknown memory service message type: {}", msg_type);
         }
diff --git a/kernel/src/holeybytes/mem.rs b/kernel/src/holeybytes/mem.rs
index 79a3614..94d6583 100644
--- a/kernel/src/holeybytes/mem.rs
+++ b/kernel/src/holeybytes/mem.rs
@@ -37,7 +37,6 @@ impl hbvm::mem::Memory for Memory {
         target: *mut u8,
         count: usize,
     ) -> Result<(), hbvm::mem::LoadError> {
-        // if addr.get() % 4096 == 0 {}
         core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count);
         Ok(())
     }
diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs
index 4420c29..9963774 100644
--- a/repbuild/src/main.rs
+++ b/repbuild/src/main.rs
@@ -395,12 +395,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
                 "-parallel", "none",
                 "-monitor", "none",
                 "-machine", accel,
-                "-cpu",
-                if accel != "accel=tcg" {
-                    "host"
-                } else {
-                    "Broadwell-v4"
-                },
+                "-cpu", "max",
                 "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04",
             ]);
         }
diff --git a/sysdata/libraries/dt_api/src/lib.hb b/sysdata/libraries/dt_api/src/lib.hb
index 8f2dffe..9159c83 100644
--- a/sysdata/libraries/dt_api/src/lib.hb
+++ b/sysdata/libraries/dt_api/src/lib.hb
@@ -1,6 +1,6 @@
 .{string} := @use("../../stn/src/lib.hb")
 
-dt_get := fn(query: ^u8): int {
+dt_get := fn($Expr: type, query: ^u8): Expr {
 	length := string.length(query)
 	return @eca(3, 5, query, length)
 }
\ No newline at end of file
diff --git a/sysdata/libraries/render/src/image.hb b/sysdata/libraries/render/src/image.hb
new file mode 100644
index 0000000..ee43be2
--- /dev/null
+++ b/sysdata/libraries/render/src/image.hb
@@ -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))
+}
\ No newline at end of file
diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb
index 5c0baed..556387c 100644
--- a/sysdata/libraries/render/src/lib.hb
+++ b/sysdata/libraries/render/src/lib.hb
@@ -1,5 +1,6 @@
 svga := @use("svga.hb")
 software := @use("software.hb")
+image := @use("image.hb")
 
 // default mode
 mode := software
@@ -8,23 +9,24 @@ init := mode.init
 doublebuffer := mode.doublebuffer
 
 // Colours
-Color := mode.Color
-white := mode.white
-black := mode.black
-gray := mode.gray
-red := mode.red
-green := mode.green
-yellow := mode.yellow
-blue := mode.blue
-magenta := mode.magenta
-cyan := mode.cyan
-light_gray := mode.light_gray
-light_red := mode.light_red
-light_green := mode.light_green
-light_yellow := mode.light_yellow
-light_blue := mode.light_blue
-light_magenta := mode.light_magenta
-light_cyan := mode.light_cyan
+Color := packed struct {b: u8, g: u8, r: u8, a: u8}
+Image := image.Image
+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)
 
 // Drawing
 put_pixel := mode.put_pixel
@@ -32,7 +34,11 @@ put_rect := mode.put_rect
 put_filled_rect := mode.put_filled_rect
 put_line := mode.put_line
 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
 width := mode.width
@@ -41,10 +47,4 @@ dimensions := mode.dimensions
 set_height := mode.set_height
 set_width := mode.set_width
 set_dimensions := mode.set_dimensions
-sync := mode.sync
-
-// Trash Image
-Image := struct {
-	start: ^Color,
-	end: ^Color,
-}
\ No newline at end of file
+sync := mode.sync
\ No newline at end of file
diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb
index a89057b..01107df 100644
--- a/sysdata/libraries/render/src/software.hb
+++ b/sysdata/libraries/render/src/software.hb
@@ -1,62 +1,32 @@
 .{math, memory} := @use("../../stn/src/lib.hb");
 .{dt_get} := @use("../../dt_api/src/lib.hb");
-.{Image} := @use("lib.hb");
+.{Color, Image} := @use("lib.hb");
 .{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)
 
-// 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,
 	width: int,
 	height: int,
-	partitions: int,
 	pixels: int,
-	bb_pages: int,
 	double_buffer: bool,
 }
 
 init := fn(): void {
-	width := dt_get("framebuffer/fb0/width\0")
-	height := dt_get("framebuffer/fb0/height\0")
+	width := dt_get(int, "framebuffer/fb0/width\0")
+	height := dt_get(int, "framebuffer/fb0/height\0")
 	pixels := width * height
-	bytes := pixels << 2
-	partitions := pixels / copy_pixels
-	pages := 1 + bytes >> 12
-	back_buffer := create_back_buffer(pages)
+	back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
 	ctx = Context.{
-		fb: dt_get("framebuffer/fb0/ptr\0"),
+		fb: dt_get(^Color, "framebuffer/fb0/ptr\0"),
 		bb: back_buffer,
 		buf: back_buffer,
 		width,
 		height,
-		partitions,
 		pixels,
-		bb_pages: pages,
 		double_buffer: true,
 	}
 	return
@@ -72,60 +42,12 @@ doublebuffer := fn(enable: bool): void {
 	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 {
-	cursor := ctx.buf
-	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
+	return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels))
 }
 
 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
+	return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels))
 }
 
 width := fn(): int {
@@ -146,35 +68,25 @@ put_pixel := fn(pos: Vec2(int), color: Color): void {
 }
 
 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
+	end_y := y + tr.y
+	loop if y == end_y break else {
+		@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x))
+		y += 1
 	}
 	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
+	end_y := y + tr.y
+	loop if y == end_y break else {
+		*(ctx.buf + @inline(screenidx, pos.x, y)) = color;
+		*(ctx.buf + @inline(screenidx, pos.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
-	}
+	@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x))
+	@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y - tr.y), @bitcast(tr.x))
 	return
 }
 
@@ -259,6 +171,67 @@ set_dimensions := fn(new: Vec2(int)): void {
 	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
+}
+
+// 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
 }
\ No newline at end of file
diff --git a/sysdata/libraries/render/src/svga.hb b/sysdata/libraries/render/src/svga.hb
index 0790198..033d762 100644
--- a/sysdata/libraries/render/src/svga.hb
+++ b/sysdata/libraries/render/src/svga.hb
@@ -1,23 +1,5 @@
-.{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)
+.{Vec2} := @use("../../stn/src/lib.hb").math;
+.{Image, Color} := @use("lib.hb")
 
 clear := fn(color: Color): void {
 	return
@@ -79,6 +61,18 @@ init := fn(): void {
 	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
 }
\ No newline at end of file
diff --git a/sysdata/libraries/stn/src/memory.hb b/sysdata/libraries/stn/src/memory.hb
index 4cbdd6d..21a0387 100644
--- a/sysdata/libraries/stn/src/memory.hb
+++ b/sysdata/libraries/stn/src/memory.hb
@@ -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 {
 	msg := "\{00}\{01}xxxxxxxx\0"
 	msg_page_count := msg + 1;
@@ -36,4 +57,14 @@ outl := fn(addr: u16, value: u32): void {
 
 inl := fn(addr: u16): u32 {
 	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, dest: ^u8, src: ^u8}
+set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void {
+	return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(dest), @bitcast(src)), @sizeof(SetMsg))
 }
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/image.hb b/sysdata/programs/render_example/src/examples/image.hb
new file mode 100644
index 0000000..6546d74
--- /dev/null
+++ b/sysdata/programs/render_example/src/examples/image.hb
@@ -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 */
+
+mini_bmp := @embed("./mini.bmp")
+
+example := fn(): void {
+	render.init()
+	mini := render.image.from_bmp(@bitcast(&mini_bmp))
+	vel := Vec2(int).(1, 1)
+	pos := Vec2(int).(100, 100)
+	width := render.width()
+	height := render.height()
+	loop {
+		render.put_image(mini, pos)
+		render.sync()
+		render.clear(render.black)
+
+		if pos.x == 0 | pos.x == width - mini.width {
+			vel.x = -vel.x
+		}
+		if pos.y == 0 | pos.y == height - mini.height {
+			vel.y = -vel.y
+		}
+
+		pos += vel
+	}
+	return
+}
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/mini.bmp b/sysdata/programs/render_example/src/examples/mini.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..7e0b4ceec3f9c4bdab3a64aa01c75826149183ac
GIT binary patch
literal 102454
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
X^XDOEuT^AZWLDtJYJIDO@b~`!1F?>E

literal 0
HcmV?d00001

diff --git a/sysdata/programs/render_example/src/examples/tactical_screen.hb b/sysdata/programs/render_example/src/examples/tactical_screen.hb
new file mode 100644
index 0000000..4f227de
--- /dev/null
+++ b/sysdata/programs/render_example/src/examples/tactical_screen.hb
@@ -0,0 +1,83 @@
+render := @use("../../../../libraries/render/src/lib.hb");
+.{math, random} := @use("../../../../libraries/stn/src/lib.hb")
+Vec2 := math.Vec2
+
+/* expected result:
+   a grid of green lines scrolling from the left top corner to the right bottom one
+   with a "target" randomly apperaing in one of them and a "seeker" "catching" it*/
+
+example := fn(): void {
+	render.init()
+
+	width := render.width()
+	height := render.height()
+	cell_size := 0
+	range := Vec2(int).(0, 0)
+	if width > height {
+		cell_size = width / 40
+		range = .(39, height / cell_size - 1)
+	} else {
+		cell_size = height / 40
+		range = .(width / cell_size - 1, 39)
+	}
+	width -= 1
+	height -= 1
+
+	scroll := 0
+	target := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y))
+
+	halfcell := cell_size / 2
+	octcell := cell_size / 8
+	sevenoctcell := cell_size - octcell
+
+	seeker := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y))
+
+	loop {
+		render.clear(render.black)
+
+		target_pixel_coord := target * .(cell_size, cell_size) + .(scroll, scroll)
+		render.put_trirect(target_pixel_coord, .(cell_size, 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(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(target_pixel_coord.x + halfcell, target_pixel_coord.y + cell_size + octcell, target_pixel_coord.y + cell_size + sevenoctcell, render.light_red)
+
+		x := scroll
+		loop if x > width break else {
+			render.put_vline(x, 0, height, .(0, 127, 0, 127))
+			x += cell_size
+		}
+
+		y := scroll
+		loop if y > height break else {
+			render.put_hline(y, 0, width, .(0, 127, 0, 127))
+			y += cell_size
+		}
+
+		render.put_hline(seeker.y * cell_size + halfcell + scroll, 0, width, render.light_green)
+		render.put_vline(seeker.x * cell_size + halfcell + scroll, 0, height, render.light_green)
+
+		render.sync()
+
+		if seeker.x < target.x {
+			seeker.x += 1
+		} else if seeker.x > target.x {
+			seeker.x -= 1
+		} else if seeker.y < target.y {
+			seeker.y += 1
+		} else if seeker.y > target.y {
+			seeker.y -= 1
+		} else {
+			target = .(random.range(int, 0, range.x), random.range(int, 0, range.y))
+		}
+
+		scroll += 1
+		if scroll > cell_size {
+			scroll = 0
+			target += .(1, 1)
+			seeker += .(1, 1)
+		}
+	}
+	return
+}
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb
index 35b2706..1ce2d4e 100644
--- a/sysdata/programs/render_example/src/main.hb
+++ b/sysdata/programs/render_example/src/main.hb
@@ -1,4 +1,4 @@
-.{example} := @use("./examples/amogus.hb")
+.{example} := @use("./examples/image.hb")
 
 main := fn(): void {
 	@inline(example)
diff --git a/sysdata/programs/tetris/meta.toml b/sysdata/programs/tetris/meta.toml
deleted file mode 100644
index d2a5f97..0000000
--- a/sysdata/programs/tetris/meta.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "tetris"
-authors = ["peony"]
-
-[dependants.libraries]
-
-[dependants.binaries]
-hblang.version = "1.0.0"
-
-[build]
-command = "hblang src/main.hb"
diff --git a/sysdata/programs/tetris/src/main.hb b/sysdata/programs/tetris/src/main.hb
deleted file mode 100644
index e61324b..0000000
--- a/sysdata/programs/tetris/src/main.hb
+++ /dev/null
@@ -1,15 +0,0 @@
-.{memory, log, string, buffer} := @use("../../../libraries/stn/src/lib.hb")
-
-main := fn(): void {
-	storage := @as(u8, 0)
-	output_buffer := memory.request_page(1)
-	input_buffer := buffer.search("XKeyboard\0")
-	loop {
-		buffer.recv(input_buffer, &storage, 1)
-		if storage != 0 {
-			log.info(string.display_int(storage, output_buffer))
-			storage = 0
-		}
-	}
-	return
-}
\ No newline at end of file