Update devices to use file descriptor rather than handel. Create REFRESH syscall

This commit is contained in:
zongor 2025-10-25 21:39:13 -07:00
parent 47d5bdd1d9
commit c80481de76
15 changed files with 114 additions and 101 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -8,7 +8,7 @@
version="1.1"
id="svg1"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
sodipodi:docname="undâr.svg"
sodipodi:docname="undar.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
@ -24,9 +24,9 @@
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showguides="false"
inkscape:zoom="10.504938"
inkscape:cx="69.062756"
inkscape:cy="50.880831"
inkscape:zoom="5.252469"
inkscape:cx="31.413798"
inkscape:cy="77.392175"
inkscape:window-width="1939"
inkscape:window-height="932"
inkscape:window-x="0"
@ -40,16 +40,16 @@
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#000000;stroke:#ffffff;stroke-width:0.259677;stroke-opacity:0.5"
style="fill:#000000;stroke:#ffffff;stroke-width:0.259677;stroke-opacity:0.80000001"
d="M 9.8701612,2.1298382 H 2.1298382 V 29.870162 h 7.740323 V 27.874455 H 3.9914349 V 4.0257595 h 5.8787263 z"
id="path1" />
<path
style="fill:#000000;stroke:#ffffff;stroke-width:0.259677;stroke-opacity:0.5"
style="fill:#000000;stroke:#ffffff;stroke-width:0.259677;stroke-opacity:0.80000001"
d="m 22.129839,2.1298386 h 7.740323 V 29.870161 h -7.740323 v -1.995707 h 5.878726 V 4.02576 h -5.878726 z"
id="path1-3" />
<path
d="m 9.9966523,7.2192166 c 0.00192,1.1921857 0,17.6324454 0,17.6324454 H 11.947933 V 10.838 c 0,0 6.10676,1.037363 7.80512,3.238279 0.180102,0.233395 0,10.775383 0,10.775383 h 1.951281 L 21.704,13.017 C 21.719643,11.169234 18.492009,9.5084126 16.302239,8.6458806 13.47112,7.5307272 9.9947373,6.0270309 9.9966523,7.2192166 Z"
style="stroke:#ffffff;stroke-width:0.292319;stroke-opacity:0.5"
style="stroke:#ffffff;stroke-width:0.292319;stroke-opacity:0.80000001"
id="path3"
sodipodi:nodetypes="zcccscccsz" />
</g>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -140,10 +140,14 @@ i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
}
i32 mouse_read(void *data, u8 *buffer, u32 size) {
MouseDeviceData *mouse_data = (MouseDeviceData *)data;
USED(data);
USED(buffer);
USED(size);
return -1;
}
if (size < 12)
return -1;
i32 mouse_refresh(void *data, u8 *buffer) {
MouseDeviceData *mouse_data = (MouseDeviceData *)data;
u8 *info = (u8 *)buffer;
memcpy(&info[4], &mouse_data->x, sizeof(u32));

View File

@ -52,6 +52,7 @@ i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer);
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 mouse_read(void *data, u8 *buffer, u32 size);
i32 mouse_refresh(void *data, u8 *buffer);
i32 mouse_write(void *data, const u8 *buffer, u32 size);
i32 mouse_close(void *data);

View File

