From 673e523b50fc351e7fb3a5420587bf094cd9db20 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Tue, 21 Jan 2025 10:04:55 -0800 Subject: [PATCH] Faster screen device --- src/devices/screen.c | 82 +++++++++++++++----------------------------- src/devices/screen.h | 7 ++-- src/uxncli.c | 2 +- src/uxnemu.c | 30 ++++++---------- 4 files changed, 43 insertions(+), 78 deletions(-) diff --git a/src/devices/screen.c b/src/devices/screen.c index 8225d79..92edfa2 100644 --- a/src/devices/screen.c +++ b/src/devices/screen.c @@ -30,23 +30,12 @@ static Uint8 blending[4][16] = { int screen_changed(void) { - if(uxn_screen.x1 < 0) - uxn_screen.x1 = 0; - else if(uxn_screen.x1 >= uxn_screen.width) - uxn_screen.x1 = uxn_screen.width; - if(uxn_screen.y1 < 0) - uxn_screen.y1 = 0; - else if(uxn_screen.y1 >= uxn_screen.height) - uxn_screen.y1 = uxn_screen.height; - if(uxn_screen.x2 < 0) - uxn_screen.x2 = 0; - else if(uxn_screen.x2 >= uxn_screen.width) - uxn_screen.x2 = uxn_screen.width; - if(uxn_screen.y2 < 0) - uxn_screen.y2 = 0; - else if(uxn_screen.y2 >= uxn_screen.height) - uxn_screen.y2 = uxn_screen.height; - return uxn_screen.x2 > uxn_screen.x1 && uxn_screen.y2 > uxn_screen.y1; + clamp(uxn_screen.x1, 0, uxn_screen.width); + clamp(uxn_screen.y1, 0, uxn_screen.height); + clamp(uxn_screen.x2, 0, uxn_screen.width); + clamp(uxn_screen.y2, 0, uxn_screen.height); + return uxn_screen.x2 > uxn_screen.x1 && + uxn_screen.y2 > uxn_screen.y1; } void @@ -58,14 +47,6 @@ screen_change(int x1, int y1, int x2, int y2) if(y2 > uxn_screen.y2) uxn_screen.y2 = y2; } -void -screen_fill(Uint8 *layer, int color) -{ - int i, len = MAR2(uxn_screen.width) * uxn_screen.height; - for(i = 0; i < len; i++) - layer[i] = color; -} - void screen_palette(void) { @@ -84,36 +65,27 @@ screen_palette(void) void screen_resize(Uint16 width, Uint16 height, int scale) { - Uint8 *bg, *fg; Uint32 *pixels = NULL; - int dim_change = uxn_screen.width != width || uxn_screen.height != height; - if(width < 0x8 || height < 0x8 || width >= 0x800 || height >= 0x800 || scale < 1 || scale >= 4) - return; - if(uxn_screen.width == width && uxn_screen.height == height && uxn_screen.scale == scale) - return; - if(dim_change) { - int wmar = MAR2(width), hmar = MAR2(height); - bg = malloc(wmar * hmar), fg = malloc(wmar * hmar); - if(bg && fg) - pixels = realloc(uxn_screen.pixels, width * height * sizeof(Uint32) * scale * scale); - if(!bg || !fg || !pixels) { - free(bg), free(fg); - return; - } - free(uxn_screen.bg), free(uxn_screen.fg); - } else { - bg = uxn_screen.bg, fg = uxn_screen.fg; - pixels = realloc(uxn_screen.pixels, width * height * sizeof(Uint32) * scale * scale); - if(!pixels) - return; - } - uxn_screen.bg = bg, uxn_screen.fg = fg; + clamp(width, 8, 0x800); + clamp(height, 8, 0x800); + clamp(scale, 1, 3); + /* on rescale */ + pixels = realloc(uxn_screen.pixels, width * height * sizeof(Uint32) * scale * scale); + if(!pixels) return; uxn_screen.pixels = pixels; - uxn_screen.width = width, uxn_screen.height = height, uxn_screen.scale = scale; - if(dim_change) - screen_fill(uxn_screen.bg, 0), screen_fill(uxn_screen.fg, 0); - emu_resize(width, height); + uxn_screen.scale = scale; + /* on resize */ + if(uxn_screen.width != width || uxn_screen.height != height) { + int i, length = MAR2(width) * MAR2(height); + Uint8 *bg = realloc(uxn_screen.bg, length), *fg = realloc(uxn_screen.fg, length); + if(!bg || !fg) return; + uxn_screen.bg = bg, uxn_screen.fg = fg; + uxn_screen.width = width, uxn_screen.height = height; + for(i = 0; i < length; i++) + uxn_screen.bg[i] = uxn_screen.fg[i] = 0; + } screen_change(0, 0, width, height); + emu_resize(width, height); } void @@ -212,7 +184,7 @@ screen_deo(Uint8 addr) case 0x2f: { int ctrl = uxn.dev[0x2f]; int twobpp = !!(ctrl & 0x80); - int blend = ctrl & 0xf; + int blend = ctrl & 0xf, opaque = blend % 5; int fx = ctrl & 0x10 ? -1 : 1, fy = ctrl & 0x20 ? -1 : 1; int i, x1, x2, y1, y2, ax, ay, qx, qy, x = rX, y = rY; int dxy = rDX * fy, dyx = rDY * fx, addr_incr = rMA << (1 + twobpp); @@ -225,7 +197,7 @@ screen_deo(Uint8 addr) Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y); if(xmar < wmar && ymar2 < hmar2) { Uint8 *sprite = &uxn.ram[rA]; - int opaque = blend % 5, by = ymar2 * wmar2; + int by = ymar2 * wmar2; for(ay = ymar * wmar2, qy = fy < 0 ? 7 : 0; ay < by; ay += wmar2, qy += fy) { int ch1 = sprite[qy], ch2 = sprite[qy + 8] << 1, bx = xmar2 + ay; for(ax = xmar + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { @@ -241,7 +213,7 @@ screen_deo(Uint8 addr) Uint16 xmar2 = MAR2(x), ymar2 = MAR2(y); if(xmar < wmar && ymar2 < hmar2) { Uint8 *sprite = &uxn.ram[rA]; - int opaque = blend % 5, by = ymar2 * wmar2; + int by = ymar2 * wmar2; for(ay = ymar * wmar2, qy = fy < 0 ? 7 : 0; ay < by; ay += wmar2, qy += fy) { int ch1 = sprite[qy], bx = xmar2 + ay; for(ax = xmar + ay, qx = fx > 0 ? 7 : 0; ax < bx; ax++, qx -= fx) { diff --git a/src/devices/screen.h b/src/devices/screen.h index 98fb5a2..d8b15ff 100644 --- a/src/devices/screen.h +++ b/src/devices/screen.h @@ -18,8 +18,6 @@ typedef struct UxnScreen { extern UxnScreen uxn_screen; extern int emu_resize(int width, int height); int screen_changed(void); -void screen_change(int x1, int y1, int x2, int y2); -void screen_fill(Uint8 *layer, int color); void screen_palette(void); void screen_resize(Uint16 width, Uint16 height, int scale); void screen_redraw(void); @@ -27,4 +25,9 @@ void screen_redraw(void); Uint8 screen_dei(Uint8 addr); void screen_deo(Uint8 addr); +/* clang-format off */ + +#define clamp(v,a,b) { if(v < a) v = a; else if(v >= b) v = b; } #define twos(v) (v & 0x8000 ? (int)v - 0x10000 : (int)v) + +/* clang-format on */ diff --git a/src/uxncli.c b/src/uxncli.c index b9ee4d7..12cbd07 100644 --- a/src/uxncli.c +++ b/src/uxncli.c @@ -47,7 +47,7 @@ main(int argc, char **argv) { int i = 1; if(argc == 2 && argv[1][0] == '-' && argv[1][1] == 'v') - return !fprintf(stdout, "Uxn(cli) - Varvara Emulator, 20 Jan 2025.\n"); + return !fprintf(stdout, "Uxn(cli) - Varvara Emulator, 21 Jan 2025.\n"); else if(argc == 1) return !fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]); else if(!system_boot((Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), argv[i++], argc > 2)) diff --git a/src/uxnemu.c b/src/uxnemu.c index a222e97..16eeb2b 100644 --- a/src/uxnemu.c +++ b/src/uxnemu.c @@ -40,8 +40,6 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. */ -#define PAD 2 -#define PAD2 4 #define WIDTH 64 * 8 #define HEIGHT 40 * 8 #define TIMEOUT_MS 334 @@ -61,12 +59,6 @@ static int window_created, fullscreen, borderless; static Uint32 stdin_event, audio0_event, zoom = 1; static Uint64 exec_deadline, deadline_interval, ms_interval; -static int -clamp(int val, int min, int max) -{ - return (val >= min) ? (val <= max) ? val : max : min; -} - static void audio_deo(int instance, Uint8 *d, Uint8 port) { @@ -161,7 +153,7 @@ set_zoom(Uint8 z, int win) { if(z < 1) return; if(win) - set_window_size(emu_window, (uxn_screen.width + PAD2) * z, (uxn_screen.height + PAD2) * z); + set_window_size(emu_window, uxn_screen.width * z, uxn_screen.height * z); zoom = z; } @@ -193,17 +185,17 @@ emu_resize(int width, int height) return 0; if(emu_texture != NULL) SDL_DestroyTexture(emu_texture); - SDL_RenderSetLogicalSize(emu_renderer, width + PAD2, height + PAD2); + SDL_RenderSetLogicalSize(emu_renderer, width, height); emu_texture = SDL_CreateTexture(emu_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STATIC, width, height); if(emu_texture == NULL || SDL_SetTextureBlendMode(emu_texture, SDL_BLENDMODE_NONE)) return system_error("SDL_SetTextureBlendMode", SDL_GetError()); if(SDL_UpdateTexture(emu_texture, NULL, uxn_screen.pixels, sizeof(Uint32)) != 0) return system_error("SDL_UpdateTexture", SDL_GetError()); - emu_viewport.x = PAD; - emu_viewport.y = PAD; + emu_viewport.x = 0; + emu_viewport.y = 0; emu_viewport.w = uxn_screen.width; emu_viewport.h = uxn_screen.height; - set_window_size(emu_window, (width + PAD2) * zoom, (height + PAD2) * zoom); + set_window_size(emu_window, width * zoom, height * zoom); return 1; } @@ -255,8 +247,6 @@ static void emu_restart(int soft) { screen_resize(WIDTH, HEIGHT, uxn_screen.scale); - screen_fill(uxn_screen.bg, 0); - screen_fill(uxn_screen.fg, 0); system_reboot(soft); SDL_SetWindowTitle(emu_window, "Varvara"); } @@ -321,7 +311,7 @@ handle_events(void) emu_redraw(); /* Mouse */ else if(event.type == SDL_MOUSEMOTION) - mouse_pos(clamp(event.motion.x - PAD, 0, uxn_screen.width - 1), clamp(event.motion.y - PAD, 0, uxn_screen.height - 1)); + mouse_pos(event.motion.x, event.motion.y); else if(event.type == SDL_MOUSEBUTTONUP) mouse_up(SDL_BUTTON(event.button.button)); else if(event.type == SDL_MOUSEBUTTONDOWN) @@ -401,8 +391,8 @@ emu_run(char *rom_path) emu_window = SDL_CreateWindow(rom_path, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - (uxn_screen.width + PAD2) * zoom, - (uxn_screen.height + PAD2) * zoom, + uxn_screen.width * zoom, + uxn_screen.height * zoom, window_flags); if(emu_window == NULL) return system_error("sdl_window", SDL_GetError()); @@ -423,7 +413,7 @@ emu_run(char *rom_path) now = SDL_GetPerformanceCounter(); next_refresh = now + frame_interval; uxn_eval(uxn_screen.vector); - if(screen_changed()) + if(uxn_screen.x2 && uxn_screen.y2 && screen_changed()) emu_redraw(); } if(uxn_screen.vector) { @@ -457,7 +447,7 @@ main(int argc, char **argv) /* flags */ if(argc > 1 && argv[i][0] == '-') { if(!strcmp(argv[i], "-v")) - return system_error("Uxn(gui) - Varvara Emulator", "19 Jan 2025."); + return system_error("Uxn(gui) - Varvara Emulator", "21 Jan 2025."); else if(!strcmp(argv[i], "-2x")) set_zoom(2, 0); else if(!strcmp(argv[i], "-3x"))