diff --git a/Cargo.lock b/Cargo.lock index 02a6658..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#b71031c1463c2bec1984316ea5f5173a9e09c028" +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#b71031c1463c2bec1984316ea5f5173a9e09c028" +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#b71031c1463c2bec1984316ea5f5173a9e09c028" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d01e31b2034e53098f92dfb07b183a21857ded1e" dependencies = [ "hbbytecode", ] @@ -824,9 +824,9 @@ dependencies = [ [[package]] name = "uart_16550" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4922792855b1bce30997fbaa5418597902c278a92d20dfe348e6f062c3bd861d" +checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049" dependencies = [ "bitflags 2.6.0", "rustversion", diff --git a/sysdata/libraries/render/TODO.md b/sysdata/libraries/render/TODO.md index c17ae88..83ee875 100644 --- a/sysdata/libraries/render/TODO.md +++ b/sysdata/libraries/render/TODO.md @@ -1,7 +1,4 @@ # Images -- General over image format -- Support formats: - - PNG - Animation # API diff --git a/sysdata/libraries/stn/src/buffer.hb b/sysdata/libraries/stn/src/buffer.hb index 2a448b8..17f5a3f 100644 --- a/sysdata/libraries/stn/src/buffer.hb +++ b/sysdata/libraries/stn/src/buffer.hb @@ -22,7 +22,7 @@ create := fn(msg: ^u8): uint { return @eca(3, 0, BufferMsg.(0, msg, @inline(string.length, msg)), @sizeof(BufferMsg)) } -$create_without_name := fn(): uint { +$create_nameless := fn(): uint { return @eca(1, 0) } diff --git a/sysdata/libraries/sunset_proto/src/client.hb b/sysdata/libraries/sunset_proto/src/client.hb index 9044bdb..9346e6c 100644 --- a/sysdata/libraries/sunset_proto/src/client.hb +++ b/sysdata/libraries/sunset_proto/src/client.hb @@ -1,59 +1,65 @@ -.{math: .{Vec2}, buffer, log, memory} := @use("../../stn/src/lib.hb"); -.{Window, WindowData, WindowProps, MessageHeader, send_message, message, await_buffer, await_message, BUFFER} := @use("./lib.hb") -render := @use("../../render/src/lib.hb") +.{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"); +.{new_surface, Color} := @use("../../render/src/lib.hb") -server_id := @as(uint, idk) -screen := @as(render.Surface, idk) +// ! in the future this should be safely handled +channel := @as(Channel, idk) find_server := fn(): void { - // ! to be removed in the future - screen = render.init(false) - render.clear(screen, render.black) - log.debug("client: waiting for server\0") - server_id = await_buffer(BUFFER) - log.debug("client: found server\0") + log.info("client: locating server\0") + channel = await_channel() + log.info("client: server located\0") } new := fn(props: WindowProps): ?Window { - send_message(MessageHeader, .(message.syn, 0), server_id) - log.debug("client: sent syn\0") - response := await_message(MessageHeader, server_id) - if response.kind != message.ack { - log.error("client: refused syn\0") + 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.debug("client: got ack\0") - - buffer_id := response.data - send_message(WindowProps, props, buffer_id) - log.debug("client: sent props\0") - - response2 := await_message(WindowData, buffer_id) - log.debug("client: got window data\0") - surface := render.new_surface( - response2.props.dimensions.x, - response2.props.dimensions.y, - ) - return .(response2, surface) + log.info("client: recv ack\0") + send_message(WindowProps, message.props, props, response.body.server) + windowdata := await_message(WindowData, response.body.client) + if windowdata.header.kind != message.ack { + return null + } + log.info("client: recv windowdata\0") + surface := new_surface(windowdata.body.props.dimensions.x, windowdata.body.props.dimensions.y) + return .(windowdata.body, surface) } -// ! client buffers are not being read by the server yet quit := fn(client: Window): void { - send_message(MessageHeader, .(message.quit, 0), client.data.buffer_id) + send_header(message.quit, client.data.channel.server) } -shutdown_server := fn(): void { - send_message(MessageHeader, .(message.shutdown, 0), server_id) +connected := fn(client: Window): bool { + return true } -update_props := fn(client: Window): bool { - log.error("client: update props unimplemented\0") +shutdown_server := fn(client: Window): bool { return false } -//! temporarily just throw our window at the screen -frame_ready := fn(client: Window): void { - send_message(MessageHeader, .(message.ready, 0), client.data.buffer_id) - log.warn("client: we are blitting to screen from the client\n\r this is temporary behaviour\0") - render.put_surface(screen, client.surface, client.data.props.position, false) +update_props := fn(client: Window): bool { + return false +} + +update_permissions := fn(client: Window): bool { + return false +} + +send_frame := fn(client: Window): bool { + server_id := client.data.channel.server + client_id := client.data.channel.client + send_header(message.frame_ready, server_id) + response := await_message(uint, client_id) + 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 } \ 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 f4f0a5d..498447f 100644 --- a/sysdata/libraries/sunset_proto/src/lib.hb +++ b/sysdata/libraries/sunset_proto/src/lib.hb @@ -1,43 +1,92 @@ .{math: .{Vec2}, buffer, memory} := @use("../../stn/src/lib.hb"); .{Surface} := @use("../../render/src/lib.hb") -$BUFFER := "sunset\0" +$BUFFER_SERVER := "sunset_server\0" +$BUFFER_CLIENT := "sunset_client\0" + +Channel := packed struct { + client: uint, + server: uint, +} client := @use("./client.hb") server := @use("./server.hb") message := @use("./message.hb") +permissions := @use("./permissions.hb") -receive_message := fn($Expr: type, buffer_id: uint): ?Expr { - recv := @as(?Expr, null) - buffer.recv(?Expr, buffer_id, &recv) - return recv +opaque := fn(i: uint): bool { + if i == 0 { + return true + } + return false } -send_message := fn($Expr: type, msg: Expr, buffer_id: uint): void { - buffer.write(?Expr, buffer_id, &@as(?Expr, msg)) +sleep := fn(): void { + i := 10000000 + loop if opaque(i) break else i -= 1 } -await_buffer := fn(name: ^u8): uint { - id := 0 - loop if id != 0 return id else id = buffer.search(BUFFER) +$send_message := fn($Expr: type, kind: uint, msg: Expr, buffer_id: uint): void { + buffer.write(?Message(Expr), buffer_id, &@as(?Message(Expr), .(.(kind), msg))) } -await_message := fn($Expr: type, buffer_id: uint): Expr { - response := @as(?Expr, null) +$send_header := fn(kind: uint, buffer_id: uint): void { + buffer.write(?MessageHeader, buffer_id, &@as(?MessageHeader, .(kind))) +} + +$recv_message := fn($Expr: type, buffer_id: uint): Message(Expr) { + response := @as(?Message(Expr), null) + buffer.recv(?Message(Expr), buffer_id, &response) + return response +} + +$recv_header := fn(buffer_id: uint): ?MessageHeader { + response := @as(?MessageHeader, null) + buffer.recv(?MessageHeader, buffer_id, &response) + return response +} + +await_channel := fn(): Channel { + server_id := 0 + loop if server_id == 0 { + server_id = buffer.search(BUFFER_SERVER) + } + client_id := 0 + loop if client_id == 0 { + client_id = buffer.search(BUFFER_CLIENT) + } + return .{client: client_id, server: server_id} +} + +await_message := fn($Expr: type, buffer_id: uint): Message(Expr) { + response := @as(?Message(Expr), null) loop { - buffer.recv(?Expr, buffer_id, &response) + buffer.recv(?Message(Expr), buffer_id, &response) if response != null { - i := 0 - return @as(Expr, response) + return @as(Message(Expr), response) + } + } +} + +await_header := fn(buffer_id: uint): MessageHeader { + response := @as(?MessageHeader, null) + loop { + buffer.recv(?MessageHeader, buffer_id, &response) + if response != null { + return @as(?MessageHeader, response) } } } -// ! we need a better message format but this will do for now. -// enums would be nice MessageHeader := packed struct { kind: uint, - data: uint, +} + +Message := fn($Expr: type): type { + return packed struct { + header: MessageHeader, + body: Expr, + } } WindowProps := struct { @@ -49,7 +98,8 @@ WindowProps := struct { WindowData := struct { props: WindowProps, - buffer_id: uint, + channel: Channel, + permissions: uint, } Window := struct { diff --git a/sysdata/libraries/sunset_proto/src/message.hb b/sysdata/libraries/sunset_proto/src/message.hb index b12d3d7..918f55e 100644 --- a/sysdata/libraries/sunset_proto/src/message.hb +++ b/sysdata/libraries/sunset_proto/src/message.hb @@ -3,6 +3,6 @@ $syn := 1 $ack := 2 $refused := 3 $quit := 4 -$update_props := 5 +$props := 5 $shutdown := 6 -$ready := 7 \ No newline at end of file +$frame_ready := 7 \ No newline at end of file diff --git a/sysdata/libraries/sunset_proto/src/permissions.hb b/sysdata/libraries/sunset_proto/src/permissions.hb new file mode 100644 index 0000000..57bf4d8 --- /dev/null +++ b/sysdata/libraries/sunset_proto/src/permissions.hb @@ -0,0 +1,5 @@ +$none := 0b0 +$exclusive_framebuffer := 0b1 +$shutdown := 0b100 + +$default := none \ No newline at end of file diff --git a/sysdata/libraries/sunset_proto/src/server.hb b/sysdata/libraries/sunset_proto/src/server.hb index b205070..f44bb44 100644 --- a/sysdata/libraries/sunset_proto/src/server.hb +++ b/sysdata/libraries/sunset_proto/src/server.hb @@ -1,46 +1,60 @@ .{math, log, string, random, buffer, memory} := @use("../../stn/src/lib.hb"); -.{Surface, new_surface} := @use("../../render/src/lib.hb"); -.{Window, WindowProps, WindowData, MessageHeader, BUFFER, message, receive_message, send_message, await_message} := @use("./lib.hb") +.{Color, Surface, new_surface, put_surface, sync} := @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, - id: uint, + channel: Channel, // ! replace this with an actual collection when we get an allocator - windows: ^WindowData, + windows: [?WindowData; 10], } // ! in the future this should be safely handled server := @as(WindowServer, idk) start := fn(): void { - windows := memory.alloc(WindowData, 10) - server = .(0, buffer.create(BUFFER), windows) - log.debug("server: started server\0") + server = .(0, .{client: buffer.create(BUFFER_CLIENT), server: buffer.create(BUFFER_SERVER)}, .(null, null, null, null, null, null, null, null, null, null)) + log.info("server: started server\0") } -// ! this function will be rewritten to several functions that allow the server mainloop to handle these itself -handle_connections := fn(): bool { - recv := receive_message(MessageHeader, server.id) - if recv == null { +incoming := fn(): bool { + msg := recv_header(server.channel.server) + if msg == null { return true } - if recv.kind == message.syn { - buffer_id := buffer.create_without_name() - - send_message(MessageHeader, .(message.ack, buffer_id), server.id) - log.debug("server: sent ack\0") - - resp := await_message(WindowProps, buffer_id) - log.debug("server: received props\0") - - data := WindowData.(resp, buffer_id) - send_message(WindowData, data, buffer_id) - log.debug("server: sent window data\0"); - *(server.windows + server.window_count) = data - server.window_count += 1 - } else if recv.kind == message.shutdown { - log.warn("server: shutdown handled without validation\n\r this is temporary behaviour\0") - return false + 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) + 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) } 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 + } + sync(screen) } \ 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 9369afd..77cb04c 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1 +1 @@ -.{example: main} := @use("./examples/colors.hb") \ No newline at end of file +.{example: main} := @use("./examples/text.hb") \ 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 1dfc989..eec5c12 100644 --- a/sysdata/programs/sunset_client/src/main.hb +++ b/sysdata/programs/sunset_client/src/main.hb @@ -4,17 +4,14 @@ render := @use("../../../libraries/render/src/lib.hb") main := fn(): void { sunset.client.find_server() - client := sunset.client.new(.(.(100, 100), .(100, 100), "Hello, World!\0")) - if client == null { - log.error("we did not get a window\0") + + window := sunset.client.new(.(.(100, 100), .(100, 100), "Hello, World!\0")) + if window == null { + log.error("got no window\0") return } - if sunset.client.update_props(client) == false { - log.error("we did not update props\0") + 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") } - - render.put_filled_circle(client.surface, .(50, 50), 20, render.white) - sunset.client.frame_ready(client) - sunset.client.quit(client) - sunset.client.shutdown_server() } \ No newline at end of file diff --git a/sysdata/programs/sunset_server/src/main.hb b/sysdata/programs/sunset_server/src/main.hb index 79dc01e..f11694e 100644 --- a/sysdata/programs/sunset_server/src/main.hb +++ b/sysdata/programs/sunset_server/src/main.hb @@ -1,7 +1,10 @@ sunset := @use("../../../libraries/sunset_proto/src/lib.hb") +render := @use("../../../libraries/render/src/lib.hb") main := fn(): void { + screen := render.init(true) sunset.server.start() - loop if sunset.server.handle_connections() { + loop if sunset.server.incoming() { + sunset.server.render_clients(screen) } } \ No newline at end of file diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml index ab597c0..da9cbd0 100644 --- a/sysdata/system_config.toml +++ b/sysdata/system_config.toml @@ -22,8 +22,8 @@ resolution = "1024x768x24" [boot.limine.ableos.modules] -[boot.limine.ableos.modules.render_example] -path = "boot:///render_example.hbf" +# [boot.limine.ableos.modules.render_example] +# path = "boot:///render_example.hbf" # [boot.limine.ableos.modules.horizon] # path = "boot:///horizon.hbf" @@ -34,8 +34,8 @@ path = "boot:///render_example.hbf" # [boot.limine.ableos.modules.ps2_keyboard_driver] # path = "boot:///ps2_keyboard_driver.hbf" -# [boot.limine.ableos.modules.sunset_client] -# path = "boot:///sunset_client.hbf" +[boot.limine.ableos.modules.sunset_client] +path = "boot:///sunset_client.hbf" -# [boot.limine.ableos.modules.sunset_server] -# path = "boot:///sunset_server.hbf" +[boot.limine.ableos.modules.sunset_server] +path = "boot:///sunset_server.hbf"