diff --git a/Cargo.lock b/Cargo.lock
index bfd0b3e1..25cd7bfc 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 8d676927..0d077d36 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 935ca9ba..e99a1aa4 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 79a36149..94d65833 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 4420c29e..9963774e 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 8f2dffe3..9159c839 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 00000000..ee43be28
--- /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 5c0baed8..556387c6 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 a89057b7..01107dff 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 0790198e..033d7626 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 4cbdd6d8..21a0387f 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 00000000..6546d747
--- /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 00000000..7e0b4cee
Binary files /dev/null and b/sysdata/programs/render_example/src/examples/mini.bmp differ
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 00000000..4f227de2
--- /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 35b2706e..1ce2d4e6 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 d2a5f974..00000000
--- 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 e61324b3..00000000
--- 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