#include "devices.h" #include #include #include i32 console_open(void *data, u32 mode) { USED(mode); USED(data); /* Nothing to open — stdin/stdout are always available */ return 0; /* Success */ } i32 console_read(void *data, u8 *buffer, u32 size) { USED(data); for (u32 i = 0; i < size; i++) { u8 ch = getchar(); if (ch == '\0') break; if (ch == '\n') break; buffer[i] = ch; } return 0; } i32 console_write(void *data, const u8 *buffer, u32 size) { USED(data); for (u32 i = 0; i < size; i++) { putchar(buffer[i]); } return 0; } i32 console_close(void *data) { USED(data); /* Nothing to close — stdin/stdout are process-owned */ return 0; } i32 console_ioctl(void *data, u32 cmd, const u8 *buffer) { USED(data); USED(cmd); USED(buffer); return -1; /* Unsupported */ } i32 screen_open(void *data, u32 mode) { USED(mode); ScreenDeviceData *screen = (ScreenDeviceData *)data; screen->window = SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen->width, screen->height, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); if (!screen->window) return -1; SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); return 0; } i32 screen_read(void *data, u8 *buffer, u32 size) { USED(data); USED(buffer); USED(size); return -1; } i32 screen_write(void *data, const u8 *buffer, u32 size) { ScreenDeviceData *screen = (ScreenDeviceData *)data; 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); return 0; } i32 screen_close(void *data) { ScreenDeviceData *screen = (ScreenDeviceData *)data; if (screen->window) { SDL_DestroyWindow(screen->window); screen->window = NULL; } return 0; } 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 } } /* MOUSE */ i32 mouse_open(void *data, u32 mode) { USED(data); USED(mode); return 0; } i32 mouse_read(void *data, u8 *buffer, u32 size) { MouseDeviceData *mouse_data = (MouseDeviceData *)data; if (size < 12) return -1; SDL_PumpEvents(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { // Mouse events case SDL_MOUSEMOTION: mouse_data->x = event.motion.x; mouse_data->y = event.motion.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: 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; break; // Touch events (map to mouse_data as left-click equivalent) case SDL_FINGERMOTION: case SDL_FINGERDOWN: case SDL_FINGERUP: { float x = event.tfinger.x * 640; float y = event.tfinger.y * 480; mouse_data->x = (int)x; mouse_data->y = (int)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; } } break; } } } 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)); return 0; } i32 mouse_write(void *data, const u8 *buffer, u32 size) { USED(data); USED(buffer); USED(size); return -1; } i32 mouse_close(void *data) { USED(data); return 0; } i32 keyboard_open(void *data, u32 mode) { USED(data); USED(mode); return 0; } i32 keyboard_read(void *data, u8 *buffer, u32 size) { KeyboardDeviceData *kbd = (KeyboardDeviceData *)data; if (size < (u32)kbd->key_count) return -1; memcpy(buffer, kbd->keys, kbd->key_count); return 0; } i32 keyboard_write(void *data, const u8 *buffer, u32 size) { USED(data); USED(buffer); USED(size); return -1; /* not writable */ } i32 keyboard_close(void *data) { USED(data); return 0; }