diff --git a/docs/favicon.ico b/docs/favicon.ico index 1bfaf27..7a815a8 100644 Binary files a/docs/favicon.ico and b/docs/favicon.ico differ diff --git a/docs/undar.png b/docs/undar.png index 40cd807..cb50d0b 100644 Binary files a/docs/undar.png and b/docs/undar.png differ diff --git a/docs/undar.svg b/docs/undar.svg index a54757f..4e34255 100644 --- a/docs/undar.svg +++ b/docs/undar.svg @@ -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"> diff --git a/src/arch/linux/devices.c b/src/arch/linux/devices.c index fb85cb8..4d667b1 100644 --- a/src/arch/linux/devices.c +++ b/src/arch/linux/devices.c @@ -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)); diff --git a/src/arch/linux/devices.h b/src/arch/linux/devices.h index b252c03..d0a5549 100644 --- a/src/arch/linux/devices.h +++ b/src/arch/linux/devices.h @@ -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); diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 9e52f93..8bcfe9a 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -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}; diff --git a/src/tools/assembler.c b/src/tools/assembler.c index d7005cb..e528283 100644 --- a/src/tools/assembler.c +++ b/src/tools/assembler.c @@ -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); diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index 4b5da65..e3c038b 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -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 */ diff --git a/src/vm/vm.c b/src/vm/vm.c index 50701f2..a511262 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -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]); diff --git a/test/paint-bw.asm.lisp b/test/paint-bw.asm.lisp index 4c45753..92b5785 100644 --- a/test/paint-bw.asm.lisp +++ b/test/paint-bw.asm.lisp @@ -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 diff --git a/test/paint.asm.lisp b/test/paint.asm.lisp index 44c617d..8e96811 100644 --- a/test/paint.asm.lisp +++ b/test/paint.asm.lisp @@ -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) diff --git a/test/paint.ul b/test/paint.ul index f6b936e..0bf6aa8 100644 --- a/test/paint.ul +++ b/test/paint.ul @@ -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 { diff --git a/test/simple.asm.lisp b/test/simple.asm.lisp index 8aed424..6562d0b 100644 --- a/test/simple.asm.lisp +++ b/test/simple.asm.lisp @@ -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) diff --git a/test/simple.ul b/test/simple.ul index 5b26383..ff59272 100644 --- a/test/simple.ul +++ b/test/simple.ul @@ -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); } /** diff --git a/test/window.asm.lisp b/test/window.asm.lisp index 5b2c0e5..5246bab 100644 --- a/test/window.asm.lisp +++ b/test/window.asm.lisp @@ -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")