diff --git a/Cargo.lock b/Cargo.lock
index 25cd7bf..bc371f9 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#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000"
 
 [[package]]
 name = "hblang"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000"
 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#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000"
 dependencies = [
  "hbbytecode",
 ]
@@ -985,9 +985,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.17"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
 
 [[package]]
 name = "ryu"
diff --git a/sysdata/libraries/render/src/image.hb b/sysdata/libraries/render/src/image.hb
index ee43be2..1f55cbd 100644
--- a/sysdata/libraries/render/src/image.hb
+++ b/sysdata/libraries/render/src/image.hb
@@ -1,11 +1,5 @@
-.{Color} := @use("./lib.hb");
-.{memory, log} := @use("../../stn/src/lib.hb")
-
-Image := struct {
-	buf: ^Color,
-	width: i32,
-	height: i32,
-}
+.{Color, Surface} := @use("./lib.hb");
+.{log} := @use("../../stn/src/lib.hb")
 
 BitmapFileHeader := packed struct {
 	img_type: u16,
@@ -38,14 +32,35 @@ BitmapColorHeader := packed struct {
 	unused: u32,
 }
 
-from_bmp := fn(bmp: ^u8): Image {
+surface_from_bmp := fn(bmp: ^u8): Surface {
 	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)
+		return @as(Surface, idk)
 	}
 	info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
 	bmp += file_header.offset
 
-	return .(@bitcast(bmp), @bitcast(info_header.width), @bitcast(info_header.height))
+	a := 0
+	px := info_header.width * info_header.height
+	ptr := @as(^Color, @bitcast(bmp))
+	tmp := @as(Color, idk)
+	row := 0
+
+	loop if row == info_header.height / 2 break else {
+		col := 0
+		loop if col == info_header.width break else {
+			top_index := row * info_header.width + col
+			bottom_index := (info_header.height - 1 - row) * info_header.width + col
+
+			tmp = *(ptr + top_index);
+			*(ptr + top_index) = *(ptr + bottom_index);
+			*(ptr + bottom_index) = tmp
+
+			col += 1
+		}
+		row += 1
+	}
+
+	return .(@bitcast(bmp), @intcast(info_header.width), @intcast(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 556387c..3bb56c3 100644
--- a/sysdata/libraries/render/src/lib.hb
+++ b/sysdata/libraries/render/src/lib.hb
@@ -1,4 +1,4 @@
-svga := @use("svga.hb")
+.{memory} := @use("../../stn/src/lib.hb")
 software := @use("software.hb")
 image := @use("image.hb")
 
@@ -8,9 +8,36 @@ mode := software
 init := mode.init
 doublebuffer := mode.doublebuffer
 
+Surface := struct {
+	buf: ^Color,
+	width: int,
+	height: int,
+}
+
+new_surface := fn(width: int, height: int): Surface {
+	return .(
+		@inline(memory.alloc, Color, width * height * @bitcast(@sizeof(Color))),
+		width,
+		height,
+	)
+}
+
+surface_from_ptr := fn(ptr: ^Color, width: int, height: int): Surface {
+	return .(
+		ptr,
+		width,
+		height,
+	)
+}
+
+clone_surface := fn(surface: Surface): Surface {
+	new := new_surface(surface.width, surface.height)
+	@inline(memory.copy, Color, surface.buf, new.buf, @intcast(surface.width * surface.height))
+	return new
+}
+
 // Colours
 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)
@@ -34,17 +61,17 @@ put_rect := mode.put_rect
 put_filled_rect := mode.put_filled_rect
 put_line := mode.put_line
 clear := mode.clear
-put_image := mode.put_image
+put_surface := mode.put_surface
 // thanks peony for these three!
 put_trirect := mode.put_trirect
 put_vline := mode.put_vline
 put_hline := mode.put_hline
 
 // 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
+// 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
\ No newline at end of file
diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb
index aa83562..3dcbd09 100644
--- a/sysdata/libraries/render/src/software.hb
+++ b/sysdata/libraries/render/src/software.hb
@@ -1,102 +1,109 @@
 .{math, memory, dt} := @use("../../stn/src/lib.hb");
-.{Color, Image} := @use("lib.hb");
+.{Color, Surface, new_surface} := @use("lib.hb");
 .{Vec2} := math
 
-ctx := @as(Context, idk)
+framebuffer := @as(^Color, idk)
 
-Context := struct {
-	fb: ^Color,
-	bb: ^Color,
-	buf: ^Color,
-	width: int,
-	height: int,
-	pixels: int,
-	double_buffer: bool,
-}
+// init := fn(): void {
+// 	width := dt.get(int, "framebuffer/fb0/width\0")
+// 	height := dt.get(int, "framebuffer/fb0/height\0")
+// 	pixels := width * height
+// 	back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
+// 	ctx = Context.{
+// 		fb: dt.get(^Color, "framebuffer/fb0/ptr\0"),
+// 		bb: back_buffer,
+// 		buf: back_buffer,
+// 		width,
+// 		height,
+// 		pixels,
+// 		double_buffer: true,
+// 	}
+// 	return
+// }
 
-init := fn(): void {
+init := fn(double_buffer: bool): Surface {
+	framebuffer = dt.get(^Color, "framebuffer/fb0/ptr\0")
 	width := dt.get(int, "framebuffer/fb0/width\0")
 	height := dt.get(int, "framebuffer/fb0/height\0")
-	pixels := width * height
-	back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
-	ctx = Context.{
-		fb: dt.get(^Color, "framebuffer/fb0/ptr\0"),
-		bb: back_buffer,
-		buf: back_buffer,
-		width,
-		height,
-		pixels,
-		double_buffer: true,
-	}
-	return
-}
-
-doublebuffer := fn(enable: bool): void {
-	if enable {
-		ctx.buf = ctx.bb
+	if double_buffer {
+		return new_surface(width, height)
 	} 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, @bitcast(surface.width * surface.height))
+}
+
+sync := fn(surface: Surface): void {
+	return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
+}
+
+screenidx := fn(surface: Surface, x: int, y: int): int {
+	return x + surface.width * y
+}
+
+put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void {
+	*(surface.buf + @inline(screenidx, surface, pos.x, pos.y)) = color
 	return
 }
 
-clear := fn(color: Color): void {
-	return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels))
-}
+// put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
+// 	start_idx := @inline(screenidx, surface, pos.x, pos.y)
+// 	end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y)
 
-sync := fn(): void {
-	return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels))
-}
+// 	loop if start_idx >= end_idx break else {
+// 		@inline(memory.set, Color, &color, surface.buf + start_idx, @bitcast(tr.x))
+// 		start_idx += surface.width
+// 	}
 
