From b6261d014d64642c5c5cac2cb7436da0670c0acf Mon Sep 17 00:00:00 2001
From: koniifer <koniifer@proton.me>
Date: Wed, 13 Nov 2024 23:08:20 +0000
Subject: [PATCH] bad frame synchronisation implementation

---
 Cargo.lock                                   |  6 +-
 sysdata/libraries/sunset_proto/src/client.hb | 12 ++--
 sysdata/libraries/sunset_proto/src/lib.hb    | 14 ++---
 sysdata/libraries/sunset_proto/src/server.hb | 59 ++++++++++++--------
 sysdata/programs/sunset_client/src/main.hb   | 16 ++++--
 5 files changed, 62 insertions(+), 45 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2a1a426..bc4f684 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -228,12 +228,12 @@ dependencies = [
 [[package]]
 name = "hbbytecode"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e"
 
 [[package]]
 name = "hblang"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e"
 dependencies = [
  "hashbrown 0.15.1",
  "hbbytecode",
@@ -245,7 +245,7 @@ dependencies = [
 [[package]]
 name = "hbvm"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#f524013c34ff5868eadc0afdf1168239f31c7ee0"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e"
 dependencies = [
  "hbbytecode",
 ]
diff --git a/sysdata/libraries/sunset_proto/src/client.hb b/sysdata/libraries/sunset_proto/src/client.hb
index 9346e6c..d47f5a8 100644
--- a/sysdata/libraries/sunset_proto/src/client.hb
+++ b/sysdata/libraries/sunset_proto/src/client.hb
@@ -1,13 +1,15 @@
 .{math: .{Vec2}, buffer, log, memory, string} := @use("../../stn/src/lib.hb");
-.{Channel, Window, send_header, send_message, await_channel, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
+.{Channel, Window, send_header, send_message, await_channel, await_header, await_message, message, BUFFER_SERVER, BUFFER_CLIENT, WindowProps, WindowData} := @use("./lib.hb");
 .{new_surface, Color} := @use("../../render/src/lib.hb")
 
 // ! in the future this should be safely handled
-channel := @as(Channel, idk)
+channel := Channel.(0, 0)
 
 find_server := fn(): void {
 	log.info("client: locating server\0")
-	channel = await_channel()
+	channel2 := await_channel(channel)
+	channel.server = channel2.server
+	channel.client = channel2.client
 	log.info("client: server located\0")
 }
 
@@ -15,7 +17,6 @@ new := fn(props: WindowProps): ?Window {
 	send_header(message.syn, channel.server)
 	response := await_message(Channel, channel.client)
 	if response.header.kind != message.ack {
-		log.info(string.display_int(@bitcast(response.header.kind), "\0\0\0\0\0\0\0\0\0\0\0\0\0", 10))
 		return null
 	}
 	log.info("client: recv ack\0")
@@ -57,9 +58,8 @@ send_frame := fn(client: Window): bool {
 	if response.header.kind != message.ack {
 		return false
 	}
-	log.info("client: recv ack\0")
 	// ! FOR NOW, server will ALWAYS be local,
 	// ! so we can send pointer to surface.
 	send_message(^Color, message.ack, client.surface.buf, server_id)
-	return true
+	return await_header(client_id).kind == message.ack
 }
\ No newline at end of file
diff --git a/sysdata/libraries/sunset_proto/src/lib.hb b/sysdata/libraries/sunset_proto/src/lib.hb
index 498447f..630d960 100644
--- a/sysdata/libraries/sunset_proto/src/lib.hb
+++ b/sysdata/libraries/sunset_proto/src/lib.hb
@@ -46,16 +46,14 @@ $recv_header := fn(buffer_id: uint): ?MessageHeader {
 	return response
 }
 
-await_channel := fn(): Channel {
-	server_id := 0
-	loop if server_id == 0 {
-		server_id = buffer.search(BUFFER_SERVER)
+await_channel := fn(channel: Channel): Channel {
+	loop if channel.server != 0 break else {
+		channel.server = buffer.search(BUFFER_SERVER)
 	}
-	client_id := 0
-	loop if client_id == 0 {
-		client_id = buffer.search(BUFFER_CLIENT)
+	loop if channel.client != 0 break else {
+		channel.client = buffer.search(BUFFER_CLIENT)
 	}
-	return .{client: client_id, server: server_id}
+	return channel
 }
 
 await_message := fn($Expr: type, buffer_id: uint): Message(Expr) {
diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb
index f44bb44..23e250b 100644
--- a/sysdata/libraries/sunset_proto/src/server.hb
+++ b/sysdata/libraries/sunset_proto/src/server.hb
@@ -1,19 +1,27 @@
 .{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb");
-.{Color, Surface, new_surface, put_surface, sync} := @use("../../render/src/lib.hb");
+.{Color, Surface, new_surface, put_surface, sync, put_rect, put_filled_rect, text, put_text} := @use("../../render/src/lib.hb");
 .{Channel, Window, WindowProps, WindowData, MessageHeader, BUFFER_SERVER, BUFFER_CLIENT, message, permissions, recv_header, recv_message, send_message, send_header, await_message} := @use("./lib.hb")
 
 WindowServer := struct {
 	window_count: uint,
 	channel: Channel,
-	// ! replace this with an actual collection when we get an allocator
+	// ! replace this with a collection when we get an allocator
 	windows: [?WindowData; 10],
+	font: text.Font,
 }
 
 // ! in the future this should be safely handled
 server := @as(WindowServer, idk)
 
+psf := @embed("../../../assets/consolefonts/tamsyn/10x20r.psf")
+
 start := fn(): void {
-	server = .(0, .{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)}, .(null, null, null, null, null, null, null, null, null, null))
+	font := text.font_from_psf2(@bitcast(&psf), false)
+	if font == null {
+		log.error("server: failed to load asset\0")
+		return
+	}
+	server = .(0, .{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)}, .(null, null, null, null, null, null, null, null, null, null), @as(text.Font, font))
 	log.info("server: started server\0")
 }
 
@@ -25,36 +33,43 @@ incoming := fn(): bool {
 	if msg.kind == message.syn {
 		log.info("server: recv syn\0")
 		channel := Channel.(buffer.create_nameless(), buffer.create_nameless())
-		send_message(Channel, message.ack, channel, channel.client)
+		send_message(Channel, message.ack, channel, server.channel.client)
 		props := await_message(WindowProps, channel.server)
 		if props.header.kind != message.props {
 			return true
 		}
 		log.info("server: recv props\0")
 		// ! do inspection of requested props here
-		send_message(WindowData, message.ack, .(props.body, channel, permissions.default), channel.client)
+		data := WindowData.(props.body, channel, permissions.default)
+		send_message(WindowData, message.ack, data, channel.client)
+		server.windows[server.window_count] = data
+		server.window_count += 1
 	}
 	return true
 }
 
 render_clients := fn(screen: Surface): void {
-	i := 0
-	loop if i == 10 break else {
-		window := server.windows[i]
-		if window == null {
-			continue
-		}
-		header := recv_header(window.channel.server)
-		if header == null | @unwrap(header).kind != message.frame_ready {
-			continue
-		}
-		send_header(message.ack, window.channel.client)
-		ptr := await_message(^Color, window.channel.server)
-		if ptr.header.kind != message.ack {
-			continue
-		}
-		put_surface(screen, .(ptr.body, window.props.dimensions.x, window.props.dimensions.y, window.props.dimensions.x * window.props.dimensions.y), window.props.position, false)
-		i += 1
+	// support one window for test case
+	window := server.windows[0]
+	if window == null {
+		return
 	}
+	header := recv_header(window.channel.server)
+	if header == null {
+		return
+	}
+	if header.kind != message.frame_ready {
+		return
+	}
+	send_header(message.ack, window.channel.client)
+	ptr := await_message(^Color, window.channel.server)
+	if ptr.header.kind != message.ack {
+		return
+	}
+	put_surface(screen, .(ptr.body, window.props.dimensions.x, window.props.dimensions.y, window.props.dimensions.x * window.props.dimensions.y), window.props.position, false)
+	put_rect(screen, window.props.position - .(1, 1), window.props.dimensions + .(1, 1), .(255, 255, 255, 255))
+	put_filled_rect(screen, window.props.position - .(1, 21), .(window.props.dimensions.x + 2, 20), .(255, 255, 255, 255))
+	put_text(screen, server.font, window.props.position - .(-2, 20), .(0, 0, 0, 255), window.props.title)
 	sync(screen)
+	send_header(message.ack, window.channel.client)
 }
\ No newline at end of file
diff --git a/sysdata/programs/sunset_client/src/main.hb b/sysdata/programs/sunset_client/src/main.hb
index eec5c12..8b46a12 100644
--- a/sysdata/programs/sunset_client/src/main.hb
+++ b/sysdata/programs/sunset_client/src/main.hb
@@ -1,17 +1,21 @@
-.{log, string} := @use("../../../libraries/stn/src/lib.hb")
+.{log} := @use("../../../libraries/stn/src/lib.hb")
 sunset := @use("../../../libraries/sunset_proto/src/lib.hb")
 render := @use("../../../libraries/render/src/lib.hb")
 
 main := fn(): void {
 	sunset.client.find_server()
-
-	window := sunset.client.new(.(.(100, 100), .(100, 100), "Hello, World!\0"))
+	window := sunset.client.new(.(.(100, 100), .(700, 100), "Hello, World!\0"))
 	if window == null {
 		log.error("got no window\0")
 		return
 	}
-	render.put_filled_circle(window.surface, .(50, 50), 25, render.white)
-	if sunset.client.send_frame(window) == false {
-		log.error("did not send frame\0")
+	x := 0
+	loop {
+		render.clear(window.surface, render.cyan)
+		render.put_filled_circle(window.surface, .(50 + x % window.data.props.dimensions.x, 50), 25, render.magenta)
+		if sunset.client.send_frame(window) == false {
+			log.error("did not send frame\0")
+		}
+		x += 1
 	}
 }
\ No newline at end of file