From 9d60a9753e4196875afe6f343e1d2aaee5708ff9 Mon Sep 17 00:00:00 2001 From: zongor Date: Thu, 12 Feb 2026 23:53:38 -0800 Subject: [PATCH] add device scaling --- src/arch/linux/devices.c | 3 +- src/arch/linux/main.c | 109 ++++++++++++++++++++++++--------------- src/vm/opcodes.h | 1 - 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/src/arch/linux/devices.c b/src/arch/linux/devices.c index 03aba8f..cfded7e 100644 --- a/src/arch/linux/devices.c +++ b/src/arch/linux/devices.c @@ -69,7 +69,7 @@ i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) { screen->window = SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen->width, screen->height, - SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); + SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); if (!screen->window) { return -1; @@ -90,7 +90,6 @@ i32 screen_open(void *data, u32 mode, u32 handle, u8 *buffer, u32 size) { return -1; } - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); return 0; } diff --git a/src/arch/linux/main.c b/src/arch/linux/main.c index 27ec9a9..e3c7a21 100644 --- a/src/arch/linux/main.c +++ b/src/arch/linux/main.c @@ -210,6 +210,29 @@ bool assembleAndSave(const char *source_file, const char *output_file, VM *vm) { return true; } +void scale_mouse_pos(u32 mouse_x, u32 mouse_y, u32 *vm_x, u32 *vm_y) { + int win_w, win_h; + SDL_GetWindowSize(screen_data.window, &win_w, &win_h); + + f32 scale_x = (f32)win_w / screen_data.width; + f32 scale_y = (f32)win_h / screen_data.height; + f32 scale = SDL_min(scale_x, scale_y); + + u32 dst_w = (u32)(screen_data.width * scale); + u32 dst_h = (u32)(screen_data.height * scale); + u32 dst_x = (win_w - dst_w) / 2; + u32 dst_y = (win_h - dst_h) / 2; + + f32 rel_x = (f32)(mouse_x - dst_x); + f32 rel_y = (f32)(mouse_y - dst_y); + + *vm_x = (u32)((rel_x / (f32)dst_w) * screen_data.width); + *vm_y = (u32)((rel_y / (f32)dst_h) * screen_data.height); + + if (*vm_x >= screen_data.width) *vm_x = screen_data.width - 1; + if (*vm_y >= screen_data.height) *vm_y = screen_data.height - 1; +} + i32 main(i32 argc, char *argv[]) { bool dump_rom = false; char *input_file = nil; @@ -294,6 +317,7 @@ i32 main(i32 argc, char *argv[]) { return 1; } SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); screen_data.width = 640; screen_data.height = 480; @@ -324,53 +348,54 @@ i32 main(i32 argc, char *argv[]) { case SDL_QUIT: running = false; break; - // Mouse events - case SDL_MOUSEMOTION: - mouse_data.x = event.motion.x; - mouse_data.y = event.motion.y; + case SDL_WINDOWEVENT:{ + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + screen_data.update = true; + break; + } + break; + } + case SDL_MOUSEMOTION: { + u32 vm_x, vm_y; + scale_mouse_pos(event.motion.x, event.motion.y, &vm_x, &vm_y); + mouse_data.x = vm_x; + mouse_data.y = vm_y; break; - + } case SDL_MOUSEBUTTONDOWN: - if (event.button.button == SDL_BUTTON_LEFT) - mouse_data.btn1 = 1; - if (event.button.button == SDL_BUTTON_RIGHT) - mouse_data.btn2 = 1; - if (event.button.button == SDL_BUTTON_MIDDLE) - mouse_data.btn3 = 1; - if (event.button.button == SDL_BUTTON_X1) - mouse_data.btn4 = 1; - break; + case SDL_MOUSEBUTTONUP: { + u32 vm_x, vm_y; + scale_mouse_pos(event.button.x, event.button.y, &vm_x, &vm_y); + + mouse_data.x = vm_x; + mouse_data.y = vm_y; - case SDL_MOUSEBUTTONUP: - if (event.button.button == SDL_BUTTON_LEFT) - mouse_data.btn1 = 0; - if (event.button.button == SDL_BUTTON_RIGHT) - mouse_data.btn2 = 0; - if (event.button.button == SDL_BUTTON_MIDDLE) - mouse_data.btn3 = 0; - if (event.button.button == SDL_BUTTON_X1) - mouse_data.btn4 = 0; + bool pressed = (event.type == SDL_MOUSEBUTTONDOWN); + if (event.button.button == SDL_BUTTON_LEFT) mouse_data.btn1 = pressed; + if (event.button.button == SDL_BUTTON_RIGHT) mouse_data.btn2 = pressed; + if (event.button.button == SDL_BUTTON_MIDDLE) mouse_data.btn3 = pressed; + if (event.button.button == SDL_BUTTON_X1) mouse_data.btn4 = pressed; break; - - // Touch events (map to mouse_data as left-click equivalent) + } case SDL_FINGERMOTION: case SDL_FINGERDOWN: case SDL_FINGERUP: { + int win_w, win_h; + SDL_GetWindowSize(screen_data.window, &win_w, &win_h); + + u32 touch_pixel_x = (u32)(event.tfinger.x * win_w); + u32 touch_pixel_y = (u32)(event.tfinger.y * win_h); - f32 x = event.tfinger.x * 640; - f32 y = event.tfinger.y * 480; + u32 vm_x, vm_y; + scale_mouse_pos(touch_pixel_x, touch_pixel_y, &vm_x, &vm_y); - mouse_data.x = (i32)x; - mouse_data.y = (i32)y; + mouse_data.x = vm_x; + mouse_data.y = vm_y; - // Only treat the first finger as mouse input (ignore multi-touch - // beyond 1 finger) if (event.tfinger.fingerId == 0) { - if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) { - mouse_data.btn1 = 1; - } else if (event.type == SDL_FINGERUP) { - mouse_data.btn1 = 0; - } + bool pressed = (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION); + mouse_data.btn1 = pressed ? 1 : 0; } break; } @@ -395,17 +420,17 @@ i32 main(i32 argc, char *argv[]) { // Clear and render SDL_RenderClear(screen_data.renderer); - SDL_Rect output_rect; - SDL_RenderGetViewport(screen_data.renderer, &output_rect); + int window_w, window_h; + SDL_GetWindowSize(screen_data.window, &window_w, &window_h); // Calculate aspect ratio preserving scaling - f32 scale_x = (f32)output_rect.w / screen_data.width; - f32 scale_y = (f32)output_rect.h / screen_data.height; + f32 scale_x = (f32)window_w / screen_data.width; + f32 scale_y = (f32)window_h / screen_data.height; f32 scale = SDL_min(scale_x, scale_y); SDL_Rect dstrect = { - (i32)((output_rect.w - screen_data.width * scale) / 2), - (i32)((output_rect.h - screen_data.height * scale) / 2), + (i32)((window_w - screen_data.width * scale) / 2), + (i32)((window_h - screen_data.height * scale) / 2), (i32)(screen_data.width * scale), (i32)(screen_data.height * scale)}; diff --git a/src/vm/opcodes.h b/src/vm/opcodes.h index d14d8ae..66c10f7 100644 --- a/src/vm/opcodes.h +++ b/src/vm/opcodes.h @@ -126,7 +126,6 @@ typedef struct device_ops_s { i32 (*refresh)(void *device_data, u8 *buffer); } DeviceOps; - typedef struct device_s { const char *type; /* e.g., "screen", "mouse", "gpio" */ const char *path; /* "/dev/screen", "/dev/input/mouse/0", etc. */