-width := fn(): int {
-	return ctx.width
-}
+// 	return
+// }
 
-height := fn(): int {
-	return ctx.height
-}
+put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
+	top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
+	bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y - 1)
+	rows_to_fill := tr.y / 2
+	top_cursor := 0
+	bottom_cursor := (tr.y - 1) * surface.width
+	i := 0
+	loop if i == rows_to_fill break else {
+		@inline(memory.set, Color, &color, surface.buf + top_start_idx, @bitcast(tr.x))
+		@inline(memory.set, Color, &color, surface.buf + bottom_start_idx, @bitcast(tr.x))
 
-screenidx := fn(x: int, y: int): int {
-	return x + ctx.width * y
-}
+		top_start_idx += surface.width
+		bottom_start_idx -= surface.width
+		i += 1
+	}
 
-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 {
-	start_idx := @inline(screenidx, pos.x, pos.y)
-	end_idx := @inline(screenidx, pos.x, pos.y + tr.y)
-
-	loop if start_idx >= end_idx break else {
-		@inline(memory.set, Color, &color, ctx.buf + start_idx, @bitcast(tr.x))
-		start_idx += ctx.width
+	if tr.y % 2 != 0 {
+		middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_fill)
+		@inline(memory.set, Color, &color, surface.buf + middle_idx, @bitcast(tr.x))
 	}
 
 	return
 }
 
