[wip] rewrite device open to use plex

This commit is contained in:
zongor 2025-10-16 09:25:34 -07:00
parent 9d30ffb69b
commit 3f3c6e1b80
13 changed files with 204 additions and 151 deletions

View File

@ -1,46 +1,78 @@
Device screen("/dev/screen/0");
u8[] colors = [0,255,36,73,146,182,128,224,144,
252,9,18,12,16,28,159,2,3,10,19,131,147,130,227,129,226,
72,141,136,241,208,244];
str screen_namespace = "/dev/screen/0";
str mouse_namespace = "/dev/mouse/0";
byte selected_color = 255;
fn main() {
const byte BLACK = 0;
const byte WHITE = 255;
const byte DARK_GRAY = 73;
const byte GRAY = 146;
const byte LIGHT_GRAY = 182;
function main() {
Device screen(screen_namespace);
screen.open(0);
Device mouse(mouse_namespace);
mouse.open(0);
outline_swatch(screen, BLACK, 1, 1);
outline_swatch(screen, WHITE, 21, 1);
screen.draw();
int x = 10;
int y = 20;
for (int i = 0; i < colors.length; i+=2) {
draw_outline_swatch(colors[i], x, y);
draw_outline_swatch(colors[i + 1], x + 20, y);
x += 20;
y += 20;
while (true) {
mouse.read();
if (mouse.btn1) {
int box_size = 20;
int x = 1;
int y = 1;
byte color = BLACK;
outlined_swatch(screen, color, x, y);
set_color_if_clicked(box_size, x, y, mouse.x, mouse.y, color, mouse.btn1);
color = WHITE;
x = 21;
outlined_swatch(screen, color, x, y);
set_color_if_clicked(box_size, x, y, mouse.x, mouse.y, color, mouse.btn1);
screen.draw();
box(screen, selected_color, x, y, 5, 5);
}
}
screen.draw();
exit(0);
}
fn draw_outline_swatch(u8 color, int x, int y) {
u8 gray = colors[5];
int outline_size = 20;
int fill_size = 17;
int offset = 2;
function set_color_if_clicked(int box_size, int bx, int by, int mx, int my, byte color, bool btn1_down) {
int right = bx + box_size;
int bottom = by + box_size;
if (mx < mx) return;
if (mx > right) return;
if (my < by) return;
if (my > bottom) return;
if (not btn1_down) return;
selected_color = color;
draw_box(gray, x, y, outline_size, outline_size);
int swatch_pos = x + 2;
int offset_pos = y + 2;
draw_box(color, swatch_pos, offset_pos, fill_size, fill_size);
return;
}
fn draw_box(u8 color, int x, int y, int width, int height) {
int screen_width = screen.width;
int pos = y * 640 + x;
do (int i = height; i > 0; i--) {
int row = pos + width;
int pixel = offset;
do (int j = ; pos;j++) {
screen.buffer[j] = color;
}
function outline_swatch(ref Device screen, byte color, int x, int y) {
byte bg_color = GRAY;
if (selected_color == color) {
bg_color = DARK_GRAY;
}
}
box(screen, bg_color, x, y, 20, 20);
box(screen, color, x + 2, y + 2, 17, 17);
return;
}
function box(ref Device screen, byte color, int x, int y, int width, int height) {
int pixel = y * width + x + &screen.buffer + 4;
do (int i = height, i > 0, i--) {
int row = pixel + width;
screen.set(row, color, width);
pixel += width;
}
return;
}

View File

@ -5,9 +5,11 @@
#include <emscripten/html5.h>
i32 console_open(void *data, u32 mode) {
i32 console_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
USED(data);
USED(buffer);
USED(size);
return 0;
}
@ -41,18 +43,23 @@ i32 console_ioctl(void *data, u32 cmd, const u8 *buffer) {
return -1;
}
i32 screen_open(void *data, u32 mode) {
i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
ScreenDeviceData *screen = (ScreenDeviceData *)data;
// Initialize with proper values
screen->width = 640;
screen->height = 480;
screen->size = 640 * 480;
screen->size = 640 * 480 + 12;
screen->window = NULL;
screen->renderer = NULL;
screen->texture = NULL;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &screen->width, sizeof(u32));
memcpy(&info[4], &screen->height, sizeof(u32));
memcpy(&info[8], &screen->size, sizeof(u32));
#ifdef __EMSCRIPTEN__
emscripten_set_canvas_element_size("#canvas", screen->width, screen->height);
#endif
@ -161,30 +168,13 @@ i32 screen_read(void *data, u8 *buffer, u32 size) {
}
i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer) {
ScreenDeviceData *screen = (ScreenDeviceData *)data;
switch (cmd) {
case IOCTL_GET_INFO: {
u8 *info = (u8 *)buffer;
u32 size;
memcpy(&size, &info[0], sizeof(u32));
if (size < 16) {
return -1;
}
memcpy(&info[4], &screen->pos, sizeof(u32));
memcpy(&info[8], &screen->size, sizeof(u32));
memcpy(&info[12], &screen->width, sizeof(u32));
memcpy(&info[16], &screen->height, sizeof(u32));
return 0;
}
default:
return -1;
}
USED(data);
USED(cmd);
USED(buffer);
return 0;
}
i32 mouse_open(void *data, u32 mode) {
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
return 0;
}
@ -216,9 +206,10 @@ i32 mouse_close(void *data) {
return 0;
}
i32 keyboard_open(void *data, u32 mode) {
i32 keyboard_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(data);
USED(mode);
USED(buffer);
return 0;
}

View File

@ -1,14 +1,13 @@
#include "../../vm/vm.h"
#include <SDL2/SDL.h>
#define IOCTL_GET_INFO 0x01
typedef struct screen_device_data_s {
u32 handle;
u32 width;
u32 height;
u32 pos;
u32 size;
u8 *screen_buffer;
u32 pos;
bool update;
SDL_Window *window;
SDL_Renderer *renderer;
@ -17,6 +16,7 @@ typedef struct screen_device_data_s {
/* Mouse device data */
typedef struct mouse_device_data_s {
u32 handle;
u32 x;
u32 y;
u8 btn1;
@ -29,29 +29,36 @@ typedef struct mouse_device_data_s {
/* Keyboard device data */
typedef struct keyboard_device_data_s {
u32 handle;
i32 key_count;
const u8 *keys;
i32 key_count;
u32 pos;
u32 size;
} KeyboardDeviceData;
i32 screen_open(void *data, u32 mode);
/* Console device data */
typedef struct console_device_data_s {
u32 handle;
u32 size;
} ConsoleDeviceData;
i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 screen_read(void *data, u8 *buffer, u32 size);
i32 screen_write(void *data, const u8 *buffer, u32 size);
i32 screen_close(void *data);
i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer);
i32 mouse_open(void *data, u32 mode);
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 mouse_read(void *data, u8 *buffer, u32 size);
i32 mouse_write(void *data, const u8 *buffer, u32 size);
i32 mouse_close(void *data);
i32 keyboard_open(void *data, u32 mode);
i32 keyboard_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 keyboard_read(void *data, u8 *buffer, u32 size);
i32 keyboard_write(void *data, const u8 *buffer, u32 size);
i32 keyboard_close(void *data);
i32 console_open(void *data, u32 mode);
i32 console_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 console_read(void *data, u8 *buffer, u32 size);
i32 console_write(void *data, const u8 *buffer, u32 size);
i32 console_close(void *data);

View File

@ -3,10 +3,14 @@
#include <string.h>
#include <unistd.h>
i32 console_open(void *data, u32 mode) {
i32 console_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
USED(data);
/* Nothing to open — stdin/stdout are always available */
USED(size);
ConsoleDeviceData *console = (ConsoleDeviceData *)data;
console->handle = handle;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &console->handle, sizeof(u32));
return 0; /* Success */
}
@ -44,9 +48,17 @@ i32 console_ioctl(void *data, u32 cmd, const u8 *buffer) {
return -1; /* Unsupported */
}
i32 screen_open(void *data, u32 mode) {
i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
USED(size);
ScreenDeviceData *screen = (ScreenDeviceData *)data;
screen->handle = handle;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &screen->handle, sizeof(u32));
memcpy(&info[4], &screen->width, sizeof(u32));
memcpy(&info[8], &screen->height, sizeof(u32));
memcpy(&info[12], &screen->size, sizeof(u32));
screen->window =
SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
@ -111,34 +123,21 @@ i32 screen_close(void *data) {
}
i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer) {
ScreenDeviceData *screen = (ScreenDeviceData *)data;
switch (cmd) {
case IOCTL_GET_INFO: {
u8 *info = (u8 *)buffer;
u32 size;
memcpy(&size, &info[0], sizeof(u32));
if (size < 16) {
return -1;
}
memcpy(&info[4], &screen->pos, sizeof(u32));
memcpy(&info[8], &screen->size, sizeof(u32));
memcpy(&info[12], &screen->width, sizeof(u32));
memcpy(&info[16], &screen->height, sizeof(u32));
return 0;
}
default:
return -1; // Error
}
USED(data);
USED(cmd);
USED(buffer);
return 0;
}
/* MOUSE */
i32 mouse_open(void *data, u32 mode) {
USED(data);
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
USED(size);
MouseDeviceData *mouse = (MouseDeviceData *)data;
mouse->handle = handle;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &mouse->handle, sizeof(u32));
return 0;
}
@ -160,12 +159,12 @@ i32 mouse_read(void *data, u8 *buffer, u32 size) {
mouse_data->btn4 = (state & SDL_BUTTON(SDL_BUTTON_X1)) ? 1 : 0;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &mouse_data->x, sizeof(u32));
memcpy(&info[4], &mouse_data->y, sizeof(u32));
memcpy(&info[8], &mouse_data->btn1, sizeof(u8));
memcpy(&info[9], &mouse_data->btn2, sizeof(u8));
memcpy(&info[10], &mouse_data->btn3, sizeof(u8));
memcpy(&info[11], &mouse_data->btn4, sizeof(u8));
memcpy(&info[4], &mouse_data->x, sizeof(u32));
memcpy(&info[8], &mouse_data->y, sizeof(u32));
memcpy(&info[9], &mouse_data->btn1, sizeof(u8));
memcpy(&info[10], &mouse_data->btn2, sizeof(u8));
memcpy(&info[11], &mouse_data->btn3, sizeof(u8));
memcpy(&info[12], &mouse_data->btn4, sizeof(u8));
return 0;
}
@ -181,9 +180,15 @@ i32 mouse_close(void *data) {
return 0;
}
i32 keyboard_open(void *data, u32 mode) {
USED(data);
i32 keyboard_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) {
USED(mode);
USED(size);
KeyboardDeviceData *kbd = (KeyboardDeviceData *)data;
kbd->handle = handle;
u8 *info = (u8 *)buffer;
memcpy(&info[0], &kbd->handle, sizeof(u32));
return 0;
}
@ -193,7 +198,8 @@ i32 keyboard_read(void *data, u8 *buffer, u32 size) {
if (size < (u32)kbd->key_count)
return -1;
memcpy(buffer, kbd->keys, kbd->key_count);
u8 *info = (u8 *)buffer;
memcpy(&info[4], kbd->keys, kbd->key_count);
return 0;
}

View File

@ -6,9 +6,9 @@
/* Screen device data */
typedef struct screen_device_data_s {
u32 handle;
u32 width;
u32 height;
u32 pos;
u32 size;
u8 *screen_buffer;
u32 update;
@ -19,41 +19,48 @@ typedef struct screen_device_data_s {
/* Mouse device data */
typedef struct mouse_device_data_s {
u32 handle;
u32 x;
u32 y;
u8 btn1;
u8 btn2;
u8 btn3;
u8 btn4;
u32 pos;
u32 size;
} MouseDeviceData;
/* Keyboard device data */
typedef struct keyboard_device_data_s {
u32 handle;
const u8 *keys;
i32 key_count;
u32 pos;
u32 size;
} KeyboardDeviceData;
i32 screen_open(void *data, u32 mode);
/* Console device data */
typedef struct console_device_data_s {
u32 handle;
u32 size;
} ConsoleDeviceData;
i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 screen_read(void *data, u8 *buffer, u32 size);
i32 screen_write(void *data, const u8 *buffer, u32 size);
i32 screen_close(void *data);
i32 screen_ioctl(void *data, u32 cmd, const u8 *buffer);
i32 mouse_open(void *data, u32 mode);
i32 mouse_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 mouse_read(void *data, u8 *buffer, u32 size);
i32 mouse_write(void *data, const u8 *buffer, u32 size);
i32 mouse_close(void *data);
i32 keyboard_open(void *data, u32 mode);
i32 keyboard_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 keyboard_read(void *data, u8 *buffer, u32 size);
i32 keyboard_write(void *data, const u8 *buffer, u32 size);
i32 keyboard_close(void *data);
i32 console_open(void *data, u32 mode);
i32 console_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 console_read(void *data, u8 *buffer, u32 size);
i32 console_write(void *data, const u8 *buffer, u32 size);
i32 console_close(void *data);

View File

@ -39,6 +39,7 @@ static DeviceOps console_device_ops = {
static ScreenDeviceData screen_data = {0};
static MouseDeviceData mouse_data = {0};
static KeyboardDeviceData keyboard_data = {0};
static ConsoleDeviceData console_data = {0};
// Function to save VM state to ROM file
bool saveVM(const char *filename, VM *vm) {
@ -382,7 +383,9 @@ i32 main(i32 argc, char *argv[]) {
return EXIT_SUCCESS;
}
vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops);
vm_register_device(&vm, "/dev/term/0", "terminal", &console_data,
&console_device_ops, 4);
if (gui_mode) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL initialization failed: %s\n", SDL_GetError());
@ -395,7 +398,7 @@ i32 main(i32 argc, char *argv[]) {
screen_data.size = screen_data.width * screen_data.height;
vm_register_device(&vm, "/dev/screen/0", "screen", &screen_data,
&screen_ops);
&screen_ops, 16 + screen_data.size);
mouse_data.x = 0;
mouse_data.y = 0;
@ -403,13 +406,14 @@ i32 main(i32 argc, char *argv[]) {
mouse_data.btn2 = 0;
mouse_data.btn3 = 0;
mouse_data.btn4 = 0;
mouse_data.size = 12;
mouse_data.size = 16;
vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops);
vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops,
mouse_data.size);
keyboard_data.keys = SDL_GetKeyboardState(&keyboard_data.key_count);
vm_register_device(&vm, "/dev/keyboard/0", "keyboard", &keyboard_data,
&keyboard_ops);
&keyboard_ops, keyboard_data.key_count + 4);
SDL_Event event;
bool running = true;

View File

@ -75,8 +75,7 @@ int get_instruction_byte_size(ExprNode *node) {
}
// Register-based opcodes (2 bytes: opcode + register)
if (strcmp(opname, "pop") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
strcmp(opname, "jump") == 0 || strcmp(opname, "push") == 0) {
if (strcmp(opname, "pop") == 0 || strcmp(opname, "push") == 0) {
return 2;
}
@ -111,7 +110,8 @@ int get_instruction_byte_size(ExprNode *node) {
}
// (5 bytes: 1 + 4)
if (strcmp(opname, "call") == 0) {
if (strcmp(opname, "call") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
strcmp(opname, "jump") == 0) {
return 5;
}

View File

@ -2,7 +2,7 @@
#include "str.h"
i32 vm_register_device(VM *vm, const char *path, const char *type, void *data,
DeviceOps *ops) {
DeviceOps *ops, u32 size) {
Device *dev;
if (vm->dc >= DEVICES_SIZE)
@ -18,6 +18,7 @@ i32 vm_register_device(VM *vm, const char *path, const char *type, void *data,
dev->data = data;
dev->ops = ops;
dev->size = size;
dev->flags = 0;
return dev->handle;
}

View File

@ -3,7 +3,7 @@
#include "opcodes.h"
i32 vm_register_device(VM *vm, const char *path, const char *type, void *data, DeviceOps *ops);
i32 vm_register_device(VM *vm, const char *path, const char *type, void *data, DeviceOps *ops, u32 size);
Device* find_device_by_path(VM *vm, const char *path);
Device* find_device_by_type(VM *vm, const char *type);
i32 find_devices_by_type(VM *vm, const char *type, Device **results, uint32_t max_results);

View File

@ -102,7 +102,7 @@ typedef enum {
} SyscallID;
typedef struct device_ops_s {
i32 (*open)(void *device_data, u32 mode);
i32 (*open)(void *device_data, u32 mode, u32 handle, u8 *buffer, u32 size);
i32 (*read)(void *device_data, u8 *buffer, u32 size);
i32 (*write)(void *device_data, const u8 *buffer, u32 size);
i32 (*close)(void *device_data);
@ -121,6 +121,7 @@ typedef struct device_s {
DeviceOps *ops; /* operations vtable */
u32 flags; /* permissions, status, etc. */
u32 handle; /* id for fast access in VM */
u32 size; /* id for fast access in VM */
} Device;
#define MEMORY_SIZE (640 * 480 + 65536)

View File

@ -355,17 +355,15 @@ bool step_vm(VM *vm) {
return true;
}
case OP_JMP: {
dest = read_u8(vm, code, vm->pc);
vm->pc++;
vm->pc = frame->registers[dest]; /* Jump to address */
u32 jmp = read_u32(vm, code, vm->pc);
vm->pc = jmp; /* Jump to address */
return true;
}
case OP_JMPF: { /* error handling for syscall, jump if flag == 0 */
u32 mask;
dest = read_u8(vm, code, vm->pc);
vm->pc++;
u32 jmp = read_u32(vm, code, vm->pc);
mask = -(u32)(vm->flag == 0);
vm->pc = (dest & mask) | (vm->pc & ~mask);
vm->pc = (jmp & mask) | (vm->pc & ~mask);
return true;
}
case OP_SYSCALL: {
@ -377,7 +375,7 @@ bool step_vm(VM *vm) {
switch (syscall_id) {
case SYSCALL_DEVICE_OPEN: {
Device *dev;
u32 path_ptr, mode;
u32 path_ptr, mode, buffer_ptr;
u8 path_reg, mode_reg, dest_reg;
dest_reg = read_u8(vm, code, vm->pc);
vm->pc++;
@ -391,8 +389,14 @@ bool step_vm(VM *vm) {
dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
if (dev) {
if (dev->ops->open) {
vm->flag = dev->ops->open(dev->data, mode);
frame->registers[dest_reg] = dev->handle;
/* return device plex to user */
buffer_ptr = vm->mp;
frame->registers[dest_reg] = buffer_ptr;
/* malloc size for device */
write_u32(vm, memory, buffer_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);
} else {
vm->flag = 1; /* success, no open needed */
}

View File

@ -4,25 +4,27 @@
; 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 $0 $0 $11)
(syscall OPEN $18 $0 $11) ; open(out Plex screen, in namespace, in flags)
(get $0 $18) ; load handle (offset 0)
(load-immediate $16 1) ; device info call
(load-immediate $17 16) ; sizeof screen device info
(malloc $18 $17)
(syscall IOCTL $0 $16 $18)
(load-immediate $1 12) ; offset for width
; open mouse
(load-immediate $16 &mouse-namespace)
(syscall OPEN $15 $16 0)
(get $16 $15) ; load handle (offset 0)
(load-immediate $1 4) ; offset for width
(add-nat $19 $18 $1)
(get $20 $19) ; load width
(load-immediate $1 8) ; offset for size
(add-nat $19 $18 $1)
(get $22 $19) ; load size
(malloc $21 $22) ; malloc frame buffer
(get $22 $19) ; load size
(load-immediate $16 &mouse-namespace)
(load-immediate $3 12) ; malloc sizeof mouse data
(malloc $4 $3)
(syscall OPEN $16 $16 $4)
(load-immediate $1 12) ; offset for screen buffer
(add-nat $19 $18 $1)
(get $21 $19)
; outline_swatch(screen, BLACK, 1, 1);
(push $21)
(push $20)
(load $1 &BLACK)
@ -33,6 +35,7 @@
(push $13)
(call &draw-outlined-swatch)
; outline_swatch(screen, WHITE, 1, 1);
(push $21)
(push $20)
(load $1 &WHITE)
@ -45,7 +48,6 @@
(syscall WRITE $0 $21 $22)
(label draw-loop
; load mouse click data
(syscall READ $16 $2 $3 $4)
@ -53,8 +55,6 @@
(add-nat $6 $5 $2)
(get-8 $9 $6) ; load btn1 pressed
(load-immediate $14 20) ; box size
(jump-eq-nat &draw-loop $9 $11)
(load-immediate $5 4) ; offset for x
@ -63,9 +63,8 @@
(load-immediate $5 8) ; offset for y
(add-nat $6 $5 $2)
(get $8 $6) ; load y
(load-immediate $5 13) ; offset for btn2
(add-nat $6 $5 $2)
(get-8 $10 $6) ; load btn2 pressed
(load-immediate $14 20) ; box size
; first row
(push $21)
@ -120,7 +119,7 @@
(push $1)
(call &draw-box)
(jump-eq-nat &draw-loop $10 $11))
(jump &draw-loop))
; Flush and halt
(halt))
@ -147,7 +146,8 @@
(jump-lt-int &fail $1 $3)
(jump-gt-int &fail $1 $7)
; If btn1 is pressed (==1), set color
(jump-eq-int &fail $12 1)
(load-immediate $8 1)
(jump-eq-int &fail $12 $8)
(load-immediate $10 &SELECTED-COLOR)
(store-8 $10 $11)

View File

@ -239,7 +239,7 @@
(jump-eq-nat &draw-loop $9 $11)
(load $22 &SELECTED-COLOR) ; color
(load-immediate $1 5) ; size of brush
(load-immediate $1 3) ; size of brush
(push $21) ;base
(push $20) ;width