@ -15,19 +15,22 @@ static DeviceOps screen_ops = {.open = screen_open,
.read = screen_read,
.write = screen_write,
.close = screen_close,
.ioctl = screen_ioctl};
.ioctl = screen_ioctl,
.refresh = nil};
static DeviceOps mouse_ops = {.open = mouse_open,
.read = mouse_read,
.write = mouse_write,
.close = mouse_close,
.ioctl = nil};
.ioctl = nil,
.refresh = mouse_refresh};
static DeviceOps keyboard_ops = {.open = keyboard_open,
.read = keyboard_read,
.write = keyboard_write,
.close = keyboard_close,
.ioctl = nil};
.ioctl = nil,
.refresh = nil};
static DeviceOps console_device_ops = {
.open = console_open,
@ -35,6 +38,7 @@ static DeviceOps console_device_ops = {
.write = console_write,
.close = console_close,
.ioctl = console_ioctl,
.refresh = nil
};
static ScreenDeviceData screen_data = {0};

View File

@ -721,6 +721,8 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
syscall_id = SYSCALL_DEVICE_CLOSE;
else if (strcmp(syscall_name, "IOCTL") == 0)
syscall_id = SYSCALL_DEVICE_IOCTL;
else if (strcmp(syscall_name, "REFRESH") == 0)
syscall_id = SYSCALL_DEVICE_REFRESH;
emit_u32(vm, syscall_id);

View File

@ -103,7 +103,8 @@ typedef enum {
SYSCALL_DEVICE_READ,
SYSCALL_DEVICE_WRITE,
SYSCALL_DEVICE_CLOSE,
SYSCALL_DEVICE_IOCTL
SYSCALL_DEVICE_IOCTL,
SYSCALL_DEVICE_REFRESH
} SyscallID;
typedef struct device_ops_s {
@ -113,6 +114,7 @@ typedef struct device_ops_s {
i32 (*close)(void *device_data);
i32 (*ioctl)(void *device_data, u32 cmd,
const u8 *buffer); /* optional control */
i32 (*refresh)(void *device_data, u8 *buffer);
} DeviceOps;
#define DEVICE_TYPE_MAX_LENGTH 16 /* 15 chars + null terminator */

View File

@ -556,7 +556,7 @@ bool step_vm(VM *vm) {
switch (syscall_id) {
case SYSCALL_DEVICE_OPEN: {
Device *dev;
u32 path_ptr, mode, buffer_ptr;
u32 path_ptr, mode, device_ptr;
u8 path_reg, mode_reg, dest_reg;
dest_reg = read_u8(vm, code, vm->pc);
vm->pc++;
@ -571,14 +571,14 @@ bool step_vm(VM *vm) {
if (dev) {
if (dev->ops->open) {
/* return device plex to user */
buffer_ptr = vm->mp;
frame->registers[dest_reg] = buffer_ptr;
device_ptr = vm->mp;
frame->registers[dest_reg] = device_ptr;
/* malloc size for device */
write_u32(vm, memory, buffer_ptr, dev->size);
write_u32(vm, memory, device_ptr, dev->size);
vm->mp += (dev->size + 4);
/* set flag from user */
vm->flag = dev->ops->open(dev->data, mode, dev->handle,
&vm->memory[buffer_ptr + 4], dev->size);
&vm->memory[device_ptr + 4], dev->size);
} else {
vm->flag = 1; /* success, no open needed */
}
@ -591,25 +591,23 @@ bool step_vm(VM *vm) {
case SYSCALL_DEVICE_READ: {
Device *dev;
u32 handle, buffer_ptr, size;
u16 handle_reg, buffer_reg, size_reg;
handle_reg = read_u8(vm, code, vm->pc);
u32 device_ptr, buffer_ptr, size;
u8 device_reg, buffer_reg, size_reg, handle;
device_reg = read_u8(vm, code, vm->pc);
vm->pc++;
buffer_reg = read_u8(vm, code, vm->pc);
vm->pc++;
size_reg = read_u8(vm, code, vm->pc);
vm->pc++;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
handle = frame->registers[handle_reg]; /* path pointer */
device_ptr = frame->registers[device_reg]; /* device pointer */
buffer_ptr = frame->registers[buffer_reg];
size = frame->registers[size_reg]; /* size */
buffer_ptr = frame->registers[dest];
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops->read) {
vm->flag = dev->ops->read(dev->data, &vm->memory[buffer_ptr + 4], size);
frame->registers[buffer_reg] = buffer_ptr;
} else {
vm->flag = 0;
}
@ -617,21 +615,42 @@ bool step_vm(VM *vm) {
return true;
}
case SYSCALL_DEVICE_REFRESH: {
Device *dev;
u32 handle, device_ptr;
u8 device_reg;
device_reg = read_u8(vm, code, vm->pc);
vm->pc++;
device_ptr = frame->registers[device_reg]; /* device pointer */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops->refresh) {
vm->flag = dev->ops->refresh(dev->data, &vm->memory[device_ptr + 4]);
} else {
vm->flag = 0;
}
return true;
}
case SYSCALL_DEVICE_WRITE: {
Device *dev;
u32 handle, buffer_ptr, size;
u16 handle_reg, buffer_reg, size_reg;
handle_reg = read_u8(vm, code, vm->pc);
u32 handle, buffer_ptr, size, device_ptr;
u8 device_reg, buffer_reg, size_reg;
device_reg = read_u8(vm, code, vm->pc);
vm->pc++;
buffer_reg = read_u8(vm, code, vm->pc);
vm->pc++;
size_reg = read_u8(vm, code, vm->pc);
vm->pc++;
handle = frame->registers[handle_reg]; /* R0: path pointer */
device_ptr = frame->registers[device_reg]; /* device pointer */
buffer_ptr = frame->registers[buffer_reg]; /* R1: buffer pointer */
size = frame->registers[size_reg]; /* R2: size */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops->write) {
vm->flag = dev->ops->write(
@ -645,13 +664,14 @@ bool step_vm(VM *vm) {
case SYSCALL_DEVICE_CLOSE: {
Device *dev;
u32 handle;
u8 handle_reg;
handle_reg = read_u8(vm, code, vm->pc);
u32 handle, device_ptr;
u8 device_reg;
device_reg = read_u8(vm, code, vm->pc);
vm->pc++;
handle = frame->registers[handle_reg]; /* R0: path pointer */
device_ptr = frame->registers[device_reg]; /* device pointer */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops->close) {
i32 result = dev->ops->close(dev->data);
@ -665,19 +685,20 @@ bool step_vm(VM *vm) {
case SYSCALL_DEVICE_IOCTL: {
Device *dev;
u32 handle, args_ptr, cmd;
u8 handle_reg, cmd_reg, args_ptr_reg;
handle_reg = read_u8(vm, code, vm->pc);
u32 handle, args_ptr, cmd, device_ptr;
u8 device_reg, cmd_reg, args_ptr_reg;
device_reg = read_u8(vm, code, vm->pc);
vm->pc++;
cmd_reg = read_u8(vm, code, vm->pc);
vm->pc++;
args_ptr_reg = read_u8(vm, code, vm->pc);
vm->pc++;
handle = frame->registers[handle_reg]; /* R0: device path */
device_ptr = frame->registers[device_reg]; /* device pointer */
cmd = frame->registers[cmd_reg]; /* R1: ioctl command */
args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */
handle = vm->memory[device_ptr + 4]; /* get device handle */
dev = &vm->devices[handle];
if (dev && dev->ops && dev->ops->ioctl) {
i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]);

View File

@ -4,20 +4,17 @@
; use load immediate because it is a pointer to a string, not a value
(load-immediate $0 &screen-namespace)
(load-immediate $11 0)
(syscall OPEN $18 $0 $11) ; open(out Plex screen, in namespace, in flags)
(syscall OPEN $0 $18 $11) ; open(out Plex screen, in namespace, in flags)
(load-offset-32 $0 $18 4) ; load handle
(load-offset-32 $20 $18 8) ; load width
(load-offset-32 $22 $18 12) ; load size
(load-offset-32 $20 $0 8) ; load width
(load-offset-32 $22 $0 12) ; load size
(load-immediate $1 16) ; offset for screen buffer
(add-nat $21 $18 $1)
(add-nat $21 $0 $1)
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; open(out Plex mouse, in namespace, in flags)
(load-offset-32 $16 $15 4) ; load handle
; outline_swatch(screen, BLACK, 1, 1);
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
@ -33,16 +30,15 @@
; screen.draw();
(syscall WRITE $0 $21 $22)
(load-immediate $3 16)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $15)
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $2 8) ; load x
(load-offset-32 $8 $2 12) ; load y
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
(load-immediate $14 20) ; box size

View File

@ -4,20 +4,17 @@
; use load immediate because it is a pointer to a string, not a value
(load-immediate $0 &screen-namespace)
(load-immediate $11 0)
(syscall OPEN $18 $0 $11) ; Screen screen = open(namespace, flags)
(syscall OPEN $0 $0 $11) ; Screen screen = open(namespace, flags)
(load-offset-32 $0 $18 4) ; load handle
(load-offset-32 $20 $18 8) ; load width
(load-offset-32 $22 $18 12) ; load size
(load-immediate $1 16) ; offset for screen buffer
(add-nat $21 $18 $1)
(load-offset-32 $20 $0 8) ; load width
(load-offset-32 $22 $0 12) ; load size
(load-immediate $1 16) ; pointer offset for screen buffer
(add-nat $21 $0 $1)
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; Mouse mouse = open(namespace, flags)
(load-offset-32 $16 $15 4) ; load handle
; outline_swatch(screen, BLACK, 1, 1);
(load-absolute-32 $1 &BLACK)
(load-immediate $12 1)
@ -73,16 +70,15 @@
; screen.draw();
(syscall WRITE $0 $21 $22)
(load-immediate $3 16)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $15)
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $2 8) ; load x
(load-offset-32 $8 $2 12) ; load y
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
(load-immediate $14 20) ; box size
@ -229,8 +225,8 @@
(return nil)))
(data
(label screen-namespace "/dev/screen/0")
(label mouse-namespace "/dev/mouse/0")
(label SELECTED-COLOR 255)
(label mouse-namespace "/dev/mouse/0")
(label SELECTED-COLOR 255)
(label BLACK 0)
(label WHITE 255)
(label CHARCOAL 36)

View File

@ -1,8 +1,6 @@
/**
* Constants
*/
const str screen_namespace = "/dev/screen/0";
const str mouse_namespace = "/dev/mouse/0";
const byte BLACK = 0;
const byte WHITE = 255;
const byte DARK_GRAY = 73;
@ -22,8 +20,10 @@ plex Screen implements Device {
nat buffer_size;
byte[] screen_buffer;
init(str namespace) {
this.handle = open(namespace);
draw() {
unsafe {
write(this.handle, &this.screen_buffer, this.buffer_size);
}
}
}
@ -35,29 +35,21 @@ plex Mouse implements Device {
bool right;
bool middle;
bool btn4;
nat size;
init(str namespace) {
this.handle = open(namespace);
}
}
/**
* Main function
*/
function main() {
Screen screen(screen_namespace);
screen.open(0);
Mouse mouse(mouse_namespace);
mouse.open(0);
Screen screen = open("/dev/screen/0", 0);
Mouse mouse = open("/dev/mouse/0", 0);
outline_swatch(screen, BLACK, 1, 1);
outline_swatch(screen, WHITE, 21, 1);
screen.draw();
loop {
mouse.read();
mouse.refresh();
if (not mouse.left) continue;
int box_size = 20;
@ -98,7 +90,7 @@ function set_color(int box_size, int bx, int by, int mx, int my, byte color) {
/**
* Draw a color box with a grey outline, if selected use a darker color
*/
function outline_swatch(ref Device screen, byte color, int x, int y) {
function outline_swatch(Device screen, byte color, int x, int y) {
byte bg_color = GRAY;
if (selected_color == color) {
bg_color = DARK_GRAY;
@ -112,7 +104,7 @@ function outline_swatch(ref Device screen, byte color, int x, int y) {
/**
* Draw a rectangle
*/
function rectangle(ref Device screen, byte color, int x, int y, int width, int height) {
function rectangle(Device screen, byte color, int x, int y, int width, int height) {
// we need unsafe because we are using `ptr` and `memset` directly
// unsafe takes the guardrails off and allows you to access/modify memory directly
unsafe {

View File

@ -11,7 +11,7 @@
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(load-offset-32 $7 $1 4) ; load handle
(load-offset-32 $7 $1 4) ; load handle
(string-length $2 $0)
(syscall WRITE $7 $0 $2)
(string-length $4 $3)

View File

@ -2,12 +2,14 @@
* Constants
*/
const str nl = "\n";
const real x = 1.0;
const real y = 1.0;
plex Terminal {
nat handle;
init() {
handle = open("/dev/term/0", 0);
this.handle = open("/dev/term/0", 0);
}
}
@ -15,7 +17,7 @@ plex Terminal {
* Main function
*/
function main() {
pln((1 + 2).str);
pln((x + y).str);
}
/**

View File

@ -2,26 +2,24 @@
(label main
; Open screen
; use load immediate because it is a pointer to a string, not a value
(load-immediate $0 &screen-namespace)
(syscall OPEN $18 $0 $11) ; open(out Plex screen, in namespace, in flags)
(load-offset-32 $0 $18 4) ; load handle
(load-immediate $18 &screen-namespace)
(syscall OPEN $0 $18 $11) ; open(out Plex screen, in namespace, in flags)
(nat-to-string $5 $0)
(call &pln ($5) nil)
(load-offset-32 $20 $18 8) ; load width
(load-offset-32 $20 $0 8) ; load width
(nat-to-string $5 $20)
(call &pln ($5) nil)
(load-offset-32 $22 $18 12) ; load size
(load-offset-32 $22 $0 12) ; load size
(nat-to-string $5 $22)
(call &pln ($5) nil)
(load-immediate $1 16) ; offset for screen buffer
(add-nat $21 $18 $1)
(add-nat $21 $0 $1)
(nat-to-string $5 $21)
(call &pln ($5) nil)
@ -30,21 +28,17 @@
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 $11) ; open(out Plex mouse, in namespace, in flags)
(load-offset-32 $16 $15 4) ; load handle
(syscall WRITE $0 $21 $22) ; redraw
(load-immediate $3 16)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $15)
(syscall REFRESH $15)
(load-offset-8 $9 $15 16) ; load btn1 pressed
(jump-eq-nat &draw-loop $9 $11)
(load-offset-32 $7 $2 8) ; load x
(load-offset-32 $8 $2 12) ; load y
(load-offset-32 $7 $15 8) ; load x
(load-offset-32 $8 $15 12) ; load y
; Compute start address: y*width + x
(mul-nat $30 $8 $20) ; $15 = y * width
@ -64,11 +58,10 @@
(load-immediate $11 0)
(syscall OPEN $1 $1 $11)
(load-immediate $3 &new-line)
(load-offset-32 $7 $1 4) ; load handle
(string-length $2 $0)
(syscall WRITE $7 $0 $2)
(syscall WRITE $1 $0 $2)
(string-length $4 $3)
(syscall WRITE $7 $3 $4)
(syscall WRITE $1 $3 $4)
(return nil)))
(data
(label screen-namespace "/dev/screen/0")