-put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
-	start_idx := @inline(screenidx, pos.x, pos.y)
-	end_idx := @inline(screenidx, pos.x, pos.y + tr.y)
-	right_start_idx := @inline(screenidx, pos.x + tr.x, pos.y)
+put_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
+	start_idx := @inline(screenidx, surface, pos.x, pos.y)
+	end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y)
+	right_start_idx := @inline(screenidx, surface, pos.x + tr.x, pos.y)
 
 	loop if start_idx > end_idx break else {
-		*(ctx.buf + start_idx) = color;
-		*(ctx.buf + right_start_idx) = color
-		start_idx += ctx.width
-		right_start_idx += ctx.width
+		*(surface.buf + start_idx) = color;
+		*(surface.buf + right_start_idx) = color
+		start_idx += surface.width
+		right_start_idx += surface.width
 	}
 
-	@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y), @bitcast(tr.x + 1))
-	@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
+	@inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y), @bitcast(tr.x + 1))
+	@inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
 
 	return
 }
 
-put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
+put_line_low := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	dx := p1.x - p0.x
 	dy := p1.y - p0.y
 	yi := 1
@@ -108,7 +115,7 @@ put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	y := p0.y
 	x := p0.x
 	loop if x == p1.x break else {
-		*(ctx.buf + @inline(screenidx, x, y)) = color
+		*(surface.buf + @inline(screenidx, surface, x, y)) = color
 		if D > 0 {
 			y += yi
 			D += 2 * (dy - dx)
@@ -120,7 +127,7 @@ put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	return
 }
 
-put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
+put_line_high := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	dx := p1.x - p0.x
 	dy := p1.y - p0.y
 	xi := 1
@@ -132,7 +139,7 @@ put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	x := p0.x
 	y := p0.y
 	loop if y == p1.y break else {
-		*(ctx.buf + @inline(screenidx, x, y)) = color
+		*(surface.buf + @inline(screenidx, surface, x, y)) = color
 		if D > 0 {
 			x += xi
 			D += 2 * (dx - dy)
@@ -144,61 +151,64 @@ 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 {
+put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): void {
 	if math.abs(int, p1.y - p0.y) < math.abs(int, p1.x - p0.x) {
 		if p0.x > p1.x {
-			@inline(put_line_low, p1, p0, color)
+			@inline(put_line_low, surface, p1, p0, color)
 		} else {
-			@inline(put_line_low, p0, p1, color)
+			@inline(put_line_low, surface, p0, p1, color)
 		}
 	} else {
 		if p0.y > p1.y {
-			@inline(put_line_high, p1, p0, color)
+			@inline(put_line_high, surface, p1, p0, color)
 		} else {
-			@inline(put_line_high, p0, p1, color)
+			@inline(put_line_high, surface, p0, p1, color)
 		}
 	}
 	return
 }
 
-set_height := fn(new: int): void {
-	return
-}
+// put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
+// 	start_idx := @inline(screenidx, surface, pos.x, pos.y)
+// 	end_idx := @inline(screenidx, surface, pos.x, pos.y + top.height)
+// 	cursor := top.width * top.height
 
-set_width := fn(new: int): void {
-	return
-}
+// 	loop if start_idx >= end_idx break else {
+// 		@inline(memory.copy, Color, top.buf + cursor, surface.buf + start_idx, @intcast(top.width))
+// 		start_idx += surface.width
+// 		cursor -= top.width
+// 	}
+// 	return
+// }
 
-dimensions := fn(): Vec2(int) {
-	return .(ctx.width, ctx.height)
-}
+put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void {
+	top_start_idx := @inline(screenidx, surface, pos.x, pos.y)
+	bottom_start_idx := @inline(screenidx, surface, pos.x, pos.y + top.height - 1)
+	rows_to_copy := top.height / 2
+	top_cursor := 0
+	bottom_cursor := top.width * (top.height - 1)
+	i := 0
+	loop if i == rows_to_copy break else {
+		@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + top_start_idx, @intcast(top.width))
+		@inline(memory.copy, Color, top.buf + bottom_cursor, surface.buf + bottom_start_idx, @intcast(top.width))
 
-set_dimensions := fn(new: Vec2(int)): void {
-	return
-}
-
-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
+		top_start_idx += surface.width
+		bottom_start_idx -= surface.width
+		top_cursor += top.width
+		bottom_cursor -= top.width
+		i += 1
 	}
+
+	if top.height % 2 != 0 {
+		middle_idx := @inline(screenidx, surface, pos.x, pos.y + rows_to_copy)
+		@inline(memory.copy, Color, top.buf + top_cursor, surface.buf + middle_idx, @intcast(top.width))
+	}
+
 	return
 }
 
 // peony-made
-put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
+put_trirect := fn(surface: Surface, pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
 	step := Vec2(int).(1, 1)
 	if size.x < 0 {
 		step.x = -1
@@ -211,8 +221,8 @@ put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color)
 	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)
+		put_vline(surface, pos.x, pos.y, target.y, color0)
+		@inline(put_vline, surface, pos.x, pos.y, start_y, color1)
 		pos += step
 	}
 
@@ -220,7 +230,7 @@ put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color)
 }
 
 // peony-made
