Browse Source

Faster screen device

main
Devine Lu Linvega 1 year ago
parent
commit
673e523b50
  1. 82
      src/devices/screen.c
  2. 7
      src/devices/screen.h
  3. 2
      src/uxncli.c
  4. 30
      src/uxnemu.c

82
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) {

7
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 */

2
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))

30
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"))

Loading…
Cancel
Save