This commit is contained in:
koniifer 2024-11-13 17:03:31 +00:00
parent dc9273b3c1
commit b07bac1f1f
12 changed files with 188 additions and 116 deletions

10
Cargo.lock generated
View file

@ -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",

View file

@ -1,7 +1,4 @@
# Images
- General over image format
- Support formats:
- PNG
- Animation
# API

View file

@ -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)
}

View file

@ -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
}

View file

@ -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 {

View file

@ -3,6 +3,6 @@ $syn := 1
$ack := 2
$refused := 3
$quit := 4
$update_props := 5
$props := 5
$shutdown := 6
$ready := 7
$frame_ready := 7

View file

@ -0,0 +1,5 @@
$none := 0b0
$exclusive_framebuffer := 0b1
$shutdown := 0b100
$default := none

View file

@ -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)
}

View file

@ -1 +1 @@
.{example: main} := @use("./examples/colors.hb")
.{example: main} := @use("./examples/text.hb")

View file

@ -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()
}

View file

@ -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)
}
}

View file

@ -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"