diff --git a/src/arch/linux/devices.c b/src/arch/linux/devices.c index f9f33e7..cf45dcb 100644 --- a/src/arch/linux/devices.c +++ b/src/arch/linux/devices.c @@ -53,8 +53,24 @@ i32 screen_open(void *data, u32 mode) { SDL_WINDOWPOS_CENTERED, screen->width, screen->height, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); - if (!screen->window) + if (!screen->window) { return -1; + } + + screen->renderer = + SDL_CreateRenderer(screen->window, -1, SDL_RENDERER_ACCELERATED); + if (!screen->renderer) { + return -1; + } + + screen->texture = SDL_CreateTexture(screen->renderer, SDL_PIXELFORMAT_RGB332, + SDL_TEXTUREACCESS_STREAMING, + screen->width, screen->height); + + if (!screen->texture) { + fprintf(stderr, "SDL_CreateTexture failed: %s\n", SDL_GetError()); + return -1; + } SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); return 0; @@ -73,30 +89,29 @@ i32 screen_write(void *data, const u8 *buffer, u32 size) { if (size > screen->size * sizeof(u8)) { return -1; } - - if (!screen->surface && screen->window) { - const u8 *pixel_buffer = buffer; - int pitch = screen->width; // bytes per row - - screen->surface = SDL_CreateRGBSurfaceFrom((void *)pixel_buffer, - screen->width, screen->height, - 8, // bits per pixel - pitch, - 0xE0, // R mask (RGB332) - 0x1C, // G mask - 0x03, // B mask - 0x00 // no alpha - ); - - if (!screen->surface) { - fprintf(stderr, "SDL_CreateRGBSurfaceFrom failed: %s\n", SDL_GetError()); - return -1; - } - } - - SDL_BlitScaled(screen->surface, NULL, SDL_GetWindowSurface(screen->window), - NULL); - SDL_UpdateWindowSurface(screen->window); + // Update texture with new frame data + SDL_UpdateTexture(screen->texture, NULL, buffer, screen->width); + + // Clear and render + SDL_RenderClear(screen->renderer); + + SDL_Rect output_rect; + SDL_RenderGetViewport(screen->renderer, &output_rect); + + // Calculate aspect ratio preserving scaling + float scale_x = (float)output_rect.w / screen->width; + float scale_y = (float)output_rect.h / screen->height; + float scale = SDL_min(scale_x, scale_y); + + SDL_Rect dstrect = { + (i32)((output_rect.w - screen->width * scale) / 2), + (i32)((output_rect.h - screen->height * scale) / 2), + (i32)(screen->width * scale), + (i32)(screen->height * scale) + }; + + SDL_RenderCopy(screen->renderer, screen->texture, NULL, &dstrect); + SDL_RenderPresent(screen->renderer); return 0; } diff --git a/src/arch/linux/devices.h b/src/arch/linux/devices.h index 8cd9910..6c00fcb 100644 --- a/src/arch/linux/devices.h +++ b/src/arch/linux/devices.h @@ -11,7 +11,8 @@ typedef struct screen_device_data_s { u32 pos; u32 size; SDL_Window *window; - SDL_Surface *surface; + SDL_Renderer *renderer; + SDL_Texture *texture; } ScreenDeviceData; /* Mouse device data */ diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 57ffc12..1a10efd 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -236,31 +236,6 @@ void repl(VM *vm) { exit(0); } -/* - * This needs to be done dynamically eventually - */ -void register_sdl_devices(VM *vm) { - screen_data.width = 640; - screen_data.height = 480; - screen_data.size = screen_data.width * screen_data.height; - - vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops); - - mouse_data.x = 0; - mouse_data.y = 0; - mouse_data.btn1 = 0; - mouse_data.btn2 = 0; - mouse_data.btn3 = 0; - mouse_data.btn4 = 0; - mouse_data.size = 12; - - vm_register_device(vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops); - - keyboard_data.keys = SDL_GetKeyboardState(&keyboard_data.key_count); - vm_register_device(vm, "/dev/keyboard/0", "keyboard", &keyboard_data, - &keyboard_ops); -} - #ifdef ASM_DEBUG const char *opcode_to_string(Opcode op) { static const char *names[] = {[OP_HALT] = "halt", @@ -407,28 +382,45 @@ i32 main(i32 argc, char *argv[]) { return EXIT_SUCCESS; } - bool running = true; - vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops); if (gui_mode) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL initialization failed: %s\n", SDL_GetError()); return 1; } - register_sdl_devices(&vm); SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + screen_data.width = 640; + screen_data.height = 480; + screen_data.size = screen_data.width * screen_data.height; + + vm_register_device(&vm, "/dev/screen/0", "screen", + &screen_data, &screen_ops); + + mouse_data.x = 0; + mouse_data.y = 0; + mouse_data.btn1 = 0; + mouse_data.btn2 = 0; + mouse_data.btn3 = 0; + mouse_data.btn4 = 0; + mouse_data.size = 12; + + vm_register_device(&vm, "/dev/mouse/0", "mouse", &mouse_data, &mouse_ops); + + keyboard_data.keys = SDL_GetKeyboardState(&keyboard_data.key_count); + vm_register_device(&vm, "/dev/keyboard/0", "keyboard", &keyboard_data, + &keyboard_ops); + + bool running = true; while (running) { -#ifdef ASM_DEBUG - printf("| %s %d\n", opcode_to_string(vm.code[vm.pc]), vm.pc); -#endif - running = step_vm(&vm); + if (!step_vm(&vm)) { + running = false; + break; + } } } else { + bool running = true; while (running) { -#ifdef ASM_DEBUG - printf("| %s %d\n", opcode_to_string(vm.code[vm.pc]), vm.pc); -#endif running = step_vm(&vm); } } diff --git a/src/tools/assembler.c b/src/tools/assembler.c index 5bb1a38..e265f52 100644 --- a/src/tools/assembler.c +++ b/src/tools/assembler.c @@ -524,6 +524,24 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) { int src1 = parse_register(node->children[1]->token); emit_byte(vm, dest); emit_byte(vm, src1); + } else if (strcmp(opname, "put-8") == 0) { + emit_opcode(vm, OP_PUT_8); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "put-16") == 0) { + emit_opcode(vm, OP_PUT_16); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); + } else if (strcmp(opname, "put") == 0) { + emit_opcode(vm, OP_PUT_32); + int dest = parse_register(node->children[0]->token); + int src1 = parse_register(node->children[1]->token); + emit_byte(vm, dest); + emit_byte(vm, src1); } else if (strcmp(opname, "push") == 0) { emit_opcode(vm, OP_PUSH); int reg = parse_register(node->children[0]->token); diff --git a/src/vm/device.c b/src/vm/device.c index e6c3ebb..5d93c9f 100644 --- a/src/vm/device.c +++ b/src/vm/device.c @@ -8,8 +8,8 @@ i32 vm_register_device(VM *vm, const char *path, const char *type, void *data, if (vm->dc >= DEVICES_SIZE) return -1; - dev = &vm->devices[vm->dc++]; - + dev = &vm->devices[vm->dc]; + dev->handle = vm->dc++; strcopy(dev->path, path, DEVICE_PATH_MAX_LENGTH); dev->path[DEVICE_PATH_MAX_LENGTH - 1] = '\0'; @@ -19,7 +19,7 @@ i32 vm_register_device(VM *vm, const char *path, const char *type, void *data, dev->data = data; dev->ops = ops; dev->flags = 0; - return 0; + return dev->handle; } /* Find device by path */ diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index 332fec7..f1811f6 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -110,7 +110,7 @@ typedef struct device_ops_s { const u8 *buffer); /* optional control */ } DeviceOps; -#define DEVICE_TYPE_MAX_LENGTH 24 /* 23 chars + null terminator */ +#define DEVICE_TYPE_MAX_LENGTH 16 /* 15 chars + null terminator */ #define DEVICE_PATH_MAX_LENGTH 64 /* 63 chars + null terminator */ typedef struct device_s { @@ -120,6 +120,7 @@ typedef struct device_s { void *data; /* device-specific data */ DeviceOps *ops; /* operations vtable */ u32 flags; /* permissions, status, etc. */ + u32 handle; /* id for fast access in VM */ } Device; #define MEMORY_SIZE (640 * 480 + 65536) diff --git a/src/vm/vm.c b/src/vm/vm.c index 13b7cc2..0253eb9 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -378,7 +378,9 @@ bool step_vm(VM *vm) { case SYSCALL_DEVICE_OPEN: { Device *dev; u32 path_ptr, mode; - u8 path_reg, mode_reg; + u8 path_reg, mode_reg, dest_reg; + dest_reg = read_u8(vm, code, vm->pc); + vm->pc++; path_reg = read_u8(vm, code, vm->pc); vm->pc++; mode_reg = read_u8(vm, code, vm->pc); @@ -390,6 +392,7 @@ bool step_vm(VM *vm) { if (dev) { if (dev->ops->open) { vm->flag = dev->ops->open(dev->data, mode); + frame->registers[dest_reg] = dev->handle; } else { vm->flag = 1; /* success, no open needed */ } @@ -402,9 +405,9 @@ bool step_vm(VM *vm) { case SYSCALL_DEVICE_READ: { Device *dev; - u32 path_ptr, buffer_ptr, size; - u16 path_reg, buffer_reg, size_reg; - path_reg = read_u8(vm, code, vm->pc); + u32 handle, buffer_ptr, size; + u16 handle_reg, buffer_reg, size_reg; + handle_reg = read_u8(vm, code, vm->pc); vm->pc++; buffer_reg = read_u8(vm, code, vm->pc); vm->pc++; @@ -413,11 +416,11 @@ bool step_vm(VM *vm) { dest = read_u8(vm, code, vm->pc); vm->pc++; - path_ptr = frame->registers[path_reg]; /* path pointer */ + handle = frame->registers[handle_reg]; /* path pointer */ size = frame->registers[size_reg]; /* size */ buffer_ptr = frame->registers[dest]; - dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); + 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; @@ -430,20 +433,20 @@ bool step_vm(VM *vm) { case SYSCALL_DEVICE_WRITE: { Device *dev; - u32 path_ptr, buffer_ptr, size; - u16 path_reg, buffer_reg, size_reg; - path_reg = read_u8(vm, code, vm->pc); + u32 handle, buffer_ptr, size; + u16 handle_reg, buffer_reg, size_reg; + handle_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++; - path_ptr = frame->registers[path_reg]; /* R0: path pointer */ + handle = frame->registers[handle_reg]; /* R0: path pointer */ buffer_ptr = frame->registers[buffer_reg]; /* R1: buffer pointer */ size = frame->registers[size_reg]; /* R2: size */ - dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); + dev = &vm->devices[handle]; if (dev && dev->ops->write) { vm->flag = dev->ops->write( dev->data, (const u8 *)&vm->memory[buffer_ptr + 4], size); @@ -456,15 +459,14 @@ bool step_vm(VM *vm) { case SYSCALL_DEVICE_CLOSE: { Device *dev; - u32 path_ptr; - u8 path_reg; - path_reg = read_u8(vm, code, vm->pc); + u32 handle; + u8 handle_reg; + handle_reg = read_u8(vm, code, vm->pc); vm->pc++; - path_ptr = frame->registers[path_reg]; /* R0: path pointer */ - - dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); + handle = frame->registers[handle_reg]; /* R0: path pointer */ + dev = &vm->devices[handle]; if (dev && dev->ops->close) { i32 result = dev->ops->close(dev->data); vm->flag = result; @@ -477,21 +479,20 @@ bool step_vm(VM *vm) { case SYSCALL_DEVICE_IOCTL: { Device *dev; - u32 path_ptr, args_ptr, cmd; - u8 path_reg, cmd_reg, args_ptr_reg; - path_reg = read_u8(vm, code, vm->pc); + u32 handle, args_ptr, cmd; + u8 handle_reg, cmd_reg, args_ptr_reg; + handle_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++; - path_ptr = frame->registers[path_reg]; /* R0: device path */ + handle = frame->registers[handle_reg]; /* R0: device path */ cmd = frame->registers[cmd_reg]; /* R1: ioctl command */ args_ptr = frame->registers[args_ptr_reg]; /* R2: args pointer */ - dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]); - + dev = &vm->devices[handle]; if (dev && dev->ops && dev->ops->ioctl) { i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]); vm->flag = result; diff --git a/test/add.asm.lisp b/test/add.asm.lisp index 68c4d93..9bd95bf 100644 --- a/test/add.asm.lisp +++ b/test/add.asm.lisp @@ -1,24 +1,33 @@ -(module add - (const terminal-namespace "/dev/term/0") - (const new-line "\n") - - (fn :1 main () +((code + (label main (load-immediate $0 1) - (load-immediate $1 1) - (call &add ($0 $1) $2) - (int-to-string $1 $2) - (call &pln ($1)) + (push $0) + (load-immediate $0 1) + (push $0) + (call &add) + (pop $0) + (int-to-string $1 $0) + (push $1) + (call &println) (halt)) - - (fn :1 add ($0 $1) + + (label add + (pop $0) + (pop $1) (add-int $2 $1 $0) - (return $2)) + (push $2) + (return)) - (fn :1 pln ($1) + (label println (load-immediate $0 &terminal-namespace) + (syscall OPEN $0 $0 $0) (load-immediate $3 &new-line) + (pop $1) (string-length $2 $1) (syscall WRITE $0 $1 $2) (string-length $4 $3) (syscall WRITE $0 $3 $4) (return))) +(data + (label terminal-namespace "/dev/term/0") + (label new-line "\n"))) diff --git a/test/fib.asm.lisp b/test/fib.asm.lisp index 3c5fffd..9ba5ea7 100644 --- a/test/fib.asm.lisp +++ b/test/fib.asm.lisp @@ -30,6 +30,7 @@ (return))) (label pln (load-immediate $0 &terminal-namespace) + (syscall OPEN $0 $0 $0) (load-immediate $3 &new-line) (pop $1) (string-length $2 $1) diff --git a/test/hello.asm.lisp b/test/hello.asm.lisp index 2e3e33a..ce12640 100644 --- a/test/hello.asm.lisp +++ b/test/hello.asm.lisp @@ -1,6 +1,7 @@ ((code (label main (load-immediate $0 &terminal-namespace) ; load terminal namespace + (syscall OPEN $0 $0 $0) (load-immediate $1 &hello-str) ; load hello string ptr (string-length $2 $1) ; get length to write to stdout (syscall WRITE $0 $1 $2) ; do the write syscall diff --git a/test/loop.asm.lisp b/test/loop.asm.lisp index 66f4e61..6f13625 100644 --- a/test/loop.asm.lisp +++ b/test/loop.asm.lisp @@ -29,6 +29,7 @@ (halt)) (label pln (load-immediate $0 &terminal-namespace) + (syscall OPEN $0 $0 $0) (load-immediate $3 &new-line) (pop $1) (string-length $2 $1) diff --git a/test/malloc.asm.lisp b/test/malloc.asm.lisp index ee827be..5ace03f 100644 --- a/test/malloc.asm.lisp +++ b/test/malloc.asm.lisp @@ -12,6 +12,7 @@ (halt)) (label pln (load-immediate $0 &terminal-namespace) + (syscall OPEN $0 $0 $0) (load-immediate $3 &new-line) (pop $1) (string-length $2 $1) diff --git a/test/paint.asm.lisp b/test/paint.asm.lisp index 8e4450b..b06dffe 100644 --- a/test/paint.asm.lisp +++ b/test/paint.asm.lisp @@ -4,7 +4,7 @@ ; 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 $11) + (syscall OPEN $0 $0 $11) (load-immediate $16 1) ; device info call (load-immediate $17 16) ; sizeof screen device info @@ -22,6 +22,7 @@ (load-immediate $16 &mouse-namespace) (load-immediate $3 12) ; malloc sizeof mouse data (malloc $4 $3) + (syscall OPEN $16 $16 $4) (label draw-loop ; load mouse click data @@ -240,14 +241,17 @@ (jump-eq-nat &draw-loop $9 $11) - (mul-nat $15 $8 $20) ; $15 = y * width - (add-nat $15 $15 $7) ; $15 += x - (add-nat $15 $21 $15) ; $15 = base + pixel_offset - (load-immediate $1 4) ; need to add offset for fat pointer size - (add-nat $15 $15 $1) - (load $22 &SELECTED-COLOR) ; color - (store-8 $15 $22) ; draw color at screen [x,y] + (load-immediate $1 5) ; size of brush + + (push $21) ;base + (push $20) ;width + (push $22) ; color + (push $7) ;x + (push $8) ;y + (push $1) + (push $1) + (call &draw-box) (jump-eq-nat &draw-loop $10 $11)) diff --git a/test/simple.asm.lisp b/test/simple.asm.lisp index 4f89b36..55a17b3 100644 --- a/test/simple.asm.lisp +++ b/test/simple.asm.lisp @@ -9,6 +9,7 @@ (halt)) (label pln (load-immediate $0 &terminal-namespace) + (syscall OPEN $0 $0 $0) (load-immediate $3 &new-line) (pop $1) (string-length $2 $1) diff --git a/test/window.asm.lisp b/test/window.asm.lisp index ee6947b..39e3a78 100644 --- a/test/window.asm.lisp +++ b/test/window.asm.lisp @@ -2,7 +2,9 @@ (label main (load-immediate $0 &screen-namespace) (load-immediate $11 0) - (syscall OPEN $0 $11) + (syscall OPEN $0 $0 $11) + (load-immediate $32 &terminal-namespace) + (syscall OPEN $32 $32 $11) (load-immediate $16 1) ; device info call (load-immediate $17 16) ; sizeof screen device info @@ -20,8 +22,10 @@ (load-immediate $16 &mouse-namespace) (load-immediate $3 12) ; malloc sizeof mouse data (malloc $4 $3) + (syscall OPEN $16 $16 $4) (nat-to-string $5 $4) + (push $32) (push $5) (call &pln) @@ -59,9 +63,9 @@ (jump-eq-nat &draw-loop $10 $11)) (halt)) (label pln - (load-immediate $0 &terminal-namespace) (load-immediate $3 &new-line) (pop $1) + (pop $0) (string-length $2 $1) (syscall WRITE $0 $1 $2) (string-length $4 $3)