-put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
+put_vline := fn(surface: Surface, x: int, y0: int, y1: int, color: Color): void {
 	if y1 < y0 {
 		tmp := y0
 		y0 = y1
@@ -229,7 +239,7 @@ put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
 	y := y0
 
 	loop if y == y1 break else {
-		*(ctx.buf + @inline(screenidx, x, y)) = color
+		*(surface.buf + @inline(screenidx, surface, x, y)) = color
 		y += 1
 	}
 
@@ -237,7 +247,7 @@ put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
 }
 
 // peony-made
-put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
+put_hline := fn(surface: Surface, y: int, x0: int, x1: int, color: Color): void {
 	if x1 < x0 {
 		tmp := x0
 		x0 = x1
@@ -246,7 +256,7 @@ put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
 	x := x0
 
 	loop if x == x1 break else {
-		*(ctx.buf + @inline(screenidx, x, y)) = color
+		*(surface.buf + @inline(screenidx, surface, x, y)) = color
 		x += 1
 	}
 
diff --git a/sysdata/libraries/render/src/svga.hb b/sysdata/libraries/render/src/svga.hb
deleted file mode 100644
index 033d762..0000000
--- a/sysdata/libraries/render/src/svga.hb
+++ /dev/null
@@ -1,78 +0,0 @@
-.{Vec2} := @use("../../stn/src/lib.hb").math;
-.{Image, Color} := @use("lib.hb")
-
-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_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 9167b32..9b89cbe 100644
--- a/sysdata/libraries/stn/src/memory.hb
+++ b/sysdata/libraries/stn/src/memory.hb
@@ -2,7 +2,7 @@ PAGE_SIZE := 4096
 MAX_ALLOC := 0xFF
 
 alloc := fn($Expr: type, bytes: int): ^Expr {
-	pages := (1 + bytes) / PAGE_SIZE
+	pages := 1 + bytes / PAGE_SIZE
 	if pages <= MAX_ALLOC {
 		return @bitcast(@inline(request_page, pages))
 	}
diff --git a/sysdata/programs/render_example/src/examples/able.bmp b/sysdata/programs/render_example/src/examples/able.bmp
index 7de373d..059086b 100644
Binary files a/sysdata/programs/render_example/src/examples/able.bmp and b/sysdata/programs/render_example/src/examples/able.bmp differ
diff --git a/sysdata/programs/render_example/src/examples/amogus.hb b/sysdata/programs/render_example/src/examples/amogus.hb
index eca4e48..eb68a10 100644
--- a/sysdata/programs/render_example/src/examples/amogus.hb
+++ b/sysdata/programs/render_example/src/examples/amogus.hb
@@ -4,16 +4,16 @@ render := @use("../../../../libraries/render/src/lib.hb")
    the impostor travels left and loops around the screen */
 
 example := fn(): void {
-	render.init()
+	screen := render.init(true)
 	x := 0
 	loop {
-		render.put_rect(.(200 - x, 80), .(430, 380), render.red)
-		render.put_rect(.(630 - x, 120), .(120, 300), render.red)
-		render.put_rect(.(200 - x, 460), .(160, 270), render.red)
-		render.put_rect(.(470 - x, 460), .(160, 270), render.red)
-		render.put_rect(.(140 - x, 140), .(340, 250), render.cyan)
-		render.sync()
-		render.clear(render.black)
+		render.put_rect(screen, .(200 - x, 80), .(430, 380), render.red)
+		render.put_rect(screen, .(630 - x, 120), .(120, 300), render.red)
+		render.put_rect(screen, .(200 - x, 460), .(160, 270), render.red)
+		render.put_rect(screen, .(470 - x, 460), .(160, 270), render.red)
+		render.put_rect(screen, .(140 - x, 140), .(340, 250), render.cyan)
+		render.sync(screen)
+		render.clear(screen, render.black)
 		x += 1
 	}
 	return
diff --git a/sysdata/programs/render_example/src/examples/colors.hb b/sysdata/programs/render_example/src/examples/colors.hb
index 9f8bbd7..bb23933 100644
--- a/sysdata/programs/render_example/src/examples/colors.hb
+++ b/sysdata/programs/render_example/src/examples/colors.hb
@@ -6,12 +6,12 @@ render := @use("../../../../libraries/render/src/lib.hb")
    note that this may happen too fast for you to notice... */
 
 example := fn(): void {
-	render.init()
+	screen := render.init(true)
 	color := render.light_cyan
 	n := @as(u8, 1)
 	loop {
-		render.clear(color)
-		render.sync()
+		render.clear(screen, color)
+		render.sync(screen)
 		if (color.b & 255) == 255 | (color.b & 255) == 0 {
 			n = -n
 		}
diff --git a/sysdata/programs/render_example/src/examples/image.hb b/sysdata/programs/render_example/src/examples/image.hb
index 689fbb7..b1ac1de 100644
--- a/sysdata/programs/render_example/src/examples/image.hb
+++ b/sysdata/programs/render_example/src/examples/image.hb
@@ -4,25 +4,31 @@ render := @use("../../../../libraries/render/src/lib.hb")
 /* expected result:
    a cute image bounces around the screen */
 
-bmp := @embed("./able.bmp")
+bmp_1 := @embed("./able.bmp")
+bmp_2 := @embed("./mini.bmp")
 
 example := fn(): void {
-	render.init()
-	image := render.image.from_bmp(@bitcast(&bmp))
+	screen := render.init(true)
+	images := [render.Surface; 2].(
+		render.image.surface_from_bmp(@bitcast(&bmp_1)),
+		render.image.surface_from_bmp(@bitcast(&bmp_2)),
+	)
 	vel := Vec2(int).(1, 1)
 	pos := Vec2(int).(100, 100)
-	width := render.width()
-	height := render.height()
+	n := -1
 	loop {
-		render.put_image(image, pos)
-		render.sync()
-		render.clear(render.black)
+		image := images[n]
+		render.put_surface(screen, image, pos)
+		render.sync(screen)
+		render.clear(screen, render.black)
 
-		if pos.x == 0 | pos.x == width - image.width {
+		if pos.x == 0 | pos.x == screen.width - image.width {
 			vel.x = -vel.x
+			n = -1 - n
 		}
-		if pos.y == 0 | pos.y == height - image.height {
+		if pos.y == 0 | pos.y == screen.height - image.height {
 			vel.y = -vel.y
+			n = -1 - n
 		}
 
 		pos += vel
diff --git a/sysdata/programs/render_example/src/examples/lines.hb b/sysdata/programs/render_example/src/examples/lines.hb
index be4a536..386883d 100644
--- a/sysdata/programs/render_example/src/examples/lines.hb
+++ b/sysdata/programs/render_example/src/examples/lines.hb
@@ -6,18 +6,16 @@ render := @use("../../../../libraries/render/src/lib.hb")
    created on a blue background */
 
 example := fn(): void {
-	render.init()
-	render.clear(.(100, 50, 0, 255))
-	width := render.width()
-	height := render.height()
+	screen := render.init(true)
+	render.clear(screen, .(100, 50, 0, 255))
 	p0 := Vec2(int).(0, 0)
-	p1 := Vec2(int).(0, height)
-	loop if p0.y >= height break else {
-		render.put_line(p0, p1, .(255, 180, 100, 255))
-		render.put_line(.(width, height) - p0, .(width, height) - p1, .(255, 180, 100, 255))
-		p0.y += height >> 6
-		p1.x += width >> 6
+	p1 := Vec2(int).(0, screen.height)
+	loop if p0.y >= screen.height break else {
+		render.put_line(screen, p0, p1, .(255, 180, 100, 255))
+		render.put_line(screen, .(screen.width, screen.height) - p0, .(screen.width, screen.height) - p1, .(255, 180, 100, 255))
+		p0.y += screen.height >> 6
+		p1.x += screen.width >> 6
 	}
-	render.sync()
+	render.sync(screen)
 	return
 }
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/random.hb b/sysdata/programs/render_example/src/examples/random.hb
index 7c68c5e..fed2790 100644
--- a/sysdata/programs/render_example/src/examples/random.hb
+++ b/sysdata/programs/render_example/src/examples/random.hb
@@ -2,16 +2,15 @@
 render := @use("../../../../libraries/render/src/lib.hb")
 
 example := fn(): void {
-	render.init()
-	render.doublebuffer(false)
-	render.clear(render.black)
+	screen := render.init(false)
+	render.clear(screen, render.black)
 	loop {
 		x := random.range(int, 0, 1024)
 		y := random.range(int, 0, 768)
 		r := random.range(int, 0, 255)
 		g := random.range(int, 0, 75)
 		b := random.range(int, 0, 155)
-		render.put_pixel(.(x, y), .(b, g, r, 255))
+		render.put_pixel(screen, .(x, y), .(b, g, r, 255))
 	}
 	return
 }
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/square.hb b/sysdata/programs/render_example/src/examples/square.hb
index 46ee810..09f71e0 100644
--- a/sysdata/programs/render_example/src/examples/square.hb
+++ b/sysdata/programs/render_example/src/examples/square.hb
@@ -6,22 +6,20 @@ render := @use("../../../../libraries/render/src/lib.hb")
    a square that changes colour bounces around the screen */
 
 example := fn(): void {
-	render.init()
+	screen := render.init(true)
 	vel := Vec2(int).(1, 1)
 	pos := Vec2(int).(100, 100)
-	width := render.width()
-	height := render.height()
 	color := @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
 	loop {
-		render.put_filled_rect(pos, .(100, 100), color)
-		render.sync()
-		render.clear(render.black)
+		render.put_filled_rect(screen, pos, .(100, 100), color)
+		render.sync(screen)
+		render.clear(screen, render.black)
 
-		if pos.x == 0 | pos.x == width - 100 {
+		if pos.x == 0 | pos.x == screen.width - 100 {
 			vel.x = -vel.x
 			color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
 		}
-		if pos.y == 0 | pos.y == height - 100 {
+		if pos.y == 0 | pos.y == screen.height - 100 {
 			vel.y = -vel.y
 			color = @as(render.Color, @intcast(random.range(int, 0, 0xFFFFFF)))
 		}
diff --git a/sysdata/programs/render_example/src/examples/surface.hb b/sysdata/programs/render_example/src/examples/surface.hb
new file mode 100644
index 0000000..95fbd51
--- /dev/null
+++ b/sysdata/programs/render_example/src/examples/surface.hb
@@ -0,0 +1,39 @@
+.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math
+render := @use("../../../../libraries/render/src/lib.hb")
+
+/* expected result:
+       the lines example bounces around the screen */
+
+example := fn(): void {
+	screen := render.init(true)
+
+	image := render.new_surface(341, 256)
+
+	p0 := Vec2(int).(0, 0)
+	p1 := Vec2(int).(0, image.height)
+	render.clear(image, .(100, 50, 0, 255))
+	loop if p0.y >= image.height break else {
+		render.put_line(image, p0, p1, .(255, 180, 100, 255))
+		render.put_line(image, .(image.width, image.height) - p0, .(image.width, image.height) - p1, .(255, 180, 100, 255))
+		p0.y += image.height >> 6
+		p1.x += image.width >> 6
+	}
+
+	vel := Vec2(int).(1, 1)
+	pos := Vec2(int).(100, 100)
+	loop {
+		render.put_surface(screen, image, pos)
+		render.sync(screen)
+		render.clear(screen, render.black)
+
+		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
+		}
+
+		pos += vel
+	}
+	return
+}
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/svga.hb b/sysdata/programs/render_example/src/examples/svga.hb
deleted file mode 100644
index 101aa6f..0000000
--- a/sysdata/programs/render_example/src/examples/svga.hb
+++ /dev/null
@@ -1,8 +0,0 @@
-render := @use("../../../../libraries/render/src/lib.hb")
-
-render.mode = render.svga
-
-example := fn(): void {
-  render.init()
-	return
-}
\ No newline at end of file
diff --git a/sysdata/programs/render_example/src/examples/tactical_screen.hb b/sysdata/programs/render_example/src/examples/tactical_screen.hb
index 4f227de..5b2e909 100644
--- a/sysdata/programs/render_example/src/examples/tactical_screen.hb
+++ b/sysdata/programs/render_example/src/examples/tactical_screen.hb
@@ -7,10 +7,10 @@ Vec2 := math.Vec2
    with a "target" randomly apperaing in one of them and a "seeker" "catching" it*/
 
 example := fn(): void {
-	render.init()
+	screen := render.init(true)
 
-	width := render.width()
-	height := render.height()
+	width := screen.width
+	height := screen.height
 	cell_size := 0
 	range := Vec2(int).(0, 0)
 	if width > height {
@@ -33,32 +33,32 @@ example := fn(): void {
 	seeker := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y))
 
 	loop {
-		render.clear(render.black)
+		render.clear(screen, 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_trirect(screen, 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)
+		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(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(screen, 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 + 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))
+			render.put_vline(screen, 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))
+			render.put_hline(screen, 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.put_hline(screen, seeker.y * cell_size + halfcell + scroll, 0, width, render.light_green)
+		render.put_vline(screen, seeker.x * cell_size + halfcell + scroll, 0, height, render.light_green)
 
-		render.sync()
+		render.sync(screen)
 
 		if seeker.x < target.x {
 			seeker.x += 1
diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml
index 1792d68..e5deef9 100644
--- a/sysdata/system_config.toml
+++ b/sysdata/system_config.toml
@@ -37,11 +37,11 @@ path = "boot:///render_example.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]
+# path = "boot:///horizon.hbf"
 
-[boot.limine.ableos.modules.horizon_testing_program]
-path = "boot:///horizon_testing_program.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"